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) {