Android通知栏介绍与适配总结(上篇)

此文已由做者黎星受权网易云社区发布。html

欢迎访问网易云社区,了解更多网易技术产品运营经验。android

 

因为历史缘由,Android在发布之初对通知栏Notification的设计至关简单,而现在面对各式各样的通知栏玩法,谷歌也不得不对其进行更新迭代调整,增长新功能的同时,也在不断地改变样式,试图迎合更多人的口味。本文总结了Android通知栏的版本迭代过程,在通知栏开发过程当中所遇到的各类各样的坑,以及一些解决技巧,特别的,对于大众期盼的Android 7.0的到来,通知栏又会发生怎样的改变呢?接下来一一进行介绍。安全

 

Android通知栏发展历史

首先来看一张各个Android版本通知栏消息的全家福。服务器

 

点击查看大图app

 

Android通知栏从最初的Android1.1系统一直到现在的7.X版本,发生了翻天覆地的变化。从图中能够看出,1.X-2.2版本的通知栏采用了白色背景和黑色字体;2.3-4.X版本,默认背景变成了黑色,而主标题采用白色字体,内容为灰色字体。从Android5.0开始,又更改成白色背景和黑色字体。固然,这只是原生的Android系统通知栏默认颜色,许多厂商对每一个Android的版本都尝试了各式各样的修改,在此不一一介绍。ide

 

下面分别介绍每一个版本的更新和修改记录。布局

 

Android 1.X 修改记录^1

Android 1.X版本也就是第一个Android诞生的版本。从Android1.1版本开始,提供基本的通知栏消息功能,包含小图标、主标题、副标题和时间这四个元素。右上角有一个清除通知栏消息的按钮。须要说明的是,Android从一开始就提供了清除通知栏消息的功能而且保留至今,而iOS到如今都没有提供清除按钮。学习

 

Android 2.X 修改记录^2

Android 2.X版本的通知栏消息功能上并未发生变化,右上角的“clear notifications”缩减为了“clear”。2.2版本之前沿用了1.5的通知栏样式,从2.3版本开始从新设计,改为了暗色背景。测试

 

Android 3.X 修改记录^3

Android 3.X版本是专为Pad而设计的系统。通知栏消息带来了一些新的功能。字体

 

  • 非永久的通知栏消息的右边增长了“X”按钮,点击后该条通知能够当即清除。

  • 增长了RemoteControlClient,即远程控制媒体应用的功能。

  • 增长了LargeIcon,可使用大图展现通知栏消息。

 

Android 4.1 修改记录^4

Android 4.1版本的通知栏在3.X版本的基础上进行了大量修改。增长了很多新功能。

  • 增长了Style

  • 增长了通知栏按钮

  • 支持通知栏展现的优先级配置

  • 通知栏背景改成黑色透明

 

通知栏样式

Android 4.1通知栏最大的变化就是增长了丰富多样的Style样式。经过设置样式,能够展现更大区域的通知消息,如展现大图和多行文字,也能够展现相似邮箱收发信的样式,同时支持自定义按钮并增长点击事件。但须要注意的是,只有最顶部的那条通知栏消息能够默认展现Style样式,其余消息默认是以普通样式展现。Style能够经过Notification.Builder.setStyle(Style)进行设置。具体支持的样式有:

 

Notification.BigPictureStyle

大图样式,即除了普通的通知栏消息内容外,能够在通知栏消息下方展现一张大图,最大高度支持256dp。

 

Notification.BigTextStyle

多行文字样式,能够支持多行文字的展现。经测试,在不一样手机上可以支持的行数不同,测试过的机子,最大支持12行。

 

Notification.InboxStyle

收件箱样式。支持展现具备一串消息内容的会话样式,适用于短信、邮件、IM等。

 

通知栏按钮

通知栏消息无论是普通样式仍是Style样式,都支持两个按钮同时出如今一条通知栏消息的底部,经过这两个按钮,能够自定义一系列动做,包括回复信息和邮件,点赞等。经过Notification.Builder.addAction(Action)添加按钮。

 

通知栏优先级

Android 4.1通知栏增长了优先级的配置,优先级高的消息能够展现在最上方。谷歌设计优先级的初衷是根据不一样的优先级来防止用户成天被各类莫名其妙的通知栏消息骚扰,重要的通知则应该适当提升优先级,使得用户能够快速地看到并回应,不重要的通知则下降优先级,防止用户被打扰。优先级一共有5个级别,分别是:

