6

非常に基本的な質問のように思えますが、特に 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で外部ストレージの画像をファイルとして使用するにはどうすればよいですか。

注:必要な権限はすべて持っているので、それは問題ではありません

4

2 に答える 2