如何知道通知栏的展示的 Notification 被点击了?
在某些业务需求下,我们需要知道用户是否点击了通知栏,但是察看 Notifycation 和 NotifycationManager 里面都没有相关方法来设置点击监听器!
那怎么办?
Notifycation 本来就需要我们给他设置一个 Intent 来执行点击之后的动作,这个 Intent 通过 PendingIntent 赋予。
关于 PendingIntent 刚接触可能会觉得不理解,官方解释:A description of an Intent and target action to perform with it. 即将要执行的动作
我们先从区别上来看他们:
1.普通的 Intent 我们发出去之后立马就执行了,比如 startActivity(new Intent(Intent.ACTION_VIEW, Uri.parser("http://baidu.com"))) 之后立马就跳到浏览器打开百度首页了
2.Notifycation 发出去之后用户什么时候点击是不确定的,我们先将点击之后要执行的 Intent 保存下来,等到用户点击之后在取出来执行,那用什么来保存 Intent 呢?PendingIntent(注:我这里为了方便理解而这样解释,事实上 PendingIntent 远比保存 Intent 复杂,涉及跨进程)
而,Intent 本身实现了 Parcelable 接口,可以用来跨进程传输,所以我们可以通过 Intent.putExtra("name", intemt) 将真正要执行的 Intent 保存在 clickIntent 对象里!
// 自定义显示的通知 ,创建RemoteView对象
private synchronized void showCustomizeNotification(Context context,
String contentTitle, String contentText, Intent intent, int type) {
int icon = R.drawable.ic_launcher;
long when = new Date().getTime() / 1000;
Notification noti = new Notification(icon, contentTitle, when);
noti.flags = Notification.FLAG_AUTO_CANCEL;
noti.defaults = Notification.DEFAULT_ALL;// 开启铃声
// 1、创建一个自定义的消息布局 view.xml
// 2、在程序代码中使用RemoteViews的方法来定义image和text。然后把RemoteViews对象传到contentView字段
RemoteViews remoteView = new RemoteViews(context.getPackageName(),
R.layout.notification);
remoteView.setImageViewResource(R.id.notification_img,
R.drawable.ic_launcher);
remoteView.setTextViewText(R.id.notification_title, contentTitle);
remoteView.setTextViewText(R.id.notification_txt, contentText);
remoteView.setTextViewText(R.id.notification_time,
getTime(String.valueOf(when)));
noti.contentView = remoteView;
// 3、为Notification的contentIntent字段定义一个Intent(注意,使用自定义View不需要setLatestEventInfo()方法)
Intent clickIntent = new Intent();
clickIntent.setClass(context, ClickReceiver.class);
clickIntent.putExtra("realIntent", intent);
PendingIntent contentIntent = PendingIntent.getBroadcast(context, type,
clickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
noti.contentIntent = contentIntent;
NotificationManager mnotiManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
mnotiManager.notify(type, noti);
// Intent mIntent = new Intent(AppContext.REMOVE_WARN_RECORD);
// sendStickyBroadcast(mIntent);
}
当用户点击 Notifycation 之后,系统调用 ClickReceiver 的 onReceiver() 方法,你在此时执行真正的点击逻辑就OK,看码:
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class ClickReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancelAll();
Intent realIntent = intent.getParcelableExtra("realIntent");
context.startActivity(realIntent);
}
}
1.千万注意别忘记了广播在androidmainfest.xml中注册
2.在 onReceiver 的 context 直接启动 Activity 是会报错的,需要给 Intent 加上 Intent.FLAG_ACTIVITY_NEW_TASK 标志!