AndroidでつくるEvernote連携アプリ

第3回Evernoteにノートを作る

前回は Evernoteのサーバに対して認証を行うところまでを実装しました。今回はユーザの認証情報を元に、ノートを作成するところまで進めます。

はじめに、Evernoteのデータモデルについて簡単に記載します。

Evernoteのデータモデル
Evernoteのデータモデル

上記はEvernoteの開発者向け公式サイトから転載したデータモデルの概要図ですが、大きく分けてユーザの情報(左側)とノートの情報(右側)があり、ノートの情報には

  • ノートブック
  • ノート
  • リソース
  • タグ
  • 保存された検索(SavedSearch)

といったデータがあるのがわかるかと思います。これらの各データはすべて「guid」と呼ばれる固有のidを保持しており、guidによって一意に特定することが可能です。

今回はシンプルに題名・本文だけのノートの作成をしますので、必要な情報はノートとノートブックだけです。

ノートとノートブックの関係

すべてのノートはいずれか1つのノートブックに所属することになります。ノートにはノート自身のguid、タイトル、本文といった情報の他にノートが属しているノートブックのguidを格納していて、これによりノートとノートブックの関連性を定義しています。

ノートとノートブックの関係
ノートとノートブックの関係

1つのノートが複数のノートブックに属することはできず、明示的に指定しない場合はデフォルトのノートブックに保存されます。ノートやノートブックには他にも沢山の属性があります。本連載でも追って紹介していきますが、詳細な情報は公式の開発者サイト「Evernoteのデータモデル⁠⁠、網羅的な情報は公式リファレンスで確認してください。

ENML:Evernote Markup Language

次にノートの本文の形式について説明します。

Evernoteのノートの本文は、ENML(Evernote Markup Language)と呼ばれるXHTMLのサブセットベースの独自マークアップ言語で記述しなければいけません。たとえ本文にテキストが必要のないアプリ(例: 写真を保存するだけのアプリ)でも、本文のフォーマットはENML形式に従う必要があります。XHTMLのタグのうちどれが使用可能かと、ENMLタグ独自の記述方法をおさえておく必要があります。

ENML文書の最小構成は以下のようになります。

ENMLのテンプレート
<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd">
<en-note>
ここにコンテンツを記載
</en-note>

1行目の宣言部分はなくてもかまいませんが、ノートの本文は必ず<en-note>タグで囲まれている必要があります。

この<en-note>までの開始タグまでと、</en-note>の閉じタグについてはそれぞれEvernoteUtil.NOTE_PREFIX と EvernoteUtil.NOTE_SUFFIX で呼び出すことができますので、 ノートの本文の内容(content)についてはコンテンツをENMLの構文で記載した後

content = EvernoteUtil.NOTE_PREFIX + content + EvernoteUtil.NOTE_SUFFIX;

のようにしてENML文書を作成しておくのが良いでしょう。

またcontentがプレーンテキストで改行したいブロックごとにdiv要素で囲うことが推奨されています。

ENMLで使用できるXHTMLのタグ一覧については公式デベロッパーサイトのENMLの項目を参照ください。

ノートを作ってみる

それでは実際にノートを作ってみましょう。

前回最後に表示したメニュー画面(MenuFragment)において"Create a new note"をタッチすると、下記のノート作成画面に遷移するようにします。

SimpleNoteFragmentの画面
SimpleNoteFragmentの画面

今回は

MainActivity
├ MenuFragment
├ SimpleNoteFragment
:

のように大元のActivityの上に各機能をFragmentとして乗せる設計にしていますので、MenuFragmentで各アイテムが押下された際にMainActivityに通知してやる必要があります。

具体的にはMenuFragment側で各アイテムが押された際に、⁠リストの何番目のアイテムが押されたか」を引数に呼ばれるListenerをInterfaceとして定義してやり、

MenuFragment.java
OnMenuItemSelectedListener mListener; 
:
    public interface OnMenuItemSelectedListener {
        public void onMenuItemSelected(int pos);
    }
:
    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        mListener.onMenuItemSelected(position);
    }

MainActivity側で、渡された番号に応じて対応するFragmentにreplaceするようにonMenuItemSelectedを実装してやればOKです。

MainActivity.java
@Override
public void onMenuItemSelected(int position) {
    FragmentManager fm = getFragmentManager();
    FragmentTransaction ft = fm.beginTransaction();

    switch (position) {
        case 0:
            ft.replace(R.id.fragment_container, new SimpleNoteFragment(), "SimpleNote");
            break;
        default:
            ;
    }
…省略…
}

今回はノート作成画面で

  • 保存するノートブックの選択
  • タイトルの指定
  • 本文の指定

を行えるようにします。

以下、ユーザのノートに対する操作は基本的にすべて、前回取得したユーザのセッション情報のオブジェクトを元に行っていきます。

ノートブックの選択

それではユーザの持つノートブック一覧をEvernoteのサーバから取得してみましょう。

Androidではhttp通信の処理についてはメインのUIスレッドを止めないように非同期で行うのが一般的ですが、Evernote SDKのサーバ間通信も非同期処理になっています。ノートを取得する処理は以下のように書くことができます。

mEvernoteSession.getClientFactory().createNoteStoreClient().listNotebooks(new OnClientCallback<List<Notebook>>() {
    @Override
    public void onSuccess(final List<Notebook> notebooks) {
        // 成功時の処理
     }

    @Override
    public void onException(Exception exception) {
        // 失敗時の処理
    }
}

セッションオブジェクトを基にノートストアのクライアントを作成し、listNotebooksメソッドでノートブックの一覧をサーバに取得しに行きます。成功時/失敗時ともに処理はコールバック関数の中で記述します。

今回のSimpleNoteFragmentではSelect a notebookのボタンを押下した際に上記のメソッを呼び出し、成功時→ダイアログを開いて取得できたノートブック一覧を取得とします。

成功時に開くダイアログの画面
成功時に開くダイアログの画面

これは、失敗時→エラーのToastを表示としています。

ユーザがいずれかのノートブックを選択して「OK」ボタンを押下した時点で、選択されたノートブックのguidを裏でセットしています。

ノートの作成

ノートブックの選択機能を作成したら、あとはノートそのものを選択したノートブックに保存する処理の作成です。

基本はノートブック一覧の取得時と同じで、違うのはあらかじめ保存するノートのオブジェクトを作っておくところだけです。ノートのオブジェクトを作成すると、オブジェクトに必要な情報をセットするための様々なメソッドが利用できます。

今回のサンプルでは、

  1. ノートのオブジェクトを作成し
  2. タイトルをセットし
  3. AndroidのEditText欄に入力されたテキストをcontentに格納し(ユーザの入力で改行"\n"があった場合、そこまでを1ブロックとしてdivタグで囲っています)
  4. ユーザがノートブックを選択していた場合は対応するノートブックのguidを格納し
  5. 最後にcontentの内容をノートの本文にセットする

という流れで実装しています。

Note note = new Note();  //(1)
note.setTitle(title);  //(2)

// (3)
if(content.contains("\n")) {
    String[] contents = content.split("\n");
                        content = "";
                        for(int i = 0; i < contents.length; i++) {
                            if(contents[i].equals("")){
                                contents[i] = "<br />";
                            }
                            contents[i] = "<div>" + contents[i] + "</div>";
                            content += contents[i];
                        }
                    }
                    content = EvernoteUtil.NOTE_PREFIX + content;

                    // (4)
                    if(guid != null) {
                        note.setNotebookGuid(guid);
                    }

                    // (5)
                    content = content + EvernoteUtil.NOTE_SUFFIX;
                    note.setContent(content);

作成するノートの準備ができれば、実際にノートを保存する処理はノートブック一覧の取得とそこまで変わりません。

mEvernoteSession.getClientFactory().createNoteStoreClient().createNote(note, new OnClientCallback<Note>() {
                            @Override
                            public void onSuccess(Note data) {
                                // 成功時の処理
                            }

                            @Override
                            public void onException(Exception exception) {
                                // 失敗時の処理
                            }
                        });

作成したノートのオブジェクトを引数に、非同期通信でEvernoteに対して保存処理を実施します。

実際にエミュレータでアプリを実行してみましょう。

エミュレータでアプリを実行
エミュレータでアプリを実行

"Select a notebook"で適当なノートブックを選んで、タイトルと本文を上記のように入力して"Save"を押下します。

成功したら、サンドボックスのサーバにブラウザからアクセスして、自身のアカウントでノートを確認してみましょう。

サンドボックスで試す
サンドボックスで試す

指定したノートブックに確かにノートが保存されているのがわかるはずです(ノートブックを指定しなかった場合は、デフォルトのノートブックに保存されます⁠⁠。

他にもENMLのタグを使ったテストをしてみましょう。

ENMLのタグを使ったテスト
ENMLのタグを使ったテスト

en-todoタグは、ノート内でチェックボックスを定義できる独自タグです。checked="true"をつけるとデフォルトでチェックが付いた状態になります。また下のspanタグは文字を赤く、サイズを大きく装飾していて、こちらは標準のcssと変わらない指定です。Evernoteのノート内では、すべてのスタイルはstyle属性を使ってインラインで行う必要があります。

このノートを保存すると実際に反映されていることが確認できます。

ノートの保存を確認
ノートの保存を確認

ここまでで、

  • ノートブックを選択して
  • タイトルと本文のみのノートを作成する

という実装が完了しました。

認証済みのセッションオブジェクトがあれば、用意された非同期通信のメソッドのみで簡単に処理が行えることがお分かりいただけるかと思います。

次回はノート作成についてもう少し踏み込んで、リソースについてお話します。

おすすめ記事

記事・ニュース一覧