forked from organicmaps/organicmaps
[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:
parent
15c4bc0d52
commit
00c87da82f
4 changed files with 96 additions and 75 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue