介绍
最近的项目中,需要用到Notification。上一下效果图:
首先,学习一下关于Notification的基本知识。
状态通知栏主要涉及到2个类: Notification 和 NotificationManager 。
Notification为通知信息类,它里面对应了通知栏的各个属性。
NotificationManager : 是状态栏通知的管理类,负责发通知、清除通知等操作。
注意:NotificationManager 是一个系统Service,必须通过 getSystemService(NOTIFICATION_SERVICE)方法来获取:
1 | mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); |
自定义Notification大致分为以下几步:
- 自定义布局;
- 使用NotificationCompat.Builder创建Notification。使用RemoteViews填充自定义布局,然后通过setContent()添加到Builder中;
- 使用广播,添加按钮点击事件;
- NotificationManager.notify()将Notification显示到手机状态栏。
下面结合代码进行说明。
代码
第一步,对应于Notification的布局文件:
1 |
|
布局文件很简单,不做过多叙述。
再来看到Notification的创建。
1 | public class PlayerService extends Service { |
播放音乐使用的自然是Service了。于是我定义了PlayerService继承自Service,声明相应的变量,然后在onCreate()中进行初始化。
我们可以看到,代码中使用RemoteViews
填充了布局,并将其设置到Notification创建的Builder中。
RemoteViews不同于View,它不能通过findViewById()来获取View控件。它里面的控件的点击事件必须通过setOnClickPendingIntent()
来进行设置。它有2个参数,1个是控件ID,另外1个是进行处理的PendingIntent。PendingIntent的创建必须通过广播的方式来实现。重复下上面的代码:
1 | Intent playIntent = new Intent(NOTIFICATION_PLAY_ACTION); |
然后在广播的onReceive()方法中,判断是哪个控件被点击。然后执行相应的逻辑。
记得广播一定要先注册才能使用。
最后,便是将Notification显示到手机了。
1 | final Track track = getCurrentEntry().getTrack(); |
Track是我进行音乐播放的一个Model类。包含一些播放音乐的基本信息。这里我是通过的Universal-Image-Loader进行图片加载。在其加载成功后的回调中,通过setTextViewText()
等类似方法给控件设值。也是有2个参数,第1个是控件Id,第二个便是要设置的值。
最后通过mNotificationManager.notify(PLAYING_NOTIFY_ID, notification)
将Notification显示到手机。
经过上述几个步骤,自定义Notification便能显示到手机了,并且具备点击事件。
Tips
- 自定义布局仅支持FrameLayout、LinearLayout、RelativeLayout三种布局控件和AnalogClock、Chronometer、Button、ImageButton、ImageView、ProgressBar、TextView、ViewFlipper、ListView、GridView、StackView和AdapterViewFlipper这些显示控件,不支持这些类的子类或Android提供的其他控件,否则会引起ClassNotFoundException异常。
之前播放的按钮打算用ToggleButton,使用之后发现显示不了,后面才找到原因。 - Notification属于系统级别的组件,使用了RemoteViews的setViewVisibility()、setTextViewText()等方法后,必须通知系统重绘才能更新UI,最简单的方式就是重新notify一下。只要传入的Id一样,就会覆盖掉之前的通知。
在播放、暂停按钮切换的时候,就碰到这个问题,一直不能显示,加上notify语句后就能正常执行了。 - 关于Notification的取消。
使用mNotificationManager.cancel(PLAYING_NOTIFY_ID)
即可。但是一定要注意Notification的flag。这里补充下Notification的标识符。
提醒标志符成员:
Notification.FLAG_SHOW_LIGHTS //三色灯提醒,在使用三色灯提醒时候必须加该标志符
Notification.FLAG_ONGOING_EVENT //发起正在运行事件(活动中)
Notification.FLAG_INSISTENT //让声音、振动无限循环,直到用户响应 (取消或者打开)
Notification.FLAG_ONLY_ALERT_ONCE //发起Notification后,铃声和震动均只执行一次
Notification.FLAG_AUTO_CANCEL //用户单击通知后自动消失
Notification.FLAG_NO_CLEAR //只有全部清除时,Notification才会清除 ,不清楚该通知(QQ的通知无法清除,就是用的这个)
Notification.FLAG_FOREGROUND_SERVICE //表示正在运行的服务
我当时使用的FLAG_FOREGROUND_SERVICE,导致cancel一直关闭不了Notification,更换flag后就能关闭了。