Android O在通知机制上做了较大改动,所以适配8.0开发时,需要注意检测通知的情况,一般用户可以通过长按APP进入应用信息,然后查看和配置通知。 在AndroidO之前,系统对应用的通知仅提供一套统一的管理机制,对APP内所有的通知允许或屏蔽,静音或响铃等,升级到Android O后,系统提供对通知更细粒度的管理,可以对APP内不同功能的通知进行分类,然后用户可以根自己喜好对不同类型的通知来进行单独的配置,该分类主要通过NotificationChannel实现。
通知管道NotificationChannel Android O上app发送的每个通知必须依附于一个channel。即每个notification对象必须发送到指定的NotificationChannel。如果找不到channel,就会报No Channel found的错。
系统通知服务NotificationManagerService主要的职能是对通知的管理和调度,在init初始化的时候会加载/data/system/notification_policy.xml中的通知信息到内存数据结构,该文件中保存所有package注册的所有NotificationChannel。拿短信APP举例,有正常的来信通知和信息发送失败通知两类,我们来查看一下短信通知管道的情况:
<package name="com.android.messaging" show_badge="true" uid="10031">
<channel id="channel_normal" name="短信通知" importance="4" sound=" content://settings/system/notification_sound" usage="5" content_type="4" flags="0" lights="true" light_color="-16711936" vibration_enabled="true" show_badge="true" />
<channel id=" channel_fail_msg " name="发送失败" importance="4" sound=" android.resource://com.android.messaging/2131689473" usage="5" content_type="4" flags="0" lights="true" light_color="-16711936" vibration_enabled="true" show_badge="true" />
</package>
需要说明一点:NotificationChannel不同用户下是通过uid来区分的,所以存在多用户时系统在寻找channel时是以pkg + "|" +uid为key来进行查找的。 在应用启动时,需要创建两个通知管道,并对管道设置一些初始状态,包括管道名称、铃声、振动、LED提醒、圆点通知等,如下所示,为新信息通知的管道创建代码。
private void initNormalChannel(){
Stringname = Factory.get().getApplicationContext().getResources().getString(R.string.normal_channel_name);
NORMAL_CHANNEL = new NotificationChannel(CHANNEL_ID_NORMAL, name, NotificationManager.IMPORTANCE_HIGH);
NORMAL_CHANNEL.enableVibration(true);
NORMAL_CHANNEL.setSound(RingtoneUtil.getNotificationRingtoneUri(null), Notification.AUDIO_ATTRIBUTES_DEFAULT);
NORMAL_CHANNEL.enableLights(true);
NORMAL_CHANNEL.setLightColor(Color.GREEN);
NORMAL_CHANNEL.setShowBadge(true);
mManager.createNotificationChannel(NORMAL_CHANNEL);
}
需要注意的是,这些初始状态一旦设定,APP将无法再修改,只能由用户在应用信息的通知界面进行配置,如果一定要修改,比如切换语言时更新管道名称,则只能重新创建管道(使用与之前相同的管道id),切记不能先删除管道,因为这样会导致已弹出的通知消失,重新走一遍创建流程即可。
如上所示,在创建每个notification对象时,都必须指定NotificationChannel,设置channelId,设置的方式有两种,如下代码所示:
// 第一种,直接以参数的形式传给builder
NotificationCompat.Builder builder = newNotificationCompat.Builder(context, ChannelManager.CHANNEL_ID_NORMAL);
// 第二种,builder调用setChannelId方法
builder.setChannelId(ChannelManager.CHANNEL_ID_NORMAL);
补充因Android升级原因,通知相关的很多接口其实已经不生效了,但考虑到低版本兼容,所以一般不做删除。比如给通知设置优先级setPriority,因Channel初始化的时候已经设置重要等级了,APP调用setPriority更新优先级已无实际意义,另外如果通知设置了setGroupSummary(true),它的标题、内容等都不会显示,设置了也无意义,系统会自动根据子通知来进行组装处理。 对于群组通知,有时候我们只希望子通知有提醒,而群组本身不需要提醒,则可以通过设置setGroupAlertBehavior(GROUP_ALERT_CHILDREN)来达到目的,GROUP_ALERT_CHILDREN出自android.app.Notification,由它来决定群组通知的提醒行为。
|