- AlarmManager提供对系统alarm服务的访问。
- Alarm Manager在alarm receiver的onReceive()方法执行期间持有一个CPU唤醒锁,以保证完成处理广播。方法返回,则释放唤醒锁,设备即可睡去。
- 这导致,如果你在处理广播时调用了Context.startService(),则手机可能会在服务起来之前睡去。所以必须实现独立的唤醒锁策略,使手机在服务起来之前保持运转。
- Alarm Manager主要用来使你的程序代码在指定的事件运行,即使你的应用当前没有运行。其它普通的计时操作用Handler来实现更为简便高效。
- Context.getSystemService(Context.ALARM_SERVICE)
.
几个常量:
- AlarmManager.RTC_WAKEUP: 唤醒设备,按System.currentTimeMills()计时
- AlarmManager.RTC:不唤醒设备,直到设备下次被唤醒时才发送
- AlarmManager.ELAPSED_REALTIME_WAKEUP:到时唤醒设备,按开机时间计时
- AlarmManager.ELAPSED_REALTIME:按开机时间计时,其余同2
提供的方法:
- 设置一个闹钟
void set(int type, long triggerAtMillis, PendingIntent operation) |
void setInexactRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation) |
void setRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation) |
void setTime(long millis) |
void setTimeZone( String timeZone) |
cancel( PendingIntent operation) |
- 唤醒锁是一种让设备保持唤醒的机制
- 使用它需要权限:android.permission.WAKE_LOCK
- 用完立即释放
- 用法
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag"); wl.acquire(); ..screen will stay on during this section.. wl.release();
Email应用通过一个名叫MailService的服务来进行邮件帐户的刷新操作:
if (ACTION_CHECK_MAIL.equals(action)) { // DB access required to satisfy this intent, so offload from UI thread EmailAsyncTask.runAsyncParallel(new Runnable() { @Override public void run() { ...
// 设置一个看门狗 if (accountId >= 0) { setWatchdog(accountId, alarmManager); } // 对帐户进行同步 syncStarted = syncOneAccount(mController, accountId, ... // 设置下一个要同步的帐户 reschedule(alarmManager);
// Stop the service, unless actually syncing (which will stop the service) stopSelf(startId); } } }); }
/** * Create a watchdog alarm and set it. This is used in case a mail check fails (e.g. we are * killed by the system due to memory pressure.) Normally, a mail check will complete and * the watchdog will be replaced by the call to reschedule(). * @param accountId the account we were trying to check * @param alarmMgr system alarm manager */ private void setWatchdog(long accountId, AlarmManager alarmMgr) { PendingIntent pi = createAlarmIntent(accountId, null, true); long timeNow = SystemClock.elapsedRealtime(); long nextCheckTime = timeNow + WATCHDOG_DELAY; alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, nextCheckTime, pi); }
/** * Create and send an alarm with the entire list. This also sends a list of known last-sync * times with the alarm, so if we are killed between alarms, we don't lose this info. * * @param alarmMgr passed in so we can mock for testing. */ private void reschedule(AlarmManager alarmMgr) { ... synchronized (mSyncReports) { ... // set/clear alarm as needed long idToCheck = (nextAccount == null) ? -1 : nextAccount.accountId; PendingIntent pi = createAlarmIntent(idToCheck, accountInfo, false); if (nextAccount == null) { alarmMgr.cancel(pi); ... } else { alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, nextCheckTime, pi); ... } } }
/** * Return a pending intent for use by this alarm. Most of the fields must be the same * (in order for the intent to be recognized by the alarm manager) but the extras can * be different, and are passed in here as parameters. */ private PendingIntent createAlarmIntent(long checkId, long[] accountInfo, boolean isWatchdog) { Intent i = new Intent(); i.setClass(this, MailService.class); i.setAction(ACTION_CHECK_MAIL); i.putExtra(EXTRA_ACCOUNT, checkId); i.putExtra(EXTRA_ACCOUNT_INFO, accountInfo); if (isWatchdog) { i.putExtra(EXTRA_DEBUG_WATCHDOG, true); } PendingIntent pi = PendingIntent.getService(this, 0, i, PendingIntent.FLAG_UPDATE_CURRENT); return pi; }