[android] Refactored geolocation a bit.

This commit is contained in:
Dmitry Yunitsky 2016-08-09 18:53:04 +03:00 committed by Vladimir Byko-Ianko
parent 69ddc9ea2f
commit 9f0bade6e8
6 changed files with 74 additions and 90 deletions

View file

@ -1345,7 +1345,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
}
@Override
public void onLocationUpdated(Location location)
public void onLocationUpdated(@NonNull Location location)
{
if (!mPlacePage.isHidden())
mPlacePage.refreshLocation(location);
@ -1360,7 +1360,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
}
@Override
public void onCompassUpdated(CompassData compass)
public void onCompassUpdated(@NonNull CompassData compass)
{
MapFragment.nativeCompassUpdated(compass.getMagneticNorth(), compass.getTrueNorth(), false);
mPlacePage.refreshAzimuth(compass.getNorth());

View file

@ -3,9 +3,9 @@ package com.mapswithme.maps.location;
import android.content.Context;
import android.location.Location;
import android.location.LocationManager;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import com.mapswithme.maps.MwmApplication;
@ -27,7 +27,7 @@ class AndroidNativeProvider extends BaseLocationProvider
if (mIsActive)
return true;
List<String> providers = filterProviders();
List<String> providers = filterProviders(mLocationManager);
if (providers.isEmpty())
return false;
@ -37,13 +37,16 @@ class AndroidNativeProvider extends BaseLocationProvider
LocationHelper.INSTANCE.startSensors();
Location location = findBestNotExpiredLocation(providers, LocationUtils.LOCATION_EXPIRATION_TIME_MILLIS_SHORT);
Location location = findBestNotExpiredLocation(mLocationManager, providers,
LocationUtils.LOCATION_EXPIRATION_TIME_MILLIS_SHORT);
if (!isLocationBetterThanLast(location))
{
location = LocationHelper.INSTANCE.getSavedLocation();
if (location == null || LocationUtils.isExpired(location, LocationHelper.INSTANCE.getSavedLocationTime(),
LocationUtils.LOCATION_EXPIRATION_TIME_MILLIS_SHORT))
{
return true;
}
}
onLocationChanged(location);
@ -58,35 +61,35 @@ class AndroidNativeProvider extends BaseLocationProvider
}
@Nullable
Location findBestNotExpiredLocation(List<String> providers, long expirationMs)
public static Location findBestNotExpiredLocation(long expirationMillis)
{
final LocationManager manager = (LocationManager) MwmApplication.get().getSystemService(Context.LOCATION_SERVICE);
return findBestNotExpiredLocation(manager,
filterProviders(manager),
expirationMillis);
}
@Nullable
public static Location findBestNotExpiredLocation(LocationManager manager, List<String> providers, long expirationMillis)
{
Location res = null;
for (final String pr : providers)
{
final Location l = mLocationManager.getLastKnownLocation(pr);
if (l != null && !LocationUtils.isExpired(l, l.getTime(), expirationMs))
{
if (res == null || res.getAccuracy() > l.getAccuracy())
res = l;
}
final Location last = manager.getLastKnownLocation(pr);
if (last == null || LocationUtils.isExpired(last, last.getTime(), expirationMillis))
continue;
if (res == null || res.getAccuracy() > last.getAccuracy())
res = last;
}
return res;
}
List<String> filterProviders()
@NonNull
public static List<String> filterProviders(LocationManager locationManager)
{
List<String> allProviders = mLocationManager.getProviders(false);
List<String> res = new ArrayList<>(allProviders.size());
for (final String provider : allProviders)
{
if (LocationManager.PASSIVE_PROVIDER.equals(provider))
continue;
if (mLocationManager.isProviderEnabled(provider))
res.add(provider);
}
final List<String> res = locationManager.getProviders(true /* enabledOnly */);
res.remove(LocationManager.PASSIVE_PROVIDER);
return res;
}
}

View file

