在notification中设置PendingIntent



在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);

直接调用registerReceiver才能工作

		/**
		 * 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);




你可能感兴趣的:(Android)