web-dev-qa-db-ja.com

Android Q:ギャラリーから画像を取得して処理します

非常に基本的な質問のように思えますが、Android Q.

Galleryから画像を取得して圧縮し、サーバーに送信したいだけです。ただし、Android Qのスコープストレージのため、思ったより難しいです。まず、コードで何をしたかを説明します。

まず、画像を選択する意図を送信します。

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
Parag Pawar

私はそれが望ましい解決策だとは思いませんが、Android Q以上で外部ストレージへのアクセスを取得したいだけの場合は、このコードをマニフェストファイル内に配置します。

<application
    Android:requestLegacyExternalStorage="true"
...
</application>

また、これは一時的な解決策であり、永久に機能するわけではないので、別の解決策を試すことをお勧めします。

0
schemabuoi