From fd05a1f058ab933163c3dbdc7d68f98d913cf79e Mon Sep 17 00:00:00 2001 From: sonora Date: Sat, 4 May 2019 19:53:09 +0200 Subject: [PATCH] Use setExact for long-interval recording --- .../net/osmand/plus/NavigationService.java | 28 +++++++++++++++++-- .../OnNavigationServiceAlarmReceiver.java | 25 +++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/NavigationService.java b/OsmAnd/src/net/osmand/plus/NavigationService.java index f0c856a25c..5b12b25112 100644 --- a/OsmAnd/src/net/osmand/plus/NavigationService.java +++ b/OsmAnd/src/net/osmand/plus/NavigationService.java @@ -10,6 +10,7 @@ import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Binder; +import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -41,6 +42,7 @@ public class NavigationService extends Service implements LocationListener { private int serviceOffInterval; private String serviceOffProvider; private int serviceError; + private long nextManualWakeup; private OsmandSettings settings; private Handler handler; @@ -71,6 +73,14 @@ public class NavigationService extends Service implements LocationListener { return serviceError; } + public long getNextManualWakeup() { + return nextManualWakeup; + } + + public void setNextManualWakeup(long value) { + nextManualWakeup = value; + } + public int getServiceOffInterval() { return serviceOffInterval; } @@ -111,7 +121,14 @@ public class NavigationService extends Service implements LocationListener { app.setNavigationService(this); AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE); pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(this, OnNavigationServiceAlarmReceiver.class), PendingIntent.FLAG_UPDATE_CURRENT); - alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 500, serviceOffInterval, pendingIntent); + nextManualWakeup = SystemClock.elapsedRealtime() + serviceOffInterval; + if (Build.VERSION.SDK_INT >= 23) { + alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 500, pendingIntent); + } else if (Build.VERSION.SDK_INT >= 19) { + alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 500, pendingIntent); + } else { + alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 500, serviceOffInterval, pendingIntent); + } } app.getNotificationHelper().updateTopNotification(); @@ -159,7 +176,14 @@ public class NavigationService extends Service implements LocationListener { } else { AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE); pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(this, OnNavigationServiceAlarmReceiver.class), PendingIntent.FLAG_UPDATE_CURRENT); - alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 500, serviceOffInterval, pendingIntent); + nextManualWakeup = SystemClock.elapsedRealtime() + serviceOffInterval; + if (Build.VERSION.SDK_INT >= 23) { + alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 500, pendingIntent); + } else if (Build.VERSION.SDK_INT >= 19) { + alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 500, pendingIntent); + } else { + alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 500, serviceOffInterval, pendingIntent); + } } // registering icon at top level diff --git a/OsmAnd/src/net/osmand/plus/OnNavigationServiceAlarmReceiver.java b/OsmAnd/src/net/osmand/plus/OnNavigationServiceAlarmReceiver.java index ece000af8c..69eae81df6 100644 --- a/OsmAnd/src/net/osmand/plus/OnNavigationServiceAlarmReceiver.java +++ b/OsmAnd/src/net/osmand/plus/OnNavigationServiceAlarmReceiver.java @@ -1,10 +1,15 @@ package net.osmand.plus; +import android.app.AlarmManager; +import android.app.PendingIntent; + import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.location.LocationManager; +import android.os.Build; import android.os.PowerManager.WakeLock; +import android.os.SystemClock; public class OnNavigationServiceAlarmReceiver extends BroadcastReceiver { @Override @@ -19,6 +24,26 @@ public class OnNavigationServiceAlarmReceiver extends BroadcastReceiver { lock.acquire(); // request location updates final LocationManager locationManager = (LocationManager) service.getSystemService(Context.LOCATION_SERVICE); + + //Unless setRepeating was used, manually re-schedule service to the next measurement point in the future + if (Build.VERSION.SDK_INT >= 23) { + // Avoid drift + while ((service.getNextManualWakeup() - SystemClock.elapsedRealtime()) < 0) { + service.setNextManualWakeup(service.getNextManualWakeup() + service.getServiceOffInterval()); + } + AlarmManager alarmManager = (AlarmManager) service.getSystemService(Context.ALARM_SERVICE); + PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 1, new Intent(context, OnNavigationServiceAlarmReceiver.class), PendingIntent.FLAG_UPDATE_CURRENT); + alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, service.getNextManualWakeup(), pendingIntent); + } else if (Build.VERSION.SDK_INT >= 19) { + // Avoid drift + while ((service.getNextManualWakeup() - SystemClock.elapsedRealtime()) < 0) { + service.setNextManualWakeup(service.getNextManualWakeup() + service.getServiceOffInterval()); + } + AlarmManager alarmManager = (AlarmManager) service.getSystemService(Context.ALARM_SERVICE); + PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 1, new Intent(context, OnNavigationServiceAlarmReceiver.class), PendingIntent.FLAG_UPDATE_CURRENT); + alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, service.getNextManualWakeup(), pendingIntent); + } + try { locationManager.requestLocationUpdates(service.getServiceOffProvider(), 0, 0, service); if (service.getServiceOffInterval() > service.getServiceError()) {