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:
I didn't find perfect solution for this problem - only workarounds where each has some drawbacks:
setAlarmClock
insteadsetExact
(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.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...