iOS で Evernote API を使う(前編)
iPad から Evernote にアクセスするアプリを作ろうと思い、試してみました。
1. Evernote APIを理解する
a. ドキュメントに目を通す
Evernote API Overview | Evernote Corporation ページにある API Overview (PDF)を眺めると、 Evernoteのデータ構造、 APIの概略が解ります。
b. APIとサンプルコードをダウンロードして眺める
Evernote API Overview | Evernote Corporation ページある Download the API SDK から API, サンプルコードの入った zipファイルがダウンロードできます、現在のバージョンは1.17です。中にはいろいろな言語で書かれたサンプルがありませので、自分の好きな言語のサンプルを眺めてみます。私は当然Rubyですね。
c. サンプルを動かす為のAPI Keyを取得する
Evernote APIは OAuthを使ってクライアントソフトを認識するので、OAuth用のconsumer key, consumer secretを取得する必要があります。
Keyの取得は Evernote API Overview | Evernote Corporation ページのRequest an API Keyフォームを記述しSubmitボタンを押すと、consumer key , consumer secret が画面に表示されますのでメモしておきましょう。
d. Sandboxにテストデータを準備する
開発用にアクセスできるのは通常のEvernoteではなく、Sandbox です。 ここ でテスト用のアカウントを作成し、テスト用のコンテンツを格納して下さい。
e. サンプルコードを動かしてみる
b. で展開したサンプルコードに c. で取得した consumer key , consumer secret を書き込むと Sandbox の Evernoteがアクセスできます。
実行例:
% cd evernote-api-1.17/sample/ruby/client % vi EDAMTest.rb ← consumer key , consumer secret を書き込む % ruby EDAMTest.rb Sandboxのアカウント Sandboxのパスワード Unable to load thrift_native extension. Defaulting to pure Ruby libraries. warning: peer certificate won't be verified in this SSL session Is my EDAM protocol version up to date? true warning: peer certificate won't be verified in this SSL session Authentication was successful for yuumi3 Authentication token = S=s1:U=5381:E=130f97c8d8a:C=130f9459f0e:P=37:A=yuumi3:H=0bdbe82e2e87bf54ac6121ff0e3246e1 warning: peer certificate won't be verified in this SSL session Found 1 notebooks: * yuumi3 のノートブック Creating a new note in the default notebook: yuumi3 のノートブック warning: peer certificate won't be verified in this SSL session Successfully created a new note with GUID: 64983248-7d3f-438e-bbb0-7eeb0409c4f4
2. iOS用ライブラリーの作成
いよいよ、iOS用ライブラリーを作りましょう。手順は Evernote APIを使うiPhoneアプリの作りかた - the time ship を参考にしました。ありがとございます!
- Xcode4 で新規プロジェクト(Navigation-based Application)を作成します(Xcode3とはプロジェクトのディレクトリー構造が違いますね)。
- Evernote APIを入れるフォルダー/グループを作成し evernote-api-1.17/src/cocoa/thrift, evernote-api-1.17/src/cocoa/edam を以下の様にコピーします
- Build Settingsの Header Search Path に ./EvernoteTest/Library/thrift (Recusiveをチェック) を追加
- ビルド。エラーが無ければ成功
3. iOS用テストコードの作成
EvenoteのサンプルコードにはiOSや Mac OS X用ありません。そこで Evernote APIを使うiPhoneアプリの作りかた - the time ship] のコードをベースに Evernoteに格納されているノート名の一覧をテーブルで表示するテストコードを作ってみました。
Evernoteアクセスの主要部分は以下のようなります、 APIの詳細は Thrift API Reference を参照して下さい。
- user(アカウント)情報の取得
- 認証用トークンの取得
- Note情報の取得
- RootViewController.m の主要部分
#import "RootViewController.h" #import "THTTPClient.h" #import "TBinaryProtocol.h" #import "UserStore.h" #import "NoteStore.h" #define USERNAM @"XXXXXX" // Sandboxのアカウント #define PASSWORD @"XXXXXX" // Sandboxのパスワード #define CONSUMER_KEY @"XXXXX" // 取得したconsumer key #define CONSUMER_SECRET @"XXXXXX" // 取得したconsumer secret @implementation RootViewController @synthesize noteTitles; - (void) getEvernoteTitles { NSURL *userStoreURL = [NSURL URLWithString:@"https://sandbox.evernote.com/edam/user"]; NSString *noteStoreURLBase = @"http://sandbox.evernote.com/edam/note/"; // user情報を扱うオブジェクトの作成 THTTPClient *userStoreHTTPClient = [[[THTTPClient alloc] initWithURL:userStoreURL] autorelease]; TBinaryProtocol *userStoreProtocol = [[[TBinaryProtocol alloc] initWithTransport:userStoreHTTPClient] autorelease]; EDAMUserStoreClient *userStore = [[[EDAMUserStoreClient alloc] initWithProtocol:userStoreProtocol] autorelease]; // 通信プロトコルのバージョンのチェック BOOL versionOK = [userStore checkVersion:@"EDMATest" :[EDAMUserStoreConstants EDAM_VERSION_MAJOR] :[EDAMUserStoreConstants EDAM_VERSION_MINOR]]; if(!versionOK) { NSLog(@"checkVersion error"); return; } @try { // 認証用トークンの作成 EDAMAuthenticationResult *authResult = [userStore authenticate:USERNAM :PASSWORD :CONSUMER_KEY :CONSUMER_SECRET]; EDAMUser *user = [authResult user]; NSString *authToken = [authResult authenticationToken]; // Note情報を扱うオブジェクトの作成 NSURL *noteStoreURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@", noteStoreURLBase, [user shardId]]]; THTTPClient *noteStoreHTTPClient = [[[THTTPClient alloc] initWithURL:noteStoreURL] autorelease]; TBinaryProtocol *noteStoreProtocol = [[[TBinaryProtocol alloc] initWithTransport:noteStoreHTTPClient] autorelease]; EDAMNoteStoreClient *noteStore = [[[EDAMNoteStoreClient alloc] initWithProtocol:noteStoreProtocol] autorelease]; // Notebookの一覧取得 NSArray *notebooks = [noteStore listNotebooks:authToken]; for(int i = 0; i < [notebooks count]; i++) { EDAMNotebook *notebook = (EDAMNotebook*)[notebooks objectAtIndex:i]; NSLog(@"%@", [notebook name]); } // Note検索用フィルターの作成 EDAMNoteFilter *allFileter = [[[EDAMNoteFilter alloc] initWithOrder:0 ascending:YES words:nil notebookGuid:nil tagGuids:nil timeZone:nil inactive:NO] autorelease]; // Noteの一覧取得 EDAMNoteList *list = [noteStore findNotes:authToken :allFileter :0 :1000]; NSArray *notes = [list notes]; NSLog(@"notes count %d", [notes count]); [noteTitles removeAllObjects]; for (EDAMNote *note in notes) { // Note名の取得 NSLog(@"-- %@", [note title]); [noteTitles addObject:[note title]]; } [self.tableView reloadData]; } @catch (NSException * e) { NSLog(@"Caught %@: %@", [e name], [e reason]); } @finally { } [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; } ・・・・・・
- RootViewController.h
#import <UIKit/UIKit.h> @interface RootViewController : UITableViewController { NSMutableArray *noteTitles; } @property(nonatomic, retain) NSMutableArray *noteTitles; @end
- RootViewController.m その他
・・・・・・ - (void)viewDidLoad { [super viewDidLoad]; self.noteTitles = [NSMutableArray array]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [UIApplication sharedApplication].networkActivityIndicatorVisible = YES; [self performSelector:@selector(getEvernoteTitles) withObject:nil afterDelay:0.2]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [noteTitles count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; } cell.textLabel.text = [noteTitles objectAtIndex:[indexPath row]]; return cell; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; self.noteTitles = nil; } - (void)viewDidUnload { [super viewDidUnload]; self.noteTitles = nil; } - (void)dealloc { [noteTitles release]; [super dealloc]; } @end