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

NotificationManager.notify()仅在Android11/12抛SecurityException

问题原因

从崩溃堆栈最底层的UriGrantsManagerService.checkGrantUriPermissionUnlocked报错可以直接定位:崩溃和通知渠道的铃声权限无关,核心原因是构造的Notification实例中携带了当前应用无有效访问权限的文件Uri,系统通知服务在入队通知、校验Uri授权时直接抛出SecurityException。

之前的修复方案无效,是因为仅修改了通知渠道绑定的铃声,问题根源根本不在渠道配置:buildNormal()方法生成通知对象时,大概率在大图标、PendingIntent携带的参数、通知附件等位置传入了权限失效的Uri。最常见的触发场景是用户选择自定义铃声/通知图片时,代码只拿到了系统返回的临时授权Uri,没有申请持久访问权限,等闹钟触发、BroadcastReceiver执行时临时Uri权限已经过期;或是直接使用了file://格式的本地文件路径跨进程传递,在Android 7.0+的严格模式下本身就禁止跨进程访问这类文件Uri。

贴出的初始化和通知发送代码片段没有包含buildNormal()的实现,这也是之前排查方向走偏的核心原因:问题点不在贴出的渠道初始化逻辑里。

修复方案
  • 全量排查buildNormal()方法构造通知的逻辑,梳理所有传入通知对象的Uri:包括大图标资源、NotificationBuilder上单独设置的通知音、ContentIntent/Action按钮对应的PendingIntent中Intent携带的所有Uri参数,不要只排查通知渠道的铃声配置。
  • 禁止使用file://格式的Uri传递给通知相关的任何字段,Android 7.0+不允许应用暴露file://Uri给其他进程,所有本地文件资源统一通过FileProvider生成content://格式的Uri,构造相关PendingIntent时给Intent添加FLAG_GRANT_READ_URI_PERMISSION标记,给系统通知进程授予临时读权限。
  • 如果功能支持用户自定义铃声/通知背景图,从系统选择器拿到返回的Uri后,第一时间调用ContentResolver.takePersistableUriPermission()申请持久化读权限,避免临时权限过期后无法访问。
  • 修正异常兜底逻辑:catch到notify抛出的异常时,不要只修改渠道铃声,要把通知里所有外部来源的Uri全部替换为应用内置资源或系统默认值(比如大图标改用应用内drawable生成的Bitmap、铃声回退到系统默认闹钟音),再重试notify,避免二次崩溃。
  • 补充适配:Android 13及以上版本需要在Manifest声明POST_NOTIFICATIONS权限并动态申请,否则通知无法正常弹出,虽然这个配置不是当前崩溃的诱因,但需要同步补全避免其他兼容性问题。

内容的提问来源于stack exchange,提问作者Simple UX Apps

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 10:12:23