AlarmManager使用
AlarmManager是Android中常用的一種系統(tǒng)級(jí)別的提示服務(wù),在特定的時(shí)刻為我們廣播一個(gè)指定的Intent,為你的應(yīng)用設(shè)定一個(gè)在未來(lái)某個(gè)時(shí)間喚醒的功能。
當(dāng)鬧鐘響起,實(shí)際上是系統(tǒng)發(fā)出了為這個(gè)鬧鐘注冊(cè)的廣播,會(huì)自動(dòng)開(kāi)啟目標(biāo)應(yīng)用。
注冊(cè)的鬧鐘在設(shè)備睡眠的時(shí)候仍然會(huì)保留,可以選擇性地設(shè)置是否喚醒設(shè)備,但是當(dāng)設(shè)備關(guān)機(jī)和重啟后,鬧鐘將會(huì)被清除。
對(duì)于常規(guī)的短時(shí)間計(jì)時(shí)操作(ticks, timeouts, etc),使用Handler處理更加方便和有效率。
在alarm的receiver的onReceive()方法被執(zhí)行的時(shí)候,AlarmManager持有一個(gè)CPU喚醒鎖,這樣就保證了設(shè)備在處理完廣播之前不會(huì)sleep。一旦onReceive()方法返回,AlarmManager就會(huì)釋放這個(gè)鎖,表明一些情況下可能onReceive()方法一執(zhí)行完設(shè)備就會(huì)sleep。如果你的alarmreceiver中調(diào)用了Context.startService(),那么很可能service還沒(méi)起來(lái)設(shè)備就sleep了。為了阻止這種情況,你的BroadcastReceiver和Service需要實(shí)現(xiàn)不同的喚醒鎖機(jī)制,來(lái)確保設(shè)備持續(xù)運(yùn)行到service可用為止。
如果onReceive()方法里確實(shí)需要異步操作的話,可以用goAsync方法,然后在新開(kāi)一個(gè)線程去執(zhí)行。
如果onReceive()有過(guò)于耗時(shí)的操作,建議使用PendingIntent.getService()啟動(dòng)Service方式來(lái)完成。
BroadcastReceiver onReceive()使用goAsync 執(zhí)行異步操作例子:
@Overridepublic void onReceive(final Context context, final Intent intent) {final PendingResult result = goAsync();final PowerManager.WakeLock wl = AlarmAlertWakeLock.createPartialWakeLock(context);try {wl.acquire();} catch (Exception e) {e.printStackTrace();}AsyncHandler.post(new Runnable() {@Overridepublic void run() {LogUtils.writeAlarmLog("AlarmStateManager received intent " + intent);try {handleIntent(context, intent);result.finish();wl.release();} catch (Exception e) {e.printStackTrace();}}});}Alarm接口
1.cancel(PendingIntent operation)
?Remove any alarms with a matching Intent.
2.changeAlarmType(String pkgName, boolean wakeup)
3.getNextAlarmClock()
Gets information about the next alarm clock currently scheduled.
4.set(int type, long triggerAtMillis, PendingIntent operation)
Schedule an alarm.
5.setAlarmClock(AlarmManager.AlarmClockInfo info, PendingIntent operation)
Schedule an alarm that represents an alarm clock.
6.setExact(int type, long triggerAtMillis, PendingIntent operation)
Schedule an alarm to be delivered precisely at the stated time.
7.setInexactRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation)
Schedule a repeating alarm that has inexact trigger time requirements; for example, an alarm that repeats every hour, but not necessarily at the top of every hour.
8.setRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation)
Schedule a repeating alarm.
9.setTime(long millis)
Set the system wall clock time.
10.setTimeZone(String timeZone)
Set the system default time zone.
11.setWindow(int type, long windowStartMillis, long windowLengthMillis, PendingIntent operation)
Schedule an alarm to be delivered within a given window of time.
常用接口
1.public void?set/setExact(int type, long triggerAtMillis, PendingIntent operation)
?該方法用于設(shè)置一次性鬧鐘。
第一個(gè)參數(shù)int type 指定定時(shí)服務(wù)的類(lèi)型,該參數(shù)接受如下值:
ELAPSED_REALTIME:?在指定的延時(shí)過(guò)后,發(fā)送廣播,但不喚醒設(shè)備(鬧鐘在睡眠狀態(tài)下不可用)。如果在系統(tǒng)休眠時(shí)鬧鐘觸發(fā),它將不會(huì)被傳遞,直到下一次設(shè)備喚醒。
ELAPSED_REALTIME_WAKEUP:?在指定的延時(shí)過(guò)后,發(fā)送廣播,并喚醒設(shè)備(即使關(guān)機(jī)也會(huì)執(zhí)行operation所對(duì)應(yīng)的組件)。延時(shí)是要把系統(tǒng)啟動(dòng)的時(shí)間SystemClock.elapsedRealtime()算進(jìn)去的,具體用法看代碼。
RTC:?指定當(dāng)系統(tǒng)調(diào)用System.currentTimeMillis()方法返回的值與triggerAtTime相等時(shí)啟動(dòng)operation所對(duì)應(yīng)的設(shè)備(在指定的時(shí)刻,發(fā)送廣播,但不喚醒設(shè)備)。如果在系統(tǒng)休眠時(shí)鬧鐘觸發(fā),它將不會(huì)被傳遞,直到下一次設(shè)備喚醒(鬧鐘在睡眠狀態(tài)下不可用)。
RTC_WAKEUP:?指定當(dāng)系統(tǒng)調(diào)用System.currentTimeMillis()方法返回的值與triggerAtTime相等時(shí)啟動(dòng)operation所對(duì)應(yīng)的設(shè)備(在指定的時(shí)刻,發(fā)送廣播,并喚醒設(shè)備)。即使系統(tǒng)關(guān)機(jī)也會(huì)執(zhí)行 operation所對(duì)應(yīng)的組件。
第二個(gè)參數(shù)triggerAtMillis表示觸發(fā)鬧鐘的時(shí)間。
第三個(gè)參數(shù)PendingIntent pi表示鬧鐘響應(yīng)動(dòng)作:
PendingIntent pi:是鬧鐘的執(zhí)行動(dòng)作,比如發(fā)送一個(gè)廣播、給出提示等等。PendingIntent是Intent的封裝類(lèi)。需要注意的是:
啟動(dòng)服務(wù):如果是通過(guò)啟動(dòng)服務(wù)來(lái)實(shí)現(xiàn)鬧鐘提示的話,PendingIntent對(duì)象的獲取就應(yīng)該采用Pending.getService(Context c,int i,Intent intent,int j)方法;
啟動(dòng)廣播:如果是通過(guò)廣播來(lái)實(shí)現(xiàn)鬧鐘提示的話,PendingIntent對(duì)象的獲取就應(yīng)該采用PendingIntent.getBroadcast(Context c,inti,Intent intent,int j)方法;
啟動(dòng)activity:如果是采用Activity的方式來(lái)實(shí)現(xiàn)鬧鐘提示的話,PendingIntent對(duì)象的獲取就應(yīng)該采用PendingIntent.getActivity(Context c,inti,Intent intent,int j)方法。
如果這三種方法錯(cuò)用了的話,雖然不會(huì)報(bào)錯(cuò),但是看不到鬧鐘提示效果。
注意:AndroidL開(kāi)始,設(shè)置的alarm的觸發(fā)時(shí)間必須大于當(dāng)前時(shí)間 5秒
AlarmManagerService中是通過(guò)PendingItent來(lái)標(biāo)示一個(gè)Alarm的
2.public void?cancel?(PendingIntent operation)
移除intent相匹配的alarm(只要action,data, type,package,component,categories相等,就會(huì)被取消)。另外,應(yīng)用被forcestoppackage殺掉之后,所有的alarm都會(huì)被移除。
3.public void?setRepeating(int type,long startTime,long intervalTime,PendingIntent pi)
設(shè)置一個(gè)周期性執(zhí)行的定時(shí)服務(wù)。第一個(gè)參數(shù)表示鬧鐘類(lèi)型,第二個(gè)參數(shù)表示鬧鐘首次執(zhí)行時(shí)間,第三個(gè)參數(shù)表示鬧鐘兩次執(zhí)行的間隔時(shí)間,第三個(gè)參數(shù)表示鬧鐘響應(yīng)動(dòng)作。
注意:該方法提供了設(shè)置周期鬧鐘的入口,鬧鐘執(zhí)行時(shí)間嚴(yán)格按照startTime來(lái)處理,使用該方法需要的資源更多,不建議使用。
4.public void?setInexactRepeating(int type,long startTime,long intervalTime,PendingIntent pi)
該方法也用于設(shè)置重復(fù)鬧鐘,與第二個(gè)方法相似,不過(guò)其兩個(gè)鬧鐘執(zhí)行的間隔時(shí)間不是固定的而已。它相對(duì)而言更省電(power-efficient)一些,因?yàn)橄到y(tǒng)可能會(huì)將幾個(gè)差不多的鬧鐘合并為一個(gè)來(lái)執(zhí)行,減少設(shè)備的喚醒次數(shù)。第三個(gè)參數(shù)intervalTime為鬧鐘間隔,內(nèi)置的幾個(gè)變量如下:
INTERVAL_DAY:?設(shè)置鬧鐘,間隔一天
INTERVAL_HALF_DAY:?設(shè)置鬧鐘,間隔半天
INTERVAL_FIFTEEN_MINUTES:設(shè)置鬧鐘,間隔15分鐘
INTERVAL_HALF_HOUR:?設(shè)置鬧鐘,間隔半個(gè)小時(shí)
INTERVAL_HOUR:?設(shè)置鬧鐘,間隔一個(gè)小時(shí)
AndroidL開(kāi)始repeat的周期必須大于60秒
設(shè)置一個(gè)鬧鐘和取消一個(gè)鬧鐘的例子:
private static class AlarmManagerStateChangeScheduler implements StateChangeScheduler {@Overridepublic void scheduleInstanceStateChange(Context context, Calendar time,AlarmInstance instance, int newState) {long timeInMillis = time.getTimeInMillis();Intent stateChangeIntent = createStateChangeIntent(context, ALARM_MANAGER_TAG, instance,newState, VALUE_CHANGE_STATE_BY_SCHEDULE);// Treat alarm state change as high priority, use foreground broadcastsstateChangeIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);PendingIntent pendingIntent = PendingIntent.getService(context, instance.hashCode(),stateChangeIntent, PendingIntent.FLAG_UPDATE_CURRENT);//設(shè)置一個(gè)鬧鐘AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);if (CommonUtils.isMOrLater()) {am.setExactAndAllowWhileIdle(ReflectUtils.getRTC_BOOT_WAKEUP()/*AlarmManager.RTC_WAKEUP*/, timeInMillis, pendingIntent);LogUtils.writeAlarmLog("Scheduling state change success by setExactAndAllowWhileIdle");} else if (CommonUtils.isKitKatOrLater()) {am.setExact(ReflectUtils.getRTC_BOOT_WAKEUP()/*AlarmManager.RTC_WAKEUP*/, timeInMillis, pendingIntent);LogUtils.writeAlarmLog("Scheduling state change success by setExact");} else {am.set(AlarmManager.RTC_WAKEUP, timeInMillis, pendingIntent);LogUtils.writeAlarmLog("Scheduling state change success not KitKatOrLater");}}@Overridepublic void cancelScheduledInstanceStateChange(Context context, AlarmInstance instance) {LogUtils.writeAlarmLog("cancelScheduledInstance instance id = " + instance.mId);// Create a PendingIntent that will match any one set for this instancePendingIntent pendingIntent = PendingIntent.getService(context, instance.hashCode(),createStateChangeIntent(context, ALARM_MANAGER_TAG, instance, null, null),PendingIntent.FLAG_NO_CREATE);//取消一個(gè)鬧鐘if (pendingIntent != null) {AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);am.cancel(pendingIntent);pendingIntent.cancel();ReflectUtils.cancelOnePoweroffAlarm(am, pendingIntent);}}}總結(jié)
以上是生活随笔為你收集整理的AlarmManager使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 2021数学建模C题思路数据挖掘
- 下一篇: linux 固定ip_linux固定IP