iPhoneアプリにEvernote連携機能を追加する

| コメント(0) | トラックバック(0)

こんにちは。開発担当のICTFです。


今回は、iPhoneアプリにEvernote連携機能を組み込み、新規ノートをアップロードするまでの手順を紹介します。


まず、Evernoteデベロッパーサイトを表示します。

http://dev.evernote.com/intl/jp/documentation/cloud/


サイトが表示されたら、最初の手順である「APIキーの取得」を行ないます。

スクリーンショット 2012-09-19 0.18.33.png
「API キーの取得>」リンクをクリックするとアプリ情報の入力画面が開くので、入力を完了して「申請する」ボタンをクリックして下さい。
申請が完了すると、「Consumer Key」と「Consumer Secret」を取得できます。
この2項目はアプリに機能を実装する上で重要な項目となりますので、紛失しないようにしてください。

APIキーの取得が終わったら、手順2であるSDKのダウンロードに移ります。
リンクをクリックするとGitHubに移動しますので、iOS用SDKのリンクをクリックします。
スクリーンショット 2012-09-19 0.54.21.png
リンクを飛んだ先のページ上部にある「↓ZIP」ボタンをクリックすると、iOS用SDKのダウンロードが開始するはずです。
スクリーンショット 2012-09-19 0.55.31.png
次に手順3であるサンドボックス環境でのアプリ開発に移ります。
XCodeプロジェクトに先ほどダウンロードしたSDKの「evernote-sdk-ios」フォルダを丸ごと追加して下さい。
※EvernoteSDKはARCに対応していません。MRCプロジェクトであれば問題ありませんが、ARCプロジェクトの場合はSDKのすべてのソースにMRCコンパイルオプションを適用する必要がありますので注意して下さい。

さらに「Security.framework」を追加します。
スクリーンショット 2012-09-19 1.03.26.png
これで準備は完了です。
ソースコードの追加に移ります。
まず、先ほど取得したキー情報でEvernoteSessionを初期化します。
アプリ起動後1回初期化できれば問題無いので、AppDelegate内で問題無いでしょう。
AppDelegate.mにEvernoteSDK.hをインポートします。

#import "EvernoteSDK.h"


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptionsに次の記述を追加します。

    // リリース前に@"www.evernote.com"に変更すること!

    NSString *EVERNOTE_HOST = @"sandbox.evernote.com";

    NSString *CONSUMER_KEY = @"取得したConsumer Keyを記述します";

    NSString *CONSUMER_SECRET = @"取得したConsumer Secretを記述します";

    // set up Evernote session singleton

    [EvernoteSession setSharedSessionHost:EVERNOTE_HOST

                              consumerKey:CONSUMER_KEY

                           consumerSecret:CONSUMER_SECRET];


初期化処理はこれで完了です。
最後にログイン処理を実装します。
Evernoteへのログインは、アップロードしようとするタイミングや、あるいはログインボタンを追加する事などが考えられます。開発するアプリに適したIFを実装してください。
サンプルではアップロードしようとするタイミングにログイン処理を実装します。

// 計算結果をEvernoteに新規メモ登録する

-(void) addEvernote

