使用这种方法,我们统计并测试了大厂商的部分机型,得到如下表格:
厂商 | 机型 | 系统通知标题颜色 | 背景主题 | 是否支持大图/多行文字 | 系统版本 | 标题大小 | 能否获取App推送是否打开 | 备注 |
---|---|---|---|---|---|---|---|---|
华为 | 荣耀V8 | 未知 | 暗色 | 支持 | 6.0 | 14dp/19dp | 能 | 通知栏显示需要授权 |
华为 | P8 | -637534209 | 暗色透明 | 支持 | 5.0.1 | 能 | ||
华为 | 荣耀4A | -637534209 | 黑色,透明度不高 | 支持 | 5.0.1 | 能 | ||
华为 | 荣耀7 | -637534209 | 黑色,透明度不高 | 支持 | 5.0.2 | 能 | ||
华为 | MATE8 | -637534209 | 黑色 | 支持/支持12 | 6 | 14dp/16dp+ | 能 | |
华为 | G7plus | -637534209 | 黑色 | 支持 | 5.1 | 14dp | 能 | |
华为 | 荣耀4X | -637534209 | 黑色,透明度不高 | 支持 | 5.0.2 | 14dp/16dp+ | 能 | |
小米 | 3 | -452984832 | 灰色,不透明 | 不支持/不支持 | 4.4.4 | 能 | 工作线程获取系统颜色时,会产生java.lang.reflect.InvocationTargetException,带emoji表情时,系统显示颜色和普通推送一样 | |
小米 | 5s | -452984832 | 白色,不透明 | 不支持 | 6.0.1 | 13.33dp/18dp | 能 | |
红米 | NOTE | -1 | 灰色,不透明 | 不支持 | 4.4.4 | 能 | 带emoji表情时,系统显示颜色和普通推送一样 | |
红米 | NOTE3 | -1 | 灰色,透明 | 不支持 | 5.1.1 | 能 | 带emoji表情时,系统显示颜色和普通推送一样,但样式与普通推送稍有不同 | |
三星 | S4 | -16777216 | 白色,不透明 | 支持 | 5.0.1 | 17dp/17dp | 能 | 大图需要下拉才能显示 |
三星 | S5 | -16777216 | 白色,不透明 | 支持 | 5 | 能 | 大图需要下拉才能显示 | |
三星 | S6 | -14342875 | 白色,不透明 | 支持 | 6.0.1 | 17dp/17dp | 能 | 大图不需要可以显示,系统版本6.0.1 |
三星 | Note2 | -1644826 | 黑色 | 支持 | 能 | |||
三星 | S6+ | -14342875 | 白色,不透明 | 支持/支持 | 5.1.1 | 16dp | 能 | |
三星 | SM-N9100 | -16777216 | 白色,不透明 | 支持 | 17dp/18dp+ | 能 | 5.0.1 | |
魅族 | MX5 | -1 | 灰色,不透明 | 支持/支持6 | 5.1 | 18dp/21dp | 能 | 小通知和大图重叠;带emoji表情时,系统显示内容颜色为Android自带颜色,与魅族的系统推送颜色不太一样 |
魅族 | MX3 | 4.3 | 不能 | 系统是联通定制的,版本也比较低,估计还不支持该API。 | ||||
魅蓝 | NOTE2 | -1 | 灰色,透明度不高 | 支持 | 5.1 | 18dp/21dp | 能 | 小通知和大图重叠;带emoji表情时,统显示内容颜色为Android自带颜色,与魅族的系统推送颜色不太一样 |
HTC | Desire820 | -1 | 黑色,不透明 | 支持 | 4.4.4 | 未测试 | 有不可清除的系统消息存在时,大图默认不显示;普通推送小icon图标显示不正确;自定义emoji表情跟MX5类似;工作线程获取系统颜色时,会产生java.lang.reflect.InvocationTargetException |
HTC | M9w | -570425344 | 白色 | 支持 | 未测试 | |||
OPPO | R7plus | -1 | 黑色,透明度不高 | 不支持 | 5 | 16dp/16dp | 能 | 带emoji表情时,系统显示颜色和普通推送一样 |
OPPO | R3 | 黑色,透明度不高 | 不支持 | 4.3 | 18dp/18dp | 未测试 | ||
一加 | ONE | -570425344 | 白色 | 支持 | 5.1.1 | 16dp/16dp | 能 | |
一加 | One plus 3 | 白色 | 支持/支持13 | 7.0 | 能 | |||
LG | Nexus5 | -570425344 | 白色 | 支持/支持12 | 6.0.1 | 16dp/16dp | 能 | |
乐视 | MAX | -1 | 暗色,透明 | 支持 | 6.0.1 | 16dp/16dp | 能 | |
ViVO | X5L | -1 | 暗色 | 支持 | 4.4.2 | 未测试 | ||
ViVO | X5M | -1 | 暗色 | 支持 | 5.0.2 | 能 | ||
锤子 | T1 | 黑色 | 不支持 | 4.4.2 | 未测试 | |||
金立 | S5.1 | -1 | 黑色,不透明 | 支持 | 4.3 | 未测试 | 工作线程获取系统颜色时,会产生java.lang.reflect.InvocationTargetException | |
联想 | K910 | -1 | 暗色 | 支持 | 4.2.2 | 不能 | ||
联想 | A320T | -1 | 黑色,不透明 | 支持 | 4.4.4 | 未测试 |
可以看到,通知栏存在各式各样的背景色,字体大小和颜色也不尽相同。通过上述方法,有一部分机型是拿不到系统通知栏颜色的,但通过观察可以发现,所有拿不到字体颜色的机型都是暗色或黑色背景(实测7.0此经验失效),因此可以使用白色字体。
经过上述调研与测试,我们的适配方案如下:
getNotificationColor()
方法里。如果还获取不到,那么标题和内容采用Android原生系统提供的,其中标题是@android:color/primary_text_dark
,内容是@android:color/secondary_text_dark
。@android:color/primary_text_dark
和@android:color/secondary_text_dark
已经获取不到颜色值了,考虑到7.0所采用的通知栏主色调是白色,因此目前暂时的解决方案是遇到7.0的系统采用黑色字体。面对众多厂商的源码修改,目前测试有ZUK的7.0系统为暗色背景,暂时的解决方案是根据机型适配。
对于Android emoji表情的适配,我想只有体验过的人才知道这里面有多少坑。我试图通过谷歌了解Android在每一个版本对应的emoji表情的支持情况,最终发现没有一篇文章或一个网页能够完全列出emoji表情在Android上的修改历史。于是我只能自己动手,构建一张Android emoji表情支持版本对比的表格。
Android系统版本 | emoji版本 | Unicode版本 | Unicode emoji发布日期 | Android支持版本日期 | emoji表情数 | 新增表情链接/更新日志 | 备注 |
---|---|---|---|---|---|---|---|
7.1 | 4 | 9.0 | 2016.07.21 | 2016.10.20 | 2374 | http://emojipedia.org/google/android-7.1/new/ http://blog.emojipedia.org/android-7-1-emoji-changelog/ | 成为首个支持Unicode 9标准的系统! |
7.0 | 3 | 9.0 | 2016.07.21 | 2016.08.22 | 1791 | http://emojipedia.org/google/android-7.0/new/ http://blog.emojipedia.org/android-7-0-emoji-changelog/ | |
6.0.1 | 1 | 8.0 | 2015.07.17 | 2015.12.07 | 1294 | http://emojipedia.org/google/android-6.0.1/new/ http://blog.emojipedia.org/android-6-0-1-emoji-changelog/ | |
6.0 | 1 | 7.0 | 2014.07.16 | ||||
5.0 | 1 | 6.1 | 2012.02 | 2014.11.03 | 1090 | http://emojipedia.org/google/android-5.0/new/ http://blog.emojipedia.org/android-50-emoji-changelog/ | |
4.4 | 1 | 6.0 | 2010.1 | 2014.11.01 | 850 | http://emojipedia.org/google/android-4.4/new/ | 首个支持彩色Emoji表情的Android系统 |
4.3 | 1 | 6.0 | 2010.1 | 2013.07.24 | 717 | http://emojipedia.org/google/android-4.3/new/ | 首个支持Emoji表情的Android系统,但颜色是黑白的 |
首先需要说明的是为什么会有Emoji版本和Unicode版本?Emoji实际上可以说是Unicode下的一个子集,Unicode的版本更新,除了Emoji表情发生变化以外,还有许多其他的字符集定义发生变化,Emoji版本是跟随着Unicode版本的更新而逐渐迭代更新的。可以看到,基本上一个Unicode版本对应着一个Emoji版本。目前最新的Unicode版本规划是Unicode 11.0
^10,最新的Emoji版本规划是Emoji 6.0
^11,实际待发布版本是Unicode 10.0
和Emoji 5.0
,将在2017年中旬发布。
当然这只是官方Android系统所支持的emoji版本,面对众多的厂商对源码大刀阔斧的修改,结果又是怎样呢?我们拿了33个表情来进行测试,其中大部分表情是Unicode 6.0
标准,后面几个表情是Unicode8.0
标准。最终得到了如下结果。
实际测试结果与上面的表格基本匹配。特别表扬一下魅族,在5.X系统上就已经支持了Unicode 8.0
标准!乐视的系统在6.0.1系统上的表现指明支持的是Unicode 7.0
标准,实际上Android原生已经支持Unicode 8.0
标准了。
因此,emoji表情的适配其实相对较简单,就是根据不同的系统版本实现不同的支持。当然,如果需要简化那么让只需要让运营配置Unicode 6版本的emoji表情就能够适配4.4+版本的系统了!至于4.4以下版本,可以把常用的Emoji表情放到资源文件中,遇到文本中包含Emoji字符时,手动替换成资源文件中的Emoji图片,再通过上述RemoteViews方式来显示。
从上面的介绍中,大家可以发现,Android 7.0系统以后通知栏消息改版了。援引官方在Notifications public deck
中介绍的一张图,
除了基本的样式发生变化,在7.0中也做了部分接口上的修改。其中,我们需要“拥抱变化”的内容有:
在5.0修改记录中,有一条系统会忽略所有non-alpha
通道的图标,包括按钮图标和主图标。这句话是什么意思呢?实际上,Android从5.0系统开始,对于通知栏图标的设计进行了修改。现在Google要求,所有应用程序的通知栏图标,应该只使用alpha图层来进行绘制,而不应该包括RGB图层。通俗点来讲,就是让我们的通知栏图标不要带颜色就可以了^13。这也是上面的截图中为什么这么多应用都显示不出icon图标,而是显示成灰色的正方形。原因就是他们用了带背景的图片。
5.0加入的Notification.Builder.setColor()
方法,原本是渲染小图标的背景色的,7.0以后,改成了渲染的是通知栏消息第一行的颜色。
7.0系统以后需要显式调用Notification.Builder.setShownWhen(true)
才会显示时间,并且格式调整为具体发布时间相差N小时/N天的形式(见上图)。
如果要适配7.0以后的样式,可以使用以下两个包裹的Style,将RemoteViews封装在内容区域。
图中是未包裹与包裹时候的展示效果。可以说适配RemoteViews是非常蛋疼的一件事,应用可以根据需要来选择是否使用DecoratedCustomViewStyle
。
如果不是必要,建议不要使用RemoteViews。考拉之前是为了兼容在不同手机厂商上展示的emoji表情不一致,以及兼容低版本系统,而在包含emoji表情的消息推送中使用了RemoteViews。经过测试,前者的兼容完全没有必要,在下一版的日常版本发布中会移除RemoteViews相关内容,改用原生通知栏消息实现。
就在笔者即将发布这篇文章的时候,Android O系统发布了预览版!由上面的讨论可知,几乎每个Android版本都修改了Notification,相信Android O也不例外。笔者迫不及待地查看了新系统特性以及修改历史,果不其然,Android O的通知栏消息又双叒叕改版了!关于新系统的通知栏消息改变如下:^15
Android O 还引入了通知渠道,这是全新的由应用定义的通知内容类别。借助渠道,开发者可以让用户对不同种类的通知进行精细控制,用户可以单独拦截或更改每个渠道的行为,而不是统一管理应用的所有通知。^16
简单说就是增加了应用级别的通知栏消息分组功能。举个例子,用户可以分别控制微信群组和微信个人在通知栏的显示级别,群组消息混杂,可以调整较低的显示级别;而个人消息相对重要,可以调整为较高的级别。
有点类似闹钟的打盹儿功能。用户可以让一条打盹儿了的通知栏消息再次出现在通知栏上。开发者可以移除或更新一条打盹儿消息,但更新这条消息不会让已经处于打盹儿状态的通知栏消息再次展示到通知栏上。
创建一条通知栏消息时,支持设置消息有效期,超过有效期后通知栏消息会被系统取消。通过Notification.Builder.setTimeout()
方法设置。
新系统提供了API,区分一条通知是被用户移除或者被应用(即开发者)移除。通过NotificationListenerService.onNotificationRemoved()
方法可以监听得到。
新系统提供了API设置通知栏消息的背景颜色。值得注意的是,应当谨慎使用这个API,只有当消息非常紧急,必须通知到用户的时候,才需要设置背景色。例如,可以为一个正在导航的应用,或者来电设置一个背景色。可以通过Notification.Builder.setColor()
或者Notification.Builder.setColorized()
设置。
由于目前没有真机/模拟器,笔者在这里有一个疑惑。之前Notification.Builder.setColor()
这个方法在Android N上设置的是通知栏消息第一行的颜色,包括图标、应用名称、副标题等。而在Android O上变成了修改整个消息的背景色?在真机/模拟器available的时候将测试一下。
设置了Messaging style风格的消息在新系统上能够展示更多的内容。消息导向(messaging-related)的通知栏消息应该使用MessageStyle
风格代替原生消息。开发者也可以使用新的addHistoricMessage()
方法将消息添加到通知栏中,以便提供对话的上下文信息。
Android O系统引入了通知渠道,类似于分组的概念。通知渠道需要开发者手动创建,一个应用可以创建多个通知渠道,用户可以分别管理应用的每个通知渠道,管理页面由系统提供统一的UI。所有分配到同一个渠道的消息,表现都一样。当用户修改了某个渠道的以下任一种行为,都会同步到该渠道的任何一条消息:
一旦通知渠道被创建并提交到通知栏管理器(NotificationManager),那么开发者就没有权限修改通知渠道的任何配置了,所有的配置只能由用户修改。用户可以到“设置”页面,或者长按通知栏消息改变通知渠道的配置。
Android O系统弃用了旧的通知栏优先级,并提出了通知栏消息重要性这个概念。通知栏上的消息展示顺序不再由优先级控制,也无法使用重要性来控制。重要性可以控制消息展示在什么地方,例如默认级别IMPORTANCE_DEFAULT(3)
可以展示在任意地方,如通知栏、状态栏、锁屏,可以发出通知声音,但不直接展示给用户,即不会弹出heads-up
通知。重要性一共有6个级别:
开发者只能设置IMPORTANCE_NONE(0)
至IMPORTANCE_HIGH(4)
级别,最高级别不能通过代码控制。重要性控制也是针对通知渠道级别的,具体有没有全局性控制得看具体的模拟器设置。
本文介绍了Android通知栏消息随着系统的更新所发生的变化以及在各个版本的Android系统通知栏消息适配过程中所产生的一些问题,并提供解决思路。随着Android版本的逐渐迭代,可以预见Android通知栏消息将会支持越来越多可配的样式,也逐渐地把权限交给用户控制,包括消息的展示以及隐私的设置。文中提到的后台通知以及“守护”通知,是对付部分应用为了常驻内存保持进程不被杀而采取的措施,这对于国内的Android生态来说无疑是利好的。
网易云新用户大礼包:https://www.163yun.com/gift
本文来自网易实践者社区,经作者黎星授权发布。