在android屏幕的通知栏中增加notification,以显示mediaplayer控制面板
点击控制面板的按钮将发送intent来控制mediaplayer
这些intent将以PendingIntent的形式绑定到控制面板上的按钮上
不能工作的代码:
public void sendNotification(int status) {
if (playingFile != null) {
/**
* 给notification构建intent
*/
//如下是在notification中给remoteview设置PendingIntent
//receiver按NOTIFICATION_ACTION进行过滤
//过滤之后按putExtra中设置的参数分辨命令
//
//陷阱是setAction()和PendingIntent.getBroadcast()以及FLAG_UPDATE_CURRENT
//如下代码,最终所有PendingIntent都会变成最后一个!
//猜测,无论从上到下生成多少个PendingIntent
//但同一条ACTION的PendingIntent.getBroadcast()背后只对应一个静态变量!
//也即这四个实际上是一个PendingIntent
//FLAG_UPDATE_CURRENT及另外几个参数的说明也非常不易懂,看得很晕
//
//解决方案是,设置receiver可以过滤出多条ACTION而不是一条
//不按putExtra里面设置的数据进行分辨
//而是直接根据不同的ACTION来分辨命令
//可以工作的代码在后面
Intent resultIntentLast = new Intent(this, PlayService.class);
resultIntentLast.setAction(LocalConst.NOTIFICATION_ACTION);
resultIntentLast.putExtra(LocalConst.NOTIFICATION_OP, LocalConst.op_last);
PendingIntent pendingIntentLast = PendingIntent.getBroadcast(this, 0,
resultIntentLast, PendingIntent.FLAG_UPDATE_CURRENT);
Intent resultIntentNext = new Intent(this, PlayService.class);
resultIntentNext.setAction(LocalConst.NOTIFICATION_ACTION);
resultIntentLast.putExtra(LocalConst.NOTIFICATION_OP, LocalConst.op_next);
PendingIntent pendingIntentNext = PendingIntent.getBroadcast(this, 0,
resultIntentNext, PendingIntent.FLAG_UPDATE_CURRENT);
Intent resultIntentPlay = new Intent(this, PlayService.class);
resultIntentPlay.setAction(LocalConst.NOTIFICATION_ACTION);
resultIntentLast.putExtra(LocalConst.NOTIFICATION_OP, LocalConst.op_play);
PendingIntent pendingIntentPlay = PendingIntent.getBroadcast(this, 0,
resultIntentPlay, PendingIntent.FLAG_UPDATE_CURRENT);
Intent resultIntentPause = new Intent(this, PlayService.class);
resultIntentPause.setAction(LocalConst.NOTIFICATION_ACTION);
resultIntentLast.putExtra(LocalConst.NOTIFICATION_OP, LocalConst.op_pause);
PendingIntent pendingIntentPause = PendingIntent.getBroadcast(this, 0,
resultIntentPause, PendingIntent.FLAG_UPDATE_CURRENT);
/**
* 给notification构建remoteView
*/
RemoteViews notifyView = new RemoteViews(this.getPackageName(), R.layout.notification);
notifyView.setTextViewText(R.id.notification_name, playingFile.getName());
notifyView.setImageViewResource(R.id.notification_icon, R.drawable.icon);
notifyView.setOnClickPendingIntent(R.id.notification_b1, pendingIntentLast);
notifyView.setOnClickPendingIntent(R.id.notification_b2, pendingIntentNext);
notifyView.setOnClickPendingIntent(R.id.notification_b3, pendingIntentPlay);
notifyView.setOnClickPendingIntent(R.id.notification_b4, pendingIntentPause);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.bottom)
.setContentTitle(playingFile.getName())
.setContentText(getResources().getString(R.string.notification_back_msg))
//这是另外一个陷阱
//上面三个设置是不显示的,但是仅仅设置remoteView是不够的
//得有前面三个设置(或许部分设置),否则不能显示notification
.setContent(notifyView);
Intent resultIntent = new Intent(this, DirPlayerActivity.class);
PendingIntent resultPendingIntent = PendingIntent.getActivity(this, 0,
resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
// Sets an ID for the notification
int mNotificationId = 001;
// Gets an instance of the NotificationManager service
NotificationManager mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Builds the notification and issues it.
mNotifyMgr.notify(mNotificationId, mBuilder.build());
}
}
可以工作的代码:
public void sendNotification(int status) {
if (playingFile != null) {
/**
* 给notification构建remoteView
*/
RemoteViews notifyView = new RemoteViews(this.getPackageName(), R.layout.notification);
notifyView.setTextViewText(R.id.notification_name, playingFile.getName());
notifyView.setImageViewResource(R.id.notification_icon, R.drawable.icon);
//采用多条ACTION并且精简后的代码
notifyView.setOnClickPendingIntent(R.id.notification_goto_pause,
PendingIntent.getBroadcast(this, 0,
new Intent(LocalConst.NOTIFICATION_GOTO_PAUSE),
PendingIntent.FLAG_UPDATE_CURRENT));
notifyView.setOnClickPendingIntent(R.id.notification_goto_last,
PendingIntent.getBroadcast(this, 0,
new Intent(LocalConst.NOTIFICATION_GOTO_LAST),
PendingIntent.FLAG_UPDATE_CURRENT));
notifyView.setOnClickPendingIntent(R.id.notification_goto_next,
PendingIntent.getBroadcast(this, 0,
new Intent(LocalConst.NOTIFICATION_GOTO_NEXT),
PendingIntent.FLAG_UPDATE_CURRENT));
notifyView.setOnClickPendingIntent(R.id.notification_goto_play,
PendingIntent.getBroadcast(this, 0,
new Intent(LocalConst.NOTIFICATION_GOTO_PLAY),
PendingIntent.FLAG_UPDATE_CURRENT));
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.bottom)
.setContentTitle(playingFile.getName())
.setContentText(getResources().getString(R.string.notification_back_msg))
/**
* 非常奇怪,上面三个set不能省略,否则notification就不显示
* 但上面三项并不显示,因为使用了remoteView及其布局
*/
.setContent(notifyView);
Intent resultIntent = new Intent(this, DirPlayerActivity.class);
PendingIntent resultPendingIntent = PendingIntent.getActivity(this, 0,
resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
// Sets an ID for the notification
int mNotificationId = 001;
// Gets an instance of the NotificationManager service
NotificationManager mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Builds the notification and issues it.
mNotifyMgr.notify(mNotificationId, mBuilder.build());
}
}
最后一个陷阱是注册receiver不能使用LocalBroadcastManager
因为notification不在app进程之中
如下代码不能工作
/**
* notification上面的按键将发送intent给service
* notification上面其他部分被点击后发送pendingIntent给activity
*/
IntentFilter mNotificationIntentFilter = new IntentFilter(
LocalConst.NOTIFICATION_ACTION);
mNotificationInforReceiver =
new NotificationInforReceiver();
// Registers the DownloadStateReceiver and its intent filters
LocalBroadcastManager.getInstance(this).registerReceiver(
mNotificationInforReceiver,
mNotificationIntentFilter);
/**
* notification上面的按键将发送intent给service
* notification上面其他部分被点击后发送pendingIntent给activity
*/
IntentFilter mNotificationIntentFilter = new IntentFilter();
mNotificationIntentFilter.addAction(LocalConst.NOTIFICATION_GOTO_LAST);
mNotificationIntentFilter.addAction(LocalConst.NOTIFICATION_GOTO_NEXT);
mNotificationIntentFilter.addAction(LocalConst.NOTIFICATION_GOTO_PLAY);
mNotificationIntentFilter.addAction(LocalConst.NOTIFICATION_GOTO_PAUSE);
mNotificationInforReceiver =
new NotificationInforReceiver();
/**
* 注意,使用LocalBroadcastManager注册的receiver只能接收本app内部的intent
* 但notification在本app之外
* 所以这里需要直接使用registerReceiver来注册
*/
registerReceiver(
mNotificationInforReceiver,
mNotificationIntentFilter);