{

EvernoteSession* session = [EvernoteSession sharedSession];

if (session.isAuthenticated == NO) {

// 未ログインであれば、ログイン処理を行なう

[session authenticateWithViewController:self completionHandler:^(NSError *error) {

if (error || !session.isAuthenticated) {

// ログインエラー処理を記述します(メッセージ表示など)

} else {

// ログイン完了

NSLog(@"Evernoteにログイン完了 noteStoreUrl:%@ webApiUrlPrefix:%@", session.noteStoreUrl, session.webApiUrlPrefix);

[self addEvernote];

}

}];

return;

}

// プレーンテキストを得る

NSString* text = [self getText];

// プレーンテキストをENML形式に変換する

NSMutableString* enml = [NSMutableString string];

[enml setString:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"];

    [enml appendString:@"<!DOCTYPE en-note SYSTEM \"http://xml.evernote.com/pub/enml.dtd\">"];

[enml appendString:@"<en-note>"];

NSRange range = NSMakeRange(0, text.length);

NSRange lineRange;

NSString* lineString;

while (range.length > 0) {

// 改行コードかあるいは文字列の終端までを読み込み、ENML形式に変換する

lineRange = [text lineRangeForRange:NSMakeRange(range.location, 0)];

lineString = [text substringWithRange:lineRange];

NSLog(@"line: %@", lineString);

range.location = NSMaxRange(lineRange);

range.length -= lineRange.length;

if ([lineString isEqualToString:@"\n"]) {

// 改行のみの場合、<br />に変換する

lineString = @"<br />";

}

else {

// 改行以外の文字が含まれる場合、改行コードを削除する

lineString = [lineString stringByReplacingOccurrencesOfString:@"\n" withString:@""];

}

// 文字列の両端に<div> </div>を連結する

[enml appendFormat:@"<div>%@</div>", lineString];

}

[enml appendString:@"</en-note>\n"];

// tag情報の作成

NSArray* tagList = [NSArray arrayWithObjects:@"好きなタグを記述して下さい", nil];

// noteオブジェクトの生成

    EDAMNoteAttributes *newNoteAttributes = [[[EDAMNoteAttributes alloc] init] autorelease];

    EDAMNote *newNote = [[[EDAMNote alloc] init] autorelease];

    [newNote setTitle:_template.title];

    [newNote setContent:enml];

    [newNote setTagNames:tagList];

    [newNote setAttributes:newNoteAttributes];

    [newNote setCreated:(long long)[[NSDate date] timeIntervalSince1970] * 1000];

    // noteを追加する

    EvernoteNoteStore *noteStore = [EvernoteNoteStore noteStore];

    [noteStore createNote:newNote

                  success:^(EDAMNote *note) {

// アップロード成功時処理(メッセージ表示など)

                  }

                  failure:^(NSError *error) {

        // アップロード失敗時処理(メッセージ表示など)

NSLog(@"createNote error %@", error);

                  }];

// アップロードファイルのサイズによっては、ここで「アップロード中」表示を行なった方がよいかもしれません。

}


addEvernoteメソッドは、Evernoteへアップロードする為のIFが操作された際にコールされます。(addEvernoteはサンプルで使用している独自のメソッドなので、各自実装する必要があります。)
まずログイン状態であるかをチェックし、未ログインであればauthenticateWithControllerメソッドをコールしてログインを誘導します。
このメソッドはGCDで動作し、ログイン結果はブロックで受け取ります。
ログイン処理自体は非同期で行なわれますので、ここで一旦addEvernoteメソッドを終了します。
ログイン処理が終了するとブロック内の処理が動作しますので、もう一度ログイン状態を確認し、ログイン状態であるならば再度addEvernoteメソッドをコールしています。

getTextメソッドコールしている箇所から新規ノートをアップロードする為の処理になります。
getTextメソッドは、アップロードしたいメモ情報をプレーンテキストで取得する為のメソッドです。(getTextメソッドはサンプルで使用している独自メソッドですので、各自実装する必要があります。)
取得したプレーンテキストはそのままではEvernoteのドキュメントとして認められません。
Evernote独自の書式であるENML形式(ほぼHTML)に変換する必要があります。
プレーンテキストを1行ずつ読み取り、whileループでENML形式への変換を行っています。

tag情報はNSArrayで作成します。

Evernoteのnoteオブジェクトを生成します。
noteの属性はEDAMNoteAttributes、noteはEDAMNoteクラスを用います。
noteオブジェクトに各プロパティと属性クラスを追加した後、EvernoteNoteStoreのcreateNoteメソッドをコールします。
このメソッドもGCDであり、非同期にアップロードが行なわれます。
アップロード処理が終了するとブロック内が処理されます。
回線の状況やアプロードファイルのサイズによっては時間がかかる処理となりますので、createNoteメソッドをコールした後に「アップロード中」である旨の表示処理を行なった方が良いかもしれません。

アプリの開発とサンドボックスでの試験が完了したら、手順4であるAPIキーのアクティベートを行ないます。
リンクをクリックすると必要事項の入力画面に移りますので、入力を完了して申請して下さい。
私の経験ですが、APIキーの作成2日後にアクティベート申請を出したところ、
お使いのAPIキーは今週発行したばかりのものです。お手数ですが、サンドボックス上でのテストにもう少し時間をお使い頂き、その上でプロダクションへの移行のためのご依頼を頂けますと幸いです。」
という返信を頂き、アクティベートを認められませんでした。
APIの作成から1週間程時間を置いて申請した方が無難かもしれません。

アクティベートが無事終了したら、EVERNOTE_HOSTの値を忘れずに書き換えて下さい。
折角Evernote連携機能を追加したアプリが市場に出たのに、アップロード先がサンドボックスなのでは悲しすぎますからね。

トラックバック(0)

トラックバックURL: http://www.ict-fractal.com/MovableType/mt/mt-tb.cgi/38

コメントする

Twitterボタン
Twitterブログパーツ