[android] Fixed the Android native provider, i.e. make it unsubscribe its listeners to release gps provider and save the battery

This commit is contained in:
alexzatsepin 2017-01-11 18:54:07 +03:00
parent 15c4bc0d52
commit 00c87da82f
4 changed files with 96 additions and 75 deletions

View file

@ -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<LocationListener> 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<String> providers, long expirationMillis)
private static Location findBestNotExpiredLocation(LocationManager manager, List<String> providers, long expirationMillis)
{
Location res = null;
for (final String pr : providers)
@ -86,10 +104,10 @@ class AndroidNativeProvider extends BaseLocationProvider
}
@NonNull
public static List<String> filterProviders(LocationManager locationManager)
private static List<String> filterProviders(LocationManager locationManager)
{
final List<String> res = locationManager.getProviders(true /* enabledOnly */);
res.remove(LocationManager.PASSIVE_PROVIDER);
return res;
}
}
}

View file

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

View file

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

View file

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