kotlin 使用Drjacky图像选择器和Retrofit 2从厨房上传图像时出错

cl25kdpy  于 2022-12-23  发布在  Kotlin
关注(0)|答案(2)|浏览(117)

嗨伙计们,我得到了一个错误,像下面的一个当试图从厨房上传图像:

java.lang.SecurityException: Permission Denial: opening provider com.android.providers.media.MediaDocumentsProvider from ProcessRecord{efed650 15275:app.fadlyproject.com/u0a158} (pid=15275, uid=10158) requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs

错误来自这行代码:

val parcelFileDescriptor =
        contentResolver.openFileDescriptor(selectedImageUri!!, "r", null) ?: return

我使用的是第三方库,即DrJacky和Retrofit 2。我在清单中添加了一些必要的内容,如下所示:
依赖关系:

implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.github.Drjacky:ImagePicker:2.3.19'

清单:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    image_view = findViewById(R.id.image_view)
    button_upload = findViewById(R.id.button_upload)

    image_view!!.setOnClickListener {
        openImageChooser()
    }

    button_upload!!.setOnClickListener {
        uploadImage()
    }

}                                                                              
  private val profileLauncher =
    registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
        if (it.resultCode == Activity.RESULT_OK) {
            val uri = it.data?.data!!
            selectedImageUri = uri
            image_view!!.setImageURI(selectedImageUri)
        } else parseError(it)
    }

private fun openImageChooser() {
    ImagePicker.with(this)
        .provider(ImageProvider.BOTH)
        .setDismissListener {
            Log.d("ImagePicker", "onDismiss");
        }
        .createIntentFromDialog { profileLauncher.launch(it) }
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if (resultCode == Activity.RESULT_OK) {
        when (requestCode) {
            REQUEST_CODE_PICK_IMAGE -> {
                selectedImageUri = data?.data
                image_view!!.setImageURI(selectedImageUri)
            }
        }
    }
}

private fun uploadImage() {
    if (selectedImageUri == null) {
        layout_root!!.snackbar("Select an Image First")
        return
    }

    val parcelFileDescriptor =
        contentResolver.openFileDescriptor(selectedImageUri!!, "r", null) ?: return

    val inputStream = FileInputStream(parcelFileDescriptor.fileDescriptor)
    val file = File(cacheDir, contentResolver.getFileName(selectedImageUri!!))
    val outputStream = FileOutputStream(file)
    inputStream.copyTo(outputStream)

    progress_bar!!.progress = 0
    val body = UploadRequestBody(file, "image", this)
    MyAPI().uploadImage(
        MultipartBody.Part.createFormData(
            "file",
            file.name,
            body
        ),
        RequestBody.create(MediaType.parse("multipart/form-data"), "json")
    ).enqueue(object : Callback<UploadResponse> {
        override fun onFailure(call: Call<UploadResponse>, t: Throwable) {
            layout_root!!.snackbar(t.message!!)
            progress_bar!!.progress = 0
        }

        override fun onResponse(
            call: Call<UploadResponse>,
            response: Response<UploadResponse>
        ) {
            response.body()?.let {
                layout_root!!.snackbar(it.message)
                progress_bar!!.progress = 100
                classes!!.text = it.data.classes
                layout!!.visibility = View.VISIBLE
                Glide.with(this@MainActivity).load("http://167.172.72.26:1337/"+ it.data.image_after_preprocessing).into(
                    image_view!!
                )
            }
        }
    })

}

override fun onProgressUpdate(percentage: Int) {
    progress_bar!!.progress = percentage
}

companion object {
    const val REQUEST_CODE_PICK_IMAGE = 101
}
nnvyjq4y

nnvyjq4y1#

这个答案虽然迟了,但可能对其他人有所帮助。
我只是像这样添加了.crop()。

ImagePicker.with(this)
    .crop()
    .provider(ImageProvider.BOTH)
    .setDismissListener {
        Log.d("ImagePicker", "onDismiss");
    }
    .createIntentFromDialog { profileLauncher.launch(it) }

我注意到这个错误只在使用图库时存在,而添加.crop()是唯一的解决方案。

idv4meu8

idv4meu82#

如果您不使用裁剪选项,您只需添加:

mGalleryUri?.let { galleryUri ->
                        contentResolver.takePersistableUriPermission(
                            galleryUri, Intent.FLAG_GRANT_READ_URI_PERMISSION
                        )
                    }

https://developer.android.com/training/data-storage/shared/photopicker#persist-media-file-access
我会在下次更新时将ACTION_GET_CONTENT更改为ACTION_OPEN_DOCUMENT
[And如果我能找到一种兼顾两个方面方法(裁剪并让开发人员使用或不使用takePersistableUriPermission,我将再次更新。)

相关问题