私の開発している Android アプリにおいて、 MediaStore.ACTION_IMAGE_CAPTURE や MediaStore.ACTION_VIDEO_CAPTURE アクションを指定したインテントにより画像や動画を撮影し、パブリックなディレクトリに保存しつつアプリの機能で利用するということをやっていました。
しかしながら Android10のプライバシー保護のための変更 により、利用していた API がことごとく Deprecated になってしまいました。この対応をした時のメモを残します。
Android 9 まで
保存先Uriの決定
Environment.getExternalStoragePublicDirectory メソッドを利用して保存先を指定していましたが、このメソッドは Android10 で Deprecated になりました。
// パブリックなピクチャディレクトリを保存先
val picturesDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
val outputFile = File(picturesDirectory, "captured.jpg")
val outputUri = FileProvider.getUriForFile(context, autholity, outputFile)
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE).apply {
putExtra(MediaStore.EXTRA_OUTPUT, uri)
}
startActivityForResult(intent, REQUEST_CODE)
メディアスキャナーによるスキャン
キャプチャ後、パブリックなディレクトリに保存されたファイルをギャラリーアプリ等で表示するために Intent. ACTION_MEDIA_SCANNER_SCAN_FILE アクションのインテントによりメディアスキャナーにスキャンさせていましたが、こちらも Android10 で Deprecated になりました。
val scanIntent = Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, outputUri)
context.sendBroadcast(scanIntent)
Android 10
保存先Uriの決定
MediaStore に対して次のコードのようにして保存先Uriを確保します。
val values = ContentValues().apply {
put(MediaStore.Images.Media.DISPLAY_NAME, "captured.jpg")
put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
}
val collection = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
val outputUri = context.contentResolver.insert(collection, values)
キャプチャのキャンセルなど、この確保したUriにファイル保存しなかった場合は、下記のコードで削除しておきましょう。
context.contentResolver.delete(outputUri, null, null)
メディアスキャナーによるスキャン
上記のコードで保存先Uriを確保した場合、改めてスキャンしなくてもギャラリーアプリ等で表示されようです。