[android] add: Background GPS tracker.

refactor: Tuned GPS providers.
This commit is contained in:
Alexander Marchuk 2015-12-03 19:40:00 +03:00 committed by Constantin Shalnev
parent a4e6c5ccd8
commit 2b1547666c
14 changed files with 377 additions and 172 deletions

View file

@ -252,6 +252,15 @@
android:name="com.mapswithme.maps.background.WorkerService"
android:exported="false"/>
<receiver android:name="com.mapswithme.maps.location.TrackRecorderWakeReceiver">
<intent-filter>
<action android:name="com.mapswithme.maps.TRACK_RECORDER_ALARM"/>
</intent-filter>
</receiver>
<service android:name="com.mapswithme.maps.location.TrackRecorderWakeService"
android:exported="false"/>
<!-- our custom receiver, that will call Aloha & other handlers -->
<receiver
android:name="com.mapswithme.util.MultipleTrackerReferrerReceiver"
@ -311,7 +320,5 @@
<action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
</intent-filter>
</receiver>
</application>
</manifest>

View file

@ -15,10 +15,15 @@ import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import com.mapswithme.country.StorageOptions;
import com.mapswithme.maps.MapStorage.Index;
import com.mapswithme.maps.MwmActivity.MapTask;
import com.mapswithme.maps.MwmActivity.OpenUrlTask;
import com.mapswithme.maps.MapStorage.Index;
import com.mapswithme.maps.api.Const;
import com.mapswithme.maps.api.ParsedMwmRequest;
import com.mapswithme.maps.base.BaseMwmFragmentActivity;
@ -33,11 +38,6 @@ import com.mapswithme.util.Yota;
import com.mapswithme.util.concurrency.ThreadPool;
import com.mapswithme.util.statistics.Statistics;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
@SuppressLint("StringFormatMatches")
public class DownloadResourcesActivity extends BaseMwmFragmentActivity
implements LocationHelper.LocationListener, MapStorage.Listener
@ -115,7 +115,7 @@ public class DownloadResourcesActivity extends BaseMwmFragmentActivity
{
super.onResume();
LocationHelper.INSTANCE.addLocationListener(this);
LocationHelper.INSTANCE.addLocationListener(this, true);
}
@Override

View file

