2015/03/18 このエントリーをはてなブックマークに追加 はてなブックマーク - 【Android】Intentを発行してファイルパスを取得する

【Android】Intentを発行してファイルパスを取得する









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な人はこんなこと考えずとも分かるのかなぁ。
あと外部のアプリケーション頼みなので、ダサいですね。

アプリ内部でエクスプローラー相当の機能を設けたほうがアプリによる差異が出なくて
平和なんだろうな。




3 件のコメント:

  1. 情報系学生(3年目)2016年10月18日 16:27

    参考にさせていただきました、ありがとうございます。

    ただソースの制御構文が少し間違っていますx(

    返信削除
    返信
    1. 情報系学生(3年目)さん

      コメントありがとうございます!参考になったようで幸いです。
      あら、ホントですね、コードがおかしい。。
      修正しました!(直っているはず (^^;

      削除
  2. ハマったところ
    もしかしたら端末に酔って → よって

    返信削除