// 默认优先级
public static final int PRIORITY_DEFAULT = 0;
// 低优先级
public static final int PRIORITY_LOW = -1;
// 最低优先级
public static final int PRIORITY_MIN = -2;
// 高优先级
public static final int PRIORITY_HIGH = 1;
// 最高优先级
public static final int PRIORITY_MAX = 2;

Android 4.3 修改记录^6

Android 4.3通知栏没有发生大的变化。主要增长了两个小功能。

 

  • 增长了Notification AccessApi,容许可穿戴设备远程控制通知栏消息。

  • 增长了NotificationListenerService,容许接收到系统通知栏列表的变化

Android 5.X 修改记录^7

Android 5.X系统相较于之前的版本,能够说是一个真正能够和iOS抗衡的系统。材料设计给Android系统注入了新的活力,相应的通知栏消息也相较于上一个版本进行了改版。所发生的变化有:

 

  • 通知栏修改成白色背景,暗色字体,以适应材料设计风格。

  • 系统会忽略全部non-alpha通道的图标,包括按钮图标和主图标。

  • 能够经过setColor()方法在图标后设置一个背景色。

  • 通知消息的声音将经过STREAM_RING或者STREAM_NOTIFICATION控制,之前是经过STREAM_MUSIC控制。

  • 锁屏状态下,能够控制通知栏消息的隐私程度。

  • 移除了RemoteControlClient,更改成NotificationCompat.MediaStyle实现。

  • 增长了Heads-up通知,即经过状态栏浮动窗口展现通知消息。

 

Android 6.X 修改记录^8

  • 移除了Notification.setLatestEventInfo()方法,经过持有Notification.Builder,而后使用build()方法能够更新同一个通知栏实例。

  • 容许用户控制应用通知的优先级。

  • 加入了免打扰模式(Do Not Disturb)。

  • 增长了getActiveNotifications()方法获取当前展现的通知消息。

 

Android 7.X 修改记录

  • 通知栏样式全面改版,小图标在左上角,大图标在右边,小图标、App应用名、副标题、数量和时间在第一行,第二行是主标题,第三行是内容。

  • 增长了Notification.DecoratedCustomViewStyle()和Notification.DecoratedMediaCustomViewStyle(),帮助更好的装饰带有RemoteViews的通知栏消息。

  • 须要动态设置Builder.setShowWhen(true)才会显示时间。

  • 支持Action的直接回复,经过RemoteInput实现,且回复的消息内容支持当即添加到通知栏。

  • 支持通知消息组,类似的消息在达到必定数量后会按照消息组来显示。

  • 增长了NotificationManager.areNotificationsEnabled告知应用是否开启了通知权限。

Android通知栏踩坑与填坑指南

 

魅族5.X手机,大图显示问题

问题详情

Flyme系统对原生Android源码作了修改,采用BigPictureStyle方式显示大图通知栏的时候,消息与大图重合了,以下图。

 

解决方案

首先说一下为何会有解决方案。展现大图这个功能开发完成后,拿去给产品演示。碰巧产品的机型就是一魅族手机T_T,结果固然是不能接受的,而后又一个巧合的事情出现了,那就是产品的手机里,京东App推了一条带大图的广告,他们竟然可以解决这个问题!因而,我开始研究解决方案。

 

首先,经过BigPictureStyle来实现大图功能确定是走不通的,由于事实就摆着行不通的嘛。京东的App确定是经过RemoteViews来实现的。因而,开始走弯路,尝试经过RemoteViews来展现大图。可是谷歌规定,自定义布局展现的通知栏消息最大高度是64dp。那么,京东的App是怎么实现的?在尝试了各类方法之后,最后又是经过投机取巧的方式解决了问题:

private void showBigPictureNotificationWithMZ(Context context) {
    NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    Notification.Builder builder = new Notification.Builder(context);
    Notification notification = generateNotification(builder);
    notification.bigContentView = mRemoteViews;
    notificationManager.notify(notifyId, notification);
}

须要先生成Notification的实例,而后手动给notification.bigContentView赋值,再notify,就能够了

 

顶部状态栏(StatusBar)小图标显示异常

问题详情

当通知来的时候,若是不在通知栏浏览,会在顶部状态栏出现一个向上翻滚动画的通知消息,这条通知消息左边是一个小图标。部分系统这个小图标显示异常,是一个纯灰色的正方形,以下图。

 

 

