非常に基本的な質問のように思えますが、特に Android Q.
ギャラリーから画像を取得して圧縮し、サーバーに送信したいだけです。しかし、Android Q の Scoped Storage のせいで、思ったよりも大変です。最初に、コードで何をしたかを説明します。
まず、画像を選択するインテントを送信します。
fun openGallery(fragment: Fragment){
val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
intent.type = "*/*"
val mimeTypes = arrayOf("image/*")
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes)
fragment.startActivityForResult(intent, REQUEST_IMAGE_PICK)
}
正常に動作し、 onActivityResult メソッドで画像を取得できます
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == REQUEST_IMAGE_PICK && resultCode == Activity.RESULT_OK && null != data) {
val selectedImage = data.data
val source = ImageDecoder.createSource(activity!!.contentResolver, selectedImage)
val bitmap = ImageDecoder.decodeBitmap(source)
mBinding.circularProfileImage.setImageBitmap(bitmap)
}
}
さて、問題は、この画像をファイル形式でアクセスするにはどうすればよいかということです。そのため、さらに処理/圧縮できます。
私が試した次のこと:
val mImagePath = getImagePathFromUri(activity!!, selectedImage)
これは私が持っているパスです:
/storage/emulated/0/DCIM/Camera/IMG_20191022_152437.jpg
次の方法で、そこからファイルを作成しました。
val file = File(mImagePath)
以下は、画像を圧縮してアップロードするための私のカスタムロジックです。
val mNewFile = MediaCompressor.compressCapturedImage(activity!!, file, "ProfilePictures")
uploadProfile(mNewFile)
このカスタム ロジックには、次のように画像のサンプリングと回転を処理するメソッドがあります。
fun handleSamplingAndRotationBitmap(context: Context, selectedImage: File, reqWidth: Int, reqHeight: Int): Bitmap {
val mUri = Uri.fromFile(selectedImage)
// First decode with inJustDecodeBounds=true to check dimensions
val options = BitmapFactory.Options()
options.inJustDecodeBounds = true
var imageStream = context.contentResolver.openInputStream(mUri)
BitmapFactory.decodeStream(imageStream, null, options)
imageStream!!.close()
// Calculate inSampleSize
options.inSampleSize =
calculateInSampleSize(options, reqWidth, reqHeight)
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false
imageStream = context.contentResolver.openInputStream(mUri)
var img = BitmapFactory.decodeStream(imageStream, null, options)
img = rotateImageIfRequired(context, img!!, mUri)
return img
}
しかし、 context.contentResolver.openInputStreamを使用してストリームを開こうとすると 、次のエラーが発生します。
java.io.FileNotFoundException: /storage/emulated/0/DCIM/Camera/IMG_20191022_152437.jpg: open failed: EACCES (Permission denied)
Android 10 では、外部ストレージからファイルに直接アクセスする権限がないため、これを取得していることはわかっています。
Android 10で外部ストレージの画像をファイルとして使用するにはどうすればよいですか。
注:必要な権限はすべて持っているので、それは問題ではありません