原文链接:
https://www.itread01.com/content/1542816187.html
转载自https://www.itread01.com/content/1542816187.html
PendingIntent, Notification,broadcastReceiver使用遇到的坑
使用PendingIntent结合 alarmManager 传送定时广播,收到广播的时候显示notification的功能,遇到了好多坑。
先上程式码:
一、pendingIntent结合闹钟传送定时广播
Intent intent = new Intent(KeyVaule.CLOCK_IN_ACTION_NAME);
intent.putExtra(KeyName.SOURCE, KeyVaule.MANUAL_CLOCK_IN);
intent.putExtra(KeyName.CARD_NO, cardNo);
intent.putExtra(KeyName.TARGET_TIME, targetTime + "");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
ComponentName componentName = new ComponentName(context.getPackageName(),context.getPackageName() + ".receiver.AlarmReceiver");
intent.setComponent(componentName);
}
//todo 问题:flag为PendingIntent.FLAG_UPDATE_CURRENT 可以更新发送intent的内容
//todo 问题:requestcode 不变的话,最新的intent会覆蓋之前的
PendingIntent pi = PendingIntent.getBroadcast(context, 3, intent, PendingIntent.FLAG_UPDATE_CURRENT);
//PendingIntent 和 闹钟 结合传送 定时广播
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
am.setExact(AlarmManager.RTC_WAKEUP, targetTime, pi);
} else {
am.set(AlarmManager.RTC_WAKEUP, targetTime, pi);
}
二、广播接收器
public class AlarmReceiver extends BroadcastReceiver {
private static final long TEN_HOUR = 10 * 60 * 60 * 1000;
@Override
public void onReceive(Context context, final Intent intent) {
showNotification(context);
}
private void showNotification(Context context) {
String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(System.currentTimeMillis());
NotificationCompat.Builder builder;
NotificationManager notifManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
String id = "channel_01";
String name = "channel_name";
if (notifManager == null) {
notifManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_LOW;
NotificationChannel mChannel = notifManager.getNotificationChannel(id);
if (mChannel == null) {
mChannel = new NotificationChannel(id, name, importance);
mChannel.setDescription("");
notifManager.createNotificationChannel(mChannel);
}
builder = new NotificationCompat.Builder(context, id);
builder.setContentTitle("收到打卡闹钟") // required
.setSmallIcon(R.mipmap.clock) // required
.setContentText("打卡时间:" + time) // required
.setDefaults(Notification.DEFAULT_ALL)
.setAutoCancel(true)
.setTicker("收到打卡闹钟");
} else {
builder = new NotificationCompat.Builder(context);
builder.setContentTitle("收到打卡闹钟") // required
.setSmallIcon(R.mipmap.clock) // required
.setContentText("打卡时间:" + time) // required
.setDefaults(Notification.DEFAULT_ALL)
.setAutoCancel(true)
.setTicker("收到打卡闹钟")
.setPriority(Notification.PRIORITY_HIGH);
}
Notification notification = builder.build();
notifManager.notify(111, notification);
}
}
一、8.0以上传送普通广播必须指明receiver
以前只要设定action隐式广播就可以接收到,8.0以上不可以了,需要指明接收器的包名。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
ComponentName componentName = new ComponentName(context.getPackageName(),context.getPackageName() + ".receiver.AlarmReceiver");
intent.setComponent(componentName);
}
二、PendingIntent的 requestcode 和flag 引数的影响
pendingintent 的requestcode和flag影响
pendingIntent结合闹钟 使用遇到的最大的问题是,如果把APPkill了,receiver就接收不到广播了!!!应该说闹钟到了,广播发送了,但是receiver被销毁了啊,接收不到广播了??求路过的大神给解释下!
// 获取 Broadcast 关联的 PendingIntent
PendingIntent.getBroadcast(Context context, int requestCode, Intent intent, int flags)
// 获取 Activity 关联的 PendingIntent
PendingIntent.getActivity(Context context, int requestCode, Intent intent, int flags)
PendingIntent.getActivity(Context context, int requestCode, Intent intent, int flags, Bundle options)
// 获取 Service 关联的 PendingIntent
PendingIntent.getService(Context context, int requestCode, Intent intent, int flags)
1、使用alarmManager,通过PendingIntent向broadcastReceiver传递内容。
第二个引数requestCode相同的话后面的定时器会将前面的定时器"覆蓋"掉,只会启动最后一个定时器,
所以同一时间的定时器可以用同一个requestCode,不同时间的定时器用不同的requestCode。
2、使用notification,通过PendingIntent向Activity传递内容。
第二个引数requestCode不同,以及设定最后一个flags引数为PendingIntent.FLAG_UPDATE_CURRENT可以
保证每次点选notification进入activity,传的引数都是当前这个notification传过去的(Intent里附带
的引数)。如果requestCode相同,最后一个引数为PendingIntent.FLAG_UPDATE_CURRENT,那么所有未
点选的notification里的引数都会被更新为最后一个传过去的,也就是最新的。
flags的取值有四个:
FLAG_ONE_SHOT:获取的PendingIntent只能使用一次
FLAG_NO_CREATE:利用FLAG_NO_CREAT获取的PendingIntent,若描述的Intent不存在则返回NULL值
FLAG_CANCEL_CURRENT:如果描述的PendingIntent已经存在,则在产生新的Intent之前会先取消掉当前的
FLAG_UPDATE_CURRENT:能够新new一个 Intent
三、8.0以上使用notification必须要设定NotificationChannel
private void showNotification(Context context) {
String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(System.currentTimeMillis());
NotificationCompat.Builder builder;
NotificationManager notifManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
String id = "channel_01";
String name = "channel_name";
if (notifManager == null) {
notifManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_LOW;
NotificationChannel mChannel = notifManager.getNotificationChannel(id);
if (mChannel == null) {
mChannel = new NotificationChannel(id, name, importance);
mChannel.setDescription("");
notifManager.createNotificationChannel(mChannel);
}
builder = new NotificationCompat.Builder(context, id);
builder.setContentTitle("收到闹钟") // required
.setSmallIcon(R.mipmap.clock) // required
.setContentText("时间:" + time) // required
.setDefaults(Notification.DEFAULT_ALL)
.setAutoCancel(true)
.setTicker("收到闹钟");
} else {
builder = new NotificationCompat.Builder(context);
builder.setContentTitle("收到闹钟") // required
.setSmallIcon(R.mipmap.clock) // required
.setContentText("时间:" + time) // required
.setDefaults(Notification.DEFAULT_ALL)
.setAutoCancel(true)
.setTicker("收到闹钟")
.setPriority(Notification.PRIORITY_HIGH);
}
Notification notification = builder.build();
notifManager.notify(111, notification);
}