Android 确切警报总是关闭 3 分钟

Android exact Alarm is always 3 minutes off

我有一个应用程序使用 AlarmManager 定期在整点唤醒 phone 并向 Android Wear 手表发送消息,然后手表会发出短暂的振动。我有两个用户使用 Samsung Galaxy S6 库存 Android 5.1.1 和 Sony SW 3 5.1.1,他们遇到了一个奇怪的错误。在第一个完整的小时内,振动会在准确的时间发生,但所有其他振动都会延迟 3 分钟。有时甚至第一个整点的振动都会延迟。

这是一些代码:

final Calendar time = Calendar.getInstance();
time.set(Calendar.SECOND, 0);
time.set(Calendar.MILLISECOND, 0);
time.set(Calendar.MINUTE, 0);
time.set(Calendar.HOUR_OF_DAY, time.get(Calendar.HOUR_OF_DAY) + 1);

final Intent hourlyChimeIntent = new Intent(context, HourlyChimeReceiver.class);
hourlyChimeIntent.setAction(key);
final AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
final PendingIntent pi = PendingIntent.getBroadcast(context, 0, hourlyChimeIntent, PendingIntent.FLAG_CANCEL_CURRENT);
am.setExact(AlarmManager.RTC_WAKEUP, time.getTimeInMillis(), pi);

我在接收器中获取了一个WakeLock,然后在一个线程中向Wear watch发送消息。没有遗漏任何振动,他们只是迟到了3分钟。

我没有关于此问题的其他报告,我所有的测试设备都运行良好。不过我没有三星设备。

有什么想法会导致 3 分钟的延迟吗?三星会忽略 setExact 并使我的警报不准确吗?如何在三星手机上强制发出准确的警报?

编辑:

这里是 Android Wear 特定代码。在接收者的 onReceive 方法中,我这样做:

final PowerManager mgr = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
final PowerManager.WakeLock lock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, BuildConfig.APPLICATION_ID);
lock.acquire(7L * 1000L);

final GoogleApiClient googleApiClient = new GoogleApiClient.Builder(context).addApi(Wearable.API).build();

new Thread(new Runnable() {
    @Override
    public void run() {
        googleApiClient.blockingConnect();

        long pattern[];
        pattern = new long[] {0L, 500L};

        final NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(googleApiClient).await(2000L, TimeUnit.MILLISECONDS);

        if (nodes != null) {
            for (final Node node : nodes.getNodes()) {
                // just send and forget
                Wearable.MessageApi.sendMessage(googleApiClient, node.getId(), "/hourly_chime", Utils.Vibrator.serializeVibratePattern(pattern).getBytes()).await();
            }
        }
    }
}).start();

此问题似乎只发生在装有 Lollipop(5.0、5.1、5.1.1)的三星设备(例如 Galaxy Grand、S4、S5、S6、Note 3、Note 4)上。当设备使用电池供电且屏幕关闭时,警报的安排似乎不准确。如果设备正在充电或在安排闹钟期间屏幕打开,则不会出现此问题。

您可以验证下一个警报是否不准确:

adb shell dumpsys alarm

我没有找到这个问题的完美解决方案 - 只有每个都有一些缺点的解决方法:

  1. 使用 setAlarmClock 代替 setExact(参见 )。这工作得很好(不是在所有设备上),但这个解决方案的问题是闹钟会通过在状态栏中显示闹钟图标(如果有人还没有设置闹钟)和显示下一个闹钟预定时间来影响系统在闹钟小部件等上。不幸的是,虽然这适用于 5.1.1 的 Galaxy Grand,但不适用于 5.0.1 的 Galaxy S4。
  2. 在安排闹钟之前启用屏幕(我在安排下一个闹钟之前这样做了半秒以避免竞争情况)。当然,并不是每个应用程序都启用屏幕只是为了安排下一个闹钟。
  3. 一个bug report describing similar issue与应用程序包名称长度相关联!我没有验证它是否真的解决了问题,因为更改包名称不是已经发布的应用程序的选项。
  4. another report 有人声称可以使用 WakefulBroadcastReceiver 解决此问题,但在我的情况下不起作用。

顺便说一句,这个问题让我抓狂:)

编辑:当应用程序包名称中有关键字 "alarm" 或 "alert" 时,似乎不会出现此问题(正如 Mathieu 所指出的) H. 在下面的评论中)。

我还可以通过在电池设置(或智能管理器应用程序)中禁用应用程序优化 来手动解决该问题。似乎无法以编程方式完成,因此您可以尝试询问您的用户...