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

在Adapter中使用Activity获取的Uri发送邮件时权限报错如何解决

问题解决方法

错误根因

该报错由两个常见问题共同导致:

  1. 你通过ACTION_OPEN_DOCUMENT获取到的Content URI默认只有临时访问权限,App重启、进程被销毁后权限会自动失效,就算提前将URI存在数据库中也无法继续访问。
  2. 你之前写的grantUriPermission代码是给你自己的App包名授予权限,你本身在拿到URI的临时有效期内就有权限,这段代码完全没有实际作用,你需要将URI访问权限授予接收这个Intent的邮件应用才可以。

具体修复步骤

步骤1:拿到URI时提前申请持久化权限

你最初在Activity中通过ACTION_OPEN_DOCUMENT获取到用户选中的文件URI后,不要直接存入数据库,先调用以下代码申请持久化访问权限,这样后续App重启后从数据库读出来的URI依然可以正常访问:

// 拿到用户选中的URI后先执行这段代码,再持久化到数据库
val takeFlags: Int = intent.flags and (Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
contentResolver.takePersistableUriPermission(uri, takeFlags)

注意:如果你之前存到数据库的URI没有申请过持久化权限,旧URI直接作废即可,需要引导用户重新选择一次文件,走上面的流程存新的URI。

步骤2:正确给邮件应用传递URI权限

两种方案选一种即可,推荐选方案1更简单:

方案1:给Intent加权限标志位,系统自动处理授权

直接在构造发送邮件的Intent时添加读取权限标志,系统会自动给所有匹配到的邮件应用授予该URI的临时访问权限:

try {
    val emailIntent = Intent(Intent.ACTION_SEND)
    emailIntent.type = "plain/text"
    // 新增这行即可
    emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
    emailIntent.putExtra(Intent.EXTRA_EMAIL, arrayOf(kindleEmailAddress))
    emailIntent.putExtra(Intent.EXTRA_SUBJECT, title)
    emailIntent.putExtra(Intent.EXTRA_STREAM, att)
    emailIntent.putExtra(Intent.EXTRA_TEXT, message)
    context.startActivity(Intent.createChooser(emailIntent, "正在发送邮件..."))
} catch (t: Throwable) {
    Toast.makeText(context, "请求失败,请重试:$t", Toast.LENGTH_LONG).show()
}

方案2:手动查询所有可处理邮件的应用,挨个授权

如果你需要更精准控制授权范围,可以用下面的代码手动授权:

try {
    val emailIntent = Intent(Intent.ACTION_SEND)
    emailIntent.type = "plain/text"
    emailIntent.putExtra(Intent.EXTRA_EMAIL, arrayOf(kindleEmailAddress))
    emailIntent.putExtra(Intent.EXTRA_SUBJECT, title)
    emailIntent.putExtra(Intent.EXTRA_STREAM, att)
    emailIntent.putExtra(Intent.EXTRA_TEXT, message)

    // 查询所有可处理发送邮件Intent的应用,挨个授予URI读取权限
    val resInfoList = context.packageManager.queryIntentActivities(emailIntent, PackageManager.MATCH_DEFAULT_ONLY)
    for (resolveInfo in resInfoList) {
        val packageName = resolveInfo.activityInfo.packageName
        context.grantUriPermission(packageName, att, Intent.FLAG_GRANT_READ_URI_PERMISSION)
    }

    context.startActivity(Intent.createChooser(emailIntent, "正在发送邮件..."))
} catch (t: Throwable) {
    Toast.makeText(context, "请求失败,请重试:$t", Toast.LENGTH_LONG).show()
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 18:06:03