@ -4,6 +4,7 @@ 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;
@ -21,7 +22,7 @@ abstract class BaseLocationProvider implements LocationListener
return (newLocation.getAccuracy() < lastAccuracy);
}
final boolean isLocationBetterThanLast(Location newLocation)
final boolean isLocationBetterThanLast(@Nullable Location newLocation)
{
if (newLocation == null)
return false;
@ -62,6 +63,9 @@ abstract class BaseLocationProvider implements LocationListener
sLogger.d("Status changed for location provider: ", provider, status);
}
/**
* @return whether location polling was started successfully.
*/
protected abstract boolean start();
protected abstract void stop();
}

View file

@ -42,7 +42,7 @@ class GoogleFusedLocationProvider extends BaseLocationProvider
@Override
protected boolean start()
{
if (mGoogleApiClient == null || mGoogleApiClient.isConnected() || mGoogleApiClient.isConnecting())
if (mGoogleApiClient.isConnected() || mGoogleApiClient.isConnecting())
return true;
mLocationRequest = LocationRequest.create();
@ -65,9 +65,6 @@ class GoogleFusedLocationProvider extends BaseLocationProvider
@Override
protected void stop()
{
if (mGoogleApiClient == null)
return;
if (mGoogleApiClient.isConnected())
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);

View file

@ -4,11 +4,11 @@ import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Location;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import java.lang.ref.WeakReference;
import java.util.List;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
@ -46,7 +46,6 @@ public enum LocationHelper
private static final long INTERVAL_NAVIGATION_BICYCLE_MS = 1000;
private static final long INTERVAL_NAVIGATION_PEDESTRIAN_MS = 1000;
private static final long STOP_DELAY_MS = 5000;
static final int REQUEST_RESOLVE_ERROR = 101;
@ -54,8 +53,8 @@ public enum LocationHelper
{
Activity getActivity();
void onMyPositionModeChanged(int newMode);
void onLocationUpdated(Location location);
void onCompassUpdated(CompassData compass);
void onLocationUpdated(@NonNull Location location);
void onCompassUpdated(@NonNull CompassData compass);
boolean shouldNotifyLocationNotFound();
}
@ -131,10 +130,11 @@ public enum LocationHelper
private boolean mActive;
private boolean mLocationStopped;
private boolean mColdStart = true;
private boolean mPendingNoLocation;
private Location mSavedLocation;
private MapObject mMyPosition;
private long mLastLocationTime;
private long mSavedLocationTime;
private final SensorHelper mSensorHelper = new SensorHelper();
private BaseLocationProvider mLocationProvider;
@ -146,7 +146,6 @@ public enum LocationHelper
private boolean mHighAccuracy;
private CompassData mCompassData;
private boolean mPendingNoLocation;
@SuppressWarnings("FieldCanBeLocal")
private final LocationState.ModeChangeListener mModeChangeListener = new LocationState.ModeChangeListener()
@ -235,14 +234,17 @@ public enum LocationHelper
startInternal();
}
public void onLocationUpdated(Location location)
public void onLocationUpdated(@NonNull Location location)
{
mSavedLocation = location;
mMyPosition = null;
mLastLocationTime = System.currentTimeMillis();
mSavedLocationTime = System.currentTimeMillis();
notifyLocationUpdated();
}
/**
* @return MapObject.MY_POSITION, null if location is not yet determined or "My position" button is switched off.
*/
@Nullable
public MapObject getMyPosition()
{
@ -266,9 +268,10 @@ public enum LocationHelper
* <p>If you need the location regardless of the button's state, use {@link #getLastKnownLocation()}.
* @return {@code null} if no location is saved or "My position" button is in "No follow, no position" mode.
*/
@Nullable
public Location getSavedLocation() { return mSavedLocation; }
public long getSavedLocationTime() { return mLastLocationTime; }
public long getSavedLocationTime() { return mSavedLocationTime; }
void notifyCompassUpdated(long time, double magneticNorth, double trueNorth, double accuracy)
{
@ -350,7 +353,7 @@ public enum LocationHelper
public void onClick(DialogInterface dialog, int which)
{
mLocationStopped = false;
onMyPositionButtonClicked();
LocationState.nativeSwitchToNextMode();
}
}).setOnDismissListener(new DialogInterface.OnDismissListener()
{
@ -394,7 +397,7 @@ public enum LocationHelper
mLogger.d("onActivityResult(): success: " + !mLocationStopped);
if (!mLocationStopped)
onMyPositionButtonClicked();
LocationState.nativeSwitchToNextMode();
return true;
}
@ -611,6 +614,23 @@ public enum LocationHelper
}
mUiCallback = callback;
compareWithPreviousCallback();
Utils.keepScreenOn(true, mUiCallback.getActivity().getWindow());
mUiCallback.onMyPositionModeChanged(LocationState.getMode());
if (mCompassData != null)
mUiCallback.onCompassUpdated(mCompassData);
if (hasPendingNoLocation())
notifyLocationNotFound();
if (!mLocationStopped)
addListener(mLocationListener, true);
}
private void compareWithPreviousCallback()
{
if (mPrevUiCallback != null)
{
UiCallback prev = mPrevUiCallback.get();
@ -620,21 +640,7 @@ public enum LocationHelper
setHasPendingNoLocation(false);
}
}
Utils.keepScreenOn(true, mUiCallback.getActivity().getWindow());
int mode = LocationState.getMode();
mUiCallback.onMyPositionModeChanged(mode);
if (mCompassData != null)
mUiCallback.onCompassUpdated(mCompassData);
mPrevUiCallback = new WeakReference<>(mUiCallback);
if (hasPendingNoLocation())
notifyLocationNotFound();
if (!mLocationStopped)
addListener(mLocationListener, true);
}
/**
@ -655,57 +661,33 @@ public enum LocationHelper
removeListener(mLocationListener, delayed);
}
public void onMyPositionButtonClicked()
{
int mode = LocationState.getMode();
mLogger.d("onMyPositionButtonClicked(). Mode was: " + LocationState.nameOf(mode));
if (mode == LocationState.PENDING_POSITION)
{
mLogger.d("Pending. Skip");
return;
}
mLocationStopped = false;
LocationState.nativeSwitchToNextMode();
}
/**
* Obtains last known location regardless of "My position" button state.
* @return {@code null} on failure.
*/
public @Nullable Location getLastKnownLocation(long expirationMs)
@Nullable
public Location getLastKnownLocation(long expirationMillis)
{
if (mSavedLocation != null)
return mSavedLocation;
AndroidNativeProvider provider = new AndroidNativeProvider()
{
@Override
public void onLocationChanged(Location location)
{
// Block ancestor
}
};
List<String> providers = provider.filterProviders();
if (providers.isEmpty())
return null;
return provider.findBestNotExpiredLocation(providers, expirationMs);
return AndroidNativeProvider.findBestNotExpiredLocation(expirationMillis);
}
public @Nullable Location getLastKnownLocation()
@Nullable
public Location getLastKnownLocation()
{
return getLastKnownLocation(LocationUtils.LOCATION_EXPIRATION_TIME_MILLIS_LONG);
}
@Nullable
public CompassData getCompassData()
{
return mCompassData;
}
private 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 void nativeLocationUpdated(long time, double lat, double lon, float accuracy,
double altitude, float speed, float bearing);
static native float[] nativeUpdateCompassSensor(int ind, float[] arr);
}

View file

@ -8,7 +8,6 @@ import android.widget.ImageView;
import com.mapswithme.maps.LocationState;
import com.mapswithme.maps.R;
import com.mapswithme.maps.location.LocationHelper;
import com.mapswithme.util.Graphics;
import com.mapswithme.util.ThemeUtils;
import com.mapswithme.util.statistics.AlohaHelper;
@ -27,8 +26,7 @@ public class MyPositionButton
@Override
public void onClick(View v)
{
LocationHelper.INSTANCE.onMyPositionButtonClicked();
LocationState.nativeSwitchToNextMode();
Statistics.INSTANCE.trackEvent(Statistics.EventName.TOOLBAR_MY_POSITION);
AlohaHelper.logClick(AlohaHelper.TOOLBAR_MY_POSITION);
}