一, 序
最近产品小姐姐在做竞品分析, 下了堆应用体验, 发现有些应用的通知是关不掉的, 很奇怪. 每次在通知栏关掉之后, 依然可以收到这个 App 的推送.
这里不方便点名, 那就写了个 demo 看看吧.
从动图可以看到, 和描述无差别, 虽然每次都从通知栏把这个应用的推送关闭, 但是在点击推送按钮之后, 依然会在通知栏显示通知, 等于关闭的操作是无效的.
这到底是怎么回事呢?
二, 关不掉的推送
2.1 怎么做到的呢?
不兜圈子, 直接说原因吧.
这个关不掉的通知, 其实利用的就是, Android 8.0(API 26) 上新增的 Notification channel (渠道通知)功能, 它可以把通知, 拆分成不同的渠道, 进行单独控制.
在此之前, 通知是应用级别的, 如果用户不想要这个应用的通知, 只能对整个应用进行关闭.
但是从 8.0 开始, 安卓增加了 Notification Channel 的功能, 开发者可以对不同性质的通知附加一个渠道信息(这是强制的), 以此来把选择权交给用户, 让用户选择接受哪类通知, 而关闭另外一些通知, 让用户的选择更灵活.
举个例子, 现在知识付费很火, 类似于得到 App, 喜马拉雅 App 都有自己的音频内容, 同时又需要对这些内容做运营. 如果我将整个应用的通知关闭, 那么在我听音频的时候, 通知栏上就不会有我当前所听音频的快捷操作, 并且这个应用也很容易被清理掉. 与此同时, 我更多的是想主动去找需要的内容, 而不想看到运营推送给我的内容. 这里用到渠道通知, 我就可以将运营推送的渠道关闭, 以此来达到不被骚扰的目的.
2.2 安卓的通知权限已开关
既然有通知就涉及到了权限管理.
在安卓下, 应用的通知是默认打开的, 当用户没有主动将其关闭的时候是不需要额外向用户申请权限, 这不像 iOS, 很多 iOS App, 如果需要通知权限, 他们会在启动的时候向用户申请, 用户拒绝以后将无法通知, 只能引导用户再次打开.
安卓下的通知既然是默认打开的, 那么除非用户在安装后, 主动去设置里面关闭通知开关. 理论上新安装的 App 至少有一次通知的机会. 通常我们发现有一个应用, 发了我们意料之外的通知, 我们才会有意识的去关闭它.
这里就涉及到一个问题, 你从通知栏关闭的开关到底是哪个开关? 它控制的到底是什么?
当应用适配 Android 8.0 之后, 这个应用的通知开关可以分为两类:
整个应用的通知开关
单个渠道的通知开关
而我们通过通知栏直接右滑关闭的通知, 仅仅是将这个渠道的通知关闭, 而不是对整个应用的通知关闭.
这样设计也符合我们的认知, 既然已经对通知分了渠道, 那么当我们在通知栏, 看到这个通知, 并想要关闭的, 自然也是针对这个渠道的通知.
那就面临了一个问题, 如果我们只是在通知栏将这个应用的通知关闭, 那仅仅只是关闭了这个应用某个渠道的通知, 这个应用还是可以换一个渠道, 继续对我们进行通知骚扰.
而安卓在设计上, 通知的渠道是无限的, 也就是只要我们去创建, 就可以无限的产生新的 Notification channel, 那这些新创建的通知渠道就可以被开发者利用, 继续向用户发送新一轮的通知.
到这里我们小结一下, 其实前面写了这么多, 就三个知识点:
安卓 8.0 以后, 通知开关是区分整个应用的, 和单个渠道的.
在通知栏看到这个应用通知时, 直接关闭, 其实是针对这个通知的渠道进行关闭, 而不会影响整个应用的通知开关.
通知渠道的创建是没有限制的, 理论上我们可以无限的创建.
那么接下来我们再看看, 如果想实现一个, 发现通知渠道被关闭, 就无限创建通知的逻辑, 技术上需要用到哪些 API 呢?
三, 无限创建渠道的通知
安卓 8.0 的, 其实已经出来很久了, Notification channel 的使用, 本文就不细说了, 只提一些关键的步骤.
1. 创建 Notification channel
我们可以通过 NotificationManager 的 createNotifycationChannel() 方法, 创建一个通知渠道.
这个方法, 接受一个 NotificationChannel 对象, 该对象接收三个参数, 分别是渠道 ID(channel_id), 渠道描述 (channel_name) 以及渠道通知的重要性, Android 会根据其通知的重要性来决定显示或者折叠.
2. 判断这个通知渠道是否被关闭?
因为需要不断的判断旧的通知渠道是否已经被用户关闭, 以此为依据判断是否需要创建新的通知渠道.
想要检测一个通知渠道, 必然需要先获取到之前创建的通知渠道对象, 这一步可以通过 NotificationManager 的 getNotifycationChannel() 方法获取, 得到通知渠道对象后, 下一步就是判断其开关是否被关闭.
前面提到创建 NotificationChannel 的时候, 需要传递一个重要性的参数, 这个值用于帮助系统确认当前通知的显示状态. 它并非固定不变的值, 系统会根据用户的行为对其重要性进行调整, 一个长期不会用户点击的通知, 会慢慢降低其重要行, 最终可能会被折叠进 "不重要通知" 项中.
如果通知渠道被用户关闭了, 那么它的重要性 (importance) 就被设置成一个特殊值 NotificationManager.IMPORTANCE_NONE, 我们可以以此为依据去判定当前通知渠道是否被关闭.
3. 删除已经被关闭的通知
如果我们只创建不清理, 最终应用的设置页中, 就会有很多描述相同的通知开关.
合理的策略, 应该是在创建新的通知渠道时, 将旧的通知清理掉, 这个操作可以通过 deleteNotificationChannel() 方法完成.
但是这个操作也不是无迹可寻的, 系统会记录下当前 App 删除的通知渠道个数.
有这三个关键操作, 剩下的逻辑就简单了.
需要注意的是, 删除后重新创建的通知渠道的 ID, 不能和之前被删除的通知渠道相同, 但是通知描述可以相同.
四, 通知是一种无形资产
在这里我相信大家应该都理解, 那些关不掉的应用通知, 是因为我们在通知栏关闭的应用通知, 仅仅是针对独立渠道的, 而不会影响整个应用的通知开关.
就会有一些不良应用, 利用这种情况无限的去创建新的通知渠道, 来向用户持续的发送骚扰通知.
其实这样的问题也很好解决, 只需要在关闭的时候点击更多设置, 进入应用通知的设置页, 将整个应用的主开关关闭, 就可以.
对于客户端应用而言, 通知权限其实是应用的一种无形资产, 它解决的是信任问题, 我不关掉你, 是因为我信任你, 只会在我需要的时候通知我.
站在用户的角度, 你去想想哪些应用的通知你会保留? 微信作为国民应用, 他的通知我想大部分人是不会关闭的, 而很多小众的应用, 我也会开放通知权限, 例如滴答清单, 因为他真的不会有一些乱七八糟的通知.
通知本身是触达用户的手段, 但是我们如何使用能够让用户不反感, 这是个问题. 很多产品的文章其实都在讲, 如何去设计用户不反感的通知. 但是除了为数不多几个应用之外, 我看到的是大部分应用都在滥用通知渠道, 同时也很少看到有产品经理针对通知渠道做产品方案的设计.
我不想看的通知, 在我关掉之后, 我就真的看不到了, 这就是一种信任.
作为开发者, 是时候提醒产品, 针对通知渠道进行产品方案的设计了, 善待你的应用通知吧.
Android 开发资料 + 面试架构资料 免费分享 点击链接 即可领取
《Android 架构师必备学习资源免费领取(架构视频 + 面试专题文档 + 学习笔记)》
来源: http://www.jianshu.com/p/3222e9e63f78