解决方案

首先产生灰色图标的缘由就是5.0系统引入了材料设计,谷歌强制使用带有alpha通道的图标,而且RGB的alpha值必须是0(实测不为0也是能够的,但系统会忽略全部RGB值)。所以,使用JPG的图片是不行的,最好的代替方案就是一张背景透明的PNG图片。

 

Android 7.X机型,通知栏小图标显示成灰色

问题详情

这个问题跟第二个有点相似,在7.0系统及以上,有部分应用的小图标是灰色的,大图能够正常显示。碰巧的是,显示异常的小图标,颜色都是灰色的。

 

 

 

解决方案

小图标显示异常解决方案相似,将小图标替换为透明背景的PNG图片。

 

RemoteViews显示异常

问题详情

因为系统提供的通知栏消息类型有时候不能知足要求,部分通知栏消息采用自定义RemoteViews来实现。采用RemoteViews,特别是手动生成Bitmap而后直接传给一个自定义Layout,再经过setContentView方式设置通知栏消息时,会存在各类各样的坑。

 

Android通知栏的背景色有几种状况,白色、暗色、暗色透明和黑色。若是生成的Bitmap带背景色,这个背景色就很难选择。若是选择黑色背景,那么在白色通知栏的机型上就很难看。所以不能彻底在各个系统上面完美展现出来。若是不带背景色,那么字体颜色也面临一样的困惑。试想,若是在白色的背景上显示白色的文字,用户看到白茫茫一片,是什么感觉?

另外一方面,大部分厂商对原生的Android系统都会有各类各样的改造,通知栏的样式也不例外。若是按照原生的样式来设计,那么在大部分国内厂商的机子上显示都和正常的普统统知栏消息不同。例如华为6.0系统的机子,原生系统的时间线在右上角,华为的在左边,这样会给用户带来错觉。

 

 

解决方案

详见RemoteViews适配一节。

 

大尺寸小图标在部分机型上显示不正确

问题详情

这个问题主要在部分机型的4.X系统上碰见,小图标大小没有按照24dp裁剪,而是采用了桌面图标同样的大小96dp。具体适配不正常的机型有HTC Desire 820、Lenovo A320T。

 

解决方案

按照标准来,小图标大小为24dp,大图标为桌面icon图标大小96dp。具体可参考这里^14

 

部分机型不支持Style

具体机型见下图以及后面统计的表格。顺便提下,小米是其中之一,不知道他们为何不支持额外的这些Style。

点击查看大图

 

通知栏更新频率

问题详情

每一个应用基本都有自更新的逻辑,App开机的时候提示用户升级,点击升级按钮后在Notification出现一个下载带进度条的通知。应用通常是在开启一个工做线程在后台下载,而后在下载的过程当中经过回调更新通知栏中的进度条。咱们知道,下载进度的快慢是不可控的,若是每次下载中的回调都去更新通知栏,那么可能几百毫秒、几十毫秒、甚至几毫秒就更新一次通知栏,应用可能就会ANR,甚至崩溃。

 

解决方案

控制通知栏更新频率,通常控制在0.5s或者1s就能够了。在某一个更新时间间隔内下载的进度回调直接丢弃,须要注意的是下载完成的回调,须要实时回调通知栏消息显示下载完成。

 

恶心的后台通知和“守护”通知

问题详情

这个坑我不肯多介绍,只说结果。但凡存在后台通知或者“守护”通知的应用,在7.0系统之后都会原形毕露。尚未适配7.0的应用,可长点心儿吧~

 

解决方案

请弃坑。

 

小米推送SDK接入问题

问题详情

为了提高推送到达,考拉接入了小米推送的SDK。小米推送分为通知栏消息和透传消息,通知栏消息属于系统级推送,在MIUI的机子上能够在进程被杀死的状况下也能收到应用推送。然而有个问题,小米认为应用在前台时,不会回调任何方法;小米认为应用在后台的时候,收到通知栏消息的同时,会回调onNotificationMessageArrived方法。这时候就要当心翼翼地处理这条消息了。由于若是你的应用先后台判断逻辑和小米的不同,那么就有可能小米帮你发了一条通知栏消息,你本身又发了一遍,形成通知栏消息的重复发送(这个坑考拉踩过T_T)。另外一方面,在7.0系统的机子上,主标题和小图标的颜色是能够改变的,目前小米推送SDK没有开放这个接口供调用方定制。

 

