Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android exact Alarm is always 3 minutes off

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();
like image 904
shelll Avatar asked Dec 03 '15 19:12

shelll


People also ask

How do I set an alarm every 5 minutes on my Android?

On Android, you can tweak your phone's snooze duration to have an alarm sound as often as every 30 minutes. To do this, go to the Clock app and set up a regular alarm by tapping the big plus button at the bottom and adding your desired parameters.

Why does my Android alarm not go off sometimes?

Step 1: Launch the Settings and click on Apps and Notifications. Step 2: Now, click on the Clock app and then further tap on Storage. Step 3: Finally, tap on Clear Cache and Clear Storage, one by one. A simple restart will conclude the steps and resolve the Android alarm no sound issue.

Why does my alarm not go off on my phone sometimes?

To clear the cache and data for the Clock app, tap on Settings > Apps > Clock. Alternatively, long-pressing the Clock app on your phone screen and selecting App Info also does the trick. Whichever way you decide, your next move is to select Storage > Clear Cache, and this should ensure your Android alarm works again.


1 Answers

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

like image 112
Paweł Nadolski Avatar answered Oct 14 '22 03:10

Paweł Nadolski