@ -624,7 +624,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
@Override
public void onLocationError(int errorCode)
{
MapFragment.nativeOnLocationError(errorCode);
LocationHelper.nativeOnLocationError(errorCode);
if (errorCode == LocationHelper.ERROR_DENIED)
{
@ -665,13 +665,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
if (!location.getProvider().equals(LocationHelper.LOCATION_PREDICTOR_PROVIDER))
mLocationPredictor.reset(location);
MapFragment.nativeLocationUpdated(location.getTime(),
location.getLatitude(),
location.getLongitude(),
location.getAccuracy(),
location.getAltitude(),
location.getSpeed(),
location.getBearing());
LocationHelper.onLocationUpdated(location);
if (mPlacePage.getState() != State.HIDDEN)
mPlacePage.refreshLocation(location);
@ -816,7 +810,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
private void resumeLocation()
{
LocationHelper.INSTANCE.addLocationListener(this);
LocationHelper.INSTANCE.addLocationListener(this, true);
// Do not turn off the screen while displaying position
Utils.keepScreenOn(true, getWindow());
mLocationPredictor.resume();

View file

@ -17,6 +17,7 @@ import com.mapswithme.country.CountryItem;
import com.mapswithme.maps.background.AppBackgroundTracker;
import com.mapswithme.maps.background.Notifier;
import com.mapswithme.maps.bookmarks.data.BookmarkManager;
import com.mapswithme.maps.location.TrackRecorder;
import com.mapswithme.maps.sound.TtsPlayer;
import com.mapswithme.util.Config;
import com.mapswithme.util.Constants;
@ -114,6 +115,7 @@ public class MwmApplication extends Application
initParse();
mPrefs = getSharedPreferences(getString(R.string.pref_file_name), MODE_PRIVATE);
mBackgroundTracker = new AppBackgroundTracker();
TrackRecorder.init();
}
public void initNativeCore()
@ -263,6 +265,7 @@ public class MwmApplication extends Application
Config.resetAppSessionCounters();
}
@SuppressWarnings("unused")
public void runNativeFunctorOnUiThread(final long functorPointer)
{
Message m = Message.obtain(mMainLoopHandler, new Runnable()

View file

@ -9,6 +9,10 @@ import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import com.mapswithme.maps.R;
import com.mapswithme.maps.bookmarks.data.Bookmark;
import com.mapswithme.maps.bookmarks.data.BookmarkCategory;
@ -17,9 +21,6 @@ import com.mapswithme.maps.bookmarks.data.Track;
import com.mapswithme.maps.location.LocationHelper;
import com.mapswithme.util.Graphics;
import java.util.ArrayList;
import java.util.List;
public class BookmarkListAdapter extends BaseAdapter
implements LocationHelper.LocationListener
@ -43,7 +44,7 @@ public class BookmarkListAdapter extends BaseAdapter
public void startLocationUpdate()
{
LocationHelper.INSTANCE.addLocationListener(this);
LocationHelper.INSTANCE.addLocationListener(this, true);
}
public void stopLocationUpdate()

View file

@ -4,17 +4,16 @@ package com.mapswithme.maps.location;
import android.content.Context;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import com.mapswithme.maps.MwmApplication;
import com.mapswithme.util.LocationUtils;
import java.util.ArrayList;
import java.util.List;
public class AndroidNativeProvider extends BaseLocationProvider implements android.location.LocationListener
import com.mapswithme.maps.MwmApplication;
import com.mapswithme.util.LocationUtils;
public class AndroidNativeProvider extends BaseLocationProvider
{
private LocationManager mLocationManager;
private final LocationManager mLocationManager;
private boolean mIsActive;
public AndroidNativeProvider()
@ -36,7 +35,7 @@ public class AndroidNativeProvider extends BaseLocationProvider implements andro
{
mIsActive = true;
for (final String provider : providers)
mLocationManager.requestLocationUpdates(provider, LOCATION_UPDATE_INTERVAL, 0, this);
mLocationManager.requestLocationUpdates(provider, LocationHelper.INSTANCE.getUpdateInterval(), 0, this);
LocationHelper.INSTANCE.registerSensorListeners();
@ -97,36 +96,4 @@ public class AndroidNativeProvider extends BaseLocationProvider implements andro
return acceptedProviders;
}
@Override
public void onLocationChanged(Location l)
{
// Completely ignore locations without lat and lon
if (l.getAccuracy() <= 0.0)
return;
if (isLocationBetterThanLast(l))
{
LocationHelper.INSTANCE.initMagneticField(l);
LocationHelper.INSTANCE.setLastLocation(l);
}
}
@Override
public void onProviderDisabled(String provider)
{
mLogger.d("Disabled location provider: ", provider);
}
@Override
public void onProviderEnabled(String provider)
{
mLogger.d("Enabled location provider: ", provider);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
mLogger.d("Status changed for location provider: ", provider, status);
}
}

View file

@ -2,33 +2,68 @@ package com.mapswithme.maps.location;
import android.location.Location;
import android.location.LocationListener;
import android.os.Bundle;
import com.mapswithme.util.LocationUtils;
import com.mapswithme.util.log.Logger;
import com.mapswithme.util.log.SimpleLogger;
public abstract class BaseLocationProvider
abstract class BaseLocationProvider implements LocationListener
{
protected static final long LOCATION_UPDATE_INTERVAL = 500;
public static final double DEFAULT_SPEED_MPS = 5;
public static final float DISTANCE_TO_RECREATE_MAGNETIC_FIELD_M = 1000;
private static final double DEFAULT_SPEED_MPS = 5;
protected static final Logger mLogger = SimpleLogger.get(BaseLocationProvider.class.getName());
protected static final Logger sLogger = SimpleLogger.get(BaseLocationProvider.class.getName());
protected abstract void startUpdates();
protected abstract void stopUpdates();
protected boolean isLocationBetterThanLast(Location newLocation)
protected boolean isLocationBetterThanLast(Location newLocation, Location lastLocation)
{
double speed = Math.max(DEFAULT_SPEED_MPS, (newLocation.getSpeed() + lastLocation.getSpeed()) / 2.0);
double lastAccuracy = (lastLocation.getAccuracy() + speed * LocationUtils.getDiffWithLastLocation(lastLocation, newLocation));
return (newLocation.getAccuracy() < lastAccuracy);
}
protected final boolean isLocationBetterThanLast(Location newLocation)
{
if (newLocation == null)
return false;
final Location lastLocation = LocationHelper.INSTANCE.getLastLocation();
if (lastLocation == null)
return true;
return (lastLocation == null || isLocationBetterThanLast(newLocation, lastLocation));
}
final double s = Math.max(DEFAULT_SPEED_MPS, (newLocation.getSpeed() + lastLocation.getSpeed()) / 2.0);
return (newLocation.getAccuracy() < (lastLocation.getAccuracy() + s * LocationUtils.getDiffWithLastLocation(lastLocation, newLocation)));
@Override
public void onLocationChanged(Location location)
{
// Completely ignore locations without lat and lon
if (location.getAccuracy() <= 0.0)
return;
if (isLocationBetterThanLast(location))
{
LocationHelper.INSTANCE.initMagneticField(location);
LocationHelper.INSTANCE.setLastLocation(location);
}
}
@Override
public void onProviderDisabled(String provider)
{
sLogger.d("Disabled location provider: ", provider);
}
@Override
public void onProviderEnabled(String provider)
{
sLogger.d("Enabled location provider: ", provider);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
sLogger.d("Status changed for location provider: ", provider, status);
}
}

View file

@ -11,34 +11,36 @@ import com.google.android.gms.location.LocationServices;
import com.mapswithme.maps.MwmApplication;
public class GoogleFusedLocationProvider extends BaseLocationProvider
implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener
implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener
{
private static final String GS_LOCATION_PROVIDER = "fused";
private final GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
private GoogleApiClient mGoogleApiClient;
private boolean mIsResolvingError;
public GoogleFusedLocationProvider()
{
mGoogleApiClient = new GoogleApiClient.Builder(MwmApplication.get())
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(LOCATION_UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(LOCATION_UPDATE_INTERVAL / 2);
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
@Override
protected void startUpdates()
{
if (mGoogleApiClient != null && !mGoogleApiClient.isConnected() && !mGoogleApiClient.isConnecting())
{
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(LocationHelper.INSTANCE.getUpdateInterval());
mLocationRequest.setFastestInterval(LocationHelper.INSTANCE.getUpdateInterval() / 2);
mGoogleApiClient.connect();
}
}
@Override
@ -53,25 +55,18 @@ public class GoogleFusedLocationProvider extends BaseLocationProvider
}
@Override
protected boolean isLocationBetterThanLast(Location newLocation)
protected boolean isLocationBetterThanLast(Location newLocation, Location lastLocation)
{
if (newLocation == null)
return false;
Location lastLocation = LocationHelper.INSTANCE.getLastLocation();
if (lastLocation == null)
return true;
// We believe that google service always returns good locations.
return GS_LOCATION_PROVIDER.equalsIgnoreCase(newLocation.getProvider()) ||
!GS_LOCATION_PROVIDER.equalsIgnoreCase(lastLocation.getProvider()) && super.isLocationBetterThanLast(newLocation);
!GS_LOCATION_PROVIDER.equalsIgnoreCase(lastLocation.getProvider()) && super.isLocationBetterThanLast(newLocation, lastLocation);
}
@Override
public void onConnected(Bundle bundle)
{
mLogger.d("Fused onConnected. Bundle " + bundle);
sLogger.d("Fused onConnected. Bundle " + bundle);
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
LocationHelper.INSTANCE.registerSensorListeners();
final Location l = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
@ -82,28 +77,14 @@ public class GoogleFusedLocationProvider extends BaseLocationProvider
@Override
public void onConnectionSuspended(int i)
{
mLogger.d("Fused onConnectionSuspended. Code " + i);
sLogger.d("Fused onConnectionSuspended. Code " + i);
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult)
{
mLogger.d("Fused onConnectionFailed. Fall back to native provider. ConnResult " + connectionResult);
sLogger.d("Fused onConnectionFailed. Fall back to native provider. ConnResult " + connectionResult);
// TODO handle error in a smarter way
LocationHelper.INSTANCE.initLocationProvider(true);
}
@Override
public void onLocationChanged(Location location)
{
// Completely ignore locations without lat and lon
if (location.getAccuracy() <= 0.0)
return;
if (isLocationBetterThanLast(location))
{
LocationHelper.INSTANCE.initMagneticField(location);
LocationHelper.INSTANCE.setLastLocation(location);
}
}
}

View file

@ -15,17 +15,14 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.mapswithme.maps.LocationState;
import com.mapswithme.maps.MwmApplication;
import com.mapswithme.maps.R;
import com.mapswithme.maps.background.AppBackgroundTracker;
import com.mapswithme.maps.bookmarks.data.MapObject;
import com.mapswithme.util.Listeners;
import com.mapswithme.util.LocationUtils;
import com.mapswithme.util.concurrency.UiThread;
import com.mapswithme.util.log.Logger;
@ -43,6 +40,9 @@ public enum LocationHelper implements SensorEventListener
public static final int ERROR_GPS_OFF = 3;
public static final String LOCATION_PREDICTOR_PROVIDER = "LocationPredictorProvider";
private static final float DISTANCE_TO_RECREATE_MAGNETIC_FIELD_M = 1000;
private static final long UPDATE_INTERVAL_FOREGROUND = 500;
private static final long UPDATE_INTERVAL_BACKGROUND = 10000;
private static final long STOP_DELAY = 5000;
public interface LocationListener
@ -52,9 +52,10 @@ public enum LocationHelper implements SensorEventListener
void onLocationError(int errorCode);
}
private final Set<LocationListener> mListeners = new LinkedHashSet<>();
private final List<LocationListener> mListenersToRemove = new ArrayList<>();
private boolean mIteratingListener;
private final Listeners<LocationListener> mListeners = new Listeners<>();
private boolean mActive;
private boolean mForegroundMode;
private Location mLastLocation;
private MapObject.MyPosition mMyPosition;
@ -76,6 +77,10 @@ public enum LocationHelper implements SensorEventListener
@Override
public void run()
{
if (!mActive)
return;
mActive = false;
mLocationProvider.stopUpdates();
mMagneticField = null;
if (mSensorManager != null)
@ -93,6 +98,15 @@ public enum LocationHelper implements SensorEventListener
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mMagnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
}
MwmApplication.backgroundTracker().addListener(new AppBackgroundTracker.OnTransitionListener()
{
@Override
public void onTransit(boolean foreground)
{
setForegroundMode(foreground);
}
});
}
@SuppressWarnings("deprecation")
@ -135,7 +149,8 @@ public enum LocationHelper implements SensorEventListener
mLocationProvider = new AndroidNativeProvider();
}
if (!mListeners.isEmpty())
mActive = !mListeners.isEmpty();
if (mActive)
mLocationProvider.startUpdates();
}
@ -168,77 +183,53 @@ public enum LocationHelper implements SensorEventListener
notifyLocationUpdated();
}
private void startIteratingListeners()
{
mIteratingListener = true;
}
private void finishIteratingListeners()
{
mIteratingListener = false;
if (!mListenersToRemove.isEmpty())
{
mListeners.removeAll(mListenersToRemove);
mListenersToRemove.clear();
}
}
void notifyLocationUpdated()
{
if (mLastLocation == null)
return;
startIteratingListeners();
for (LocationListener listener : mListeners)
listener.onLocationUpdated(mLastLocation);
finishIteratingListeners();
mListeners.finishIterate();
}
void notifyLocationError(int errCode)
{
startIteratingListeners();
for (LocationListener listener : mListeners)
listener.onLocationError(errCode);
finishIteratingListeners();
mListeners.finishIterate();
}
private void notifyCompassUpdated(long time, double magneticNorth, double trueNorth, double accuracy)
{
startIteratingListeners();
for (LocationListener listener : mListeners)
listener.onCompassUpdated(time, magneticNorth, trueNorth, accuracy);
finishIteratingListeners();
mListeners.finishIterate();
}
@android.support.annotation.UiThread
public void addLocationListener(LocationListener listener)
public void addLocationListener(LocationListener listener, boolean forceUpdate)
{
UiThread.cancelDelayedTasks(mStopLocationTask);
if (mListeners.isEmpty())
{
mActive = true;
mLocationProvider.startUpdates();
mListeners.add(listener);
notifyLocationUpdated();
}
mListeners.register(listener);
if (forceUpdate)
notifyLocationUpdated();
}
@android.support.annotation.UiThread
public void removeLocationListener(LocationListener listener)
{
boolean empty = false;
if (mIteratingListener)
{
if (mListeners.contains(listener))
{
mListenersToRemove.add(listener);
empty = (mListeners.size() == 1);
}
}
else
{
mListeners.remove(listener);
empty = mListeners.isEmpty();
}
boolean wasEmpty = mListeners.isEmpty();
mListeners.unregister(listener);
if (empty)
if (!wasEmpty && mListeners.isEmpty())
// Make a delay with disconnection from location providers, so that orientation changes and short app sleeps
// doesn't take long time to connect again.
UiThread.runLater(mStopLocationTask, STOP_DELAY);
@ -248,18 +239,19 @@ public enum LocationHelper implements SensorEventListener
{
if (mSensorManager != null)
{
final int COMPASS_REFRESH_MKS = SensorManager.SENSOR_DELAY_UI;
if (mAccelerometer != null)
mSensorManager.registerListener(this, mAccelerometer, COMPASS_REFRESH_MKS);
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_UI);
if (mMagnetometer != null)
mSensorManager.registerListener(this, mMagnetometer, COMPASS_REFRESH_MKS);
mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_UI);
}
}
@Override
public void onSensorChanged(SensorEvent event)
{
if (!MwmApplication.get().isFrameworkInitialized())
return;
boolean hasOrientation = false;
switch (event.sensor.getType())
@ -298,8 +290,6 @@ public enum LocationHelper implements SensorEventListener
}
}
private native float[] nativeUpdateCompassSensor(int ind, float[] arr);
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
@ -309,9 +299,41 @@ public enum LocationHelper implements SensorEventListener
{
// Recreate magneticField if location has changed significantly
if (mMagneticField == null || mLastLocation == null ||
newLocation.distanceTo(mLastLocation) > BaseLocationProvider.DISTANCE_TO_RECREATE_MAGNETIC_FIELD_M)
newLocation.distanceTo(mLastLocation) > DISTANCE_TO_RECREATE_MAGNETIC_FIELD_M)
mMagneticField = new GeomagneticField((float) newLocation.getLatitude(), (float) newLocation.getLongitude(),
(float) newLocation.getAltitude(), newLocation.getTime());
}
}
private void setForegroundMode(boolean set)
{
mForegroundMode = set;
if (!mActive)
return;
mLocationProvider.stopUpdates();
if (!mListeners.isEmpty())
mLocationProvider.startUpdates();
}
public long getUpdateInterval()
{
return (mForegroundMode ? UPDATE_INTERVAL_FOREGROUND
: UPDATE_INTERVAL_BACKGROUND);
}
public static void onLocationUpdated(Location location)
{
nativeLocationUpdated(location.getTime(),
location.getLatitude(),
location.getLongitude(),
location.getAccuracy(),
location.getAltitude(),
location.getSpeed(),
location.getBearing());
}
public static native void nativeOnLocationError(int errorCode);
private static native void nativeLocationUpdated(long time, double lat, double lon, float accuracy, double altitude, float speed, float bearing);
private static native float[] nativeUpdateCompassSensor(int ind, float[] arr);
}