解决方案

目前只能解决第一个问题——先后台判断的问题。应用是否在后台能够根据如下代码进行判断。在Android 5.0以上,能够经过ActivityManager.RunningAppProcessInfo判断,Android 5.0及如下版本经过ActivityManager.RunningTaskInfo判断。经测试,这个方案在Android 4.4以上结果是能够彻底匹配的。

 

public static boolean isAppInBackgroundInternal(Context context) {
    ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
        List<ActivityManager.RunningAppProcessInfo> runningProcesses = manager.getRunningAppProcesses();
        if (!ListUtils.isEmpty(runningProcesses)) {
            for (ActivityManager.RunningAppProcessInfo runningProcess : runningProcesses) {
                if (runningProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
                    return false;
                }
            }
        }
    } else {
        List<ActivityManager.RunningTaskInfo> task = manager.getRunningTasks(1);
        if (!ListUtils.isEmpty(task)) {
            ComponentName info = task.get(0).topActivity;
            if (null != info) {
                return !isKaolaProcess(info.getPackageName());
            }
        }
    }
    return true;
}

Android通知栏适配

RemoteViews适配

因为系统自带的通知栏消息样式不能彻底知足产品们脑洞大开的需求,有时候咱们须要自定义布局样式展现通知栏消息。Android系统能够将自定义布局经过setContent(7.X系统推荐使用setCustomContentView)设置到Notification.Builder中,来实现样式的更变。setContent方法须要传入一个RemoteViews对象,它是一个普通的数据类型,不是View,做用是供其余进程展现视图。RemoteViews只支持4种基本的布局^9:

  • FrameLayout

  • LinearLayout

  • RelativeLayout

  • GridLayout

 

这些布局下面只支持几种视图控件:

  • AnalogClock

  • Button

  • Chronometer

  • ImageButton

  • ImageView

  • ProgressBar

  • TextView

  • ViewFlipper

  • ListView

  • GridView

  • StackView

  • AdapterViewFlipper

 

只能经过上述组合生成一个RemoteViews。

 

自定义布局与视图

除了上面提到的布局与控件,有没有办法自定义布局与视图呢?咱们知道,任何一个View,均可以生成一个Bitmap对象,支持的视图控件里有ImageView,能够经过ImageView.setBitmapResource()将自定义视图设置到一个ImageView中,而后再随便放到一个布局上,就能够实现通知栏消息的任意布局。理想是美好的,但现实是残酷的。使用这种方式自定义的布局,会存在与原生的通知栏消息样式不一致的可能,包括小图标/大图标的大小,字体的大小与颜色,时间的显示方式(不一样版本的时间显示位置和样式都不同)。下面解决一个最关键,也最致命的问题——字体颜色。若是字体颜色和背景颜色同样,那这条通知栏消息就无法看了,如RemoteViews显示异常一节介绍的同样。

 

解决字体颜色和背景颜色同样的问题有三种解决方案,分别是:

  • 背景色固定不透明,字体颜色与背景色造成反差。(360和京东的作法)

  • 背景色透明,字体颜色采用系统原生的notification_style。

  • 背景色透明,经过特殊方式拿到通知栏字体颜色和字体大小。

 

 

 

其中,第一种方案简单,可以兼容全部厂商机型。例如京东固定背景色为黑色,字体为红色。这种方式的惟一缺陷是样式上不能与普统统知栏消息重合,在白色背景的通知栏上极为显眼。第二种方式,经过阅读源码可知,系统的通知栏标题和内容采用的颜色分别是@android:color/primary_text_dark和@android:color/secondary_text_dark,但踩过坑以后发现并不是全部的机型默认都是这两个颜色,有可能获取不到值。所以这种方案只能做为参考,不能用于实际环境中。最后详细介绍一下第三种方式。

 

原文:Android通知栏介绍与适配总结(上篇)

相关阅读:Android通知栏介绍与适配总结(下篇)

 

免费领取验证码、内容安全、短信发送、直播点播体验包及云服务器等套餐

更多网易技术、产品、运营经验分享请点击

 

 

相关文章:
【推荐】 探一探快应用的虚实
【推荐】 从整理看视觉设计(网易云课堂个人学习中心-微专业视觉优化)

相关文章
相关标签/搜索