需求:應用啟動時檢查之前設置的鬧鐘是否仍在系統中處於啟動狀態,若無則重新設置。
鬧鐘由 PendingIntent 標識,**相同 requestCode + action + data 的 PendingIntent 視為同一鬧鐘**。
public boolean isAlarmActive(Context context, String action, int requestCode) {
Intent intent = new Intent(action);
// FLAG_NO_CREATE:若不存在則返回 null,不創建新對象
PendingIntent pi = PendingIntent.getBroadcast(context, requestCode, intent,
PendingIntent.FLAG_NO_CREATE | PendingIntent.FLAG_IMMUTABLE);
return pi != null;
}
public void setAlarm(Context context, String action, int requestCode, long triggerAtMillis) {
Intent intent = new Intent(action);
// FLAG_UPDATE_CURRENT:若存在則更新 Intent 內容(如 extras)
PendingIntent pi = PendingIntent.getBroadcast(context, requestCode, intent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAtMillis, pi);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
am.setExact(AlarmManager.RTC_WAKEUP, triggerAtMillis, pi);
} else {
am.set(AlarmManager.RTC_WAKEUP, triggerAtMillis, pi);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String action = "com.vit.upload";
int requestCode = 12345; // 固定唯一值
long nextTrigger = System.currentTimeMillis() + 30 * 60 * 1000; // 30 分鐘後
if (!isAlarmActive(this, action, requestCode)) {
setAlarm(this, action, requestCode, nextTrigger);
Log.d("Alarm", "Alarm not active, reset.");
} else {
Log.d("Alarm", "Alarm already active.");
}
}
setExactAndAllowWhileIdle 確保準時喚醒。BOOT_COMPLETED 接收器中恢復。掌握 PendingIntent 唯一性原理,精準控制鬧鐘生命周期。