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

通过ACTION_SEND intent filter获取URI调用takePersistableUriPermission报SecurityException如何解决

问题根因

该异常由Android系统的权限机制导致:

  • 通过ACTION_OPEN_DOCUMENT返回的URI由系统DocumentsProvider统一管理,系统会为App发放可持久化的读写权限,因此调用takePersistableUriPermission()可以正常获取长期访问权限。
  • 通过ACTION_SEND分享的URI属于发送方App临时授予的一次性权限,有效期最长仅到你的App任务栈销毁为止,系统没有对应持久化授权记录,因此调用takePersistableUriPermission()会直接抛出SecurityException。

可行解决方案

Android系统本身限制了无法直接获取ACTION_SEND分享URI的持久权限,可根据业务场景选择以下方案解决:

  • 方案1:拷贝文件到App私有目录(适合需要长期访问文件的场景)

这是兼容性最好的方案,拿到分享的URI后直接读取内容,写入到你的App内部存储/外部私有存储目录下,后续直接访问本地拷贝的文件即可,无需依赖第三方App的权限。
示例代码:

private fun copySharedUriToPrivateDir(uri: Uri): File? {
    return try {
        val inputStream = contentResolver.openInputStream(uri) ?: return null
        // 自定义私有目录下的存储文件名
        val outputFile = File(filesDir, "shared_${System.currentTimeMillis()}.jpg")
        val outputStream = FileOutputStream(outputFile)
        inputStream.copyTo(outputStream)
        inputStream.close()
        outputStream.close()
        outputFile
    } catch (e: Exception) {
        e.printStackTrace()
        null
    }
}

在onNewIntent中拿到URI后直接调用该方法即可,无需再执行takePersistableUriPermission逻辑。

  • 方案2:直接使用临时权限(适合仅短期使用文件的场景)

如果你只需要在当前App运行时读取一次文件,不需要重启App后仍能访问,直接删除takePersistableUriPermission这行代码即可,你拿到的URI已经自带临时读权限,可以正常读取内容。

  • 方案3:引导用户用系统文件选择器授权(仅适合必须访问原URI的特殊场景)

如果业务要求必须访问原始URI不能做本地拷贝,可以在拿到分享的URI后,引导用户跳转到系统文件选择器主动选中对应文件,走ACTION_OPEN_DOCUMENT流程获取可持久化权限,该方案会打断用户操作,优先级低于前两个方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 12:06:02