Merge pull request #5181 from alexzatsepin/MAPSME-2870-location-service-system-dialog

[android] Reduced shows of annoying Location Error dialog
This commit is contained in:
Aleksandr Zatsepin 2017-01-16 11:02:41 +03:00 committed by GitHub
commit 07dbaa9e81
9 changed files with 156 additions and 63 deletions

View file

@ -17,28 +17,28 @@ static void LocationStateModeChanged(location::EMyPositionMode mode, shared_ptr<
// public static void nativeSwitchToNextMode();
JNIEXPORT void JNICALL
Java_com_mapswithme_maps_LocationState_nativeSwitchToNextMode(JNIEnv * env, jclass clazz)
Java_com_mapswithme_maps_location_LocationState_nativeSwitchToNextMode(JNIEnv * env, jclass clazz)
{
g_framework->SwitchMyPositionNextMode();
}
// private static int nativeGetMode();
JNIEXPORT jint JNICALL
Java_com_mapswithme_maps_LocationState_nativeGetMode(JNIEnv * env, jclass clazz)
Java_com_mapswithme_maps_location_LocationState_nativeGetMode(JNIEnv * env, jclass clazz)
{
return g_framework->GetMyPositionMode();
}
// public static void nativeSetListener(ModeChangeListener listener);
JNIEXPORT void JNICALL
Java_com_mapswithme_maps_LocationState_nativeSetListener(JNIEnv * env, jclass clazz, jobject listener)
Java_com_mapswithme_maps_location_LocationState_nativeSetListener(JNIEnv * env, jclass clazz, jobject listener)
{
g_framework->SetMyPositionModeListener(bind(&LocationStateModeChanged, _1, jni::make_global_ref(listener)));
}
// public static void nativeRemoveListener();
JNIEXPORT void JNICALL
Java_com_mapswithme_maps_LocationState_nativeRemoveListener(JNIEnv * env, jclass clazz)
Java_com_mapswithme_maps_location_LocationState_nativeRemoveListener(JNIEnv * env, jclass clazz)
{
g_framework->SetMyPositionModeListener(location::TMyPositionModeChanged());
}

View file

@ -2,6 +2,7 @@ package com.mapswithme.maps;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Rect;
@ -129,6 +130,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
// Instance state
private static final String STATE_PP = "PpState";
private static final String STATE_MAP_OBJECT = "MapObject";
private static final String EXTRA_LOCATION_DIALOG_IS_ANNOYING = "LOCATION_DIALOG_IS_ANNOYING";
// Map tasks that we run AFTER rendering initialized
private final Stack<MapTask> mTasks = new Stack<>();
@ -173,6 +175,21 @@ public class MwmActivity extends BaseMwmFragmentActivity
private boolean mFirstStart;
private boolean mPlacePageRestored;
private boolean mLocationErrorDialogAnnoying = false;
@NonNull
private final OnClickListener mOnMyPositionClickListener = new OnClickListener()
{
@Override
public void onClick(View v)
{
mLocationErrorDialogAnnoying = false;
LocationHelper.INSTANCE.switchToNextMode();
Statistics.INSTANCE.trackEvent(Statistics.EventName.TOOLBAR_MY_POSITION);
AlohaHelper.logClick(AlohaHelper.TOOLBAR_MY_POSITION);
}
};
public interface LeftAnimationTrackListener
{
void onTrackStarted(boolean collapsed);
@ -430,6 +447,9 @@ public class MwmActivity extends BaseMwmFragmentActivity
{
super.onCreate(savedInstanceState);
if (savedInstanceState != null)
mLocationErrorDialogAnnoying = savedInstanceState.getBoolean(EXTRA_LOCATION_DIALOG_IS_ANNOYING);
mIsFragmentContainer = getResources().getBoolean(R.bool.tabletLayout);
if (!mIsFragmentContainer && (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP))
@ -602,7 +622,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
View zoomOut = frame.findViewById(R.id.nav_zoom_out);
zoomOut.setOnClickListener(this);
View myPosition = frame.findViewById(R.id.my_position);
mNavMyPosition = new MyPositionButton(myPosition);
mNavMyPosition = new MyPositionButton(myPosition, mOnMyPositionClickListener);
ImageButton traffic = (ImageButton) frame.findViewById(R.id.traffic);
mTraffic = new TrafficButton(this, traffic);
mTrafficButtonController = new TrafficButtonController(mTraffic, this);
@ -842,6 +862,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
mNavigationController.onSaveState(outState);
RoutingController.get().onSaveState();
outState.putBoolean(EXTRA_LOCATION_DIALOG_IS_ANNOYING, mLocationErrorDialogAnnoying);
super.onSaveInstanceState(outState);
}
@ -960,14 +981,14 @@ public class MwmActivity extends BaseMwmFragmentActivity
mFirstStart = FirstStartFragment.showOn(this);
if (mFirstStart)
{
if (LocationState.isTurnedOn())
if (LocationHelper.INSTANCE.isTurnedOn())
addTask(new MwmActivity.MapTask()
{
@Override
public boolean run(MwmActivity target)
{
if (LocationState.isTurnedOn())
LocationState.nativeSwitchToNextMode();
if (LocationHelper.INSTANCE.isTurnedOn())
LocationHelper.INSTANCE.switchToNextMode();
return false;
}
});
@ -1733,4 +1754,53 @@ public class MwmActivity extends BaseMwmFragmentActivity
{
return (mMapFragment != null && !mMapFragment.isFirstStart());
}
@Override
public void onLocationError()
{
if (mLocationErrorDialogAnnoying)
return;
Intent intent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
if (intent.resolveActivity(MwmApplication.get().getPackageManager()) == null)
{
intent = new Intent(android.provider.Settings.ACTION_SECURITY_SETTINGS);
if (intent.resolveActivity(MwmApplication.get().getPackageManager()) == null)
return;
}
showLocationErrorDialog(intent);
}
private void showLocationErrorDialog(@NonNull final Intent intent)
{
new AlertDialog.Builder(this)
.setTitle(R.string.enable_location_services)
.setMessage(R.string.location_is_disabled_long_text)
.setNegativeButton(R.string.close, new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
mLocationErrorDialogAnnoying = true;
}
})
.setOnCancelListener(new DialogInterface.OnCancelListener()
{
@Override
public void onCancel(DialogInterface dialog)
{
mLocationErrorDialogAnnoying = true;
}
})
.setPositiveButton(R.string.connection_settings, new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
//TODO: try to use startActivityForResult to handle settings result back
startActivity(intent);
}
}).show();
}
}

