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的檔案路徑。