使用PendingIntent結合 alarmManager 傳送定時廣播,收到廣播的時候顯示notification的功能,遇到了好多坑。
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以上隱式廣播限制
以前只要設定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結合鬧鐘 使用遇到的最大的問題是,如果把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
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);
}