View file

@ -6,6 +6,7 @@ import android.content.res.Resources;
import android.support.annotation.NonNull;
import android.view.View;
import com.mapswithme.maps.location.LocationState;
import com.mapswithme.maps.routing.RoutingController;
import com.mapswithme.util.Animations;
import com.mapswithme.util.Config;

View file

@ -93,6 +93,7 @@ class GoogleFusedLocationProvider extends BaseLocationProvider
private void checkSettingsAndRequestUpdates()
{
sLogger.d("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());
@ -102,6 +103,7 @@ class GoogleFusedLocationProvider extends BaseLocationProvider
public void onResult(@NonNull LocationSettingsResult locationSettingsResult)
{
final Status status = locationSettingsResult.getStatus();
sLogger.d("onResult status: " + status);
switch (status.getStatusCode())
{
case LocationSettingsStatusCodes.SUCCESS:
@ -124,6 +126,7 @@ class GoogleFusedLocationProvider extends BaseLocationProvider
private static void resolveError(Status status)
{
sLogger.d("resolveError()");
if (LocationHelper.INSTANCE.isLocationStopped())
return;

View file

@ -9,14 +9,12 @@ import android.location.LocationManager;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import java.lang.ref.WeakReference;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.mapswithme.maps.Framework;
import com.mapswithme.maps.LocationState;
import com.mapswithme.maps.MwmApplication;
import com.mapswithme.maps.R;
import com.mapswithme.maps.bookmarks.data.Banner;
@ -55,12 +53,15 @@ public enum LocationHelper
private static final long STOP_DELAY_MS = 5000;
static final int REQUEST_RESOLVE_ERROR = 101;
private boolean mErrorOccurred;
public interface UiCallback
{
Activity getActivity();
void onMyPositionModeChanged(int newMode);
void onLocationUpdated(@NonNull Location location);
void onCompassUpdated(@NonNull CompassData compass);
void onLocationError();
boolean shouldNotifyLocationNotFound();
}
@ -87,11 +88,11 @@ public enum LocationHelper
{
MwmApplication.get().unregisterReceiver(mReceiver);
mReceiverRegistered = false;
return;
}
}
};
@NonNull
private final LocationListener mLocationListener = new LocationListener()
{
@Override
@ -125,43 +126,35 @@ public enum LocationHelper
mUiCallback.onCompassUpdated(mCompassData);
}
@Override
public void onLocationError(int errorCode)
{
mErrorOccurred = true;
mLogger.d("onLocationError errorCode = " + errorCode);
if (mLocationStopped)
return;
nativeOnLocationError(errorCode);
mLogger.d("nativeOnLocationError errorCode = " + errorCode +", " +
"state machine should stop pending, current state = "
+ LocationState.nameOf(LocationState.getMode()));
if (mUiCallback == null)
return;
Intent intent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
if (intent.resolveActivity(MwmApplication.get().getPackageManager()) == null)
{
intent = new Intent(android.provider.Settings.ACTION_SECURITY_SETTINGS);
if (intent.resolveActivity(MwmApplication.get().getPackageManager()) == null)
return;
}
mUiCallback.onLocationError();
}
final Intent finIntent = intent;
new AlertDialog.Builder(mUiCallback.getActivity())
.setTitle(R.string.enable_location_services)
.setMessage(R.string.location_is_disabled_long_text)
.setNegativeButton(R.string.close, null)
.setPositiveButton(R.string.connection_settings, new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
if (mUiCallback != null)
mUiCallback.getActivity().startActivity(finIntent);
}
}).show();
@Override
public String toString()
{
return "LocationHelper.mLocationListener";
}
};
private final Logger mLogger = new DebugLogger(LocationHelper.class.getSimpleName());
@NonNull
private final Listeners<LocationListener> mListeners = new Listeners<>();
private boolean mActive;
@ -172,10 +165,12 @@ public enum LocationHelper
private Location mSavedLocation;
private MapObject mMyPosition;
private long mSavedLocationTime;
@NonNull
private final SensorHelper mSensorHelper = new SensorHelper();
private BaseLocationProvider mLocationProvider;
@NonNull
private final LocationPredictor mPredictor = new LocationPredictor(mLocationListener);
@Nullable
private UiCallback mUiCallback;
private WeakReference<UiCallback> mPrevUiCallback;
@ -190,7 +185,8 @@ public enum LocationHelper
public void onMyPositionModeChanged(int newMode)
{
notifyMyPositionModeChanged(newMode);
mLogger.d("onMyPositionModeChanged mode = " + LocationState.nameOf(newMode) +
" mColdStart = " + mColdStart + " mErrorOccurred = " + mErrorOccurred);
switch (newMode)
{
case LocationState.PENDING_POSITION:
@ -198,7 +194,7 @@ public enum LocationHelper
break;
case LocationState.NOT_FOLLOW_NO_POSITION:
if (mColdStart)
if (mColdStart && !mErrorOccurred)
{
LocationState.nativeSwitchToNextMode();
break;
@ -223,6 +219,7 @@ public enum LocationHelper
}
mColdStart = false;
mErrorOccurred = false;
}
};
@ -256,9 +253,13 @@ public enum LocationHelper
public void initProvider(boolean forceNative)
{
mLogger.d("initProvider forceNative = " + forceNative);
mActive = !mListeners.isEmpty();
if (mActive)
{
mLogger.d("Stop the active provider '" + mLocationProvider + "' before starting the new one");
stopInternal();
}
final MwmApplication application = MwmApplication.get();
final boolean containsGoogleServices = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(application) == ConnectionResult.SUCCESS;
@ -320,6 +321,25 @@ public enum LocationHelper
public long getSavedLocationTime() { return mSavedLocationTime; }
public void switchToNextMode()
{
if (mErrorOccurred)
{
mLogger.d("Location services are still not available, no need to switch to the next mode.");
notifyLocationError(ERROR_DENIED);
return;
}
LocationState.nativeSwitchToNextMode();
}
/**
* @see LocationState#isTurnedOn()
*/
public boolean isTurnedOn()
{
return LocationState.isTurnedOn();
}
void notifyCompassUpdated(long time, double magneticNorth, double trueNorth, double accuracy)
{
for (LocationListener listener : mListeners)
@ -428,7 +448,7 @@ public enum LocationHelper
return mLocationStopped;
}
void stop()
public void stop()
{
mLogger.d("stop()");
mLocationStopped = true;
@ -511,6 +531,12 @@ public enum LocationHelper
removeListener(listener, false);
}
@android.support.annotation.UiThread
public void removeListener()
{
removeListener(mLocationListener);
}
void startSensors()
{
mSensorHelper.start();
@ -584,6 +610,7 @@ public enum LocationHelper
*/
public void restart()
{
mLogger.d("restart()");
mActive &= !mListeners.isEmpty();
if (!mActive)
{
@ -624,13 +651,16 @@ public enum LocationHelper
*/
private void startInternal()
{
mLogger.d("startInternal()");
mLogger.d("startInternal(), current provider is '" + mLocationProvider + "'");
mActive = mLocationProvider.start();
mLogger.d(mActive ? "SUCCESS" : "FAILURE");
if (mActive)
{
mErrorOccurred = false;
mPredictor.resume();
}
else
notifyLocationError(LocationHelper.ERROR_DENIED);
}
@ -663,7 +693,7 @@ public enum LocationHelper
*/
public void attach(UiCallback callback)
{
mLogger.d("attach()");
mLogger.d("attach() callback = " + callback);
if (mUiCallback != null)
{

View file

@ -3,7 +3,6 @@ package com.mapswithme.maps.location;
import android.location.Location;
import com.mapswithme.maps.Framework;
import com.mapswithme.maps.LocationState;
import com.mapswithme.util.concurrency.UiThread;
class LocationPredictor

View file

@ -1,8 +1,10 @@
package com.mapswithme.maps;
package com.mapswithme.maps.location;
import com.mapswithme.maps.MwmApplication;
public final class LocationState
{
public interface ModeChangeListener
interface ModeChangeListener
{
@SuppressWarnings("unused")
void onMyPositionModeChanged(int newMode);
@ -15,23 +17,23 @@ public final class LocationState
public static final int FOLLOW = 3;
public static final int FOLLOW_AND_ROTATE = 4;
public static native void nativeSwitchToNextMode();
static native void nativeSwitchToNextMode();
private static native int nativeGetMode();
public static native void nativeSetListener(ModeChangeListener listener);
public static native void nativeRemoveListener();
static native void nativeSetListener(ModeChangeListener listener);
static native void nativeRemoveListener();
private LocationState() {}
/**
* Checks if location state on the map is active (so its not turned off or pending).
*/
public static boolean isTurnedOn()
static boolean isTurnedOn()
{
return hasLocation(getMode());
}
public static boolean hasLocation(int mode)
static boolean hasLocation(int mode)
{
return (mode > NOT_FOLLOW_NO_POSITION);
}
@ -42,7 +44,7 @@ public final class LocationState
return nativeGetMode();
}
public static String nameOf(int mode)
static String nameOf(int mode)
{
switch (mode)
{

View file

@ -6,7 +6,7 @@ import android.util.Pair;
import java.util.ArrayList;
import java.util.List;
import com.mapswithme.maps.LocationState;
import com.mapswithme.maps.location.LocationState;
import com.mapswithme.maps.MwmApplication;
import com.mapswithme.maps.R;

View file

@ -7,15 +7,13 @@ import android.util.SparseArray;
import android.view.View;
import android.widget.ImageView;
import com.mapswithme.maps.LocationState;
import com.mapswithme.maps.location.LocationState;
import com.mapswithme.maps.R;
import com.mapswithme.maps.routing.RoutingController;
import com.mapswithme.util.Animations;
import com.mapswithme.util.Graphics;
import com.mapswithme.util.ThemeUtils;
import com.mapswithme.util.UiUtils;
import com.mapswithme.util.statistics.AlohaHelper;
import com.mapswithme.util.statistics.Statistics;
public class MyPositionButton
{
@ -25,20 +23,10 @@ public class MyPositionButton
private int mMode;
public MyPositionButton(@NonNull View button)
public MyPositionButton(@NonNull View button, @NonNull View.OnClickListener listener)
{
mButton = (ImageView) button;
mButton.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
LocationState.nativeSwitchToNextMode();
Statistics.INSTANCE.trackEvent(Statistics.EventName.TOOLBAR_MY_POSITION);
AlohaHelper.logClick(AlohaHelper.TOOLBAR_MY_POSITION);
}
});
mButton.setOnClickListener(listener);
mIcons.clear();
}