Android から Dropbox を利用したアプリを作成してみる
以下を参考に。
https://www.dropbox.com/developers/start/setup#android
API リファレンス https://www.dropbox.com/static/developers/dropbox-android-sdk-1.3.1-docs/index.html
Dropbox アカウントの開設
まず、Dropbox アカウントが開設されていないと話になりません。
ここ から開設できます(なおかつ、ここからアカウント登録すると、500MB の容量ボーナスがもらえます!)
Android SDK のセットアップ
My Apps ページから、新規アプリケーションを作成
アプリケーションから利用するために、アプリケーションの情報を登録する必要がある。
https://www.dropbox.com/developers/apply
以下の手順で、app キー と app シークレットキー が取得でき、API が利用可能となる。
Create App ボタンを押下すると、アプリケーション名と、以下のタイプを選択するダイアログが表示される
選択する内容は、、、
App フォルダ
ユーザーのDropbox内の、一つのフォルダにしか、アクセスする必要が無い場合(推奨)
フル Dropbox
ユーザーのDropbox 全体にアクセスする場合
あとは、ウィザードに従い、内容を設定。
SDKのダウンロード
SDK を https://www.dropbox.com/developers/reference/sdk からダウンロード
Dropbox + アイコンを押すと、自分のDropbox フォルダに、dropbox-android-sdk-1.3.1 フォルダが作成された。
中に、サンプルも入っているので、参考になる。
ライブラリの設定
Dropbox\dropbox-android-sdk-1.3.1\lib にある、jar を、プロジェクトの直下に、libs フォルダーを作成し、そこにコピー
プロジェクトのプロパティから、ライブラリをビルドパスに追加する。
実装
app キー と app シークレットキー など、定数を切っておく。
public class FlashcardRoidApplication extends Application { // app キー public static final String DROPBOX_APP_KEY = "xxxxxxxxxxxxx"; // app シークレットキー public static final String DROPBOX_APP_SCECRET = "xxxxxxxxxxxxx"; public static final String DROPBOX_APP_FOLDER_NAME = "FlashcardRoid"; public static final AccessType DROPBOX_ACCESS_TYPE = AccessType.APP_FOLDER; }
AndroidManifest.xml に Dropbox 認証用のアクティビティを登録
<activity android:name="com.dropbox.client2.android.AuthActivity" android:launchMode="singleTask" android:configChanges="orientation|keyboard"> <intent-filter> <!-- 以下のxxxxxxに app キー を設定する --> <data android:scheme="db-xxxxxx" /> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.BROWSABLE"/> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
パーミッションを追加
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
認証するまでのコード
package info.typea.flashcard; import com.dropbox.client2.DropboxAPI; import com.dropbox.client2.android.AndroidAuthSession; import com.dropbox.client2.session.AccessTokenPair; import com.dropbox.client2.session.AppKeyPair; import android.app.Activity; import android.os.Bundle; import android.util.Log; public class FlashcardRoidActivity extends Activity { private DropboxAPImDBApi; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); AndroidAuthSession session = buildDropboxSession(); mDBApi = new DropboxAPI (session); mDBApi.getSession().startAuthentication(FlashcardRoidActivity.this); } @Override protected void onResume() { super.onResume(); AndroidAuthSession session = mDBApi.getSession(); if (session.authenticationSuccessful()) { try { mDBApi.getSession().finishAuthentication(); AccessTokenPair tokens = mDBApi.getSession().getAccessTokenPair(); storeDropboxKeys(tokens.key, tokens.secret); } catch (IllegalStateException e) { Log.i(FlashcardRoidApplication.TAG, "Error authenticating", e); } } } /** * Dropbox アクセスキーを保持しておく * @param key * @param secret */ private void storeDropboxKeys(String key, String secret) { // TODO SharedPreferences に保持しておく実装 } /** * Dropbox アクセスキーを取得する * @return */ private String[] getStoredDropboxKeys() { // TODO SharedPreferences から アクセスキーを取得する実装 return null; } /** * Dropbox セッションを作成する * @return */ private AndroidAuthSession buildDropboxSession() { AppKeyPair appKeyPair = new AppKeyPair(FlashcardRoidApplication.DROPBOX_APP_KEY, FlashcardRoidApplication.DROPBOX_APP_SCECRET); AndroidAuthSession session = null; String[] keys = getStoredDropboxKeys(); if (keys == null) { session = new AndroidAuthSession(appKeyPair, FlashcardRoidApplication.DROPBOX_ACCESS_TYPE); } else { AccessTokenPair accessToken = new AccessTokenPair(keys[0], keys[1]); session = new AndroidAuthSession(appKeyPair, FlashcardRoidApplication.DROPBOX_ACCESS_TYPE, accessToken); } return session; } }
この状態だと、毎回、以下の認証画面が出てくるので、SharedPreferences などに保存しておく。上記SDKに含まれるサンプルでは、そうしているので参考にするとよい。
ここまでで実行
Dropboxの認証アクティビティが表示され、許可すると処理が続行されるようになる。
ファイルをアップロードしてみる
とりあえず、ボタンを作って、ファイルをアップロードしてみる。以下を、アクティビティの onCreate に記述(レイアウトにもボタンを追加)
Button btnUpload = (Button)findViewById(R.id.btn_upload); btnUpload.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { Date now = new Date(); InputStream in = new ByteArrayInputStream(now.toString().getBytes()); String filename = String.format("/%tY%tm%td%tH%tM%tS.txt", now, now, now, now, now, now); Entry entry = mDBApi.putFile(filename, in, now.toString().getBytes().length, null, null); } catch (Exception e) { Log.e(FlashcardRoidApplication.TAG,"Upload Error", e); } } });
ファイルがアップロード、同期された。PCの方に通知される。
ファイルの一覧を取得し、メタデータを表示してみる
search() の query 引数には、3文字以上渡す必要があるようだ。"txt" を渡しているが、"*.*" のようなワイルドカードはどうも機能しない感じ。
Button btnSearch = (Button)findViewById(R.id.btn_search); btnSearch.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { int filelimit = -1; // Default is 10,000 if you pass in 0 or less Listentries = mDBApi.search("/", "txt", filelimit, false); for (Entry entry : entries) { // メタデータを含めて表示 Log.i(FlashcardRoidApplication.TAG, String.format("path=%s,rev=%s", entry.path, entry.rev)); } } catch (Exception e) { Log.e(FlashcardRoidApplication.TAG,"Upload Error", e); } } });
上記でアップロードしたファイル情報が取得できている
ファイルをダウンロードしてみる
上記で作成して、Dropbox 上に保存したファイル(最新バージョン)を、Andoroid 端末の SDカード上にダウンロードしてみる。
Button btnDown = (Button)findViewById(R.id.btn_download); btnDown.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { String target = "20120525171459.txt"; // 対象ファイル名 // 端末の SDカード上のデータ格納先 File sdcarddir = Environment.getExternalStorageDirectory(); String apppath = sdcarddir.getAbsolutePath() + File.separatorChar + "data" + File.separatorChar + this.getClass().getPackage().getName().replaceAll("[.]", Character.toString(File.separatorChar)) + File.separatorChar ; File appDir = new File(apppath); if (!appDir.exists()) { if(!appDir.mkdirs()) { throw new IllegalStateException("おそらく、android.permission.WRITE_EXTERNAL_STORAGE が マニフェストに設定されてないのでは?"); } } File file = new File(apppath + File.separatorChar + target); Log.i(FlashcardRoidApplication.TAG, "download destination : " + file.getAbsolutePath()); OutputStream os = new FileOutputStream(file); DropboxFileInfo dfi = mDBApi.getFile(File.separatorChar + target, null, os, null); Log.i(FlashcardRoidApplication.TAG, "file's revision : " + dfi.getMetadata().rev); } catch(Exception e) { Log.e(FlashcardRoidApplication.TAG,"Download Error", e); } } });
Dropbox では、変更を 30日まで保持している(Pack-Rat アドオン利用時にはそれ以上)が、DropboxFileInfo は、メタデータエントリーを含んでおり、rev を比較することで、最新版かどうかを判定できる。
端末のSDカード、アプリケーションフォルダにダウンロードされた。
うーん簡単に使えて便利。アプリ開発の幅が拡がりそうな気はする。
あと、Revert とか、Conflict とか、通常のバージョン管理システムで意識するような点は
どうするのが Dropbox 的に良いのかが気になるが、単純に使う分には問題なさそうだ。