From 00c87da82f7630a509cae5cdeca4799184db8e4f Mon Sep 17 00:00:00 2001 From: alexzatsepin Date: Wed, 11 Jan 2017 18:54:07 +0300 Subject: [PATCH] [android] Fixed the Android native provider, i.e. make it unsubscribe its listeners to release gps provider and save the battery --- .../maps/location/AndroidNativeProvider.java | 36 ++++++++++---- .../maps/location/BaseLocationListener.java | 43 +++++++++++++++++ .../maps/location/BaseLocationProvider.java | 48 +++---------------- .../location/GoogleFusedLocationProvider.java | 44 ++++++++--------- 4 files changed, 96 insertions(+), 75 deletions(-) create mode 100644 android/src/com/mapswithme/maps/location/BaseLocationListener.java diff --git a/android/src/com/mapswithme/maps/location/AndroidNativeProvider.java b/android/src/com/mapswithme/maps/location/AndroidNativeProvider.java index 9c02bc6f90..2fc99c1366 100644 --- a/android/src/com/mapswithme/maps/location/AndroidNativeProvider.java +++ b/android/src/com/mapswithme/maps/location/AndroidNativeProvider.java @@ -2,19 +2,23 @@ package com.mapswithme.maps.location; import android.content.Context; import android.location.Location; +import android.location.LocationListener; import android.location.LocationManager; import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import java.util.List; - import com.mapswithme.maps.MwmApplication; import com.mapswithme.util.LocationUtils; +import java.util.ArrayList; +import java.util.List; + class AndroidNativeProvider extends BaseLocationProvider { private final LocationManager mLocationManager; private boolean mIsActive; + @NonNull + private final List mListeners = new ArrayList<>(); AndroidNativeProvider() { @@ -33,7 +37,11 @@ class AndroidNativeProvider extends BaseLocationProvider mIsActive = true; for (String provider : providers) - mLocationManager.requestLocationUpdates(provider, LocationHelper.INSTANCE.getInterval(), 0, this); + { + LocationListener listener = new BaseLocationListener(); + mLocationManager.requestLocationUpdates(provider, LocationHelper.INSTANCE.getInterval(), 0, listener); + mListeners.add(listener); + } LocationHelper.INSTANCE.startSensors(); @@ -49,19 +57,29 @@ class AndroidNativeProvider extends BaseLocationProvider } } - onLocationChanged(location); + if (location != null) + onLocationChanged(location); + return true; } + private void onLocationChanged(@NonNull Location location) + { + for (LocationListener listener : mListeners) + listener.onLocationChanged(location); + } + @Override protected void stop() { - mLocationManager.removeUpdates(this); + for (LocationListener listener : mListeners) + mLocationManager.removeUpdates(listener); + mListeners.clear(); mIsActive = false; } @Nullable - public static Location findBestNotExpiredLocation(long expirationMillis) + static Location findBestNotExpiredLocation(long expirationMillis) { final LocationManager manager = (LocationManager) MwmApplication.get().getSystemService(Context.LOCATION_SERVICE); return findBestNotExpiredLocation(manager, @@ -70,7 +88,7 @@ class AndroidNativeProvider extends BaseLocationProvider } @Nullable - public static Location findBestNotExpiredLocation(LocationManager manager, List providers, long expirationMillis) + private static Location findBestNotExpiredLocation(LocationManager manager, List providers, long expirationMillis) { Location res = null; for (final String pr : providers) @@ -86,10 +104,10 @@ class AndroidNativeProvider extends BaseLocationProvider } @NonNull - public static List filterProviders(LocationManager locationManager) + private static List filterProviders(LocationManager locationManager) { final List res = locationManager.getProviders(true /* enabledOnly */); res.remove(LocationManager.PASSIVE_PROVIDER); return res; } -} \ No newline at end of file +} diff --git a/android/src/com/mapswithme/maps/location/BaseLocationListener.java b/android/src/com/mapswithme/maps/location/BaseLocationListener.java new file mode 100644 index 0000000000..20d06e5ba2 --- /dev/null +++ b/android/src/com/mapswithme/maps/location/BaseLocationListener.java @@ -0,0 +1,43 @@ +package com.mapswithme.maps.location; + +import android.location.Location; +import android.location.LocationListener; +import android.os.Bundle; + +import com.mapswithme.util.log.DebugLogger; +import com.mapswithme.util.log.Logger; + +class BaseLocationListener implements LocationListener, com.google.android.gms.location.LocationListener +{ + private static final Logger LOGGER = new DebugLogger(BaseLocationListener.class.getSimpleName()); + + @Override + public void onLocationChanged(Location location) + { + // Completely ignore locations without lat and lon + if (location.getAccuracy() <= 0.0) + return; + + LocationHelper.INSTANCE.resetMagneticField(location); + LocationHelper.INSTANCE.onLocationUpdated(location); + LocationHelper.INSTANCE.notifyLocationUpdated(); + } + + @Override + public void onProviderDisabled(String provider) + { + LOGGER.d("Disabled location provider: ", provider); + } + + @Override + public void onProviderEnabled(String provider) + { + LOGGER.d("Enabled location provider: ", provider); + } + + @Override + public void onStatusChanged(String provider, int status, Bundle extras) + { + LOGGER.d("Status changed for location provider: " + provider + "; new status = " + status); + } +} diff --git a/android/src/com/mapswithme/maps/location/BaseLocationProvider.java b/android/src/com/mapswithme/maps/location/BaseLocationProvider.java index e00f644897..eca89437db 100644 --- a/android/src/com/mapswithme/maps/location/BaseLocationProvider.java +++ b/android/src/com/mapswithme/maps/location/BaseLocationProvider.java @@ -1,28 +1,18 @@ package com.mapswithme.maps.location; - import android.location.Location; -import android.location.LocationListener; -import android.os.Bundle; import android.support.annotation.Nullable; import com.mapswithme.util.LocationUtils; import com.mapswithme.util.log.Logger; import com.mapswithme.util.log.SimpleLogger; -abstract class BaseLocationProvider implements LocationListener +abstract class BaseLocationProvider { static final Logger sLogger = SimpleLogger.get(BaseLocationProvider.class.getName()); private static final double DEFAULT_SPEED_MPS = 5; - 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.getDiff(lastLocation, newLocation)); - return (newLocation.getAccuracy() < lastAccuracy); - } - - final boolean isLocationBetterThanLast(@Nullable Location newLocation) + boolean isLocationBetterThanLast(@Nullable Location newLocation) { if (newLocation == null) return false; @@ -31,37 +21,11 @@ abstract class BaseLocationProvider implements LocationListener return (lastLocation == null || isLocationBetterThanLast(newLocation, lastLocation)); } - @Override - public void onLocationChanged(Location location) + boolean isLocationBetterThanLast(Location newLocation, Location lastLocation) { - // Completely ignore locations without lat and lon - if (location.getAccuracy() <= 0.0) - return; - - if (isLocationBetterThanLast(location)) - { - LocationHelper.INSTANCE.resetMagneticField(location); - LocationHelper.INSTANCE.onLocationUpdated(location); - LocationHelper.INSTANCE.notifyLocationUpdated(); - } - } - - @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); + double speed = Math.max(DEFAULT_SPEED_MPS, (newLocation.getSpeed() + lastLocation.getSpeed()) / 2.0); + double lastAccuracy = (lastLocation.getAccuracy() + speed * LocationUtils.getDiff(lastLocation, newLocation)); + return (newLocation.getAccuracy() < lastAccuracy); } /** diff --git a/android/src/com/mapswithme/maps/location/GoogleFusedLocationProvider.java b/android/src/com/mapswithme/maps/location/GoogleFusedLocationProvider.java index 730ebbc472..ef2121b2c7 100644 --- a/android/src/com/mapswithme/maps/location/GoogleFusedLocationProvider.java +++ b/android/src/com/mapswithme/maps/location/GoogleFusedLocationProvider.java @@ -1,7 +1,5 @@ package com.mapswithme.maps.location; -import android.app.Activity; -import android.content.IntentSender; import android.location.Location; import android.os.Bundle; import android.support.annotation.NonNull; @@ -11,7 +9,6 @@ import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.common.api.PendingResult; import com.google.android.gms.common.api.ResultCallback; import com.google.android.gms.common.api.Status; -import com.google.android.gms.location.LocationListener; import com.google.android.gms.location.LocationRequest; import com.google.android.gms.location.LocationServices; import com.google.android.gms.location.LocationSettingsRequest; @@ -21,14 +18,14 @@ import com.mapswithme.maps.MwmApplication; class GoogleFusedLocationProvider extends BaseLocationProvider implements GoogleApiClient.ConnectionCallbacks, - GoogleApiClient.OnConnectionFailedListener, - LocationListener + GoogleApiClient.OnConnectionFailedListener { private static final String GMS_LOCATION_PROVIDER = "fused"; - private final GoogleApiClient mGoogleApiClient; private LocationRequest mLocationRequest; private PendingResult mLocationSettingsResult; + @NonNull + private final BaseLocationListener mListener = new BaseLocationListener(); GoogleFusedLocationProvider() { @@ -39,6 +36,19 @@ class GoogleFusedLocationProvider extends BaseLocationProvider .build(); } + @Override + boolean isLocationBetterThanLast(Location newLocation, Location lastLocation) + { + // We believe that google services always return good locations. + return (isFromFusedProvider(newLocation) || + (!isFromFusedProvider(lastLocation) && super.isLocationBetterThanLast(newLocation, lastLocation))); + } + + private static boolean isFromFusedProvider(Location location) + { + return GMS_LOCATION_PROVIDER.equalsIgnoreCase(location.getProvider()); + } + @Override protected boolean start() { @@ -66,7 +76,7 @@ class GoogleFusedLocationProvider extends BaseLocationProvider protected void stop() { if (mGoogleApiClient.isConnected()) - LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this); + LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, mListener); if (mLocationSettingsResult != null && !mLocationSettingsResult.isCanceled()) mLocationSettingsResult.cancel(); @@ -74,20 +84,6 @@ class GoogleFusedLocationProvider extends BaseLocationProvider mGoogleApiClient.disconnect(); } - @Override - protected boolean isLocationBetterThanLast(Location newLocation, Location lastLocation) - { - // We believe that google services always returns good locations. - return (isFromFusedProvider(newLocation) || - (!isFromFusedProvider(lastLocation) && super.isLocationBetterThanLast(newLocation, lastLocation))); - - } - - private static boolean isFromFusedProvider(Location location) - { - return GMS_LOCATION_PROVIDER.equalsIgnoreCase(location.getProvider()); - } - @Override public void onConnected(Bundle bundle) { @@ -139,11 +135,11 @@ class GoogleFusedLocationProvider extends BaseLocationProvider if (!mGoogleApiClient.isConnected()) return; - LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this); + LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, mListener); LocationHelper.INSTANCE.startSensors(); Location last = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); - if (last != null) - onLocationChanged(last); + if (last != null && isLocationBetterThanLast(last)) + mListener.onLocationChanged(last); } @Override