You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java迁移Kotlin后Android FileProvider authority匹配异常

问题根因

你遇到的两个报错属于两个独立问题:

  1. 初始版本抛出SecurityException的核心原因:shareFile方法中错误将Uri列表传入了Intent.EXTRA_TEXT字段。系统只会对EXTRA_STREAM字段携带的Uri,响应FLAG_GRANT_READ_URI_PERMISSION标识授予临时访问权限,EXTRA_TEXT中的Uri不会被自动授权,系统检测到无权限访问就会抛出权限异常。之所以没有可见崩溃、分享流程看起来能正常完成,是因为这个异常是系统分享组件/目标应用进程抛出的,并非你的应用主进程触发;目标邮件应用拿到了EXTRA_STREAM的合法授权,所以可以正常读取附件完成发送。
  2. 增加.helpers前缀后抛出IllegalArgumentException的原因非常直接:Manifest中配置的FileProvider authority是${applicationId}.GenericFileProvider,和带.helpers的字符串完全不匹配。FileProvider.getUriForFile会严格匹配Manifest中声明的authority值,找不到对应配置自然直接崩溃。注意:FileProvider的authority值和类的全限定包名没有强制绑定关系,完全以Manifest中android:authorities属性的配置值为准,不需要和类的存放路径对齐。
修复步骤

按以下顺序修改即可完全解决问题:

  • 保留初始版本的authority写法,不要额外加.helpers前缀,FileProvider.getUriForFile传入的authority参数必须和Manifest配置完全一致。
  • 修正shareFile方法的Intent传参错误,删除将Uri列表传入EXTRA_TEXT的错误代码,EXTRA_TEXT字段仅支持传入字符串类型的推广文案,不能传入Uri对象。
  • 增加低版本兼容逻辑:主动给所有可处理分享Intent的应用授予Uri临时读权限,避免部分定制ROM对FLAG_GRANT_READ_URI_PERMISSION的解析逻辑不兼容导致权限异常。
修复后参考代码

修正后的shareFile方法

@JvmStatic
fun shareFile(uris: ArrayList<Uri?>, fileType: String?) {
    try {
        val share = Intent(Intent.ACTION_SEND_MULTIPLE)
        share.type = fileType
        val strSubject = getStringResourceByName("mainmenu_sharethisapp_subject")
        // 替换为实际的推广文本内容,禁止传入Uri
        val shareContent = getStringResourceByName("mainmenu_sharethisapp_content")
        share.putExtra(Intent.EXTRA_SUBJECT, strSubject)
        share.putExtra(Intent.EXTRA_TEXT, shareContent)
        // 过滤空Uri避免触发异常
        val validUris = uris.filterNotNull()
        share.putParcelableArrayListExtra(Intent.EXTRA_STREAM, ArrayList(validUris))
        share.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION

        val currentActivity = activity?.get() ?: return
        // 兼容低版本系统:主动为所有可处理该分享的应用授予Uri临时读权限
        val resInfoList = currentActivity.packageManager.queryIntentActivities(share, PackageManager.MATCH_DEFAULT_ONLY)
        for (resolveInfo in resInfoList) {
            val packageName = resolveInfo.activityInfo.packageName
            for (uri in validUris) {
                currentActivity.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION)
            }
        }

        currentActivity.startActivity(
            Intent.createChooser(
                share,
                getStringResourceByName("mainmenu_sharethisapp_sharethoughttitle")
            )
        )
    } catch (ex: Exception) {
        val currentActivity = activity?.get() ?: return
        Toast.makeText(currentActivity, ex.message.toString(), Toast.LENGTH_LONG).show()
    }
}

修正后的onImageProcessingFinished方法

fun onImageProcessingFinished(ipr: ImageProcessingResult, activity: Activity) {
    val uris = ArrayList<Uri?>()
    // authority和Manifest配置严格对齐,不要加.helpers前缀
    val fileProviderAuthority = "${activity.packageName}.GenericFileProvider"
    for (file in ipr.screenShotFiles) {
        val uri = FileProvider.getUriForFile(activity, fileProviderAuthority, file)
        uri?.let { uris.add(it) }
    }
    AWDrawerMenu.listener = activity as IActionListeners
    AWDrawerMenu.activity = WeakReference(activity)
    AWDrawerMenu.shareFile(uris, "image/jpg")
}
额外说明

Java版本运行正常属于巧合:要么当时Java代码不存在将Uri传入EXTRA_TEXT的错误逻辑,要么测试时的系统版本/邮件应用对EXTRA_TEXT中的非文本内容做了静默忽略,没有触发权限检查。迁移Kotlin时保留了错误的传参逻辑,才会暴露异常。

注意:永远不要将非字符串类型数据传给Intent.EXTRA_TEXT,该字段官方定义仅支持接收CharSequence类型的文本内容,传入其他类型属于未定义行为,在不同系统版本、不同目标应用上都会出现不可预期的兼容问题。

内容的提问来源于stack exchange,提问作者Diego Perez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 06:12:13