当手机睡眠时,AlarmManager.setExact在Kitkat中仍然不准确

Per*_*rry 1 android alarmmanager android-4.4-kitkat

我几天都在使用AlarmManager.setExact().我的应用程序需要精确的警报,并且可以使用AlarmManager.setRepeating()在旧的Androids上正常工作.

我已经读过自API 19以来它已经改变并相应地更新了我的代码.

以下是负责设置警报的代码:

PendingIntent pi = PendingIntent.getBroadcast(context.getApplicationContext(), alarmOrder+1, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        getAlarmManager(context).setExact(AlarmManager.RTC_WAKEUP, alarmTimeMillis, pi);
    }
    else {
        getAlarmManager(context).setRepeating(AlarmManager.RTC_WAKEUP, alarmTimeMillis, AlarmManager.INTERVAL_DAY, pi);
    }
Run Code Online (Sandbox Code Playgroud)

广播接收器通过报警屏幕启动新活动:

@Override
public void onReceive(Context context, Intent intent) {
    PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
    PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AlarmTimeReceiver");
    wl.acquire();

    Intent alarmIntent = new Intent(context, AlarmActivity.class);
    alarmIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
    context.startActivity(alarmIntent);

    //Release the lock
    wl.release();
}
Run Code Online (Sandbox Code Playgroud)

问题是,在通过USB线连接的Android 4.4设备上进行测试时,一切正常.报警始终在指定的时间开始(屏幕打开/关闭).不幸的是,当我从计算机断开设备时,只有在打开屏幕时才能正确启动警报.当我关闭屏幕时,警报会在不准确的时间内启动.

我错过了什么吗?你们有没有经历过类似的情况?

Com*_*are 5

它在Android <19上正确运行

并不是的.

一个_WAKEUP报警的保证-通过框架管理WakeLock-该设备将保持清醒,直到onReceive()回报.然后,框架释放WakeLock,并且设备可以重新入睡...如果没有其他未完成的WakeLocks.

WakeLock正如所写的那样,你的意义毫无意义.它只是复制框架管理WakeLock而不增加价值.

startActivity()异步的.活动将不会在时间onReceive()结束时接近启动,并且框架管理WakeLock(以及您的附加版本)将被释放.现在,有时,您的活动将有机会启动,因为设备不会很快回来睡着.我假设你android:keepScreenOn在活动中使用或等效,所以一旦你到达那一点,还有另一个WakeLock未完成的,并且设备不能自动回退.

但是,有时设备在您的活动开始之前确实会睡着了.可能与Android 5.0已经改变-如果Android是更积极的关于把设备返回更快地入睡它不会在最让我感到惊讶.因此,虽然您之前的方法可能在90%的时间内都有效,但现在可能要少得多.但是,您以前的方法在100%的时间内都不起作用.

我们看到与服务相同的事情.事实上,这种情况在那里更为常见.这就是为什么,早在2009年4月,我创建WakefulIntentService,以及为什么在2013年8月谷歌发布WakefulBroadcastReceiver.两者都提供了获取输入的模式WakeLock,onReceive()但在服务工作完成之前不会释放它.

这些解决方案都不适合您,因为两者都与服务密不可分.但是,您可以将它们作为创建自己的想法来源.您需要将您移动WakeLock到一个静态数据成员(ick),并且只有release()在您的活动足够远以至于它有自己的活动时才会移动它WakeLock.例如,如果你调用setKeepScreenOn()一个View在Java代码中,一旦做到这一点,我希望它是安全的释放你的原始WakeLock.然后,框架可以WakeLock根据用户输入接管并释放保持屏幕.