AlarmManager是Android的全局定時器。就是在指定時間做一個事情(封裝在PendingIntent)。通過PendingIntent的getActivity()、getService()或getBroadcast()來執行。
聽起來AlarmManager和Timer很類似,但是Timer有可能因為手機休眠而被殺掉服務,但是AlarmManager可以做到喚醒手機。
創建方式
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
注:ALARM_SERVIC是context的一個常量。
鬧鍾類型
- RTC_WAKEUP
表示鬧鍾在睡眠狀態下喚醒系統並執行提示功能,絕對時間。 - RTC
睡眠狀態下不可用,絕對時間。 - ELAPSED_REALTIME_WAKEUP
睡眠狀態下可用,相對時間。 - ELAPSED_REALTIME
睡眠狀態下不可用,相對時間。
以上絕對時間就是手機的時間,相對時間是相對於當前開機時間來說。例如如果是絕對時間,那么你測試可以通過修改系統時間來提前觸發。而相對時間的使用場景是強調多久之后觸發,例如2小時后,這個時候把時間修改到2小時后也是沒用的。
注:以前還有一個POWER_OFF_WAKEUP,即使在關機后還能提醒,但是Android4.0以后就沒有了。
常用方法
set(int type, long triggerAtMillis, PendingIntent operation)
該方法用於設置一次性鬧鍾。第一個參數是鬧鍾類型,第二個參數是觸發時間,第三個參數是動作。
setExact(int type, long triggerAtMillis, PendingIntent operation)
和set一樣,但是時間更精准。
setInexactRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation)
重復鬧鍾,第1、2、4個參數同上,第3個參數是兩次鬧鍾的時間間隔。
setRepeating(int type, long triggerAtMillis,long intervalMillis, PendingIntent operation)
和setInexactRepeating一樣,但是時間更精准。
以上四個方法時間精不精准的原因還沒有深入研究,大概是是否允許系統同時發出多個提醒,意義在於系統喚醒cpu后會把時間接近的alarm同時發出,避免重復喚醒cpu,減少電量。
cancel(PendingIntent operation)
取消鬧鍾。
寫個小程序實驗一下
目的:在指定時間從一個發送個廣播,收到廣播后打印log。界面如下面這樣。

布局:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.xuhongchuan.alarmclocktest.MainActivity"> <LinearLayout android:id="@+id/view_group1" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TimePicker android:id="@+id/time_picker" android:layout_width="match_parent" android:layout_height="wrap_content"> </TimePicker> </LinearLayout> <LinearLayout android:id="@+id/view_group2" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:orientation="horizontal" android:layout_below="@id/view_group1"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="是否重復"/> <CheckBox android:id="@+id/checkbox" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> <Button android:id="@+id/confirm" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/view_group2" android:text="確定" /> </RelativeLayout>
廣播接收器:
public class AlarmReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action == MainActivity.INTENT_ALARM_LOG) { Log.d("AlarmReceiver", "log log log"); } } }
MainActivity
public class MainActivity extends AppCompatActivity { public static final String INTENT_ALARM_LOG = "intent_alarm_log"; private TimePicker timePicker; private CheckBox checkBox; private Button btnConfirm; private int hour; private int minute; AlarmManager am; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); } private void init() { timePicker = (TimePicker) findViewById(R.id.time_picker); timePicker.setIs24HourView(true); checkBox = (CheckBox) findViewById(R.id.checkbox); btnConfirm = (Button) findViewById(R.id.confirm); am = (AlarmManager) getSystemService(ALARM_SERVICE); btnConfirm.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (Build.VERSION.SDK_INT >= 23) { hour = timePicker.getHour(); minute = timePicker.getMinute(); } else { hour = timePicker.getCurrentHour(); minute = timePicker.getCurrentMinute(); } Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.HOUR_OF_DAY, hour); calendar.set(Calendar.MINUTE, minute); calendar.set(Calendar.SECOND, 0); Intent intent = new Intent(INTENT_ALARM_LOG); PendingIntent pi = PendingIntent.getBroadcast(MainActivity.this, 0, intent, 0); if (!checkBox.isChecked()) { am.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pi); } else