AlarmManager - Wakelock学习

Alarm Manager

- 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)

Wakelock

- 唤醒锁是一种让设备保持唤醒的机制

- 使用它需要权限: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

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);
                    }
                }
            });
        }

看门狗用来在应用程序进程被系统杀死之后重启服务,保证持续的按周期设定检查邮箱。如果没有发生,在下一次同步开始的时候会重设看门狗,总是设在当前时间之后600秒:

/**
     * 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);
                ...
            }
        }
    }

关于Intent的创建:

/**
     * 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;
    }


Exchange





你可能感兴趣的:(android,alarm,wakelock)