diff --git a/OsmAnd/AndroidManifest.xml b/OsmAnd/AndroidManifest.xml index a14099d1a6..54a269e76f 100644 --- a/OsmAnd/AndroidManifest.xml +++ b/OsmAnd/AndroidManifest.xml @@ -35,6 +35,7 @@ + diff --git a/OsmAnd/src/net/osmand/plus/NavigationService.java b/OsmAnd/src/net/osmand/plus/NavigationService.java index 4b068de509..01f2969230 100644 --- a/OsmAnd/src/net/osmand/plus/NavigationService.java +++ b/OsmAnd/src/net/osmand/plus/NavigationService.java @@ -5,6 +5,7 @@ import net.osmand.Version; import net.osmand.plus.activities.OsmandApplication; import net.osmand.plus.activities.RoutingHelper; import net.osmand.plus.activities.SavingTrackHelper; +import android.app.AlarmManager; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; @@ -21,6 +22,9 @@ import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; +import android.os.PowerManager; +import android.os.SystemClock; +import android.os.PowerManager.WakeLock; import android.widget.Toast; public class NavigationService extends Service implements LocationListener { @@ -30,62 +34,57 @@ public class NavigationService extends Service implements LocationListener { } private final static int NOTIFICATION_SERVICE_ID = 1; public final static String OSMAND_STOP_SERVICE_ACTION = "OSMAND_STOP_SERVICE_ACTION"; //$NON-NLS-1$ + private NavigationServiceBinder binder = new NavigationServiceBinder(); + + private int serviceOffInterval; private String serviceOffProvider; - private SavingTrackHelper savingTrackHelper; - private Handler handler; private int serviceError; + + private SavingTrackHelper savingTrackHelper; private RoutingHelper routingHelper; - private Notification notification; private SharedPreferences settings; - private boolean serviceActive = true; - private boolean registered = false; + + private Handler handler; + + private static WakeLock lockStatic; + private PendingIntent pendingIntent; @Override public IBinder onBind(Intent intent) { return binder; } + protected synchronized static PowerManager.WakeLock getLock(Context context) { + if (lockStatic == null) { + PowerManager mgr = (PowerManager) context.getSystemService(Context.POWER_SERVICE); + lockStatic = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "OsmandServiceLock"); + } + return lockStatic; + } + + protected Handler getHandler() { + return handler; + } + public int getServiceError() { + return serviceError; + } - private void delayedAction(final boolean register, long delay){ - handler.postDelayed(new Runnable(){ - - @Override - public void run() { - if (!serviceActive) { - return; - } - LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); - if (register) { - registered = true; - locationManager.requestLocationUpdates(serviceOffProvider, 1000, 0, NavigationService.this); - // Wait serviceError and - if (!isContinuous() || serviceOffInterval > serviceError) { - delayedAction(false, serviceError); - } - } else { - // That is needed to not remove twice - // RemovingUpdates : after serviceError and after successful found position - if(registered){ - registered = false; - locationManager.removeUpdates(NavigationService.this); - delayedAction(true, serviceOffInterval); - } - } - - } - - }, delay); - + public int getServiceOffInterval() { + return serviceOffInterval; + } + + public String getServiceOffProvider() { + return serviceOffProvider; } @Override public void onCreate() { super.onCreate(); + // initializing variables setForeground(true); - serviceActive = true; handler = new Handler(); settings = OsmandSettings.getSharedPreferences(this); serviceOffInterval = OsmandSettings.getServiceOffInterval(settings); @@ -94,8 +93,21 @@ public class NavigationService extends Service implements LocationListener { savingTrackHelper = new SavingTrackHelper(this); routingHelper = ((OsmandApplication)getApplication()).getRoutingHelper(); - OsmandSettings.setServiceOffEnabled(this, true); + ((OsmandApplication)getApplication()).setNavigationService(this); + + // requesting + if(isContinuous()){ + // request location updates + LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); + locationManager.requestLocationUpdates(serviceOffProvider, 1000, 0, NavigationService.this); + } 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); + } + + // registering icon at top level registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -103,11 +115,8 @@ public class NavigationService extends Service implements LocationListener { } }, new IntentFilter(OSMAND_STOP_SERVICE_ACTION)); - - // register listener - delayedAction(true, 500); Intent notificationIntent = new Intent(OSMAND_STOP_SERVICE_ACTION); - notification = new Notification(R.drawable.icon, "", //$NON-NLS-1$ + Notification notification = new Notification(R.drawable.icon, "", //$NON-NLS-1$ System.currentTimeMillis()); notification.flags = Notification.FLAG_NO_CLEAR; notification.setLatestEventInfo(this, Version.APP_NAME, @@ -125,10 +134,22 @@ public class NavigationService extends Service implements LocationListener { @Override public void onDestroy() { super.onDestroy(); + ((OsmandApplication)getApplication()).setNavigationService(null); + + // remove updates LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); locationManager.removeUpdates(this); - OsmandSettings.setServiceOffEnabled(this, false); - serviceActive = false; + + if (!isContinuous()) { + WakeLock lock = getLock(this); + if (lock.isHeld()) { + lock.release(); + } + } + // remove alarm + AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE); + alarmManager.cancel(pendingIntent); + // remove notification NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); mNotificationManager.cancel(NOTIFICATION_SERVICE_ID); @@ -141,7 +162,9 @@ public class NavigationService extends Service implements LocationListener { if(location != null && !OsmandSettings.getMapActivityEnabled(settings)){ if(!isContinuous()){ // unregister listener and wait next time - delayedAction(false, 500); + LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); + locationManager.removeUpdates(this); + getLock(this).release(); } savingTrackHelper.insertData(location.getLatitude(), location.getLongitude(), location.getAltitude(), location.getSpeed(), location.getTime(), settings); diff --git a/OsmAnd/src/net/osmand/plus/OnNavigationServiceAlarmReceiver.java b/OsmAnd/src/net/osmand/plus/OnNavigationServiceAlarmReceiver.java new file mode 100644 index 0000000000..a1d0fbfc80 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/OnNavigationServiceAlarmReceiver.java @@ -0,0 +1,38 @@ +package net.osmand.plus; + +import net.osmand.plus.activities.OsmandApplication; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.location.LocationManager; +import android.os.PowerManager.WakeLock; + +public class OnNavigationServiceAlarmReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + final WakeLock lock = NavigationService.getLock(context); + final NavigationService service = ((OsmandApplication) context.getApplicationContext()).getNavigationService(); + // do not do nothing + if (lock.isHeld() || service == null) { + return; + } + // + lock.acquire(); + // request location updates + final LocationManager locationManager = (LocationManager) service.getSystemService(Context.LOCATION_SERVICE); + locationManager.requestLocationUpdates(service.getServiceOffProvider(), 1000, 0, service); + if (service.getServiceOffInterval() > service.getServiceError()) { + service.getHandler().postDelayed(new Runnable() { + @Override + public void run() { + // if lock is not anymore held + if (lock.isHeld()) { + lock.release(); + locationManager.removeUpdates(service); + } + } + }, service.getServiceError()); + } + } + +} diff --git a/OsmAnd/src/net/osmand/plus/OsmandSettings.java b/OsmAnd/src/net/osmand/plus/OsmandSettings.java index 20e99bef56..87981777da 100644 --- a/OsmAnd/src/net/osmand/plus/OsmandSettings.java +++ b/OsmAnd/src/net/osmand/plus/OsmandSettings.java @@ -779,15 +779,7 @@ public class OsmandSettings { // this value string is synchronized with settings_pref.xml preference name public static final String SERVICE_OFF_ENABLED = "service_off_enabled"; //$NON-NLS-1$ - public static final boolean SERVICE_OFF_ENABLED_DEF = false; - public static boolean getServiceOffEnabled(SharedPreferences prefs) { - return prefs.getBoolean(SERVICE_OFF_ENABLED, SERVICE_OFF_ENABLED_DEF); - } - public static boolean setServiceOffEnabled(Context ctx, boolean en) { - SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE); - return prefs.edit().putBoolean(SERVICE_OFF_ENABLED, en).commit(); - } // this value string is synchronized with settings_pref.xml preference name diff --git a/OsmAnd/src/net/osmand/plus/activities/OsmandApplication.java b/OsmAnd/src/net/osmand/plus/activities/OsmandApplication.java index d6693923c9..ce5b6d77e5 100644 --- a/OsmAnd/src/net/osmand/plus/activities/OsmandApplication.java +++ b/OsmAnd/src/net/osmand/plus/activities/OsmandApplication.java @@ -11,6 +11,7 @@ import java.util.List; import net.osmand.Algoritms; import net.osmand.LogUtil; import net.osmand.plus.FavouritesDbHelper; +import net.osmand.plus.NavigationService; import net.osmand.plus.OsmandSettings; import net.osmand.plus.PoiFiltersHelper; import net.osmand.plus.ProgressDialogImplementation; @@ -45,6 +46,7 @@ public class OsmandApplication extends Application { private ProgressDialog progressDlg; private Handler uiHandler; private DayNightHelper daynightHelper; + private NavigationService navigationService; public void onCreate(){ @@ -158,6 +160,14 @@ public class OsmandApplication extends Application { } return player.init(OsmandSettings.getVoiceProvider(OsmandSettings.getPrefs(this))); } + + public NavigationService getNavigationService() { + return navigationService; + } + + public void setNavigationService(NavigationService navigationService) { + this.navigationService = navigationService; + } public void startApplication() { startDialog = new ProgressDialogImplementation(this, null, false); diff --git a/OsmAnd/src/net/osmand/plus/activities/SettingsActivity.java b/OsmAnd/src/net/osmand/plus/activities/SettingsActivity.java index 385938263c..6d16dd1070 100644 --- a/OsmAnd/src/net/osmand/plus/activities/SettingsActivity.java +++ b/OsmAnd/src/net/osmand/plus/activities/SettingsActivity.java @@ -265,7 +265,7 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference new String[]{LocationManager.GPS_PROVIDER, LocationManager.NETWORK_PROVIDER}, // OsmandSettings.getServiceOffProvider(prefs)); - routeServiceEnabled.setChecked(OsmandSettings.getServiceOffEnabled(prefs)); + routeServiceEnabled.setChecked(getMyApplication().getNavigationService() != null); fill(mapScreenOrientation, // new String[] { @@ -484,11 +484,11 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference if ((Boolean) newValue) { ComponentName name = startService(serviceIntent); if (name == null) { - routeServiceEnabled.setChecked(OsmandSettings.getServiceOffEnabled(prefs)); + routeServiceEnabled.setChecked(getMyApplication().getNavigationService() != null); } } else { if(!stopService(serviceIntent)){ - routeServiceEnabled.setChecked(OsmandSettings.getServiceOffEnabled(prefs)); + routeServiceEnabled.setChecked(getMyApplication().getNavigationService() != null); } } } else if (preference == routerPreference) {