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 DropboxAPI mDBApi;
@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
List entries = 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 的に良いのかが気になるが、単純に使う分には問題なさそうだ。
