小米开发平台应用删除前台服务通知导致的闪退问题说明

小米开发平台应用删除前台服务通知导致的闪退问题说明

  • 近期发现较多应用出现闪退现象,具体trace如下:
AndroidRuntime: FATAL EXCEPTION: main
AndroidRuntime: Process: com.xxx.app, PID: 25339
AndroidRuntime: java.lang.SecurityException: Not allowed to delete channel XXX with a foreground service
AndroidRuntime:         at android.os.Parcel.createExceptionOrNull(Parcel.java:2376)
AndroidRuntime:         at android.os.Parcel.createException(Parcel.java:2360)
AndroidRuntime:         at android.os.Parcel.readException(Parcel.java:2343)
AndroidRuntime:         at android.os.Parcel.readException(Parcel.java:2285)
AndroidRuntime:         at android.app.INotificationManager$Stub$Proxy.deleteNotificationChannel(INotificationManager.java:4040)
AndroidRuntime:         at android.app.NotificationManager.deleteNotificationChannel(NotificationManager.java:909)
AndroidRuntime:         at androidx.core.app.NotificationManagerCompat.deleteNotificationChannel(SourceFile:2)
AndroidRuntime:         at com.gyf.cactus.ext.c$a.run(SourceFile:1)
AndroidRuntime:         at android.os.Handler.handleCallback(Handler.java:938)
AndroidRuntime:         at android.os.Handler.dispatchMessage(Handler.java:99)
AndroidRuntime:         at android.os.Looper.loop(Looper.java:236)
AndroidRuntime:         at android.app.ActivityThread.main(ActivityThread.java:8142)
AndroidRuntime:         at java.lang.reflect.Method.invoke(Native Method)
AndroidRuntime:         at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:656)
AndroidRuntime:         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:967)
AndroidRuntime: Caused by: android.os.RemoteException: Remote stack trace:
AndroidRuntime:         at com.android.server.notification.NotificationManagerService$10.enforceDeletingChannelHasNoFgService(NotificationManagerService.java:3427)
AndroidRuntime:         at com.android.server.notification.NotificationManagerService$10.deleteNotificationChannel(NotificationManagerService.java:3440)
AndroidRuntime:         at android.app.INotificationManager$Stub.onTransact(INotificationManager.java:1737)
AndroidRuntime:         at android.os.Binder.execTransactInternal(Binder.java:1160)
AndroidRuntime:         at android.os.Binder.execTransact(Binder.java:1129)
  • 原因是受Google的一笔安全校验Patch影响:https://cs.android.com/android/platform/superproject/+/master:frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java;l=3413
private void enforceDeletingChannelHasNoFgService(String pkg, int userId,
                String channelId) {
            if (mAmi.hasForegroundServiceNotification(pkg, userId, channelId)) {
                Slog.w(TAG, "Package u" + userId + "/" + pkg
                        + " may not delete notification channel '"
                        + channelId + "' with fg service");
                throw new SecurityException("Not allowed to delete channel " + channelId
                        + " with a foreground service");
            }
        }

也就是Google限制了存在前台服务时,不允许应用删除与前台服务绑定的channel。

以上,请开发者检查处理,感谢支持!

vivo通知授权弹窗说明

基于开发者业务合规性与业务需求,保证用户友好使用体验,避免未经用户同意直接发送通知,或因用户不知道如何开启通知而影响后续使用。 vivo拟于2021年8月后发布的新机型上,将通知选择权交给用户,用户首次进入新安装应用时弹窗询问用户是否允许通知,新机型不再实行用户启动应用即成功订阅逻辑。

一、策略说明

通知选择权交给用户,在用户首次进入新安装的应用时,弹窗询问用户是否允许通知(以下简称“通知授权弹窗”)。

l  用户点击“允许”:应用通知、锁屏通知、悬浮通知、桌面角标都统一开启,应用具备推送通知的能力(请确保符合相关规则,不要滥用!)

l  用户点击“禁止”:应用通知、锁屏通知、悬浮通知、桌面角标都保持关闭,应用通知将不会被用户接收。

l  用户点击“更多设置”:跳转到应用的通知管理页面,进行详细设置,用户可以自由选择和组合以上通知的开关状态,做到精细化管理。

