Android自定义Notification兼容笔记

通知栏简介

状态通知栏主要涉及到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/

你可能感兴趣的:(Android自定义Notification兼容笔记)