问题描述

当我们需要周期性执行某操作时,就会用到AlarmManager,但是在小米的手机上(严格的说应该是小米Rom)执行周期太短的话,一旦系统休眠,AlarmManager就会失效。搜索结果来看,这个问题很普遍。发现是周期不能短于5分钟,否则不会唤醒系统。

解决方案

这个问题主要是因为我们大多数人使用了type=AlarmManager.RTC_WAKEUP,希望系统休眠后到达指定时间唤醒设备执行操作,而且周期短于5分钟。小米Rom的考虑节能省电,一旦系统休眠,不会频繁唤醒系统。

类型说明:

/**
     * Alarm time in {@link System# currentTimeMillis System.currentTimeMillis()}
     * (wall clock time in UTC), which will wake up the device when
     * it goes off.
     */
    public static final int RTC_WAKEUP = 0;
    /**
     * Alarm time in {@link System# currentTimeMillis System.currentTimeMillis()}
     * (wall clock time in UTC).  This alarm does not wake the
     * device up; if it goes off while the device is asleep, it will not be
     * delivered until the next time the device wakes up.
     */
    public static final int RTC = 1;
    /**
     * Alarm time in {@link android.os.SystemClock# elapsedRealtime
     * SystemClock.elapsedRealtime()} (time since boot, including sleep),
     * which will wake up the device when it goes off.
     */
    public static final int ELAPSED_REALTIME_WAKEUP = 2;
    /**
     * Alarm time in {@link android.os.SystemClock# elapsedRealtime
     * SystemClock.elapsedRealtime()} (time since boot, including sleep).
     * This alarm does not wake the device up; if it goes off while the device
     * is asleep, it will not be delivered until the next time the device
     * wakes up.
     */
    public static final int ELAPSED_REALTIME = 3;
AlarmManager.ELAPSED_REALTIME; //时间流逝时间,即相对于系统启动时间,睡眠时间考虑在内,睡眠状态不可用  
AlarmManager.ELAPSED_REALTIME_WAKEUP; //时间流逝时间,即相对于系统启动时间,睡眠时间考虑在内,睡眠状态下唤醒  
AlarmManager.RTC; //硬件时间,即系统时间,睡眠状态不可用  
AlarmManager.RTC_WAKEUP; //硬件时间,即系统时间,睡眠状态下唤醒

所以在小米的Rom中,RTC和RTC_WAKEUP在周期小于5分钟并且手机休眠的情况下,效果是一样的。所以我们能做的就尽量使周期间隔在系统休眠时大于5分钟。

结语

从实际使用和省电的角度考虑,这样做确实比较合理。应用打开期间,周期间隔可以短些,应用一旦放到后台,就应该把周期放长。但是小米的做法既是优化,又是对Android的碎片化,加重了开发者的负担,增加了开发成本。国内厂商的Rom很多深度定制导致了开发中会遇到形形色色的bug。。