1.使用AlarmManager建立或取消定時廣播
首先必須先建立定時廣播的時間
private static Calendar generateAlarmTime() { Calendar reminderTime = Calendar.getInstance(); reminderTime.setTimeInMillis(System.currentTimeMillis()); long systemTime = System.currentTimeMillis(); //同步目前時間 reminderTime.setTimeInMillis(System.currentTimeMillis()); // 設定時區避免時差 reminderTime.setTimeZone(TimeZone.getTimeZone("GMT+8")); reminderTime.set(Calendar.HOUR_OF_DAY, 10); reminderTime.set(Calendar.MINUTE, 30); reminderTime.set(Calendar.SECOND, 0); reminderTime.set(Calendar.MILLISECOND, 0); long selectTime = reminderTime.getTimeInMillis(); // 如果現在時間大於設定的時間,就從第2天的設定時間開始 if (systemTime > selectTime) { reminderTime.add(Calendar.DAY_OF_MONTH, 1); } return reminderTime; }
第9~12行即為設定定時廣播的時間,時間為早上10點30分。
時間設定之後便可透過AlarmManager來發送定時廣播。
private static void setAlarmTime(Context context, Calendar alarmTime) { Intent intent = new Intent(context, CycleAlarmReceiver.class); PendingIntent pendingIntent = PendingIntent .getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE); final int millisecondPerDay = 1000 * 60 * 60 * 24; alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, alarmTime.getTimeInMillis(), millisecondPerDay, pendingIntent); }
這裡需要注意不少地方,第2行CycleAlarmReceiver.class為自定義的Receiver,用途為定時的時間啟動後,該Receiver的onReceiver方法就會被呼叫。
第3~4行需要注意getBroadcaset方法的第2個參數和第4個參數。
第2個參數是用來識別pendingIntent是哪一個,也就是當建立一個定時廣播之後,想要取消掉該廣播或想對該廣播做修改,必須指定是哪一個廣播。以範例來說就是指定0號廣播。
第4個參數表示意義如下
FLAG_CANCEL_CURRENT:如果当前系统中已经存在一个相同的PendingIntent对象,那么就将先将已有的PendingIntent取消,然后重新生成一个PendingIntent对象。
FLAG_NO_CREATE:如果当前系统中不存在相同的PendingIntent对象,系统将不会创建该PendingIntent对象而是直接返回null。
FLAG_ONE_SHOT:该PendingIntent只作用一次。在该PendingIntent对象通过send()方法触发过后,PendingIntent将自动调用cancel()进行销毁,那么如果你再调用send()方法的话,系统将会返回一个SendIntentException。
FLAG_UPDATE_CURRENT:如果系统中有一个和你描述的PendingIntent对等的PendingInent,那么系统将使用该PendingIntent对象,但是会使用新的Intent来更新之前PendingIntent中的Intent对象数据,例如更新Intent中的Extras。
最後是第7行的setRepeat方法,該方法表示這個alarm會重複啟動,而啟動的間隔時間為第3個參數,第3個參數代表每隔一天啟動。
綜合以上2個方法如下
private static void addReminder(Context context) { Calendar alarmTime = generateAlarmTime(); setAlarmTime(context, alarmTime); }
完整類別如下
public class AlarmTimeManager { private static Calendar generateAlarmTime() { Calendar reminderTime = Calendar.getInstance(); reminderTime.setTimeInMillis(System.currentTimeMillis()); long systemTime = System.currentTimeMillis(); //同步目前時間 reminderTime.setTimeInMillis(System.currentTimeMillis()); // 設定時區避免時差 reminderTime.setTimeZone(TimeZone.getTimeZone("GMT+8")); reminderTime.set(Calendar.HOUR_OF_DAY, 10); reminderTime.set(Calendar.MINUTE, 30); reminderTime.set(Calendar.SECOND, 0); reminderTime.set(Calendar.MILLISECOND, 0); long selectTime = reminderTime.getTimeInMillis(); // 如果現在時間大於設定的時間,就從第2天的設定時間開始 if (systemTime > selectTime) { reminderTime.add(Calendar.DAY_OF_MONTH, 1); } return reminderTime; } private static void setAlarmTime(Context context, Calendar alarmTime) { Intent intent = new Intent(context, CycleAlarmReceiver.class); PendingIntent pendingIntent = PendingIntent .getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE); final int millisecondPerDay = 1000 * 60 * 60 * 24; alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, alarmTime.getTimeInMillis(), millisecondPerDay, pendingIntent); } public static void addReminder(Context context) { Calendar alarmTime = generateAlarmTime(); setAlarmTime(context, alarmTime); } }
2.當setRepeat完成後,alarm時間(早上10點30分)一到便會發送通知給CycleAlarmReceiver。
public class CycleAlarmReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Toast.makeText(context, "alarm 啟動", Toast.LENGTH_SHORT).show(); } }
onReceive被呼叫後便會顯示一個toast
注意CycleAlarmReceiver必須在AndroidManifest.xml註冊。
<receiver android:name=".alarm.CycleAlarmReceiver"> </receiver>
android:name必須指定CycleAlarmReceiver的檔案路徑。