2011/02/02
Android で Googleドキュメントの一覧を取得する
Googleドキュメントやその他のGoogleのサービスは、その多くがHTTPアクセスでXMLを取得できるAPIを用意しているため、比較的容易にその通信を実装することができます。
↓ Google Docs のプロトコル
http://code.google.com/intl/en/apis/documents/docs/3.0/developers_guide_protocol.html
しかし、定型文のプロトコルを毎回ユーザが実装するのは面倒くさい。ってことで、Google は各言語からアクセス可能なラッパーAPIを用意しています。
↓ Google Data API
http://code.google.com/intl/en/apis/gdata/docs/client-libraries.html
ちょっと前まではこの Google Data API で Android用のAPIも定義されていたのですが、最近になって分離したみたいです。というわけで、上記の Google Data API では Android用のプログラムは書けません。
トライはしてみたのですが、どうもうまくいきませんでした。API としては結構良い出来なんですがねぇ。
とはいえ、GoogleがAndroidを見捨てるはずがありません。現在は以下のAPIを使うことができます。
↓ Google API Client Library for Java
http://code.google.com/p/google-api-java-client/
というより、今後Java用のAPIはこちらに移行するんでしょうかね。 このAPIはまだアルファバージョンのため、まだ不完全感が漂っていますが、使ってみると結構良い感じです。
以下にAndroidアプリケーションから Google API Client Library for Java を使って Googleドキュメント の一覧を取得するサンプルを挙げておきます。
- いつも通り Eclipse上で Android プロジェクトを作成します
- Google API Client Library for Java から google-api-client-x.x.x-java.zip をダウンロードして解凍します。今回は、google-api-client-1.2.2-alpha-java.zip を使用しました。
- プロジェクト直下に lib ディレクトリを作成し、先のライブラリをおきます。少なくともこのバージョンでは google-api-client-1.2.2-alpha.jar という1ファイルにまとめられているようです。
(その他のファイルはソースコード等です。デバッグには使えますが、コンパイルするだけなら必要ありません。) - Eclipse上でプロジェクトをリフレッシュ(F5)します。lib ディレクトリが表示されるので、ライブラリを選択して、
右クリック→ビルド・パス→ビルド・パスに追加
としてライブラリを登録します。
- MainActivity.java、 AndroidManifest.xml を以下のように修正します。
MainActivity.javapackage com.kokufu.test; import java.io.IOException; import java.util.ArrayList; import java.util.List; import android.accounts.Account; import android.accounts.AccountManager; import android.accounts.AuthenticatorException; import android.accounts.OperationCanceledException; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.ViewGroup.LayoutParams; import android.widget.TextView; import com.google.api.client.googleapis.GoogleHeaders; import com.google.api.client.googleapis.GoogleTransport; import com.google.api.client.googleapis.GoogleUrl; import com.google.api.client.http.HttpRequest; import com.google.api.client.http.HttpTransport; import com.google.api.client.util.Key; import com.google.api.client.xml.XmlNamespaceDictionary; import com.google.api.client.xml.atom.AtomParser; public class MainActivity extends Activity { private static final String TAG = "GoogleDocsTest"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // AccountManager を通じてGoogleアカウントを取得 AccountManager manager = AccountManager.get(this); Account[] accounts = manager.getAccountsByType("com.google"); Bundle bundle = null; try { bundle = manager.getAuthToken( accounts[0], // テストなので固定 "writely", // ※1 null, this, null, null).getResult(); } catch (OperationCanceledException e) { Log.e(TAG, "", e); return; } catch (AuthenticatorException e) { Log.e(TAG, "", e); return; } catch (IOException e) { Log.e(TAG, "", e); return; } String authToken = ""; if (bundle.containsKey(AccountManager.KEY_INTENT)) { // 認証が必要な場合 Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT); int flags = intent.getFlags(); flags &= ~Intent.FLAG_ACTIVITY_NEW_TASK; intent.setFlags(flags); startActivityForResult(intent, 0); // 本当はResultを受けとる必要があるけど割愛 return; } else { // 認証用トークン取得 authToken = bundle.getString(AccountManager.KEY_AUTHTOKEN); } // 送信準備 HttpTransport transport = GoogleTransport.create(); GoogleHeaders headers = (GoogleHeaders) transport.defaultHeaders; headers.setApplicationName("Kokufu-GoogleDocsTest/1.0"); headers.gdataVersion = "3"; headers.setGoogleLogin(authToken); // 認証トークン設定 // Parser を準備して Transport にセットする AtomParser parser = new AtomParser(); // 空の Dictionary でとりあえず問題なさげ parser.namespaceDictionary = new XmlNamespaceDictionary(); transport.addParser(parser); // 送信 Feed feed = null; try { HttpRequest request = transport.buildGetRequest(); request.url = new GoogleUrl("https://docs.google.com/feeds/default/private/full"); // ※2 feed = request.execute().parseAs(Feed.class); } catch (IOException e) { Log.e(TAG, "", e); return; } // 結果を表示 String tmp = ""; for (Entry entry : feed.entries) { tmp += entry.title + "\n"; } TextView v = new TextView(this); v.setText(tmp); this.addContentView( v, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); } /** * Feed タグ */ private class Feed { @Key("entry") public List
entries = new ArrayList (); } /** * Entry タグ */ private class Entry { @Key public String summary; @Key public String title; @Key public String updated; } }
AndroidManifest.xml に以下のパーミッションを追加<uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.USE_CREDENTIALS" /> <uses-permission android:name="android.permission.INTERNET" />
わかりやすさを重視して書いているので、Google Account が登録されていないような端末で動作させるとアプリが落ちます。その他、通信状況が悪かったりしてもうまくいかないことがあると思いますが、その辺ご容赦ください。
また、このやり方で、Google Docs 以外のGoogleサービスにもほとんどアクセスが可能です。
ポイントは ※1 に書いてある"writely"という文字列(authTokenType)。この"writely"が、Google Docsに対するアクセス権の認証を意味しています。
その他の authTokenType 一覧は無いものかと探してみたら、まさにタイムリー!!
Mine さんの AndroidのGoogle Authenticatorを解析(?)してみた という投稿に詳しく書いてあります。
素晴らしい!
また、※2の Query についてはGoogle Docs のプロトコル
http://code.google.com/intl/en/apis/documents/docs/3.0/developers_guide_protocol.html
に詳しく載っています。
この辺を読まなくても良いくらいに隠蔽してくれるとAPIとして使いやすいんですけどねぇ。
まぁ、アルファ版なんで仕方がありません。API仕様もこれからどんどん変わっていく可能性があるので、この記事の賞味期限は短めだろうなぁ…
0 件のコメント:
コメントを投稿