为什么照片编辑器不接受来自照片选择器的 URI?

问题描述 投票:0回答:1

我想使用 系统照片选择器(即使用

PickVisualMedia
请求)向用户请求照片,然后发送另一个 Intent 让照片编辑器裁剪照片。如果我只是发送从照片选择器收到的 URI,Google Photos 会显示“错误,无法加载媒体”并退出。我的其他照片编辑器要么显示类似的警告,要么只是崩溃。

注册媒体选择器和裁剪活动启动器的代码:

mediaPickerLauncher = activity.registerForActivityResult(
    ActivityResultContracts.PickVisualMedia()
) { uri ->
    pickerCallback(uri)
}

cropResultLauncher = activity.registerForActivityResult(
    ActivityResultContracts.StartActivityForResult()
) { result ->
    if (result.resultCode == Activity.RESULT_OK) {
        val data: Intent? = result.data
        Log.d("Crop", "Photo received")
    }
    else {
        Log.d("Crop", "Cancelled!")
    }
}

pickerCallback
检查 URI 是否为空,如果不是,则运行以下命令:

val intent = Intent("com.android.camera.action.CROP")
intent.setData(uri)
intent.putExtra("crop", "true")
// Set the aspect ratio to 1:1 (square)
intent.putExtra("aspectX", 1)
intent.putExtra("aspectY", 1)
// Set the resolution to 500x500
intent.putExtra("outputX", 500)
intent.putExtra("outputY", 500)
// Set a few more flags
intent.putExtra("return-data", true)
cropResultLauncher!!.launch(intent)

我尝试使用

takePersistableUriPermission
,如媒体选择器文章中所述,但没有帮助。

android androidx
1个回答
0
投票

您面临的问题很可能是因为媒体选择器提供的 URI 没有授予其他应用程序访问内容的足够权限。要解决此问题,您可以创建一个 FileProvider 并使用它来生成可供其他应用程序访问的内容 URI。

在 Manifest.xml 中使用此文件提供程序“在权限标签中使用您的应用程序包”

<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="${appPackage}.provider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>

然后在res/xml中创建file_path.xml

    <?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path name="external_files" path="." />
</paths>

然后在 pickerCallback 中使用此函数从 Uri 创建临时文件

val inputStream = context.contentResolver.openInputStream(uri)
val tempFile = File(context.getExternalFilesDir(null), "temp_image.jpg")
val outputStream = FileOutputStream(tempFile)
inputStream?.copyTo(outputStream)
inputStream?.close()
outputStream.close()

然后像这样获取文件uri

val tempUri=FileProvider.getUriForFile(context,"${packageName.provider}",tempFile)

然后你可以在Crop Intent中使用这个tempUri

© www.soinside.com 2019 - 2024. All rights reserved.