View file

@ -1,9 +1,108 @@
package com.mapswithme.maps.location;
public class TrackRecorder
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import com.mapswithme.maps.MwmApplication;
import com.mapswithme.maps.background.AppBackgroundTracker;
public final class TrackRecorder
{
public static native void nativeSetEnabled(boolean enable);
public static native boolean nativeIsEnabled();
public static native void nativeSetDuration(int hours);
public static native int nativeGetDuration();
private static final AlarmManager sAlarmManager = (AlarmManager)MwmApplication.get().getSystemService(Context.ALARM_SERVICE);
private static final Intent sAlarmIntent = new Intent("com.mapswithme.maps.TRACK_RECORDER_ALARM");
private static final LocationHelper.LocationListener mLocationListener = new LocationHelper.LocationListener()
{
@Override
public void onLocationUpdated(Location location)
{
LocationHelper.onLocationUpdated(location);
TrackRecorderWakeService.stop();
checkState();
}
@Override
public void onLocationError(int errorCode)
{
setEnabled(false);
}
@Override
public void onCompassUpdated(long time, double magneticNorth, double trueNorth, double accuracy) {}
};
private TrackRecorder() {}
public static void init()
{
MwmApplication.backgroundTracker().addListener(new AppBackgroundTracker.OnTransitionListener()
{
@Override
public void onTransit(boolean foreground)
{
checkState();
}
});
}
private static void checkState()
{
if (MwmApplication.backgroundTracker().isForeground() || !isEnabled())
{
sAlarmManager.cancel(getAlarmIntent());
TrackRecorderWakeService.stop();
}
else
sAlarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + LocationHelper.INSTANCE.getUpdateInterval(), getAlarmIntent());
}
private static PendingIntent getAlarmIntent()
{
return PendingIntent.getBroadcast(MwmApplication.get(), 0, sAlarmIntent, 0);
}
public static boolean isEnabled()
{
return nativeIsEnabled();
}
public static void setEnabled(boolean enabled)
{
nativeSetEnabled(enabled);
checkState();
}
public static int getDuration()
{
return nativeGetDuration();
}
public static void setDuration(int hours)
{
nativeSetDuration(hours);
}
static void onWakeAlarm()
{
if (nativeIsEnabled())
TrackRecorderWakeService.start();
}
static void onServiceStarted()
{
LocationHelper.INSTANCE.addLocationListener(mLocationListener, false);
}
static void onServiceStopped()
{
LocationHelper.INSTANCE.removeLocationListener(mLocationListener);
}
private static native void nativeSetEnabled(boolean enable);
private static native boolean nativeIsEnabled();
private static native void nativeSetDuration(int hours);
private static native int nativeGetDuration();
}

