[android] Refactored location code regarding the first run mode

This commit is contained in:
alexzatsepin 2017-02-09 17:18:00 +03:00
parent 3e22c24ef7
commit e294e16550
10 changed files with 114 additions and 125 deletions

View file

@ -54,7 +54,6 @@ public class MapFragment extends BaseMwmFragment
private int mWidth;
private boolean mRequireResize;
private boolean mContextCreated;
private boolean mFirstStart;
private static boolean sWasCopyrightDisplayed;
interface MapRenderingListener
@ -167,11 +166,11 @@ public class MapFragment extends BaseMwmFragment
getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
final float exactDensityDpi = metrics.densityDpi;
mFirstStart = ((MwmActivity) getMwmActivity()).isFirstStart();
if (mFirstStart)
boolean firstStart = ((MwmActivity) getMwmActivity()).isFirstStart();
if (firstStart)
PushwooshHelper.nativeProcessFirstLaunch();
if (!nativeCreateEngine(surface, (int) exactDensityDpi, mFirstStart))
if (!nativeCreateEngine(surface, (int) exactDensityDpi, firstStart))
{
reportUnsupported();
return;
@ -286,13 +285,6 @@ public class MapFragment extends BaseMwmFragment
}
}
boolean isFirstStart()
{
boolean res = mFirstStart;
mFirstStart = false;
return res;
}
boolean isContextCreated()
{
return mContextCreated;

View file

@ -1010,21 +1010,9 @@ public class MwmActivity extends BaseMwmFragmentActivity
{
mFirstStart = FirstStartFragment.showOn(this);
if (mFirstStart)
{
if (LocationHelper.INSTANCE.isTurnedOn())
addTask(new MwmActivity.MapTask()
{
@Override
public boolean run(MwmActivity target)
{
//TODO: Check and remove
if (LocationHelper.INSTANCE.isTurnedOn())
LocationHelper.INSTANCE.switchToNextMode();
return false;
}
});
}
else if (!NewsFragment.showOn(this))
return;
if (!NewsFragment.showOn(this))
{
if (ViralFragment.shouldDisplay())
new ViralFragment().show(getSupportFragmentManager(), "");
@ -1832,9 +1820,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
@Override
public void onLocationNotFound()
{
if (!shouldNotifyLocationNotFound())
return;
showLocationNotFoundDialog();
}
@ -1855,11 +1840,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
}).show();
}
private boolean shouldNotifyLocationNotFound()
{
return mMapFragment != null && !mMapFragment.isFirstStart();
}
public static class ShowAuthorizationTask implements MapTask
{
@Override

View file

@ -33,7 +33,7 @@ class AndroidNativeProvider extends BaseLocationProvider
@Override
protected void start()
{
sLogger.d(TAG, "Android native provider is started");
LOGGER.d(TAG, "Android native provider is started");
if (isActive())
return;
@ -47,9 +47,11 @@ class AndroidNativeProvider extends BaseLocationProvider
setActive(true);
for (String provider : providers)
{
sLogger.d(TAG, "Request location updates from the provider: " + provider);
LocationListener listener = new BaseLocationListener(getLocationFixChecker());
mLocationManager.requestLocationUpdates(provider, LocationHelper.INSTANCE.getInterval(), 0, listener);
long interval = LocationHelper.INSTANCE.getInterval();
LOGGER.d(TAG, "Request Android native provider '" + provider
+ "' to get locations at this interval = " + interval + " ms");
mLocationManager.requestLocationUpdates(provider, interval, 0, listener);
mListeners.add(listener);
}
@ -85,7 +87,7 @@ class AndroidNativeProvider extends BaseLocationProvider
@Override
protected void stop()
{
sLogger.d(TAG, "Android native provider is stopped");
LOGGER.d(TAG, "Android native provider is stopped");
ListIterator<LocationListener> iterator = mListeners.listIterator();
// noinspection WhileLoopReplaceableByForEach
while (iterator.hasNext())

View file

@ -7,7 +7,7 @@ import com.mapswithme.util.log.LoggerFactory;
abstract class BaseLocationProvider
{
static final Logger sLogger = LoggerFactory.INSTANCE.getLogger(LoggerFactory.Type.LOCATION);
static final Logger LOGGER = LoggerFactory.INSTANCE.getLogger(LoggerFactory.Type.LOCATION);
private static final String TAG = BaseLocationProvider.class.getSimpleName();
@NonNull
private final LocationFixChecker mLocationFixChecker;
@ -37,7 +37,7 @@ abstract class BaseLocationProvider
final void setActive(boolean active)
{
sLogger.d(TAG, "setActive active = " + active);
LOGGER.d(TAG, "setActive active = " + active);
mActive = active;
}
}

View file

@ -41,7 +41,7 @@ class GoogleFusedLocationProvider extends BaseLocationProvider
@Override
protected void start()
{
sLogger.d(TAG, "Google fused provider is started");
LOGGER.d(TAG, "Google fused provider is started");
if (mGoogleApiClient.isConnected() || mGoogleApiClient.isConnecting())
{
setActive(true);
@ -52,6 +52,8 @@ class GoogleFusedLocationProvider extends BaseLocationProvider
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
long interval = LocationHelper.INSTANCE.getInterval();
mLocationRequest.setInterval(interval);
LOGGER.d(TAG, "Request Google fused provider to provide locations at this interval = "
+ interval + " ms");
mLocationRequest.setFastestInterval(interval / 2);
mGoogleApiClient.connect();
@ -61,7 +63,7 @@ class GoogleFusedLocationProvider extends BaseLocationProvider
@Override
protected void stop()
{
sLogger.d(TAG, "Google fused provider is stopped");
LOGGER.d(TAG, "Google fused provider is stopped");
if (mGoogleApiClient.isConnected())
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, mListener);
@ -75,13 +77,13 @@ class GoogleFusedLocationProvider extends BaseLocationProvider
@Override
public void onConnected(Bundle bundle)
{
sLogger.d(TAG, "Fused onConnected. Bundle " + bundle);
LOGGER.d(TAG, "Fused onConnected. Bundle " + bundle);
checkSettingsAndRequestUpdates();
}
private void checkSettingsAndRequestUpdates()
{
sLogger.d(TAG, "checkSettingsAndRequestUpdates()");
LOGGER.d(TAG, "checkSettingsAndRequestUpdates()");
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(mLocationRequest);
builder.setAlwaysShow(true); // hides 'never' button in resolve dialog afterwards.
mLocationSettingsResult = LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());
@ -91,7 +93,7 @@ class GoogleFusedLocationProvider extends BaseLocationProvider
public void onResult(@NonNull LocationSettingsResult locationSettingsResult)
{
final Status status = locationSettingsResult.getStatus();
sLogger.d(TAG, "onResult status: " + status);
LOGGER.d(TAG, "onResult status: " + status);
switch (status.getStatusCode())
{
case LocationSettingsStatusCodes.SUCCESS:
@ -116,7 +118,7 @@ class GoogleFusedLocationProvider extends BaseLocationProvider
private static void resolveResolutionRequired()
{
sLogger.d(TAG, "resolveResolutionRequired()");
LOGGER.d(TAG, "resolveResolutionRequired()");
LocationHelper.INSTANCE.initNativeProvider();
LocationHelper.INSTANCE.start();
}
@ -137,14 +139,14 @@ class GoogleFusedLocationProvider extends BaseLocationProvider
public void onConnectionSuspended(int i)
{
setActive(false);
sLogger.d(TAG, "Fused onConnectionSuspended. Code " + i);
LOGGER.d(TAG, "Fused onConnectionSuspended. Code " + i);
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult)
{
setActive(false);
sLogger.d(TAG, "Fused onConnectionFailed. Fall back to native provider. ConnResult " + connectionResult);
LOGGER.d(TAG, "Fused onConnectionFailed. Fall back to native provider. ConnResult " + connectionResult);
// TODO handle error in a smarter way
LocationHelper.INSTANCE.initNativeProvider();
LocationHelper.INSTANCE.start();

View file

@ -4,6 +4,7 @@ import android.app.Activity;
import android.location.Location;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
@ -43,7 +44,7 @@ public enum LocationHelper
private final TransitionListener mOnTransition = new TransitionListener();
@NonNull
private final LocationListener mLocationListener = new LocationListener()
private final LocationListener mCoreLocationListener = new LocationListener()
{
@Override
public void onLocationUpdated(Location location)
@ -93,7 +94,7 @@ public enum LocationHelper
@Override
public String toString()
{
return "LocationHelper.mLocationListener";
return "LocationHelper.mCoreLocationListener";
}
};
@ -109,12 +110,12 @@ public enum LocationHelper
@Nullable
private BaseLocationProvider mLocationProvider;
@NonNull
private final LocationPredictor mPredictor = new LocationPredictor(mLocationListener);
private final LocationPredictor mPredictor = new LocationPredictor(mCoreLocationListener);
@Nullable
private UiCallback mUiCallback;
private long mInterval;
private CompassData mCompassData;
private boolean mInFirstRun;
@SuppressWarnings("FieldCanBeLocal")
private final LocationState.ModeChangeListener mMyPositionModeListener =
@ -135,6 +136,14 @@ public enum LocationHelper
switch (newMode)
{
case LocationState.NOT_FOLLOW_NO_POSITION:
// In the first run mode, the NOT_FOLLOW_NO_POSITION state doesn't mean that location
// is actually not found.
if (mInFirstRun)
{
mLogger.i(TAG, "It's the first run, so this state should be skipped");
return;
}
stop();
if (LocationUtils.areLocationServicesTurnedOn())
notifyLocationNotFound();
@ -149,7 +158,7 @@ public enum LocationHelper
mLogger.d(LocationHelper.class.getSimpleName(), "ctor()");
}
@android.support.annotation.UiThread
@UiThread
public void initialize()
{
initProvider();
@ -248,6 +257,15 @@ public enum LocationHelper
return;
}
// If we are still in the first run mode, i.e. user stays on the first run screens,
// not on the map, we mustn't post location update to the core. Only this preserving allows us
// to play nice zoom animation once a user will see map.
if (mInFirstRun)
{
mLogger.d(TAG, "Location update is obtained, but ignore, because it's a first run mode");
return;
}
for (LocationListener listener : mListeners)
listener.onLocationUpdated(mSavedLocation);
mListeners.finishIterate();
@ -308,7 +326,7 @@ public enum LocationHelper
* @param listener listener to register.
* @param forceUpdate instantly notify given listener about available location, if any.
*/
@android.support.annotation.UiThread
@UiThread
public void addListener(@NonNull LocationListener listener, boolean forceUpdate)
{
mLogger.d(TAG, "addListener(): " + listener + ", forceUpdate: " + forceUpdate);
@ -320,7 +338,7 @@ public enum LocationHelper
notifyLocationUpdated(listener);
}
@android.support.annotation.UiThread
@UiThread
/**
* Removes given location listener.
* @param listener listener to unregister.
@ -411,7 +429,7 @@ public enum LocationHelper
}
/**
* Adds the {@link #mLocationListener} to listen location updates and notify UI.
* Adds the {@link #mCoreLocationListener} to listen location updates and notify UI.
* Notifies about {@link #ERROR_DENIED} if there are no enabled location providers.
* Calculates minimum time interval for location updates.
* Starts polling location updates.
@ -423,11 +441,13 @@ public enum LocationHelper
if (mLocationProvider.isActive())
throw new AssertionError("Location provider '" + mLocationProvider + "' must be stopped first");
addListener(mLocationListener, true);
addListener(mCoreLocationListener, true);
if (!LocationUtils.checkProvidersAvailability())
{
notifyLocationError(ERROR_DENIED);
// No need to notify about an error in first run mode
if (!mInFirstRun)
notifyLocationError(ERROR_DENIED);
return;
}
@ -439,8 +459,8 @@ public enum LocationHelper
}
/**
* Stops the polling location updates, i.e. removes the {@link #mLocationListener} and stops
* the current active provider. If the provider is not active the assertion error will be thrown.
* Stops the polling location updates, i.e. removes the {@link #mCoreLocationListener} and stops
* the current active provider.
*/
private void stop()
{
@ -453,7 +473,7 @@ public enum LocationHelper
return;
}
removeListener(mLocationListener);
removeListener(mCoreLocationListener);
stopInternal();
}
@ -462,7 +482,9 @@ public enum LocationHelper
*/
private void startInternal()
{
mLogger.d(TAG, "startInternal(), current provider is '" + mLocationProvider + "'");
mLogger.d(TAG, "startInternal(), current provider is '" + mLocationProvider
+ "' , my position mode = " + LocationState.nameOf(getMyPositionMode())
+ ", mInFirstRun = " + mInFirstRun);
checkProviderInitialization();
//noinspection ConstantConditions
mLocationProvider.start();
@ -470,7 +492,7 @@ public enum LocationHelper
if (mLocationProvider.isActive())
{
if (getMyPositionMode() == LocationState.NOT_FOLLOW_NO_POSITION)
if (!mInFirstRun && getMyPositionMode() == LocationState.NOT_FOLLOW_NO_POSITION)
switchToNextMode();
mPredictor.resume();
}
@ -502,7 +524,7 @@ public enum LocationHelper
/**
* Attach UI to helper.
*/
@android.support.annotation.UiThread
@UiThread
public void attach(@NonNull UiCallback callback)
{
mLogger.d(TAG, "attach() callback = " + callback);
@ -526,7 +548,7 @@ public enum LocationHelper
if (mLocationProvider.isActive())
{
mLogger.d(TAG, "attach() provider '" + mLocationProvider + "' is active, just add the listener");
addListener(mLocationListener, true);
addListener(mCoreLocationListener, true);
}
else
{
@ -537,6 +559,7 @@ public enum LocationHelper
/**
* Detach UI from helper.
*/
@UiThread
public void detach(boolean delayed)
{
mLogger.d(TAG, "detach(), delayed: " + delayed);
@ -552,6 +575,46 @@ public enum LocationHelper
stop();
}
@UiThread
public void onEnteredIntoFirstRun()
{
mLogger.i(TAG, "onEnteredIntoFirstRun");
mInFirstRun = true;
}
@UiThread
public void onExitFromFirstRun()
{
mLogger.i(TAG, "onExitFromFirstRun");
if (!mInFirstRun)
throw new AssertionError("Must be called only after 'onEnteredIntoFirstRun' method!");
mInFirstRun = false;
if (getMyPositionMode() != LocationState.NOT_FOLLOW_NO_POSITION)
throw new AssertionError("My position mode must be equal NOT_FOLLOW_NO_POSITION");
// If there is a location we need just to pass it to the listeners, so that
// my position state machine will be switched to the FOLLOW state.
Location location = getSavedLocation();
if (location != null)
{
notifyLocationUpdated();
mLogger.d(TAG, "Current location is available, so play the nice zoom animation");
Framework.nativeZoomToPoint(location.getLatitude(), location.getLongitude(), 14, true);
return;
}
checkProviderInitialization();
// If the location hasn't been obtained yet we need to switch to the next mode and wait for locations.
// Otherwise, try to restart location updates polling.
// noinspection ConstantConditions
if (mLocationProvider.isActive())
switchToNextMode();
else
restart();
}
/**
* Obtains last known location regardless of "My position" button state.
* @return {@code null} on failure.

View file

@ -15,7 +15,6 @@ public final class LocationState
@Retention(RetentionPolicy.SOURCE)
@IntDef({ PENDING_POSITION, NOT_FOLLOW_NO_POSITION, NOT_FOLLOW, FOLLOW, FOLLOW_AND_ROTATE})
@interface Value {}
// These values should correspond to location::EMyPositionMode enum (from platform/location.hpp)

View file

@ -277,7 +277,7 @@ abstract class BaseNewsFragment extends BaseMwmDialogFragment
@Override
public void onClick(View v)
{
dismissAllowingStateLoss();
onDoneClick();
}
});
@ -285,6 +285,11 @@ abstract class BaseNewsFragment extends BaseMwmDialogFragment
return res;
}
protected void onDoneClick()
{
dismissAllowingStateLoss();
}
@SuppressWarnings("TryWithIdenticalCatches")
static void create(FragmentActivity activity, Class<? extends BaseNewsFragment> clazz)
{

View file

@ -1,43 +1,18 @@
package com.mapswithme.maps.news;
import android.app.Dialog;
import android.content.DialogInterface;
import android.location.Location;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import com.mapswithme.maps.BuildConfig;
import com.mapswithme.maps.Framework;
import com.mapswithme.maps.R;
import com.mapswithme.maps.location.LocationHelper;
import com.mapswithme.maps.location.LocationListener;
import com.mapswithme.util.Config;
import com.mapswithme.util.statistics.Statistics;
public class FirstStartFragment extends BaseNewsFragment
{
private static Location sLocation;
private static int sError = LocationHelper.ERROR_UNKNOWN;
private final LocationListener mLocationListener = new LocationListener.Simple()
{
@Override
public void onLocationUpdated(Location location)
{
sLocation = location;
sError = LocationHelper.ERROR_UNKNOWN;
}
@Override
public void onLocationError(int errorCode)
{
sLocation = null;
sError = errorCode;
}
};
private class Adapter extends BaseNewsFragment.Adapter
{
@Override
@ -87,37 +62,15 @@ public class FirstStartFragment extends BaseNewsFragment
@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
LocationHelper.INSTANCE.addListener(mLocationListener, true);
LocationHelper.INSTANCE.onEnteredIntoFirstRun();
return super.onCreateDialog(savedInstanceState);
}
@Override
public void onDismiss(DialogInterface dialog)
protected void onDoneClick()
{
super.onDismiss(dialog);
if (sLocation == null)
{
String reason;
switch (sError)
{
case LocationHelper.ERROR_DENIED:
reason = "unavailable";
break;
default:
Statistics.INSTANCE.trackEvent(Statistics.EventName.FIRST_START_DONT_ZOOM);
return;
}
Statistics.INSTANCE.trackEvent(Statistics.EventName.FIRST_START_NO_LOCATION, Statistics.params().add("reason", reason));
return;
}
Framework.nativeZoomToPoint(sLocation.getLatitude(), sLocation.getLongitude(), 14, true);
sLocation = null;
LocationHelper.INSTANCE.removeListener(mLocationListener);
super.onDoneClick();
LocationHelper.INSTANCE.onExitFromFirstRun();
}
public static boolean showOn(FragmentActivity activity)
@ -136,8 +89,6 @@ public class FirstStartFragment extends BaseNewsFragment
create(activity, FirstStartFragment.class);
Config.setFirstStartDialogSeen();
Statistics.INSTANCE.trackEvent(Statistics.EventName.FIRST_START_SHOWN);
return true;
}
}

View file

@ -47,11 +47,6 @@ public enum Statistics
public static final String DOWNLOADER_ACTION = "Downloader_Map_action";
public static final String DOWNLOADER_CANCEL = "Downloader_Cancel_downloading";
// First start
public static final String FIRST_START_SHOWN = "FirstStart_Dialog_show";
public static final String FIRST_START_NO_LOCATION = "FirstStart_Location_disable";
public static final String FIRST_START_DONT_ZOOM = "FirstStart_ZAnimation_disable";
// bookmarks
public static final String BMK_DESCRIPTION_CHANGED = "Bookmark. Description changed";
public static final String BMK_GROUP_CREATED = "Bookmark. Group created";