From 9b7eb51d45240e7e9fbd295629be29eed863e37d Mon Sep 17 00:00:00 2001 From: "r.kuznetsov" Date: Mon, 6 Feb 2017 19:07:21 +0300 Subject: [PATCH 1/5] Fixed my position listener setting up --- android/jni/com/mapswithme/maps/Framework.cpp | 26 ++--------------- android/jni/com/mapswithme/maps/Framework.hpp | 1 - drape_frontend/drape_engine.cpp | 8 ++---- drape_frontend/drape_engine.hpp | 6 ++-- drape_frontend/frontend_renderer.cpp | 4 +-- drape_frontend/my_position_controller.cpp | 19 ++++--------- drape_frontend/my_position_controller.hpp | 7 ++--- map/framework.cpp | 28 +++++++++---------- 8 files changed, 33 insertions(+), 66 deletions(-) diff --git a/android/jni/com/mapswithme/maps/Framework.cpp b/android/jni/com/mapswithme/maps/Framework.cpp index 291100d0c0..eaecdc4de8 100644 --- a/android/jni/com/mapswithme/maps/Framework.cpp +++ b/android/jni/com/mapswithme/maps/Framework.cpp @@ -95,14 +95,8 @@ void Framework::OnLocationError(int errorCode) void Framework::OnLocationUpdated(location::GpsInfo const & info) { + ASSERT(IsDrapeEngineCreated(), ()); m_work.OnLocationUpdate(info); - - if (!IsDrapeEngineCreated()) - { - location::EMyPositionMode const mode = GetMyPositionMode(); - if (mode == location::PendingPosition) - SetMyPositionMode(location::Follow); - } } void Framework::OnCompassUpdated(location::CompassInfo const & info, bool forceRedraw) @@ -135,13 +129,6 @@ void Framework::TrafficStateChanged(TrafficManager::TrafficState state) m_onTrafficStateChangedFn(state); } -void Framework::SetMyPositionMode(location::EMyPositionMode mode) -{ - OnMyPositionModeChanged(mode); - settings::Set(settings::kLocationStateMode, m_currentMode); - MyPositionModeChanged(m_currentMode, false /* routingActive, does not matter */); -} - bool Framework::CreateDrapeEngine(JNIEnv * env, jobject jSurface, int densityDpi, bool firstLaunch) { m_contextFactory = make_unique_dp(new AndroidOGLContextFactory(env, jSurface)); @@ -463,15 +450,8 @@ void Framework::OnMyPositionModeChanged(location::EMyPositionMode mode) void Framework::SwitchMyPositionNextMode() { - if (IsDrapeEngineCreated()) - { - m_work.SwitchMyPositionNextMode(); - return; - } - - // Engine is not available, but the client requests to change mode. - if (GetMyPositionMode() == location::NotFollowNoPosition) - SetMyPositionMode(location::PendingPosition); + ASSERT(IsDrapeEngineCreated(), ()); + m_work.SwitchMyPositionNextMode(); } void Framework::SetupWidget(gui::EWidget widget, float x, float y, dp::Anchor anchor) diff --git a/android/jni/com/mapswithme/maps/Framework.hpp b/android/jni/com/mapswithme/maps/Framework.hpp index 9fa45ddc7a..593c6f4206 100644 --- a/android/jni/com/mapswithme/maps/Framework.hpp +++ b/android/jni/com/mapswithme/maps/Framework.hpp @@ -52,7 +52,6 @@ namespace android void TrafficStateChanged(TrafficManager::TrafficState state); void MyPositionModeChanged(location::EMyPositionMode mode, bool routingActive); - void SetMyPositionMode(location::EMyPositionMode mode); location::TMyPositionModeChanged m_myPositionModeSignal; location::EMyPositionMode m_currentMode; diff --git a/drape_frontend/drape_engine.cpp b/drape_frontend/drape_engine.cpp index 3edb8a5d4b..3024ce1098 100644 --- a/drape_frontend/drape_engine.cpp +++ b/drape_frontend/drape_engine.cpp @@ -16,7 +16,8 @@ namespace df { DrapeEngine::DrapeEngine(Params && params) - : m_viewport(params.m_viewport) + : m_myPositionModeChanged(move(params.m_myPositionModeChanged)) + , m_viewport(params.m_viewport) { VisualParams::Init(params.m_vs, df::CalculateTileSize(m_viewport.GetWidth(), m_viewport.GetHeight())); @@ -321,11 +322,6 @@ void DrapeEngine::SetModelViewListener(TModelViewListenerFn && fn) m_modelViewChanged = move(fn); } -void DrapeEngine::SetMyPositionModeListener(location::TMyPositionModeChanged && fn) -{ - m_myPositionModeChanged = move(fn); -} - void DrapeEngine::SetTapEventInfoListener(TTapEventInfoFn && fn) { m_tapListener = move(fn); diff --git a/drape_frontend/drape_engine.hpp b/drape_frontend/drape_engine.hpp index 289a80cfb8..76ddb562a7 100644 --- a/drape_frontend/drape_engine.hpp +++ b/drape_frontend/drape_engine.hpp @@ -46,6 +46,7 @@ public: double fontsScaleFactor, gui::TWidgetsInitInfo && info, pair const & initialMyPositionMode, + location::TMyPositionModeChanged && myPositionModeChanged, bool allow3dBuildings, bool trafficEnabled, bool blockTapEvents, @@ -62,6 +63,7 @@ public: , m_fontsScaleFactor(fontsScaleFactor) , m_info(move(info)) , m_initialMyPositionMode(initialMyPositionMode) + , m_myPositionModeChanged(move(myPositionModeChanged)) , m_allow3dBuildings(allow3dBuildings) , m_trafficEnabled(trafficEnabled) , m_blockTapEvents(blockTapEvents) @@ -80,6 +82,7 @@ public: double m_fontsScaleFactor; gui::TWidgetsInitInfo m_info; pair m_initialMyPositionMode; + location::TMyPositionModeChanged m_myPositionModeChanged; bool m_allow3dBuildings; bool m_trafficEnabled; bool m_blockTapEvents; @@ -125,7 +128,6 @@ public: void SwitchMyPositionNextMode(); void LoseLocation(); void StopLocationFollow(); - void SetMyPositionModeListener(location::TMyPositionModeChanged && fn); using TTapEventInfoFn = FrontendRenderer::TTapEventInfoFn; void SetTapEventInfoListener(TTapEventInfoFn && fn); @@ -198,11 +200,11 @@ private: drape_ptr m_threadCommutator; drape_ptr m_textureManager; drape_ptr m_requestedTiles; + location::TMyPositionModeChanged m_myPositionModeChanged; Viewport m_viewport; TModelViewListenerFn m_modelViewChanged; - location::TMyPositionModeChanged m_myPositionModeChanged; TUserPositionChangedFn m_userPositionChanged; TTapEventInfoFn m_tapListener; diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index 10d3cd374a..2f9a1d1b01 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -151,9 +151,7 @@ FrontendRenderer::FrontendRenderer(Params const & params) m_myPositionController.reset(new MyPositionController(params.m_initMyPositionMode, params.m_timeInBackground, params.m_firstLaunch, params.m_isRoutingActive, - params.m_isAutozoomEnabled)); - m_myPositionController->SetModeListener(params.m_myPositionModeCallback); - + params.m_isAutozoomEnabled, params.m_myPositionModeCallback)); StartThread(); } diff --git a/drape_frontend/my_position_controller.cpp b/drape_frontend/my_position_controller.cpp index 8416d49e80..d898c9d9e8 100644 --- a/drape_frontend/my_position_controller.cpp +++ b/drape_frontend/my_position_controller.cpp @@ -124,9 +124,11 @@ double CalculateZoomBySpeed(double speed, bool isPerspectiveAllowed) } // namespace MyPositionController::MyPositionController(location::EMyPositionMode initMode, double timeInBackground, - bool isFirstLaunch, bool isRoutingActive, bool isAutozoomEnabled) + bool isFirstLaunch, bool isRoutingActive, bool isAutozoomEnabled, + location::TMyPositionModeChanged const & fn) : m_mode(location::PendingPosition) , m_desiredInitMode(initMode) + , m_modeChangeCallback(fn) , m_isFirstLaunch(isFirstLaunch) , m_isInRouting(isRoutingActive) , m_needBlockAnimation(false) @@ -163,6 +165,9 @@ MyPositionController::MyPositionController(location::EMyPositionMode initMode, d { m_desiredInitMode = location::Follow; } + + if (m_modeChangeCallback != nullptr) + m_modeChangeCallback(m_mode, m_isInRouting); } MyPositionController::~MyPositionController() @@ -486,18 +491,6 @@ void MyPositionController::OnCompassUpdate(location::CompassInfo const & info, S } } -void MyPositionController::SetModeListener(location::TMyPositionModeChanged const & fn) -{ - m_modeChangeCallback = fn; - - location::EMyPositionMode mode = m_mode; - if (m_isFirstLaunch) - mode = location::NotFollowNoPosition; - - if (m_modeChangeCallback != nullptr) - m_modeChangeCallback(mode, m_isInRouting); -} - bool MyPositionController::IsInStateWithPosition() const { return m_mode == location::NotFollow || m_mode == location::Follow || diff --git a/drape_frontend/my_position_controller.hpp b/drape_frontend/my_position_controller.hpp index e3eaa21b8d..f55005cb5a 100644 --- a/drape_frontend/my_position_controller.hpp +++ b/drape_frontend/my_position_controller.hpp @@ -41,7 +41,8 @@ public: }; MyPositionController(location::EMyPositionMode initMode, double timeInBackground, - bool isFirstLaunch, bool isRoutingActive, bool isAutozoomEnabled); + bool isFirstLaunch, bool isRoutingActive, bool isAutozoomEnabled, + location::TMyPositionModeChanged const & fn); ~MyPositionController(); void UpdatePosition(); @@ -90,8 +91,6 @@ public: void OnLocationUpdate(location::GpsInfo const & info, bool isNavigable, ScreenBase const & screen); void OnCompassUpdate(location::CompassInfo const & info, ScreenBase const & screen); - void SetModeListener(location::TMyPositionModeChanged const & fn); - void Render(ScreenBase const & screen, int zoomLevel, ref_ptr mng, dp::UniformValuesStorage const & commonUniforms); @@ -133,6 +132,7 @@ private: private: location::EMyPositionMode m_mode; location::EMyPositionMode m_desiredInitMode; + location::TMyPositionModeChanged m_modeChangeCallback; bool m_isFirstLaunch; bool m_isInRouting; @@ -140,7 +140,6 @@ private: bool m_needBlockAnimation; bool m_wasRotationInScaling; - location::TMyPositionModeChanged m_modeChangeCallback; drape_ptr m_shape; ref_ptr m_listener; diff --git a/map/framework.cpp b/map/framework.cpp index ed2f26ce70..83ef79d4ee 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -1654,6 +1654,19 @@ void Framework::CreateDrapeEngine(ref_ptr contextFactory, m_model.ReadFeatures(fn, ids); }; + auto myPositionModeChangedFn = [this](location::EMyPositionMode mode, bool routingActive) + { + GetPlatform().RunOnGuiThread([this, mode, routingActive]() + { + // Deactivate selection (and hide place page) if we return to routing in F&R mode. + if (routingActive && mode == location::FollowAndRotate) + DeactivateMapSelection(true /* notifyUI */); + + if (m_myPositionListener != nullptr) + m_myPositionListener(mode, routingActive); + }); + }; + auto isCountryLoadedByNameFn = bind(&Framework::IsCountryLoadedByName, this, _1); auto updateCurrentCountryFn = bind(&Framework::OnUpdateCurrentCountry, this, _1, _2); @@ -1673,7 +1686,7 @@ void Framework::CreateDrapeEngine(ref_ptr contextFactory, df::MapDataProvider(idReadFn, featureReadFn, isCountryLoadedByNameFn, updateCurrentCountryFn), params.m_visualScale, fontsScaleFactor, move(params.m_widgetsInitInfo), make_pair(params.m_initialMyPositionState, params.m_hasMyPositionState), - allow3dBuildings, trafficEnabled, params.m_isChoosePositionMode, + move(myPositionModeChangedFn), allow3dBuildings, trafficEnabled, params.m_isChoosePositionMode, params.m_isChoosePositionMode, GetSelectedFeatureTriangles(), params.m_isFirstLaunch, m_routingSession.IsActive() && m_routingSession.IsFollowing(), isAutozoomEnabled); @@ -1694,19 +1707,6 @@ void Framework::CreateDrapeEngine(ref_ptr contextFactory, OnSize(params.m_surfaceWidth, params.m_surfaceHeight); - m_drapeEngine->SetMyPositionModeListener([this](location::EMyPositionMode mode, bool routingActive) - { - GetPlatform().RunOnGuiThread([this, mode, routingActive]() - { - // Deactivate selection (and hide place page) if we return to routing in F&R mode. - if (routingActive && mode == location::FollowAndRotate) - DeactivateMapSelection(true /* notifyUI */); - - if (m_myPositionListener != nullptr) - m_myPositionListener(mode, routingActive); - }); - }); - InvalidateUserMarks(); Allow3dMode(allow3d, allow3dBuildings); From 3e22c24ef76f1891aaae379047ce5b23cbcaef05 Mon Sep 17 00:00:00 2001 From: alexzatsepin Date: Wed, 8 Feb 2017 15:00:03 +0300 Subject: [PATCH 2/5] [android] Removed 'mColdStart', 'mActive', 'mLocationStopped' ugly flags from the LocationHelper [android] Refactored the all classes related to location updates --- .../src/com/mapswithme/maps/MwmActivity.java | 30 +- .../com/mapswithme/maps/MwmApplication.java | 2 + .../NavigationButtonsAnimationController.java | 3 +- .../maps/location/AndroidNativeProvider.java | 20 +- .../maps/location/BaseLocationProvider.java | 23 +- .../mapswithme/maps/location/GPSCheck.java | 4 +- .../location/GoogleFusedLocationProvider.java | 36 +- .../maps/location/LocationHelper.java | 433 +++++++----------- .../maps/location/LocationPredictor.java | 2 +- .../maps/location/LocationState.java | 23 +- .../maps/location/TransitionListener.java | 37 ++ .../maps/routing/ResultCodesHelper.java | 3 +- .../maps/settings/MiscPrefsFragment.java | 2 +- .../com/mapswithme/util/LocationUtils.java | 12 +- 14 files changed, 287 insertions(+), 343 deletions(-) create mode 100644 android/src/com/mapswithme/maps/location/TransitionListener.java diff --git a/android/src/com/mapswithme/maps/MwmActivity.java b/android/src/com/mapswithme/maps/MwmActivity.java index 9a81887960..ff3c929340 100644 --- a/android/src/com/mapswithme/maps/MwmActivity.java +++ b/android/src/com/mapswithme/maps/MwmActivity.java @@ -1,6 +1,7 @@ package com.mapswithme.maps; import android.annotation.SuppressLint; +import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; @@ -174,6 +175,8 @@ public class MwmActivity extends BaseMwmFragmentActivity private boolean mPlacePageRestored; private boolean mLocationErrorDialogAnnoying = false; + @Nullable + private Dialog mLocationErrorDialog; @NonNull private final OnClickListener mOnMyPositionClickListener = new OnClickListener() @@ -183,6 +186,7 @@ public class MwmActivity extends BaseMwmFragmentActivity { mLocationErrorDialogAnnoying = false; LocationHelper.INSTANCE.switchToNextMode(); + LocationHelper.INSTANCE.restart(); Statistics.INSTANCE.trackEvent(Statistics.EventName.TOOLBAR_MY_POSITION); AlohaHelper.logClick(AlohaHelper.TOOLBAR_MY_POSITION); } @@ -1013,6 +1017,7 @@ public class MwmActivity extends BaseMwmFragmentActivity @Override public boolean run(MwmActivity target) { + //TODO: Check and remove if (LocationHelper.INSTANCE.isTurnedOn()) LocationHelper.INSTANCE.switchToNextMode(); return false; @@ -1792,7 +1797,10 @@ public class MwmActivity extends BaseMwmFragmentActivity private void showLocationErrorDialog(@NonNull final Intent intent) { - new AlertDialog.Builder(this) + if (mLocationErrorDialog != null && mLocationErrorDialog.isShowing()) + return; + + mLocationErrorDialog = 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() @@ -1836,29 +1844,15 @@ public class MwmActivity extends BaseMwmFragmentActivity getString(R.string.current_location_unknown_title)); new AlertDialog.Builder(this) .setMessage(message) - .setNegativeButton(R.string.current_location_unknown_stop_button, new DialogInterface.OnClickListener() - { - @Override - public void onClick(DialogInterface dialog, int which) - { - LocationHelper.INSTANCE.stop(); - } - }) + .setNegativeButton(R.string.current_location_unknown_stop_button, null) .setPositiveButton(R.string.current_location_unknown_continue_button, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - LocationHelper.INSTANCE.switchToNextMode(); + LocationHelper.INSTANCE.start(); } - }).setOnDismissListener(new DialogInterface.OnDismissListener() - { - @Override - public void onDismiss(DialogInterface dialog) - { - LocationHelper.INSTANCE.stop(); - } - }).show(); + }).show(); } private boolean shouldNotifyLocationNotFound() diff --git a/android/src/com/mapswithme/maps/MwmApplication.java b/android/src/com/mapswithme/maps/MwmApplication.java index 8250153d88..386bab8a71 100644 --- a/android/src/com/mapswithme/maps/MwmApplication.java +++ b/android/src/com/mapswithme/maps/MwmApplication.java @@ -23,6 +23,7 @@ import com.mapswithme.maps.bookmarks.data.BookmarkManager; import com.mapswithme.maps.downloader.CountryItem; import com.mapswithme.maps.downloader.MapManager; import com.mapswithme.maps.editor.Editor; +import com.mapswithme.maps.location.LocationHelper; import com.mapswithme.maps.location.TrackRecorder; import com.mapswithme.maps.routing.RoutingController; import com.mapswithme.maps.settings.StoragePathManager; @@ -179,6 +180,7 @@ public class MwmApplication extends Application BookmarkManager.nativeLoadBookmarks(); TtsPlayer.INSTANCE.init(this); ThemeSwitcher.restart(); + LocationHelper.INSTANCE.initialize(); RoutingController.get().initialize(); TrafficManager.INSTANCE.initialize(); mIsFrameworkInitialized = true; diff --git a/android/src/com/mapswithme/maps/NavigationButtonsAnimationController.java b/android/src/com/mapswithme/maps/NavigationButtonsAnimationController.java index cd74c311a1..bd5e5c4477 100644 --- a/android/src/com/mapswithme/maps/NavigationButtonsAnimationController.java +++ b/android/src/com/mapswithme/maps/NavigationButtonsAnimationController.java @@ -7,6 +7,7 @@ import android.os.Bundle; import android.support.annotation.NonNull; import android.view.View; +import com.mapswithme.maps.location.LocationHelper; import com.mapswithme.maps.location.LocationState; import com.mapswithme.maps.routing.RoutingController; import com.mapswithme.util.Animations; @@ -219,7 +220,7 @@ class NavigationButtonsAnimationController private boolean shouldBeHidden() { - return LocationState.getMode() == LocationState.FOLLOW_AND_ROTATE + return LocationHelper.INSTANCE.getMyPositionMode() == LocationState.FOLLOW_AND_ROTATE && (RoutingController.get().isPlanning() || RoutingController.get().isNavigating()); } diff --git a/android/src/com/mapswithme/maps/location/AndroidNativeProvider.java b/android/src/com/mapswithme/maps/location/AndroidNativeProvider.java index e8723bffce..78aecf8abf 100644 --- a/android/src/com/mapswithme/maps/location/AndroidNativeProvider.java +++ b/android/src/com/mapswithme/maps/location/AndroidNativeProvider.java @@ -21,7 +21,6 @@ class AndroidNativeProvider extends BaseLocationProvider LocationManager.GPS_PROVIDER }; @NonNull private final LocationManager mLocationManager; - private boolean mIsActive; @NonNull private final List mListeners = new ArrayList<>(); @@ -32,17 +31,20 @@ class AndroidNativeProvider extends BaseLocationProvider } @Override - protected boolean start() + protected void start() { sLogger.d(TAG, "Android native provider is started"); - if (mIsActive) - return true; + if (isActive()) + return; List providers = getAvailableProviders(mLocationManager); if (providers.isEmpty()) - return false; + { + setActive(false); + return; + } - mIsActive = true; + setActive(true); for (String provider : providers) { sLogger.d(TAG, "Request location updates from the provider: " + provider); @@ -61,14 +63,12 @@ class AndroidNativeProvider extends BaseLocationProvider if (location == null || LocationUtils.isExpired(location, LocationHelper.INSTANCE.getSavedLocationTime(), LocationUtils.LOCATION_EXPIRATION_TIME_MILLIS_SHORT)) { - return true; + return; } } if (location != null) onLocationChanged(location); - - return true; } private void onLocationChanged(@NonNull Location location) @@ -92,7 +92,7 @@ class AndroidNativeProvider extends BaseLocationProvider mLocationManager.removeUpdates(iterator.next()); mListeners.clear(); - mIsActive = false; + setActive(false); } @Nullable diff --git a/android/src/com/mapswithme/maps/location/BaseLocationProvider.java b/android/src/com/mapswithme/maps/location/BaseLocationProvider.java index e4e4ddae5d..6a4dc439cc 100644 --- a/android/src/com/mapswithme/maps/location/BaseLocationProvider.java +++ b/android/src/com/mapswithme/maps/location/BaseLocationProvider.java @@ -8,9 +8,10 @@ import com.mapswithme.util.log.LoggerFactory; abstract class BaseLocationProvider { static final Logger sLogger = LoggerFactory.INSTANCE.getLogger(LoggerFactory.Type.LOCATION); + private static final String TAG = BaseLocationProvider.class.getSimpleName(); @NonNull private final LocationFixChecker mLocationFixChecker; - + private boolean mActive; @NonNull LocationFixChecker getLocationFixChecker() { @@ -22,9 +23,21 @@ abstract class BaseLocationProvider mLocationFixChecker = locationFixChecker; } - /** - * @return whether location polling was started successfully. - */ - protected abstract boolean start(); + protected abstract void start(); protected abstract void stop(); + + /** + * Indicates whether this provider is providing location updates or not + * @return true - if locations are actively coming from this provider, false - otherwise + */ + public final boolean isActive() + { + return mActive; + } + + final void setActive(boolean active) + { + sLogger.d(TAG, "setActive active = " + active); + mActive = active; + } } diff --git a/android/src/com/mapswithme/maps/location/GPSCheck.java b/android/src/com/mapswithme/maps/location/GPSCheck.java index f183b2e3ec..3ffebb822b 100644 --- a/android/src/com/mapswithme/maps/location/GPSCheck.java +++ b/android/src/com/mapswithme/maps/location/GPSCheck.java @@ -11,6 +11,8 @@ public class GPSCheck extends BroadcastReceiver @Override public void onReceive(Context context, Intent intent) { if (MwmApplication.get().isFrameworkInitialized() && MwmApplication.backgroundTracker().isForeground()) - LocationHelper.INSTANCE.checkProvidersAndStartIfNeeded(); + { + LocationHelper.INSTANCE.restart(); + } } } diff --git a/android/src/com/mapswithme/maps/location/GoogleFusedLocationProvider.java b/android/src/com/mapswithme/maps/location/GoogleFusedLocationProvider.java index 4435f16234..2810efb04c 100644 --- a/android/src/com/mapswithme/maps/location/GoogleFusedLocationProvider.java +++ b/android/src/com/mapswithme/maps/location/GoogleFusedLocationProvider.java @@ -39,27 +39,23 @@ class GoogleFusedLocationProvider extends BaseLocationProvider } @Override - protected boolean start() + protected void start() { sLogger.d(TAG, "Google fused provider is started"); if (mGoogleApiClient.isConnected() || mGoogleApiClient.isConnecting()) - return true; + { + setActive(true); + return; + } mLocationRequest = LocationRequest.create(); -// mLocationRequest.setPriority(LocationHelper.INSTANCE.isHighAccuracy() ? LocationRequest.PRIORITY_HIGH_ACCURACY -// : LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY); - // TODO @yunikkk - // Currently there are some problems concerning location strategies switching. - // With LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY priority GPS is not used and location icon isn't shown in system navbar, - // hence it confuses user. - // We should reconsider if balanced mode is needed at all after results of tests for battery usage will arrive. mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); long interval = LocationHelper.INSTANCE.getInterval(); mLocationRequest.setInterval(interval); mLocationRequest.setFastestInterval(interval / 2); mGoogleApiClient.connect(); - return true; + setActive(true); } @Override @@ -73,6 +69,7 @@ class GoogleFusedLocationProvider extends BaseLocationProvider mLocationSettingsResult.cancel(); mGoogleApiClient.disconnect(); + setActive(false); } @Override @@ -101,12 +98,14 @@ class GoogleFusedLocationProvider extends BaseLocationProvider break; case LocationSettingsStatusCodes.RESOLUTION_REQUIRED: + setActive(false); // Location settings are not satisfied. AndroidNativeProvider should be used. - resolveError(status); + resolveResolutionRequired(); return; case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE: // Location settings are not satisfied. However, we have no way to fix the settings so we won't show the dialog. + setActive(false); break; } @@ -115,13 +114,11 @@ class GoogleFusedLocationProvider extends BaseLocationProvider }); } - private static void resolveError(Status status) + private static void resolveResolutionRequired() { - sLogger.d(TAG, "resolveError()"); - if (LocationHelper.INSTANCE.isLocationStopped()) - return; - - LocationHelper.INSTANCE.initProvider(true /* forceNative */); + sLogger.d(TAG, "resolveResolutionRequired()"); + LocationHelper.INSTANCE.initNativeProvider(); + LocationHelper.INSTANCE.start(); } private void requestLocationUpdates() @@ -139,14 +136,17 @@ class GoogleFusedLocationProvider extends BaseLocationProvider @Override public void onConnectionSuspended(int i) { + setActive(false); sLogger.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); // TODO handle error in a smarter way - LocationHelper.INSTANCE.initProvider(true); + LocationHelper.INSTANCE.initNativeProvider(); + LocationHelper.INSTANCE.start(); } } diff --git a/android/src/com/mapswithme/maps/location/LocationHelper.java b/android/src/com/mapswithme/maps/location/LocationHelper.java index ebc928c2c1..0d1ef3962e 100644 --- a/android/src/com/mapswithme/maps/location/LocationHelper.java +++ b/android/src/com/mapswithme/maps/location/LocationHelper.java @@ -1,11 +1,7 @@ package com.mapswithme.maps.location; import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; import android.location.Location; -import android.location.LocationManager; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -20,12 +16,9 @@ import com.mapswithme.util.Config; import com.mapswithme.util.Listeners; import com.mapswithme.util.LocationUtils; import com.mapswithme.util.Utils; -import com.mapswithme.util.concurrency.UiThread; import com.mapswithme.util.log.Logger; import com.mapswithme.util.log.LoggerFactory; -import static com.mapswithme.maps.background.AppBackgroundTracker.OnTransitionListener; - public enum LocationHelper { INSTANCE; @@ -46,46 +39,8 @@ 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; - - private boolean mErrorOccurred; - - public interface UiCallback - { - Activity getActivity(); - void onMyPositionModeChanged(int newMode); - void onLocationUpdated(@NonNull Location location); - void onCompassUpdated(@NonNull CompassData compass); - void onLocationError(); - void onLocationNotFound(); - } - - private final OnTransitionListener mOnTransition = new OnTransitionListener() - { - private final GPSCheck mReceiver = new GPSCheck(); - private boolean mReceiverRegistered; - - @Override - public void onTransit(boolean foreground) - { - if (foreground && !mReceiverRegistered) - { - final IntentFilter filter = new IntentFilter(); - filter.addAction(LocationManager.PROVIDERS_CHANGED_ACTION); - filter.addCategory(Intent.CATEGORY_DEFAULT); - - MwmApplication.get().registerReceiver(mReceiver, filter); - mReceiverRegistered = true; - return; - } - - if (!foreground && mReceiverRegistered) - { - MwmApplication.get().unregisterReceiver(mReceiver); - mReceiverRegistered = false; - } - } - }; + @NonNull + private final TransitionListener mOnTransition = new TransitionListener(); @NonNull private final LocationListener mLocationListener = new LocationListener() @@ -123,13 +78,11 @@ public enum LocationHelper @Override public void onLocationError(int errorCode) { - mErrorOccurred = true; - mLogger.d(TAG, "onLocationError errorCode = " + errorCode); + mLogger.d(TAG, "onLocationError errorCode = " + errorCode, new Throwable()); nativeOnLocationError(errorCode); mLogger.d(TAG, "nativeOnLocationError errorCode = " + errorCode + - ", current state = " + LocationState.nameOf(LocationState.getMode())); - stop(); + ", current state = " + LocationState.nameOf(getMyPositionMode())); if (mUiCallback == null) return; @@ -148,16 +101,12 @@ public enum LocationHelper private final Logger mLogger = LoggerFactory.INSTANCE.getLogger(LoggerFactory.Type.LOCATION); @NonNull private final Listeners mListeners = new Listeners<>(); - - private boolean mActive; - private boolean mLocationStopped; - private boolean mColdStart = true; - private Location mSavedLocation; private MapObject mMyPosition; private long mSavedLocationTime; @NonNull private final SensorHelper mSensorHelper = new SensorHelper(); + @Nullable private BaseLocationProvider mLocationProvider; @NonNull private final LocationPredictor mPredictor = new LocationPredictor(mLocationListener); @@ -165,111 +114,70 @@ public enum LocationHelper private UiCallback mUiCallback; private long mInterval; - private boolean mHighAccuracy; private CompassData mCompassData; @SuppressWarnings("FieldCanBeLocal") - private final LocationState.ModeChangeListener mModeChangeListener = new LocationState.ModeChangeListener() + private final LocationState.ModeChangeListener mMyPositionModeListener = + new LocationState.ModeChangeListener() { @Override public void onMyPositionModeChanged(int newMode) { notifyMyPositionModeChanged(newMode); - mLogger.d(TAG, "onMyPositionModeChanged mode = " + LocationState.nameOf(newMode) + - " mColdStart = " + mColdStart + " mErrorOccurred = " + mErrorOccurred); - switch (newMode) + mLogger.d(TAG, "onMyPositionModeChanged mode = " + LocationState.nameOf(newMode)); + + if (mUiCallback == null) { - case LocationState.PENDING_POSITION: - addListener(mLocationListener, true); - break; - - case LocationState.NOT_FOLLOW_NO_POSITION: - if (mColdStart && !mErrorOccurred) - { - LocationState.nativeSwitchToNextMode(); - break; - } - - removeListener(mLocationListener); - - if (mLocationStopped) - break; - - if (LocationUtils.areLocationServicesTurnedOn()) - { - mLocationStopped = true; - notifyLocationNotFound(); - } - break; - - default: - mLocationStopped = false; - restart(); - break; + mLogger.d(TAG, "UI is not ready to listen my position changes, i.e. it's not attached yet."); + return; } - mColdStart = false; - mErrorOccurred = false; + switch (newMode) + { + case LocationState.NOT_FOLLOW_NO_POSITION: + stop(); + if (LocationUtils.areLocationServicesTurnedOn()) + notifyLocationNotFound(); + break; + } } }; - private final Runnable mStopLocationTask = new Runnable() - { - @Override - public void run() - { - mLogger.d(TAG, "mStopLocationTask.run(). Was active: " + mActive); - - if (mActive) - stopInternal(); - } - }; LocationHelper() { mLogger.d(LocationHelper.class.getSimpleName(), "ctor()"); + } - // TODO consider refactoring. - // Actually we shouldn't initialize Framework here, - // to allow app components to retrieve location updates without all heavy framework's stuff initialized. - // For now this is necessary to connect mModeChangeListener below. - MwmApplication.get().initNativeCore(); - LocationState.nativeSetListener(mModeChangeListener); - - calcParams(); - initProvider(false); + @android.support.annotation.UiThread + public void initialize() + { + initProvider(); + LocationState.nativeSetListener(mMyPositionModeListener); MwmApplication.backgroundTracker().addListener(mOnTransition); } - public void initProvider(boolean forceNative) + private void initProvider() { - mLogger.d(TAG, "initProvider forceNative = " + forceNative, new Throwable()); - mActive = !mListeners.isEmpty(); - if (mActive) - { - mLogger.d(TAG, "Stop the active provider '" + mLocationProvider + "' before starting the new one"); - stopInternal(); - } - + mLogger.d(TAG, "initProvider", new Throwable()); final MwmApplication application = MwmApplication.get(); final boolean containsGoogleServices = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(application) == ConnectionResult.SUCCESS; final boolean googleServicesTurnedInSettings = Config.useGoogleServices(); - if (!forceNative && - containsGoogleServices && - googleServicesTurnedInSettings) + if (containsGoogleServices && googleServicesTurnedInSettings) { mLogger.d(TAG, "Use fused provider."); mLocationProvider = new GoogleFusedLocationProvider(new FusedLocationFixChecker()); } else { - mLogger.d(TAG, "Use native provider."); - mLocationProvider = new AndroidNativeProvider(new DefaultLocationFixChecker()); + initNativeProvider(); } + } - mActive = !mListeners.isEmpty(); - if (mActive) - startInternal(); + void initNativeProvider() + { + mLogger.d(TAG, "Use native provider"); + mLocationProvider = new AndroidNativeProvider(new DefaultLocationFixChecker()); } public void onLocationUpdated(@NonNull Location location) @@ -313,12 +221,7 @@ public enum LocationHelper public void switchToNextMode() { - if (mErrorOccurred) - { - mLogger.d(TAG, "Location services are still not available, no need to switch to the next mode."); - notifyLocationError(ERROR_DENIED); - return; - } + mLogger.d(TAG, "switchToNextMode()"); LocationState.nativeSwitchToNextMode(); } @@ -385,7 +288,7 @@ public enum LocationHelper private void notifyMyPositionModeChanged(int newMode) { - mLogger.d(TAG, "notifyMyPositionModeChanged(): " + LocationState.nameOf(newMode)); + mLogger.d(TAG, "notifyMyPositionModeChanged(): " + LocationState.nameOf(newMode) , new Throwable()); if (mUiCallback != null) mUiCallback.onMyPositionModeChanged(newMode); @@ -400,105 +303,33 @@ public enum LocationHelper mUiCallback.onLocationNotFound(); } - boolean isLocationStopped() - { - return mLocationStopped; - } - - public void stop() - { - mLogger.d(TAG, "stop()"); - mLocationStopped = true; - removeListener(mLocationListener, false); - } - - void checkProvidersAndStartIfNeeded() - { - Context context = MwmApplication.get(); - LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); - boolean networkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); - boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); - mLocationStopped = !networkEnabled && !gpsEnabled; - LocationUtils.logAvailableProviders(); - - if (mLocationStopped) - { - if (LocationState.getMode() == LocationState.PENDING_POSITION) - notifyLocationError(ERROR_DENIED); - return; - } - - initProvider(false); - mLogger.i(TAG, "checkProvidersAndStartIfNeeded, current mode '" + LocationState.nameOf(LocationState.getMode()) + "'"); - LocationState.nativeSwitchToNextMode(); - } - /** - * Registers listener about location changes. Starts polling on the first listener registration. + * Registers listener about location changes. * @param listener listener to register. * @param forceUpdate instantly notify given listener about available location, if any. */ @android.support.annotation.UiThread - public void addListener(LocationListener listener, boolean forceUpdate) + public void addListener(@NonNull LocationListener listener, boolean forceUpdate) { mLogger.d(TAG, "addListener(): " + listener + ", forceUpdate: " + forceUpdate); mLogger.d(TAG, " - listener count was: " + mListeners.getSize()); - UiThread.cancelDelayedTasks(mStopLocationTask); - - boolean wasEmpty = mListeners.isEmpty(); mListeners.register(listener); - if (wasEmpty) - { - calcParams(); - startInternal(); - } - - if (mActive && forceUpdate) + if (forceUpdate) notifyLocationUpdated(listener); } @android.support.annotation.UiThread - private void removeListener(LocationListener listener, boolean delayed) - { - mLogger.d(TAG, "removeListener(), delayed: " + delayed + ", listener: " + listener); - mLogger.d(TAG, " - listener count was: " + mListeners.getSize()); - - boolean wasEmpty = mListeners.isEmpty(); - mListeners.unregister(listener); - - if (!wasEmpty && mListeners.isEmpty()) - { - mLogger.d(TAG, " - was not empty"); - - if (delayed) - { - mLogger.d(TAG, " - schedule stop"); - stopDelayed(); - } - else - { - mLogger.d(TAG, " - stop now"); - stopInternal(); - } - } - } - /** - * Removes given location listener. Stops polling if there are no listeners left. + * Removes given location listener. * @param listener listener to unregister. */ - @android.support.annotation.UiThread - public void removeListener(LocationListener listener) + public void removeListener(@NonNull LocationListener listener) { - removeListener(listener, false); - } - - @android.support.annotation.UiThread - public void removeListener() - { - removeListener(mLocationListener); + mLogger.d(TAG, "removeListener(), listener: " + listener); + mLogger.d(TAG, " - listener count was: " + mListeners.getSize()); + mListeners.unregister(listener); } void startSensors() @@ -511,11 +342,12 @@ public enum LocationHelper mSensorHelper.resetMagneticField(mSavedLocation, location); } - private void calcParams() + private void calcLocationUpdatesInterval() { - mHighAccuracy = true; + mLogger.d(TAG, "calcLocationUpdatesInterval()"); if (RoutingController.get().isNavigating()) { + mLogger.d(TAG, "calcLocationUpdatesInterval(), it's navigation mode"); final @Framework.RouterType int router = Framework.nativeGetRouter(); switch (router) { @@ -538,22 +370,20 @@ public enum LocationHelper return; } - int mode = LocationState.getMode(); + int mode = getMyPositionMode(); switch (mode) { - default: - case LocationState.NOT_FOLLOW: - mHighAccuracy = false; - mInterval = INTERVAL_NOT_FOLLOW_MS; - break; + case LocationState.FOLLOW: + mInterval = INTERVAL_FOLLOW_MS; + break; - case LocationState.FOLLOW: - mInterval = INTERVAL_FOLLOW_MS; - break; + case LocationState.FOLLOW_AND_ROTATE: + mInterval = INTERVAL_FOLLOW_AND_ROTATE_MS; + break; - case LocationState.FOLLOW_AND_ROTATE: - mInterval = INTERVAL_FOLLOW_AND_ROTATE_MS; - break; + default: + mInterval = INTERVAL_NOT_FOLLOW_MS; + break; } } @@ -562,41 +392,69 @@ public enum LocationHelper return mInterval; } - // TODO (trashkalmar): Usage of this method was temporarily commented out from GoogleFusedLocationProvider.start(). See comments there. - boolean isHighAccuracy() - { - return mHighAccuracy; - } - /** - * Recalculates location parameters and restarts locator if it was in a progress before. - *

Does nothing if there were no subscribers. + * Stops the current provider. Then initialize the location provider again, + * because location settings could be changed and a new location provider can be used, + * such as Google fused provider. And we think that Google fused provider is preferable + * for the most cases. And starts the initialized location provider. + * + * @see #start() + * */ public void restart() { mLogger.d(TAG, "restart()"); - mActive &= !mListeners.isEmpty(); - if (!mActive) + checkProviderInitialization(); + stopInternal(); + initProvider(); + start(); + } + + /** + * Adds the {@link #mLocationListener} 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. + */ + public void start() + { + checkProviderInitialization(); + //noinspection ConstantConditions + if (mLocationProvider.isActive()) + throw new AssertionError("Location provider '" + mLocationProvider + "' must be stopped first"); + + addListener(mLocationListener, true); + + if (!LocationUtils.checkProvidersAvailability()) { - stopInternal(); + notifyLocationError(ERROR_DENIED); return; } - boolean oldHighAccuracy = mHighAccuracy; long oldInterval = mInterval; - mLogger.d(TAG, "restart. Old params: " + oldInterval + " / " + (oldHighAccuracy ? "high" : "normal")); + mLogger.d(TAG, "Old time interval (ms): " + oldInterval); + calcLocationUpdatesInterval(); + mLogger.d(TAG, "start(), params: " + mInterval); + startInternal(); + } - calcParams(); - mLogger.d(TAG, "New params: " + mInterval + " / " + (mHighAccuracy ? "high" : "normal")); - - if (mHighAccuracy != oldHighAccuracy || mInterval != oldInterval) + /** + * 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. + */ + private void stop() + { + mLogger.d(TAG, "stop()"); + checkProviderInitialization(); + //noinspection ConstantConditions + if (!mLocationProvider.isActive()) { - boolean active = mActive; - stopInternal(); - - if (active) - startInternal(); + mLogger.i(TAG, "Provider '" + mLocationProvider + "' is already stopped"); + return; } + + removeListener(mLocationListener); + stopInternal(); } /** @@ -605,17 +463,27 @@ public enum LocationHelper private void startInternal() { mLogger.d(TAG, "startInternal(), current provider is '" + mLocationProvider + "'"); + checkProviderInitialization(); + //noinspection ConstantConditions + mLocationProvider.start(); + mLogger.d(TAG, mLocationProvider.isActive() ? "SUCCESS" : "FAILURE"); - mActive = mLocationProvider.start(); - mLogger.d(TAG, mActive ? "SUCCESS" : "FAILURE"); - - if (mActive) + if (mLocationProvider.isActive()) { - mErrorOccurred = false; + if (getMyPositionMode() == LocationState.NOT_FOLLOW_NO_POSITION) + switchToNextMode(); mPredictor.resume(); } - else - notifyLocationError(LocationHelper.ERROR_DENIED); + } + + private void checkProviderInitialization() + { + if (mLocationProvider == null) + { + String error = "A location provider must be initialized!"; + mLogger.e(TAG, error, new Throwable()); + throw new AssertionError(error); + } } /** @@ -624,29 +492,20 @@ public enum LocationHelper private void stopInternal() { mLogger.d(TAG, "stopInternal()"); - - mActive = false; + checkProviderInitialization(); + //noinspection ConstantConditions mLocationProvider.stop(); mSensorHelper.stop(); mPredictor.pause(); - notifyMyPositionModeChanged(LocationState.getMode()); - } - - /** - * Schedules poll termination after {@link #STOP_DELAY_MS}. - */ - private void stopDelayed() - { - mLogger.d(TAG, "stopDelayed()"); - UiThread.runLater(mStopLocationTask, STOP_DELAY_MS); } /** * Attach UI to helper. */ - public void attach(UiCallback callback) + @android.support.annotation.UiThread + public void attach(@NonNull UiCallback callback) { - mLogger.d(TAG, "attach() callback = " + callback + " mColdStart = " + mColdStart); + mLogger.d(TAG, "attach() callback = " + callback); if (mUiCallback != null) { @@ -658,15 +517,21 @@ public enum LocationHelper Utils.keepScreenOn(true, mUiCallback.getActivity().getWindow()); - mUiCallback.onMyPositionModeChanged(LocationState.getMode()); + mUiCallback.onMyPositionModeChanged(getMyPositionMode()); if (mCompassData != null) mUiCallback.onCompassUpdated(mCompassData); - if (!mLocationStopped) + checkProviderInitialization(); + //noinspection ConstantConditions + if (mLocationProvider.isActive()) + { + mLogger.d(TAG, "attach() provider '" + mLocationProvider + "' is active, just add the listener"); addListener(mLocationListener, true); + } else - checkProvidersAndStartIfNeeded(); - + { + restart(); + } } /** @@ -684,7 +549,7 @@ public enum LocationHelper Utils.keepScreenOn(false, mUiCallback.getActivity().getWindow()); mUiCallback = null; - removeListener(mLocationListener, delayed); + stop(); } /** @@ -712,8 +577,24 @@ public enum LocationHelper return mCompassData; } + @LocationState.Value + public int getMyPositionMode() + { + return LocationState.nativeGetMode(); + } + 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); static native float[] nativeUpdateCompassSensor(int ind, float[] arr); + + public interface UiCallback + { + Activity getActivity(); + void onMyPositionModeChanged(int newMode); + void onLocationUpdated(@NonNull Location location); + void onCompassUpdated(@NonNull CompassData compass); + void onLocationError(); + void onLocationNotFound(); + } } diff --git a/android/src/com/mapswithme/maps/location/LocationPredictor.java b/android/src/com/mapswithme/maps/location/LocationPredictor.java index 1aa45b5ce6..147bd71119 100644 --- a/android/src/com/mapswithme/maps/location/LocationPredictor.java +++ b/android/src/com/mapswithme/maps/location/LocationPredictor.java @@ -38,7 +38,7 @@ class LocationPredictor void resume() { - onMyPositionModeChanged(LocationState.getMode()); + onMyPositionModeChanged(LocationHelper.INSTANCE.getMyPositionMode()); } void pause() diff --git a/android/src/com/mapswithme/maps/location/LocationState.java b/android/src/com/mapswithme/maps/location/LocationState.java index 2244a3dd0c..01575464df 100644 --- a/android/src/com/mapswithme/maps/location/LocationState.java +++ b/android/src/com/mapswithme/maps/location/LocationState.java @@ -1,6 +1,9 @@ package com.mapswithme.maps.location; -import com.mapswithme.maps.MwmApplication; +import android.support.annotation.IntDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; public final class LocationState { @@ -10,6 +13,11 @@ public final class LocationState void onMyPositionModeChanged(int newMode); } + @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) public static final int PENDING_POSITION = 0; public static final int NOT_FOLLOW_NO_POSITION = 1; @@ -18,7 +26,8 @@ public final class LocationState public static final int FOLLOW_AND_ROTATE = 4; static native void nativeSwitchToNextMode(); - private static native int nativeGetMode(); + @Value + static native int nativeGetMode(); static native void nativeSetListener(ModeChangeListener listener); static native void nativeRemoveListener(); @@ -30,7 +39,7 @@ public final class LocationState */ static boolean isTurnedOn() { - return hasLocation(getMode()); + return hasLocation(nativeGetMode()); } static boolean hasLocation(int mode) @@ -38,13 +47,7 @@ public final class LocationState return (mode > NOT_FOLLOW_NO_POSITION); } - public static int getMode() - { - MwmApplication.get().initNativeCore(); - return nativeGetMode(); - } - - static String nameOf(int mode) + static String nameOf(@Value int mode) { switch (mode) { diff --git a/android/src/com/mapswithme/maps/location/TransitionListener.java b/android/src/com/mapswithme/maps/location/TransitionListener.java new file mode 100644 index 0000000000..9d7b685f1b --- /dev/null +++ b/android/src/com/mapswithme/maps/location/TransitionListener.java @@ -0,0 +1,37 @@ +package com.mapswithme.maps.location; + +import android.content.Intent; +import android.content.IntentFilter; +import android.location.LocationManager; +import android.support.annotation.NonNull; + +import com.mapswithme.maps.MwmApplication; +import com.mapswithme.maps.background.AppBackgroundTracker; + +class TransitionListener implements AppBackgroundTracker.OnTransitionListener +{ + @NonNull + private final GPSCheck mReceiver = new GPSCheck(); + private boolean mReceiverRegistered; + + @Override + public void onTransit(boolean foreground) + { + if (foreground && !mReceiverRegistered) + { + final IntentFilter filter = new IntentFilter(); + filter.addAction(LocationManager.PROVIDERS_CHANGED_ACTION); + filter.addCategory(Intent.CATEGORY_DEFAULT); + + MwmApplication.get().registerReceiver(mReceiver, filter); + mReceiverRegistered = true; + return; + } + + if (!foreground && mReceiverRegistered) + { + MwmApplication.get().unregisterReceiver(mReceiver); + mReceiverRegistered = false; + } + } +} diff --git a/android/src/com/mapswithme/maps/routing/ResultCodesHelper.java b/android/src/com/mapswithme/maps/routing/ResultCodesHelper.java index d718efb3b3..c4cf0ee4a6 100644 --- a/android/src/com/mapswithme/maps/routing/ResultCodesHelper.java +++ b/android/src/com/mapswithme/maps/routing/ResultCodesHelper.java @@ -6,6 +6,7 @@ import android.util.Pair; import java.util.ArrayList; import java.util.List; +import com.mapswithme.maps.location.LocationHelper; import com.mapswithme.maps.location.LocationState; import com.mapswithme.maps.MwmApplication; import com.mapswithme.maps.R; @@ -34,7 +35,7 @@ class ResultCodesHelper switch (errorCode) { case NO_POSITION: - if (LocationState.getMode() == LocationState.NOT_FOLLOW_NO_POSITION) + if (LocationHelper.INSTANCE.getMyPositionMode() == LocationState.NOT_FOLLOW_NO_POSITION) { titleRes = R.string.dialog_routing_location_turn_on; messages.add(resources.getString(R.string.dialog_routing_location_unknown_turn_on)); diff --git a/android/src/com/mapswithme/maps/settings/MiscPrefsFragment.java b/android/src/com/mapswithme/maps/settings/MiscPrefsFragment.java index 05b011a14a..bdf6631fd5 100644 --- a/android/src/com/mapswithme/maps/settings/MiscPrefsFragment.java +++ b/android/src/com/mapswithme/maps/settings/MiscPrefsFragment.java @@ -61,7 +61,7 @@ public class MiscPrefsFragment extends BaseXmlSettingsFragment if (oldVal != newVal) { Config.setUseGoogleService(newVal); - LocationHelper.INSTANCE.initProvider(false /* forceNative */); + LocationHelper.INSTANCE.restart(); } return true; } diff --git a/android/src/com/mapswithme/util/LocationUtils.java b/android/src/com/mapswithme/util/LocationUtils.java index 950ef3e46b..eb0d11729e 100644 --- a/android/src/com/mapswithme/util/LocationUtils.java +++ b/android/src/com/mapswithme/util/LocationUtils.java @@ -134,6 +134,16 @@ public class LocationUtils { sb = new StringBuilder("There are no enabled location providers!"); } - LOGGER.i(TAG, sb.toString(), new Throwable()); + LOGGER.i(TAG, sb.toString()); + } + + public static boolean checkProvidersAvailability() + { + Context context = MwmApplication.get(); + LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); + boolean networkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); + boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); + LocationUtils.logAvailableProviders(); + return networkEnabled || gpsEnabled; } } From e294e16550743e145bf3af4ad5902335979ff843 Mon Sep 17 00:00:00 2001 From: alexzatsepin Date: Thu, 9 Feb 2017 17:18:00 +0300 Subject: [PATCH 3/5] [android] Refactored location code regarding the first run mode --- .../src/com/mapswithme/maps/MapFragment.java | 14 +-- .../src/com/mapswithme/maps/MwmActivity.java | 26 +---- .../maps/location/AndroidNativeProvider.java | 10 +- .../maps/location/BaseLocationProvider.java | 4 +- .../location/GoogleFusedLocationProvider.java | 18 ++-- .../maps/location/LocationHelper.java | 97 +++++++++++++++---- .../maps/location/LocationState.java | 1 - .../maps/news/BaseNewsFragment.java | 7 +- .../maps/news/FirstStartFragment.java | 57 +---------- .../util/statistics/Statistics.java | 5 - 10 files changed, 114 insertions(+), 125 deletions(-) diff --git a/android/src/com/mapswithme/maps/MapFragment.java b/android/src/com/mapswithme/maps/MapFragment.java index 17da120a82..9595021a98 100644 --- a/android/src/com/mapswithme/maps/MapFragment.java +++ b/android/src/com/mapswithme/maps/MapFragment.java @@ -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; diff --git a/android/src/com/mapswithme/maps/MwmActivity.java b/android/src/com/mapswithme/maps/MwmActivity.java index ff3c929340..bf56580b9d 100644 --- a/android/src/com/mapswithme/maps/MwmActivity.java +++ b/android/src/com/mapswithme/maps/MwmActivity.java @@ -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 diff --git a/android/src/com/mapswithme/maps/location/AndroidNativeProvider.java b/android/src/com/mapswithme/maps/location/AndroidNativeProvider.java index 78aecf8abf..01191ec8f2 100644 --- a/android/src/com/mapswithme/maps/location/AndroidNativeProvider.java +++ b/android/src/com/mapswithme/maps/location/AndroidNativeProvider.java @@ -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 iterator = mListeners.listIterator(); // noinspection WhileLoopReplaceableByForEach while (iterator.hasNext()) diff --git a/android/src/com/mapswithme/maps/location/BaseLocationProvider.java b/android/src/com/mapswithme/maps/location/BaseLocationProvider.java index 6a4dc439cc..5b02bddf54 100644 --- a/android/src/com/mapswithme/maps/location/BaseLocationProvider.java +++ b/android/src/com/mapswithme/maps/location/BaseLocationProvider.java @@ -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; } } diff --git a/android/src/com/mapswithme/maps/location/GoogleFusedLocationProvider.java b/android/src/com/mapswithme/maps/location/GoogleFusedLocationProvider.java index 2810efb04c..d45b16b58d 100644 --- a/android/src/com/mapswithme/maps/location/GoogleFusedLocationProvider.java +++ b/android/src/com/mapswithme/maps/location/GoogleFusedLocationProvider.java @@ -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(); diff --git a/android/src/com/mapswithme/maps/location/LocationHelper.java b/android/src/com/mapswithme/maps/location/LocationHelper.java index 0d1ef3962e..5e0c72bbf4 100644 --- a/android/src/com/mapswithme/maps/location/LocationHelper.java +++ b/android/src/com/mapswithme/maps/location/LocationHelper.java @@ -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. diff --git a/android/src/com/mapswithme/maps/location/LocationState.java b/android/src/com/mapswithme/maps/location/LocationState.java index 01575464df..b812f9d546 100644 --- a/android/src/com/mapswithme/maps/location/LocationState.java +++ b/android/src/com/mapswithme/maps/location/LocationState.java @@ -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) diff --git a/android/src/com/mapswithme/maps/news/BaseNewsFragment.java b/android/src/com/mapswithme/maps/news/BaseNewsFragment.java index 04eda628ca..ab904358fe 100644 --- a/android/src/com/mapswithme/maps/news/BaseNewsFragment.java +++ b/android/src/com/mapswithme/maps/news/BaseNewsFragment.java @@ -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 clazz) { diff --git a/android/src/com/mapswithme/maps/news/FirstStartFragment.java b/android/src/com/mapswithme/maps/news/FirstStartFragment.java index e45a2e714c..a5ac214b5f 100644 --- a/android/src/com/mapswithme/maps/news/FirstStartFragment.java +++ b/android/src/com/mapswithme/maps/news/FirstStartFragment.java @@ -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; } } diff --git a/android/src/com/mapswithme/util/statistics/Statistics.java b/android/src/com/mapswithme/util/statistics/Statistics.java index f46b6f7aed..cc58b0f0aa 100644 --- a/android/src/com/mapswithme/util/statistics/Statistics.java +++ b/android/src/com/mapswithme/util/statistics/Statistics.java @@ -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"; From f58c1e0974b7489e86af6a060e9d162d9a61e879 Mon Sep 17 00:00:00 2001 From: alexzatsepin Date: Mon, 13 Feb 2017 13:21:36 +0300 Subject: [PATCH 4/5] [android] Added Null checking for location manager --- android/src/com/mapswithme/util/LocationUtils.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/android/src/com/mapswithme/util/LocationUtils.java b/android/src/com/mapswithme/util/LocationUtils.java index eb0d11729e..07fe2a521c 100644 --- a/android/src/com/mapswithme/util/LocationUtils.java +++ b/android/src/com/mapswithme/util/LocationUtils.java @@ -119,7 +119,7 @@ public class LocationUtils } } - public static void logAvailableProviders() + private static void logAvailableProviders() { LocationManager locMngr = (LocationManager) MwmApplication.get().getSystemService(Context.LOCATION_SERVICE); List providers = locMngr.getProviders(true); @@ -141,6 +141,12 @@ public class LocationUtils { Context context = MwmApplication.get(); LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); + if (locationManager == null) + { + LOGGER.e(TAG, "This device doesn't support the location service."); + return false; + } + boolean networkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); LocationUtils.logAvailableProviders(); From ef331c0421c5c1e7d4ab92fda7d133e310d8146e Mon Sep 17 00:00:00 2001 From: alexzatsepin Date: Mon, 13 Feb 2017 13:45:42 +0300 Subject: [PATCH 5/5] [android] Fixed review notes --- drape_frontend/drape_engine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drape_frontend/drape_engine.cpp b/drape_frontend/drape_engine.cpp index 3024ce1098..c81c5f8fa3 100644 --- a/drape_frontend/drape_engine.cpp +++ b/drape_frontend/drape_engine.cpp @@ -17,7 +17,7 @@ namespace df { DrapeEngine::DrapeEngine(Params && params) : m_myPositionModeChanged(move(params.m_myPositionModeChanged)) - , m_viewport(params.m_viewport) + , m_viewport(move(params.m_viewport)) { VisualParams::Init(params.m_vs, df::CalculateTileSize(m_viewport.GetWidth(), m_viewport.GetHeight()));