Androidでは次の方法でファイル読み込みが可能
- ACTION_OPEN_DOCUMENTでピッカーUI起動
- ユーザーにファイルを選択してもらう
- onActivityResultなどでファイルを取得
URIを取得するのは簡単です。
ただファイル内容の読み込みとなると、意外とどうやればいいのか分からなかったです。(そもそもググっても情報がヒットしなかった)
やっとその方法が分かったので、InputStreamからバイナリファイルを読み込みする方法をまとめておきます。多分なんかの役に立つはずです。
このページの目次
まずはACTION_OPEN_DOCUMENTによるファイル選択について
ここは本筋とはあまり関係ありません。
でもAndroidではファイルの扱いは厳格です。
そこらへんは次の記事とかでまとめました。
▼ ACTION_CREATE_DOCUMENTの使い方
▼ ACTION_OPEN_DOCUMENTの使い方
Android11からはファイル周りの扱いが本当に厳しくなり、今までみたく気楽に外部ストレージにファイル作成とかができなくなりました。
もし Environment.getExternalStorageDirectory() とか Environment.getExternalStoragePublicDirectory() でファイル保存しているなら、そういったAPIは使えなくなるので注意です。
一応大事なことなので強調しておきます。
InputStreamからバイナリファイル読み込みしてみる
では以下の手順でファイルURIを取得できたとしましょう
- ACTION_OPEN_DOCUMENTからピッカーUI起動
- onActivityResultなどで結果を受け取る
選択ファイルをバイナリとして読み込みたかったです。
そのために次のコードを書いてみました。
▼ Javaによるバイナリ読み込みコード例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
/// onActivityResult内にて... Uri uri = data.getData(); try ( ContentResolver cr = getContentResolver(); InputStream is = cr.openInputStream(uri); byte[] buffer = new byte[is.available()]; is.read(buffer); int i = 0; for (byte b: buffer) { if (i % 10 == 0) { System.out.println(); } System.out.printf("%02x ", b); i++; } }catch (IOException e) { /// エラー処理 } |
▼ このコードのログ出力結果
1 2 3 4 5 6 7 8 9 10 |
89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 00 10 00 00 00 10 08 06 00 00 00 1f f3 ff 61 00 00 00 04 73 42 49 54 08 08 08 08 7c 08 64 88 00 00 01 3d 49 44 41 54 38 8d a5 93 41 4b 02 41 18 86 1f 6d c1 83 20 52 3f a0 64 0f 11 4b 1e ea 1f 24 42 d7 20 d9 3c 78 89 2e 1b 28 04 1e 25 2f dd ed 17 |
このようにバイナル出力できました。
ポイントは cr.openInputStream(uri) のようにonActivityResultで受け取ったURIをInputStreamに変換することです。
あとはbyte配列にバイナリとして書き込みして、あとは1バイトずつ16進数でログ出力してるだけですね。(一応10列ごとに折り返している)
読み込みしたバイナリをBase64/DataURLに変換してみる
ここでは次のことにも挑戦してみました。
- バイナリをBase64にエンコード
- さらにDataURLとして変換する
DataURLはファイルそのものを表せるURLのことです。
▼ DataURLスキームとは何なのか
普通のURLはファイルの場所を表しますよね。
DataURLではデータそのものを埋め込めて扱えます。
Android開発でも便利なので使うことが多いです。
(というか使わざるを得ない場面が多い...)
実際にはこんなコードを書いてみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
/// onActivityResult内にて... Uri uri = data.getData(); try ( ContentResolver cr = getContentResolver(); InputStream is = cr.openInputStream(uri); byte[] buffer = new byte[is.available()]; is.read(buffer); /// Base64に変換して文字列で取得 String base64 = Base64.encodeToString(buffer, Base64.DEFAULT); /// MIMEタイプ(仮) String mimeType = "image/png"; /// DataURLとして形成 StringBuilder sb = new StringBuilder(); sb.append("data:"); sb.append(mimeType); sb.append(";base64,"); sb.append(base64); String dataUrl = sb.toString(); /// DataURLをログ出力 Log.d("MainActivity", dataUrl); }catch (IOException e) { /// エラー処理 } |
▼ このコードのログ出力のサンプル
1 |
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAT1JREFUOI2lk0FLAkEYhh9twYMgUj+gZA8RSx7qHyRC1yDZPHiJLhsoBB4lL93tF0jgIYYOeopAugdRhwVZPCzkyZOe3Jtah1jb3RlroQ+Gme+dj2devplJNJvNT/4RyahQq5YxNMFi1F4NQxPUqmUlIBF1sBi1yetpqdB2PTa2z/92kNfTFKxeSCtYPSUUQAsmhiYAsC6vEcJhOhmyubWLaZqc7n/vD+bm7w5KDQchfkAAQghKDUfpQAJMJ8PV+v7sQqmvBQzmJq16EW82Ztntkzwpsuz28WZjWvWiZB8UtwDQOXiTCivvh0oHWlQwNMGz0ZIKX+0rpQMJ4MeOfrxaf7hP68rkJtquRyabC2mZbA7b9eIBAFKpTOhkP48NeLw9AuCu8xLKYwH89/5wsxeaVf8A1jQx2G1V54PxBTO2a9MhvnstAAAAAElFTkSuQmCC |
DataURLの本体はBase64化されたデータなので、 Base64.encodeToString(buffer, Base64.DEFAULT); のようにバイト配列をBase64エンコードしてます。
あとはDataURLの作法に従ってStringBuilderとか使ってDataURLの形式にすればいいだけです。ここまでできればバイナリファイルが扱いやすくなります。
バイナリファイル読み込みのポイントまとめ
箇条書きでまとめ
- ACTION_OPEN_DOCUMENTを使ってURI取得
- ContentResolverからInputStreamを取得
- あとは普通にバイナリとして読み込めばOK
Androidのファイル読み書きは昔より厳格になりました。
まずはそこを理解することが大事かもしれません。
以上、Androidでのバイナリ読み込みでした。ではまた