二、弹窗样式

三、FAQ

Q1、通知授权弹窗为什么会在我们隐私协议/权限申请弹出之前就出现了?是否符合相关管控规定?

通知授权弹窗是系统统一弹出,而隐私协议/权限申请是应用自行弹出的,每个应用每个版本的隐私协议/权限申请弹出时机都不同,系统无法识别,也无法逐一适配,因此统一在用户首次进入新安装的应用时就弹窗。后续我们会开放弹窗的接口,应用可进行调用并做好弹窗之间的冲突处理。通知授权弹窗询问并非获取用户权限及收集用户个人信息请求,不属于狭义定义范围中的“权限”,与相关管控规定暂无冲突。

Q2、这个弹窗的样式和文案,我们能自定义内容吗?

为保持用户对于通知管理的认知一致,暂不支持自定义弹窗内容。若应用有需要,可自行设计弹窗进行引导,需要符合设计规范、控制好弹出条件、频率、频次和最大次数等,保证良好的用户使用感受。

Q3、这个弹窗是每次进应用都弹么?

系统弹窗最多只弹出一次。应用被卸载后重新计数。

Q4、从哪个版本开始做实施该策略的?

X60系列作为试点实施了该策略,后续出货的新机型(即从2021年8月发布的新机型)都使用该策略。

Q5、是否违反工信部的权限管理要求?

“通知权限”独立于存储、读取通讯录等关键权限,并非获取用户权限及收集用户个人信息请求。

Q6、应用方需要做什么适配或接入吗?

无需适配,后续开放弹窗接口后,应用可进行调用并做好弹窗之间的冲突处理。若不调用则遵循系统弹出原则,统一在用户首次进入新安装的应用时就弹窗。

Q7、用户选择关闭拒绝后,还会再开启吗?

用户拒绝后,也可以在“设置”内通过系统消息开关设置开启。应用方可根据自身策略引导用户开启通知权限。

Q8、老机型以前是什么规则?后续是否变动?

策略只针对2021年8月后发布的新机型,老机型维持原有规则不变,即用户主动激活视为订阅成功开启通知,后续不会变动。

Q9、新老机型量级频控规则是否变动?

不变,新老机型依旧遵循运营消息量级默认为一倍订阅量,5条频控原则。系统消息量级默认一倍订阅量,不限制频控。

Q10、用户没有进行选择,直接按了返回或者home键,这个权限的是全部打开还是全部关闭呢?会继续出弹窗让用户选择么?

关闭,不会再弹出了

Q11、是vivo推送和应用自身push的通知开关状态都默认关闭了吗?

是的,用户首次进入应用时,弹窗询问用户是否允许通知

一门APP 移动应用平台推送信息服务教程 一键开启云消息推送

关于移动应用推送,我不太喜欢用第3方模块,核心是懒得折腾,但为了实现移动应用推送呼起特定页面,还是折腾了下平台的推送服务。

1、控制台-[配置]-[应用与工具]-[云消息]推送:

a. 有通知和消息两种类型,为了兼容安卓和IOS,推荐使用消息类型;

b. 消息的标题就是显示在通知里的内容,消息的内容传特定的内容,用于移动应用分析。

2、移动应用内代码:

为了少折腾点,我把监听代码放在移动应用的root页(首屏的那个WIN窗口);

jsBridge.push.getPushId(function(succ, data) {
  if (succ) {
    jsBridge.setClipboardText(data.push_id);
    alert(data.push_id + "\n已复制");
  } else {
    alert("获取失败\n" + JSON.stringify(data));
  }
});

/*
data 参数说明:
{
  push_id: ""  //字符串类型,唯一标识
}
*/

这是监听点击事件,意思点击通知栏进来才有反应,是因为ret.value的值在IOS和安卓上有所不值,因此参见我的代码,我的应用只传要打开的URL,然后直接打开。

假设您的业务复杂,请自行分析自己传过来的值再处理。

还有有一点,在IOS上,点击一次通知栏,这个事件会响应二次,平台查下问题所在吧,and 这个ret.value在不同官方值不同的问题最好也处理一下。