Fix issue 405. Reimplement background service. Use alarm service to wake up phone

This commit is contained in:
Victor Shcherb 2011-04-27 00:13:11 +02:00
parent 2991672d8f
commit 6c3ada7205
6 changed files with 119 additions and 55 deletions

View file

@ -35,6 +35,7 @@
<service android:process="net.osmand.plus" android:label="@string/process_navigation_service" android:name=".NavigationService">
<intent-filter><action android:name="net.osmand.plus.NavigationService"></action></intent-filter>
</service>
<receiver android:name=".OnNavigationServiceAlarmReceiver"/>
</application>

View file

@ -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);

View file

@ -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());
}
}
}

View file

@ -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

View file

@ -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);

View file

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