欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android自定义Notification兼容笔记

程序员文章站 2022-07-13 15:38:42
...

通知栏简介

状态通知栏主要涉及到2个类: Notification 和 NotificationManager
Notification为通知信息类,它里面对应了通知栏的各个属性
NotificationManager : 是状态栏通知的管理类,负责发通知、清除通知等操作。

注册系统Service

NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

1. flags

实例化通知栏之后通过给他添加.flags属性赋值,例如

notification.flags = Notification.FLAG_AUTO_CANCEL;
提醒标志符成员:

// 三色灯提醒,在使用三色灯提醒时候必须加该标志符
Notification.FLAG_SHOW_LIGHTS
// 发起正在运行事件(活动中),无法手动移除
Notification.FLAG_ONGOING_EVENT
// 让声音、振动无限循环,直到用户响应(取消或者打开)
Notification.FLAG_INSISTENT
// 发起Notification后,铃声和震动均只执行一次
Notification.FLAG_ONLY_ALERT_ONCE
// 用户单击通知后自动消失
Notification.FLAG_AUTO_CANCEL
// 可让通知栏点清除键不消失
Notification.FLAG_NO_CLEAR
// 表示正在运行的服务
Notification.FLAG_FOREGROUND_SERVICE

2. PendingIntent

使用通知栏我们可能要监听用户点击通知栏和移除通知栏的事件,比如暂停/继续下载和用户手动移除通知栏暂停下载。

Notification mNotification = new Notification(icon, tickerText, when);
// 移除通知栏事件设置
mNotification.deleteIntent = getDeleteIntent();
// 点击通知栏事件设置
mNotification.contentIntent = getDefalutIntent();

分别对deleteIntent和contentIntent赋值,根据action或者requestCode在接收到关播的时候进行区分,例如:

private PendingIntent getDeleteIntent() {
    Intent deleteIntent = new Intent(ACTION_DELETE);
    return PendingIntent.getBroadcast(mContext, DEL_REQUESTCODE, deleteIntent, PendingIntent.FLAG_CANCEL_CURRENT);
}

getBroadcast方法的官方解释:

Retrieve a PendingIntent that will perform a broadcast..

  • 在指定intent.setClass(context, XXXReceiver.class);的广播类的时候会出现接受不到关播的情况,所以我把这段操作给取消了,发起通知栏的activity注册广播后即可接收。
PendingIntent的位标识符:

FLAG_ONE_SHOT 表示返回的PendingIntent仅能执行一次,执行完后自动取消
FLAG_NO_CREATE 表示如果描述的PendingIntent不存在,并不创建相应的PendingIntent,而是返回NULL
FLAG_CANCEL_CURRENT 表示相应的PendingIntent已经存在,则取消前者,然后创建新的PendingIntent,这个有利于数据保持为最新的,可以用于即时通信的通信场景
FLAG_UPDATE_CURRENT 表示更新的PendingIntent,所有对应的Intent里面的extra被更新为最新的

  • 通过extra数据来区分intent,应采用PendingIntent.FLAG_UPDATE_CURRENT),且每次num不一样
PendingIntent点击事件设置

contentIntent:在通知窗口区域,Notification被单击时的响应事件由该intent触发;
deleteIntent:当用户点击全部清除按钮时,响应该清除事件的Intent;
fullScreenIntent:响应紧急状态的全屏事件(例如来电事件)

有时我们使用contentIntent实现点击操作时发现它会自动收起手机下拉菜单,但我们并不想这样的时候,需要自定义监听事件,但是要注意,2.3及2.3以下版本中,自定义的通知栏中如果带有按钮,可能按钮点击事件会失灵。

// 判断版本之后才进行监听
if (getSystemVersion() > 10) {
    Intent buttonIntent = new Intent(ACTION_BUTTON);
    buttonIntent.putExtra(INTENT_BUTTONID_TAG, BUTTON_PALY_ID);
    PendingIntent intent_paly = PendingIntent.getBroadcast(mContext, 2,buttonIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    // 更改此处的id进行某个控件的监听
    contentview.setOnClickPendingIntent(R.id.llPro, intent_paly);
}

3. RemoteViews

当我们要在通知栏实现显示下载进度条进度时,会用到setProgress,此方法在4.0及以后版本才有用,如果为早期版本:需要自定义通知布局RemoteViews,其中包含ProgressBar视图。

但是使用RemoteViews是有限制的:

error:android.app.RemoteServiceException: Bad notification posted from package com.example.notifications: Couldn't expand RemoteViews for: StatusBarNotification(package=com.example.notifications id=101 tag=null notification=Notification(vibrate=null,sound=null,defaults=0x0,flags=0x2))

Notification的自定义布局是RemoteViews,和其他RemoteViews一样,在自定义视图布局文件中,仅支持FrameLayout、LinearLayout、RelativeLayout三种布局控件和AnalogClock、Chronometer、Button、ImageButton、ImageView、ProgressBar、TextView、ViewFlipper、ListView、GridView、StackView和AdapterViewFlipper这些显示控件,不支持这些类的子类或Android提供的其他控件。否则会引起ClassNotFoundException异常

  • 遵循了以上的条件有时仍然会报错,API 11+才能使用的style要谨慎使用,否则会报RemoteServiceException,且很难排查出来。

4. 低版本中,自定义布局中的字体颜色的设置

  • 由于2.3及之前版本,背景色是白色的,而2.3以上的版本背景色是暗色的,所以在2.3之后的版本中(即API >=9的版本中),在资源文件下的src/values-v9目录中的style.xml文件中设置它标题和内容的颜色应该为白色或其他暖色调,否则将无法看清通知栏上的内容。

5. 自定义布局的设置方法

2.3之后:
通过Builder以下方法赋于自定义布局。
mBuilder.setContent(view_custom)
2.3及2.3之前:
通过 Notification notify = mBuilder.build();
notify.contentView = view_custom;
mNotificationManager.notify(notifyId, notify)

所以有兼容2.3版本需求的项目可以直接选择用后者。

我的博客(第一时间更新):
http://huangss.farbox.com/