Android端末からファイルを選択してファイルパスを取得したいと思った時、
どうやろうかなぁって思い調べたらこの記事を見つけました。
Androidでファイル選択ダイアログができなかったのでIntentでファイル選択アプリを呼び出す
この記事見た時になるほどなぁと思ったんですが、「あれこれする」ってどうすりゃいいんだ、と。
勝手に続きを書こうかなと思います。
・Android端末から外部のIntentを発行してFileエクスプローラのアプリを起動する(Google Driveとか)
・onActivityResultからファイルパスを取得する
・InputStreamを生成する
いたってシンプルです。
ファイルエクスプローラーを開き、指定したファイルパスを取得するソースは以下のとおりです。
// 識別用のコード
private final static int CHOSE_FILE_CODE = "12345";
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("file/*");
startActivityForResult(intent, CHOSE_FILE_CODE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
try {
if (requestCode == CHOSE_FILE_CODE && resultCode == RESULT_OK) {
String filePath = data.getDataString().replace("file://", "");
String decodedfilePath = URLDecoder.decode(filePath, "utf-8");
imageText.setText(decodedfilePath);
}
} catch (UnsupportedEncodingException e) {
// いい感じに例外処理
}
}
こんな感じでエクスプローラー向けにIntentが飛びます。任意のアプリでファイルを指定すると
onActivityResultイベントが発生し、ファイルの情報をIntentから取得できます。
Fileインスタンスの取得やInputStreamの生成はこんな感じです。Java SE6が主流なAndroid。多分。
File file = new File(decodeFilePath);
FileInputStream fis = new FileInputStream(file);
IntentからgetDataStringで取得できるというのがまず分かりませんでした。
これが正解っぽい。
file://という文字列はいらないです。接頭辞としてfile://から始まり、端末のフルパスが続くようなので、
先頭の部分を置換で切り取ってます(もしかしたら端末に酔ってはうまくいかないとかあるのかな)。
あと、取得したファイルパスはURLエンコードされてるのでそのまま使おうとするとハマりました。
今回は以下のことを目的にソースとハマりどころを書いてみました。
・Android端末から外部のIntentを発行してFileエクスプローラのアプリを起動する(Google Driveとか)
・onActivityResultからファイルパスを取得する
・InputStreamを生成する
ハマりどころなどはこんな感じでした。
・Intentでファイルエクスプローラアプリに通知する
・onActivityResultで選択したファイルの通知を受け取る
・Intent#getDataStringでファイルパスは取得できる
・file://は不要っぽいので切り取る
・パスはURLエンコードされているのでデコードする
気がかりな点としては端末依存していないか。
汎用的に使えるような処理になっているのかがちょっと気になりますね。
(例えば端末Aでは・Intent#getDataStringが"file://....."の文字列を返し、端末Bでは"//..."になってるとか)
今どきのAndroidな人はこんなこと考えずとも分かるのかなぁ。
あと外部のアプリケーション頼みなので、ダサいですね。
アプリ内部でエクスプローラー相当の機能を設けたほうがアプリによる差異が出なくて
平和なんだろうな。