今更ながらAndroid 10以降でIntent(MediaStore.ACTION_IMAGE_CAPTURE)
を使ってキャプチャした画像を、各メディア直下のディレクトリではなくアプリ専用のディレクトリを作って保存する方法について調べました。
準備
まずxmlの設定から。AndroidManifest.xml
をいじります。AndroidManifest.xml
の<application>
タグ内にFileProviderの記述を追加します。
1 | <provider |
<meta-data>
タグ内で参照しているfile_provider.xml
はres/xml配下に作成し中身は下記のようになっています。
1 | <paths> |
Uri取得
次に画像の保存先をMediaStoreから取得します。
1 | val fileName = "hoge.jpg" |
RELATIVE_PATH
はfile_provider.xml
で記述したpath
の値と同じにします。imageUri
はプロパティとして保持しておきonActivityResult
で再利用します。
Intentを投げる
事前に取得しておいたUriをIntentにくっつけて投げます。
1 | val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) |
カメラアプリがいくつか候補に出てくると思うので好きなアプリを選択して写真を撮ります。
戻り値を受け取る
ImageDecoder
というクラスを使ってBitmap
を生成して、ImageView
にセットすれば終わりです。
1 | if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) { |
感想
公式動画やブログでも再三言われていたことですが、Google的にはファイルパスは極力使わないでUriを使って画像を扱って欲しいのだなと改めて思う内容でした。
近い将来、動画をファイルパスでしか読み込めないライブラリたちがUriをサポートしたらファイルパスの参照も禁止になってしまうのかもしれません。
そう考えるとできるだけファイルパスに依存しない実装にしておくのが吉なのでしょう。知らんけど。
参考サイト
- https://developer.android.com/about/versions/11/privacy/storage#other-apps-private-dirs
- https://developer.android.com/training/data-storage/app-specific#external
- https://developer.android.com/training/secure-file-sharing/setup-sharing?hl=ja
- https://stackoverflow.com/questions/56651444/deprecated-getbitmap-with-api-29-any-alternative-codes