Android 精确闹钟总是关闭 3 分钟 [英] Android exact Alarm is always 3 minutes off

查看:32
本文介绍了Android 精确闹钟总是关闭 3 分钟的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个应用程序,它使用 AlarmManager 定期在整整一小时唤醒手机并向 Android Wear 手表发送消息,然后发出短促的振动.我有两个用户使用三星 Galaxy S6 和 Android 5.1.1 和索尼 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);最终 PendingIntent pi = PendingIntent.getBroadcast(context, 0, hourlyChimeIntent, PendingIntent.FLAG_CANCEL_CURRENT);am.setExact(AlarmManager.RTC_WAKEUP, time.getTimeInMillis(), pi);

我在接收器中获取了一个 WakeLock,然后在一个线程中向 Wear 手表发送一条消息.没有错过任何振动,他们只是迟到了 3 分钟.

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

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

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

final PowerManager mgr = (PowerManager)context.getSystemService(Context.POWER_SERVICE);最终 PowerManager.WakeLock 锁 = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, BuildConfig.APPLICATION_ID);lock.acquire(7L * 1000L);最终 GoogleApiClient googleApiClient = new GoogleApiClient.Builder(context).addApi(Wearable.API).build();新线程(新运行(){@覆盖公共无效运行(){googleApiClient.blockingConnect();长模式[];模式=新长[] {0L,500L};final NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(googleApiClient).await(2000L, TimeUnit.MILLISECONDS);如果(节点!= null){对于(最终节点节点:nodes.getNodes()){//只是发送然后忘记Wearable.MessageApi.sendMessage(googleApiClient, node.getId(), "/hourly_chime", Utils.Vibrator.serializeVibratePattern(pattern).getBytes()).await();}}}}).开始();

解决方案

该问题似乎仅出现在具有 Lollipop(5.0、5.1、5.1.1).当设备使用电池且屏幕关闭时,警报的安排似乎不准确.如果设备正在充电或在调度警报期间有屏幕,则不会出现此问题.

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

adb shell dumpsys 报警

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

  1. 使用 setAlarmClock 代替 setExact(参见 这个答案).这非常有效(并非在所有设备上),但此解决方案的问题是警报会通过在状态栏中显示警报图标(如果有人尚未设置闹钟)并显示下一个警报计划时间来影响系统闹钟小部件等.不幸的是,虽然这适用于 5.1.1 的 Galaxy Grand,但不适用于 5.0.1 的 Galaxy S4.
  2. 在安排闹钟之前启用屏幕(我在安排下一个闹钟之前执行此操作半秒以避免竞争条件).当然,并不是每个应用都启用屏幕只是为了安排下一次闹钟.
  3. 一个 描述类似问题的错误报告将其与应用程序包名称长度联系起来!我没有验证它是否真的解决了问题,因为更改包名称不是已发布的应用程序的选项.
  4. 另一份报告,有人声称这可能是通过使用 WakefulBroadcastReceiver 修复,但它在我的情况下不起作用.

顺便说一句,这个问题让我发疯:)

当应用程序包名称中有关键字alarm"或alert"时,看起来这个问题不会发生(正如 Mathieu H. 在下面的评论中指出的那样).>

我还可以通过在电池设置(或 Smart Manager 应用)中禁用应用优化来手动修复该问题.似乎无法以编程方式完成,因此您可以尝试询问您的用户...

I have an app which uses the AlarmManager to regularly wake up the phone at full hour and send a message to an Android Wear watch which than makes a short vibration. I have two users with a Samsung Galaxy S6 with stock Android 5.1.1 and the Sony SW 3 with 5.1.1 who experience a weird bug. At the very first full hour the vibration is at the exact time but all other vibrations are 3 minutes delayed. Sometimes even the first full hour vibration is delayed.

Here is some code:

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

I acquire a WakeLock in the receiver and then send a message to the Wear watch in a thread. No vibration is missed, they are just 3 minutes late.

I have no other reports about this issue and all my testing devices are working good. I have no Samsung device though.

Any ideas what could cause the 3 minutes delay? Does Samsung ignore setExact and makes my alarm an inexact? How to force exact alarms on Samsungs?

EDIT:

Here is the Android Wear specific code. In the receiver's onReceive method I do this:

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

解决方案

The issue seems to occur only on Samsung devices (e.g. Galaxy Grand, S4, S5, S6, Note 3, Note 4) with Lollipop (5.0, 5.1, 5.1.1). It seems that alarms are scheduled inexact when device is on battery with screen off. If device is charging or has screen on during scheduling alarm the issue will not occur.

You can verify if next alarm will be inexact with:

adb shell dumpsys alarm

I didn't find perfect solution for this problem - only workarounds where each has some drawbacks:

  1. Use setAlarmClock instead setExact (see this answer). This works very well (not on all devices), but the issue with this solution is that the alarm will affect the system by showing alarm icon in status bar (if someone doesn't have alarm clock set already) and displaying next alarm scheduled time on alarm widgets etc. Unfortunately while this works on Galaxy Grand with 5.1.1 it doesn't on Galaxy S4 with 5.0.1.
  2. Enable screen before scheduling the alarm (I do this half second before scheduling next alarm to avoid race condition). Of course it is not good solution for every app to enable screen just to schedule next alarm.
  3. One bug report describing similar issue connects it with app package name length! I didn't verify if it really fixes the issue, because changing package name is not an option for already published app.
  4. There is another report where someone claims this can be fixed by using WakefulBroadcastReceiver, but it doesn't work in my case.

BTW This issue drives me crazy :)

Edit: Looks like this issue does not occur when there is keyword "alarm" or "alert" in the app package name (as pointed out by Mathieu H. in comments below).

I was also able to fix the issue manually by disabling App optimization in Battery settings (or in Smart Manager app). It seems it cannot be done programmatically, so you can try asking your users...

这篇关于Android 精确闹钟总是关闭 3 分钟的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