View file

@ -0,0 +1,14 @@
package com.mapswithme.maps.location;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class TrackRecorderWakeReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
TrackRecorder.onWakeAlarm();
}
}

View file

@ -0,0 +1,82 @@
package com.mapswithme.maps.location;
import android.app.IntentService;
import android.content.Intent;
import android.support.annotation.Nullable;
import android.support.v4.content.WakefulBroadcastReceiver;
import java.lang.ref.WeakReference;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import com.mapswithme.maps.MwmApplication;
public class TrackRecorderWakeService extends IntentService
{
private static final long TIMEOUT_MS = 30000;
private static WeakReference<TrackRecorderWakeService> sServiceRef;
private final CountDownLatch mWaitMonitor = new CountDownLatch(1);
private static @Nullable TrackRecorderWakeService getService()
{
if (sServiceRef == null)
return null;
TrackRecorderWakeService res = sServiceRef.get();
if (res == null)
sServiceRef = null;
return res;
}
public TrackRecorderWakeService()
{
super("TrackRecorderWakeService");
}
protected void cancel()
{
mWaitMonitor.countDown();
}
@Override
protected final void onHandleIntent(Intent intent)
{
synchronized (TrackRecorderWakeService.class)
{
TrackRecorderWakeService svc = getService();
if (svc != null)
return;
sServiceRef = new WeakReference<>(this);
}
TrackRecorder.onServiceStarted();
try
{
mWaitMonitor.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
} catch (InterruptedException ignored) {}
synchronized (getClass())
{
sServiceRef = null;
}
TrackRecorder.onServiceStopped();
WakefulBroadcastReceiver.completeWakefulIntent(intent);
}
public synchronized static void start()
{
if (getService() == null)
WakefulBroadcastReceiver.startWakefulService(MwmApplication.get(), new Intent(MwmApplication.get(), TrackRecorderWakeService.class));
}
public synchronized static void stop()
{
TrackRecorderWakeService svc = getService();
if (svc != null)
svc.cancel();
}
}

View file

@ -263,7 +263,7 @@ public class SearchFragment extends BaseMwmFragment
public void onResume()
{
super.onResume();
LocationHelper.INSTANCE.addLocationListener(this);
LocationHelper.INSTANCE.addLocationListener(this, true);
}
@Override

View file

@ -95,7 +95,7 @@ public class DirectionFragment extends DialogFragment implements LocationHelper.
public void onResume()
{
super.onResume();
LocationHelper.INSTANCE.addLocationListener(this);
LocationHelper.INSTANCE.addLocationListener(this, true);
refreshViews();
}