1

I need to wake up a service every 60 seconds (for example).

The service configures itself to wake up with the following code:

private void rescheduleService() {

    // setup calendar
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(new Date());
    calendar.add(Calendar.SECOND, 60);

    // setup intent
    Intent serviceGeofence = new Intent(this, ServiceGeofence.class); // this service
    PendingIntent pendingIntent = PendingIntent.getService(this, 0, serviceGeofence, PendingIntent.FLAG_CANCEL_CURRENT);

    // setup alarm
    AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
    if(Build.VERSION.SDK_INT >= 23) {
        alarmManager.setExactAndAllowWhileIdle(
                AlarmManager.RTC_WAKEUP,
                calendar.getTimeInMillis(),
                pendingIntent);
    } else if(Build.VERSION.SDK_INT >= 19){
        alarmManager.setExact(
                AlarmManager.RTC_WAKEUP,
                calendar.getTimeInMillis(),
                pendingIntent);
    } else {
        alarmManager.set(
                AlarmManager.RTC_WAKEUP,
                calendar.getTimeInMillis(),
                pendingIntent);
    }

    Log.i(TAG, "next alarm: " + calendar.toString());
    Log.i(TAG, "alarm configured");

}

The code above works fine while the phone is charging or connected via USB. It executes every 60 seconds as expect. And I able to see it in LogCat.

BUT, when I unplug phone from USB, the service is wake up randomly (3 or 5 minutes,... even 30 minutes later).

I'm using methods like setExactAndAllowWhileIdle, setExact (it depends of Android version) to wake up the device extrictly in the time I configured it. But it only works when device is connected to USB.

TL;DR; With code above:

  • When device is connected to USB: works fine.
  • When device is disconnected from USB: doesnt work as expected.

Any idea of what is happening?

Cristian
  • 514
  • 4
  • 21
  • That's really weird... Can you post how you use the rescheduleService method? Even this is not replying to your question, but maybe you want to give a try to classes like JobScheduler (introduced in Android L) and FirebaseJobDispatcher. – narko Jun 29 '17 at 14:04

1 Answers1

-1

" Note: Beginning with API 19 (KITKAT) alarm delivery is inexact: the OS will shift alarms in order to minimize wakeups and battery use. There are new APIs to support applications which need strict delivery guarantees; see setWindow(int, long, long, PendingIntent) and setExact(int, long, PendingIntent). Applications whose targetSdkVersion is earlier than API 19 will continue to see the previous behavior in which all alarms are delivered exactly when requested. "

Basically... If sdk >= 19 you need to use serExact. Dont use setExactAndAllowWhileIdle

Javi Moya
  • 193
  • 1
  • 4
  • 11
  • I'm also need to call setExactAndAllowWhileIdle (https://developer.android.com/reference/android/app/AlarmManager.html#setExactAndAllowWhileIdle(int,%20long,%20android.app.PendingIntent)) As you can read, this method is used on api 23 and above, to throw the alarm even if device is in doze zone or idle. Anyway, Im testing on a device with Android Lolipop, wich throw setExact method – Cristian Jun 30 '17 at 07:05