From d620f6e68872d64ce19b0c3ac02751627ed4849a Mon Sep 17 00:00:00 2001 From: Roman Romanov Date: Tue, 25 Oct 2016 16:25:35 +0400 Subject: [PATCH] [android] up target api to 23 (+4 squashed commits) Squashed commits: [1773b27] [android] Review fixes [9a09696] [android] Dynamic permissions. [0bdcdd6] [android] dynamic permissions [5306cfd] [android] up target api to 23 [android] settings refactoring [strings] added new strings [strings] generated translations --- .../com/cocosw/bottomsheet/BottomSheet.java | 4 +- .../BottomSheet/src/main/res/values/attrs.xml | 2 +- android/build.gradle | 12 +- android/gradle.properties | 4 +- .../res/layout-w1020dp/activity_settings.xml | 23 + android/res/layout/activity_settings.xml | 17 + android/res/layout/toolbar_extended.xml | 22 + android/res/values-ru/strings.xml | 10 + android/res/values-w1020dp-land/dimens.xml | 4 + android/res/values-w1020dp/dimens.xml | 2 + android/res/values/dimens.xml | 4 + android/res/values/donottranslate.xml | 7 + android/res/values/strings.xml | 10 + android/res/values/themes-base.xml | 2 + android/res/xml-v21/prefs_map.xml | 61 -- android/res/xml-v21/prefs_misc.xml | 40 - android/res/xml-v21/prefs_route.xml | 32 - android/res/xml/prefs_headers.xml | 33 - android/res/xml/prefs_main.xml | 158 ++++ android/res/xml/prefs_map.xml | 53 -- android/res/xml/prefs_misc.xml | 32 - android/res/xml/prefs_route.xml | 24 - .../maps/DownloadResourcesActivity.java | 12 +- .../src/com/mapswithme/maps/MwmActivity.java | 117 +-- .../com/mapswithme/maps/MwmApplication.java | 26 +- .../maps/base/BaseActivityDelegate.java | 22 +- .../maps/base/BaseMwmDialogFragment.java | 77 ++ .../mapswithme/maps/base/BaseMwmFragment.java | 70 ++ .../maps/base/BaseMwmFragmentActivity.java | 135 +++- .../maps/base/BaseMwmListFragment.java | 66 ++ .../maps/base/BaseMwmRecyclerFragment.java | 68 +- .../maps/base/BaseMwmToolbarFragment.java | 5 +- .../maps/base/BaseToolbarActivity.java | 7 +- .../bookmarks/BookmarkCategoriesFragment.java | 45 +- .../maps/bookmarks/BookmarksListFragment.java | 62 +- .../maps/bookmarks/data/Bookmark.java | 3 +- .../maps/bookmarks/data/BookmarkManager.java | 5 - .../maps/downloader/BottomPanel.java | 11 +- .../maps/downloader/DownloaderFragment.java | 37 +- .../maps/downloader/OnmapDownloader.java | 11 +- .../maps/editor/EditorFragment.java | 11 +- .../maps/editor/EditorHostFragment.java | 11 +- .../maps/editor/FeatureCategoryFragment.java | 8 +- .../maps/editor/StreetFragment.java | 11 +- .../maps/location/AndroidNativeProvider.java | 28 +- .../location/GoogleFusedLocationProvider.java | 18 +- .../maps/location/LocationHelper.java | 11 +- .../maps/search/SearchCategoriesFragment.java | 5 +- .../maps/search/SearchFragment.java | 12 +- .../maps/search/SearchHistoryAdapter.java | 1 + .../maps/search/SearchHistoryFragment.java | 27 +- .../mapswithme/maps/search/SearchRecents.java | 5 - .../maps/settings/AboutFragment.java | 16 +- .../maps/settings/BaseSettingsFragment.java | 43 +- .../settings/BaseXmlSettingsFragment.java | 30 +- .../maps/settings/CopyrightFragment.java | 14 +- .../maps/settings/HelpFragment.java | 12 - .../maps/settings/MapPrefsFragment.java | 235 ------ .../maps/settings/MiscPrefsFragment.java | 146 ---- .../maps/settings/RoutePrefsFragment.java | 216 ----- .../maps/settings/SettingsActivity.java | 306 ++----- .../maps/settings/SettingsPrefsFragment.java | 756 ++++++++++++++++++ .../maps/settings/StoragePathFragment.java | 14 - .../placepage/EditBookmarkFragment.java | 4 +- .../placepage/EditDescriptionFragment.java | 11 +- android/src/com/mapswithme/util/Utils.java | 41 +- .../ar.lproj/Localizable.strings | 16 + .../cs.lproj/Localizable.strings | 16 + .../da.lproj/Localizable.strings | 16 + .../de.lproj/Localizable.strings | 16 + .../en-GB.lproj/Localizable.strings | 16 + .../en.lproj/Localizable.strings | 16 + .../es.lproj/Localizable.strings | 16 + .../fi.lproj/Localizable.strings | 16 + .../fr.lproj/Localizable.strings | 16 + .../hu.lproj/Localizable.strings | 16 + .../id.lproj/Localizable.strings | 16 + .../it.lproj/Localizable.strings | 16 + .../ja.lproj/Localizable.strings | 16 + .../ko.lproj/Localizable.strings | 16 + .../nb.lproj/Localizable.strings | 16 + .../nl.lproj/Localizable.strings | 16 + .../pl.lproj/Localizable.strings | 16 + .../pt.lproj/Localizable.strings | 16 + .../ro.lproj/Localizable.strings | 16 + .../ru.lproj/Localizable.strings | 16 + .../sk.lproj/Localizable.strings | 16 + .../sv.lproj/Localizable.strings | 16 + .../th.lproj/Localizable.strings | 16 + .../tr.lproj/Localizable.strings | 16 + .../uk.lproj/Localizable.strings | 16 + .../vi.lproj/Localizable.strings | 16 + .../zh-Hans.lproj/Localizable.strings | 16 + .../zh-Hant.lproj/Localizable.strings | 16 + strings.txt | 32 + 95 files changed, 2379 insertions(+), 1428 deletions(-) create mode 100644 android/res/layout-w1020dp/activity_settings.xml create mode 100644 android/res/layout/activity_settings.xml create mode 100644 android/res/layout/toolbar_extended.xml create mode 100644 android/res/values-w1020dp-land/dimens.xml delete mode 100644 android/res/xml-v21/prefs_map.xml delete mode 100644 android/res/xml-v21/prefs_misc.xml delete mode 100644 android/res/xml-v21/prefs_route.xml delete mode 100644 android/res/xml/prefs_headers.xml create mode 100644 android/res/xml/prefs_main.xml delete mode 100644 android/res/xml/prefs_map.xml delete mode 100644 android/res/xml/prefs_misc.xml delete mode 100644 android/res/xml/prefs_route.xml delete mode 100644 android/src/com/mapswithme/maps/settings/MapPrefsFragment.java delete mode 100644 android/src/com/mapswithme/maps/settings/MiscPrefsFragment.java delete mode 100644 android/src/com/mapswithme/maps/settings/RoutePrefsFragment.java create mode 100644 android/src/com/mapswithme/maps/settings/SettingsPrefsFragment.java diff --git a/android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/BottomSheet.java b/android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/BottomSheet.java index 4d6e9df115..33eb1f131a 100644 --- a/android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/BottomSheet.java +++ b/android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/BottomSheet.java @@ -115,7 +115,7 @@ public class BottomSheet extends Dialog implements DialogInterface { super(context, theme); TypedArray a = getContext() - .obtainStyledAttributes(null, R.styleable.BottomSheet, R.attr.bottomSheetStyle, 0); + .obtainStyledAttributes(null, R.styleable.BottomSheet, R.attr.customBottomSheetStyle, 0); try { more = a.getDrawable(R.styleable.BottomSheet_bs_moreDrawable); close = a.getDrawable(R.styleable.BottomSheet_bs_closeDrawable); @@ -625,7 +625,7 @@ public class BottomSheet extends Dialog implements DialogInterface { */ public Builder(@NonNull Activity context) { this(context, R.style.BottomSheet_Dialog); - TypedArray ta = context.getTheme().obtainStyledAttributes(new int[]{R.attr.bottomSheetStyle}); + TypedArray ta = context.getTheme().obtainStyledAttributes(new int[]{R.attr.customBottomSheetStyle }); try { theme = ta.getResourceId(0, R.style.BottomSheet_Dialog); } finally { diff --git a/android/3rd_party/BottomSheet/src/main/res/values/attrs.xml b/android/3rd_party/BottomSheet/src/main/res/values/attrs.xml index efeacc3378..a526689586 100644 --- a/android/3rd_party/BottomSheet/src/main/res/values/attrs.xml +++ b/android/3rd_party/BottomSheet/src/main/res/values/attrs.xml @@ -2,7 +2,7 @@ - + diff --git a/android/build.gradle b/android/build.gradle index ba07aadafb..107dfb4fbf 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -31,13 +31,15 @@ apply plugin: 'io.fabric' dependencies { // android support libs - compile ('com.android.support:support-v4:23.2.1') { + compile ('com.android.support:support-v4:23.4.0') { force = true; } - compile 'com.android.support:appcompat-v7:23.2.1' - compile 'com.android.support:recyclerview-v7:23.2.1' - compile 'com.android.support:design:23.2.1' - compile 'com.android.support:cardview-v7:23.2.1' + compile 'com.android.support:appcompat-v7:23.4.0' + compile 'com.android.support:recyclerview-v7:23.4.0' + compile 'com.android.support:design:23.4.0' + compile 'com.android.support:cardview-v7:23.4.0' + compile 'com.android.support:preference-v7:23.4.0' + compile 'com.android.support:preference-v14:23.4.0' // google play services compile 'com.google.android.gms:play-services-location:10.0.1' compile 'com.google.android.gms:play-services-analytics:10.0.1' diff --git a/android/gradle.properties b/android/gradle.properties index 390096495e..1ae416be9f 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,7 +1,7 @@ propMinSdkVersion=15 # TODO use 23 target and build tools version, when ProGuard problem will be fixed # https://code.google.com/p/android/issues/detail?id=184567 -propTargetSdkVersion=22 +propTargetSdkVersion=23 propCompileSdkVersion=23 propBuildToolsVersion=25.0.2 propVersionCode=724 @@ -23,3 +23,5 @@ propObbWorlds ../data/World.mwm \ ../data/WorldCoasts_obsolete.mwm propObbWorldsOutput build/worlds.obb propObbFontsOutput build/fonts.obb + +org.gradle.jvmargs=-Xmx1536M diff --git a/android/res/layout-w1020dp/activity_settings.xml b/android/res/layout-w1020dp/activity_settings.xml new file mode 100644 index 0000000000..7806acc20d --- /dev/null +++ b/android/res/layout-w1020dp/activity_settings.xml @@ -0,0 +1,23 @@ + + + + + + + + + + diff --git a/android/res/layout/activity_settings.xml b/android/res/layout/activity_settings.xml new file mode 100644 index 0000000000..4df7f04a25 --- /dev/null +++ b/android/res/layout/activity_settings.xml @@ -0,0 +1,17 @@ + + + + + + + + diff --git a/android/res/layout/toolbar_extended.xml b/android/res/layout/toolbar_extended.xml new file mode 100644 index 0000000000..f0ac7db8bf --- /dev/null +++ b/android/res/layout/toolbar_extended.xml @@ -0,0 +1,22 @@ + + + + + + + diff --git a/android/res/values-ru/strings.xml b/android/res/values-ru/strings.xml index 7a6e778020..28ca8dd1d7 100644 --- a/android/res/values-ru/strings.xml +++ b/android/res/values-ru/strings.xml @@ -300,6 +300,14 @@ Длина Поделиться местоположением Поиск + + Общие настройки + + Информация + + Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.). + + For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device\'s settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine. Карта @@ -1095,4 +1103,6 @@ Хостел Дом отдыха Мотель + Вкл. + Выкл. diff --git a/android/res/values-w1020dp-land/dimens.xml b/android/res/values-w1020dp-land/dimens.xml new file mode 100644 index 0000000000..7fa394973d --- /dev/null +++ b/android/res/values-w1020dp-land/dimens.xml @@ -0,0 +1,4 @@ + + + 672dp + \ No newline at end of file diff --git a/android/res/values-w1020dp/dimens.xml b/android/res/values-w1020dp/dimens.xml index ee03656052..9e5c7c170d 100644 --- a/android/res/values-w1020dp/dimens.xml +++ b/android/res/values-w1020dp/dimens.xml @@ -6,4 +6,6 @@ -72dp + + 560dp diff --git a/android/res/values/dimens.xml b/android/res/values/dimens.xml index d4e8d30e1c..36061cf6d8 100644 --- a/android/res/values/dimens.xml +++ b/android/res/values/dimens.xml @@ -184,4 +184,8 @@ 128dp 20dp + + 8dp + + 72dp diff --git a/android/res/values/donottranslate.xml b/android/res/values/donottranslate.xml index 4ce38ca510..a41dcd4d10 100644 --- a/android/res/values/donottranslate.xml +++ b/android/res/values/donottranslate.xml @@ -40,18 +40,25 @@ Settings MapsMePrefs MapStyle + TtsScreen TtsEnabled TtsLanguage + TtsInfo AutoDownloadMap 3D 3DBuildings + TrackScreen TrackRecord + TrackRecordTime DisplayShowcase Osm profile AutoZoom LargeFontSize UseMobileData TrafficSimplifiedColors + GeneralSettings + Navigation + Information %1$s: %2$s %2$s :%1$s diff --git a/android/res/values/strings.xml b/android/res/values/strings.xml index 8c80b1a2fd..00d393313b 100644 --- a/android/res/values/strings.xml +++ b/android/res/values/strings.xml @@ -302,6 +302,14 @@ Length Share My Location Search + + General settings + + Information + + Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.). + + For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device\'s settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine. Map @@ -1107,4 +1115,6 @@ Motel Create ad campaign View ad campaign + On + Off diff --git a/android/res/values/themes-base.xml b/android/res/values/themes-base.xml index a4f4e1448a..e805959318 100644 --- a/android/res/values/themes-base.xml +++ b/android/res/values/themes-base.xml @@ -100,6 +100,7 @@ @color/warm_gray @color/search_local_ads_customer_result + @style/PreferenceThemeOverlay.v14.Material @@ -203,5 +204,6 @@ @color/warm_gray_night @color/search_local_ads_customer_result_night + @style/PreferenceThemeOverlay.v14.Material diff --git a/android/res/xml-v21/prefs_map.xml b/android/res/xml-v21/prefs_map.xml deleted file mode 100644 index 1affa5f8a2..0000000000 --- a/android/res/xml-v21/prefs_map.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/android/res/xml-v21/prefs_misc.xml b/android/res/xml-v21/prefs_misc.xml deleted file mode 100644 index b9eabbd3ec..0000000000 --- a/android/res/xml-v21/prefs_misc.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - diff --git a/android/res/xml-v21/prefs_route.xml b/android/res/xml-v21/prefs_route.xml deleted file mode 100644 index 1a75689965..0000000000 --- a/android/res/xml-v21/prefs_route.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/android/res/xml/prefs_headers.xml b/android/res/xml/prefs_headers.xml deleted file mode 100644 index cb251afd69..0000000000 --- a/android/res/xml/prefs_headers.xml +++ /dev/null @@ -1,33 +0,0 @@ - - -
- -
- -
- -
- -
- -
- \ No newline at end of file diff --git a/android/res/xml/prefs_main.xml b/android/res/xml/prefs_main.xml new file mode 100644 index 0000000000..2c7cfbb4f3 --- /dev/null +++ b/android/res/xml/prefs_main.xml @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android/res/xml/prefs_map.xml b/android/res/xml/prefs_map.xml deleted file mode 100644 index ae014c6a23..0000000000 --- a/android/res/xml/prefs_map.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/android/res/xml/prefs_misc.xml b/android/res/xml/prefs_misc.xml deleted file mode 100644 index 7e50633223..0000000000 --- a/android/res/xml/prefs_misc.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - diff --git a/android/res/xml/prefs_route.xml b/android/res/xml/prefs_route.xml deleted file mode 100644 index e1884eae88..0000000000 --- a/android/res/xml/prefs_route.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/android/src/com/mapswithme/maps/DownloadResourcesActivity.java b/android/src/com/mapswithme/maps/DownloadResourcesActivity.java index 4dbbeb93dd..8a3c915536 100644 --- a/android/src/com/mapswithme/maps/DownloadResourcesActivity.java +++ b/android/src/com/mapswithme/maps/DownloadResourcesActivity.java @@ -7,6 +7,8 @@ import android.graphics.Color; import android.location.Location; import android.net.Uri; import android.os.Bundle; +import android.support.annotation.CallSuper; +import android.support.annotation.Nullable; import android.support.annotation.StringRes; import android.text.TextUtils; import android.view.View; @@ -210,10 +212,11 @@ public class DownloadResourcesActivity extends BaseMwmFragmentActivity } }; + @CallSuper @Override - protected void onCreate(Bundle savedInstanceState) + protected void safeOnCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + super.safeOnCreate(savedInstanceState); setContentView(R.layout.activity_download_resources); initViewsAndListeners(); @@ -246,11 +249,10 @@ public class DownloadResourcesActivity extends BaseMwmFragmentActivity } } + @CallSuper @Override - protected void onResume() + protected void safeOnResume() { - super.onResume(); - if (!isFinishing()) LocationHelper.INSTANCE.addListener(mLocationListener, true); } diff --git a/android/src/com/mapswithme/maps/MwmActivity.java b/android/src/com/mapswithme/maps/MwmActivity.java index d619033919..729cbb38e8 100644 --- a/android/src/com/mapswithme/maps/MwmActivity.java +++ b/android/src/com/mapswithme/maps/MwmActivity.java @@ -10,6 +10,7 @@ import android.graphics.Rect; import android.location.Location; import android.os.Build; import android.os.Bundle; +import android.support.annotation.CallSuper; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.StyleRes; @@ -139,6 +140,7 @@ public class MwmActivity extends BaseMwmFragmentActivity @Nullable private MapFragment mMapFragment; + @Nullable private PlacePageView mPlacePage; private RoutingPlanInplaceController mRoutingPlanInplaceController; @@ -148,6 +150,7 @@ public class MwmActivity extends BaseMwmFragmentActivity private MainMenu mMainMenu; private PanelAnimator mPanelAnimator; + @Nullable private OnmapDownloader mOnmapDownloader; private FadeView mFadeView; @@ -246,7 +249,7 @@ public class MwmActivity extends BaseMwmFragmentActivity int oldLeft, int oldTop, int oldRight, int oldBottom) { mScreenFullRect = new Rect(left, top, right, bottom); - if (mPlacePageVisible && mPlacePage.GetPreview().getVisibility() != View.VISIBLE) + if (mPlacePageVisible && (mPlacePage == null || mPlacePage.GetPreview().getVisibility() != View.VISIBLE)) mPlacePageVisible = false; recalculateVisibleRect(mScreenFullRect); } @@ -259,7 +262,7 @@ public class MwmActivity extends BaseMwmFragmentActivity int orientation = MwmActivity.this.getResources().getConfiguration().orientation; Rect rect = new Rect(r.left, r.top, r.right, r.bottom); - if (mPlacePageVisible) + if (mPlacePage != null && mPlacePageVisible) { int[] loc = new int[2]; mPlacePage.GetPreview().getLocationOnScreen(loc); @@ -447,14 +450,13 @@ public class MwmActivity extends BaseMwmFragmentActivity } @SuppressLint("InlinedApi") + @CallSuper @Override - public void onCreate(@Nullable Bundle savedInstanceState) + protected void safeOnCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - + super.safeOnCreate(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)) @@ -490,8 +492,11 @@ public class MwmActivity extends BaseMwmFragmentActivity initNavigationButtons(); mPlacePage = (PlacePageView) findViewById(R.id.info_box); - mPlacePage.setOnVisibilityChangedListener(this); - mPlacePage.setOnAnimationListener(this); + if (mPlacePage != null) + { + mPlacePage.setOnVisibilityChangedListener(this); + mPlacePage.setOnAnimationListener(this); + } if (!mIsFragmentContainer) { @@ -549,6 +554,9 @@ public class MwmActivity extends BaseMwmFragmentActivity private void initPositionChooser() { mPositionChooser = findViewById(R.id.position_chooser); + if (mPositionChooser == null) + return; + final Toolbar toolbar = (Toolbar) mPositionChooser.findViewById(R.id.toolbar_position_chooser); UiUtils.extendViewWithStatusBar(toolbar); UiUtils.showHomeUpButton(toolbar); @@ -615,8 +623,11 @@ public class MwmActivity extends BaseMwmFragmentActivity } View container = findViewById(R.id.map_fragment_container); - container.setOnTouchListener(this); - mRootView = (ViewGroup) container.getParent(); + if (container != null) + { + container.setOnTouchListener(this); + mRootView = (ViewGroup) container.getParent(); + } } public void detachMap(@NonNull FragmentTransaction transaction) @@ -643,6 +654,9 @@ public class MwmActivity extends BaseMwmFragmentActivity private void initNavigationButtons() { View frame = findViewById(R.id.navigation_buttons); + if (frame == null) + return; + View zoomIn = frame.findViewById(R.id.nav_zoom_in); zoomIn.setOnClickListener(this); View zoomOut = frame.findViewById(R.id.nav_zoom_out); @@ -658,7 +672,7 @@ public class MwmActivity extends BaseMwmFragmentActivity public boolean closePlacePage() { - if (mPlacePage.isHidden()) + if (mPlacePage == null || mPlacePage.isHidden()) return false; mPlacePage.hide(); @@ -723,7 +737,7 @@ public class MwmActivity extends BaseMwmFragmentActivity { RoutingController.get().prepare(endPoint); - if (mPlacePage.isDocked() || !mPlacePage.isFloating()) + if (mPlacePage != null && (mPlacePage.isDocked() || !mPlacePage.isFloating())) closePlacePage(); } }); @@ -758,7 +772,7 @@ public class MwmActivity extends BaseMwmFragmentActivity case TOGGLE: if (!mMainMenu.isOpen()) { - if (mPlacePage.isDocked() && closePlacePage()) + if (mPlacePage == null || (mPlacePage.isDocked() && closePlacePage())) return; if (closeSidePanel()) @@ -857,7 +871,7 @@ public class MwmActivity extends BaseMwmFragmentActivity return; } - if (mPlacePage.isDocked()) + if (mPlacePage != null && mPlacePage.isDocked()) mPlacePage.setLeftAnimationTrackListener(mMainMenu.getLeftAnimationTrackListener()); } @@ -881,7 +895,7 @@ public class MwmActivity extends BaseMwmFragmentActivity @Override protected void onSaveInstanceState(Bundle outState) { - if (!mPlacePage.isHidden()) + if (mPlacePage != null && !mPlacePage.isHidden()) { outState.putInt(STATE_PP, mPlacePage.getState().ordinal()); outState.putParcelable(STATE_MAP_OBJECT, mPlacePage.getMapObject()); @@ -914,12 +928,12 @@ public class MwmActivity extends BaseMwmFragmentActivity } @Override - protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) + protected void safeOnRestoreInstanceState(@NonNull Bundle savedInstanceState) { - super.onRestoreInstanceState(savedInstanceState); + super.safeOnRestoreInstanceState(savedInstanceState); final State state = State.values()[savedInstanceState.getInt(STATE_PP, 0)]; - if (state != State.HIDDEN) + if (mPlacePage != null && state != State.HIDDEN) { mPlacePageRestored = true; mPlacePage.setMapObject((MapObject) savedInstanceState.getParcelable(STATE_MAP_OBJECT), true, @@ -1005,11 +1019,9 @@ public class MwmActivity extends BaseMwmFragmentActivity } @Override - protected void onResume() + protected void safeOnResume() { - super.onResume(); - - mPlacePageRestored = mPlacePage.getState() != State.HIDDEN; + mPlacePageRestored = mPlacePage != null && mPlacePage.getState() != State.HIDDEN; mSearchController.refreshToolbar(); mMainMenu.onResume(new Runnable() { @@ -1023,7 +1035,8 @@ public class MwmActivity extends BaseMwmFragmentActivity } } }); - mOnmapDownloader.onResume(); + if (mOnmapDownloader != null) + mOnmapDownloader.onResume(); if (mNavigationController != null) mNavigationController.onResume(); if (mNavAnimationController != null) @@ -1041,10 +1054,8 @@ public class MwmActivity extends BaseMwmFragmentActivity } @Override - protected void onResumeFragments() + protected void safeOnResumeFragments() { - super.onResumeFragments(); - if (!RoutingController.get().isNavigating()) { mFirstStart = FirstStartFragment.showOn(this); @@ -1061,7 +1072,8 @@ public class MwmActivity extends BaseMwmFragmentActivity } RoutingController.get().restore(); - mPlacePage.restore(); + if (mPlacePage != null) + mPlacePage.restore(); } @@ -1071,8 +1083,10 @@ public class MwmActivity extends BaseMwmFragmentActivity { TtsPlayer.INSTANCE.stop(); LikesManager.INSTANCE.cancelDialogs(); - mOnmapDownloader.onPause(); - mPlacePage.onActivityPause(); + if (mOnmapDownloader != null) + mOnmapDownloader.onPause(); + if (mPlacePage != null) + mPlacePage.onActivityPause(); super.onPause(); } @@ -1081,7 +1095,11 @@ public class MwmActivity extends BaseMwmFragmentActivity { super.onStart(); RoutingController.get().attach(this); + } + @Override + protected void safeOnStart() + { if (MapFragment.nativeIsEngineCreated()) LocationHelper.INSTANCE.attach(this); if (mTrafficButtonController != null) @@ -1205,16 +1223,19 @@ public class MwmActivity extends BaseMwmFragmentActivity setFullscreen(false); - mPlacePage.setMapObject(object, true, new PlacePageView.SetMapObjectListener() + if (mPlacePage != null) { - @Override - public void onSetMapObjectComplete() + mPlacePage.setMapObject(object, true, new PlacePageView.SetMapObjectListener() { - if (!mPlacePageRestored) - mPlacePage.setState(State.PREVIEW); - mPlacePageRestored = false; - } - }); + @Override + public void onSetMapObjectComplete() + { + if (!mPlacePageRestored) + mPlacePage.setState(State.PREVIEW); + mPlacePageRestored = false; + } + }); + } if (UiUtils.isVisible(mFadeView)) mFadeView.fadeOut(); @@ -1233,7 +1254,8 @@ public class MwmActivity extends BaseMwmFragmentActivity } else { - mPlacePage.hide(); + if (mPlacePage != null) + mPlacePage.hide(); } } @@ -1327,7 +1349,8 @@ public class MwmActivity extends BaseMwmFragmentActivity else { Framework.nativeDeactivatePopup(); - mPlacePage.setMapObject(null, false, null); + if (mPlacePage != null) + mPlacePage.setMapObject(null, false, null); } } @@ -1371,7 +1394,7 @@ public class MwmActivity extends BaseMwmFragmentActivity @Override public boolean onTouch(View view, MotionEvent event) { - return mPlacePage.hideOnTouch() || + return (mPlacePage != null && mPlacePage.hideOnTouch()) || (mMapFragment != null && mMapFragment.onTouch(view, event)); } @@ -1632,7 +1655,8 @@ public class MwmActivity extends BaseMwmFragmentActivity updateSearchBar(); } - mPlacePage.refreshViews(); + if (mPlacePage != null) + mPlacePage.refreshViews(); } private void adjustCompassAndTraffic(int offsetY) @@ -1689,11 +1713,13 @@ public class MwmActivity extends BaseMwmFragmentActivity @Override public void showNavigation(boolean show) { - mPlacePage.refreshViews(); + if (mPlacePage != null) + mPlacePage.refreshViews(); if (mNavigationController != null) mNavigationController.show(show); refreshFade(); - mOnmapDownloader.updateState(false); + if (mOnmapDownloader != null) + mOnmapDownloader.updateState(false); adjustCompass(UiUtils.getCompassYOffset(this)); } @@ -1801,7 +1827,7 @@ public class MwmActivity extends BaseMwmFragmentActivity @Override public void onLocationUpdated(@NonNull Location location) { - if (!mPlacePage.isHidden()) + if (mPlacePage != null && !mPlacePage.isHidden()) mPlacePage.refreshLocation(location); if (!RoutingController.get().isNavigating()) @@ -1817,7 +1843,8 @@ public class MwmActivity extends BaseMwmFragmentActivity public void onCompassUpdated(@NonNull CompassData compass) { MapFragment.nativeCompassUpdated(compass.getMagneticNorth(), compass.getTrueNorth(), false); - mPlacePage.refreshAzimuth(compass.getNorth()); + if (mPlacePage != null) + mPlacePage.refreshAzimuth(compass.getNorth()); if (mNavigationController != null) mNavigationController.updateNorth(compass.getNorth()); } diff --git a/android/src/com/mapswithme/maps/MwmApplication.java b/android/src/com/mapswithme/maps/MwmApplication.java index 1053f93fcd..af8293af93 100644 --- a/android/src/com/mapswithme/maps/MwmApplication.java +++ b/android/src/com/mapswithme/maps/MwmApplication.java @@ -7,10 +7,10 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.os.Environment; import android.os.Handler; import android.os.Message; -import android.preference.PreferenceManager; import android.support.annotation.NonNull; import android.support.annotation.UiThread; import android.support.multidex.MultiDex; +import android.support.v7.preference.PreferenceManager; import android.text.TextUtils; import android.util.Log; @@ -58,6 +58,7 @@ public class MwmApplication extends Application private boolean mAreCountersInitialized; private boolean mIsFrameworkInitialized; + private boolean mIsPlatformInitialized; private Handler mMainLoopHandler; private final Object mMainQueueToken = new Object(); @@ -147,10 +148,20 @@ public class MwmApplication extends Application mMainLoopHandler = new Handler(getMainLooper()); initCrashlytics(); - final boolean isInstallationIdFound = - setInstallationIdToCrashlytics(); initPushWoosh(); + + mPrefs = getSharedPreferences(getString(R.string.pref_file_name), MODE_PRIVATE); + mBackgroundTracker = new AppBackgroundTracker(); + } + + public void initNativePlatform() + { + if (mIsPlatformInitialized) + return; + + final boolean isInstallationIdFound = setInstallationIdToCrashlytics(); + initTracker(); String settingsPath = getSettingsPath(); @@ -174,6 +185,8 @@ public class MwmApplication extends Application mBackgroundTracker.addListener(mBackgroundListener); TrackRecorder.init(); Editor.init(); + + mIsPlatformInitialized = true; } public void initNativeCore() @@ -251,6 +264,11 @@ public class MwmApplication extends Application return mIsFrameworkInitialized; } + public boolean isPlatformInitialized() + { + return mIsPlatformInitialized; + } + public String getApkPath() { try @@ -358,7 +376,7 @@ public class MwmApplication extends Application { mAreCountersInitialized = true; Config.updateLaunchCounter(); - PreferenceManager.setDefaultValues(this, R.xml.prefs_misc, false); + PreferenceManager.setDefaultValues(this, R.xml.prefs_main, false); } } diff --git a/android/src/com/mapswithme/maps/base/BaseActivityDelegate.java b/android/src/com/mapswithme/maps/base/BaseActivityDelegate.java index fa821b27c3..2d69367e0d 100644 --- a/android/src/com/mapswithme/maps/base/BaseActivityDelegate.java +++ b/android/src/com/mapswithme/maps/base/BaseActivityDelegate.java @@ -1,21 +1,31 @@ package com.mapswithme.maps.base; import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Build; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import com.mapswithme.maps.MwmApplication; import com.mapswithme.maps.location.LocationHelper; import com.mapswithme.util.Config; import com.mapswithme.util.UiUtils; +import com.mapswithme.util.Utils; import com.mapswithme.util.ViewServer; import com.mapswithme.util.concurrency.UiThread; import com.mapswithme.util.statistics.Statistics; import com.my.tracker.MyTracker; +import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE; + public class BaseActivityDelegate { + @NonNull private final BaseActivity mActivity; + @Nullable private String mThemeName; - public BaseActivityDelegate(BaseActivity activity) + public BaseActivityDelegate(@NonNull BaseActivity activity) { mActivity = activity; } @@ -38,18 +48,24 @@ public class BaseActivityDelegate public void onStart() { + if (!MwmApplication.get().isPlatformInitialized() || !Utils.isWriteExternalGranted(mActivity.get())) + return; Statistics.INSTANCE.startActivity(mActivity.get()); MyTracker.onStartActivity(mActivity.get()); } public void onStop() { + if (!MwmApplication.get().isPlatformInitialized() || !Utils.isWriteExternalGranted(mActivity.get())) + return; Statistics.INSTANCE.stopActivity(mActivity.get()); MyTracker.onStopActivity(mActivity.get()); } public void onResume() { + if (!MwmApplication.get().isPlatformInitialized() || !Utils.isWriteExternalGranted(mActivity.get())) + return; org.alohalytics.Statistics.logEvent("$onResume", mActivity.getClass().getSimpleName() + ":" + UiUtils.deviceOrientationAsString(mActivity.get())); ViewServer.get(mActivity.get()).setFocusedWindow(mActivity.get()); @@ -57,12 +73,14 @@ public class BaseActivityDelegate public void onPause() { + if (!MwmApplication.get().isPlatformInitialized() || !Utils.isWriteExternalGranted(mActivity.get())) + return; org.alohalytics.Statistics.logEvent("$onPause", mActivity.getClass().getSimpleName()); } public void onPostResume() { - if (mThemeName.equals(Config.getCurrentUiTheme())) + if (mThemeName == null || mThemeName.equals(Config.getCurrentUiTheme()) || !Utils.isWriteExternalGranted(mActivity.get())) return; // Workaround described in https://code.google.com/p/android/issues/detail?id=93731 diff --git a/android/src/com/mapswithme/maps/base/BaseMwmDialogFragment.java b/android/src/com/mapswithme/maps/base/BaseMwmDialogFragment.java index a6728747f5..be559b7756 100644 --- a/android/src/com/mapswithme/maps/base/BaseMwmDialogFragment.java +++ b/android/src/com/mapswithme/maps/base/BaseMwmDialogFragment.java @@ -1,15 +1,28 @@ package com.mapswithme.maps.base; import android.os.Bundle; +import android.support.annotation.CallSuper; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.StyleRes; import android.support.v4.app.DialogFragment; +import android.view.View; +import com.mapswithme.maps.MwmApplication; import com.mapswithme.maps.R; import com.mapswithme.util.ThemeUtils; +import com.mapswithme.util.Utils; + +import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; public class BaseMwmDialogFragment extends DialogFragment { + @Nullable + private View mView; + @Nullable + private Bundle mSavedInstanceState; + protected final @StyleRes int getFullscreenTheme() { return (ThemeUtils.isNightTheme() ? R.style.MwmTheme_DialogFragment_Fullscreen_Night @@ -30,12 +43,20 @@ public class BaseMwmDialogFragment extends DialogFragment public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); + mSavedInstanceState = savedInstanceState; int style = getStyle(); int theme = getCustomTheme(); if (style != STYLE_NORMAL || theme != 0) //noinspection WrongConstant setStyle(style, theme); + + if (MwmApplication.get().isPlatformInitialized() && Utils.isWriteExternalGranted(getActivity())) + safeOnCreate(savedInstanceState); + } + + protected void safeOnCreate(@Nullable Bundle savedInstanceState) + { } @Override @@ -44,6 +65,13 @@ public class BaseMwmDialogFragment extends DialogFragment super.onResume(); org.alohalytics.Statistics.logEvent("$onResume", getClass().getSimpleName() + ":" + com.mapswithme.util.UiUtils.deviceOrientationAsString(getActivity())); + + if (MwmApplication.get().isPlatformInitialized() && Utils.isWriteExternalGranted(getActivity())) + safeOnResume(); + } + + protected void safeOnResume() + { } @Override @@ -53,6 +81,55 @@ public class BaseMwmDialogFragment extends DialogFragment org.alohalytics.Statistics.logEvent("$onPause", getClass().getSimpleName()); } + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) + { + super.onViewCreated(view, savedInstanceState); + mView = view; + mSavedInstanceState = savedInstanceState; + if (MwmApplication.get().isPlatformInitialized() && Utils.isWriteExternalGranted(getActivity())) + safeOnViewCreated(view, savedInstanceState); + } + + protected void safeOnViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) + { + } + + @CallSuper + @Override + public void onDestroyView() + { + mView = null; + mSavedInstanceState = null; + super.onDestroyView(); + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) + { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (grantResults.length == 0) + return; + + boolean isWriteGranted = false; + for (int i = 0; i < permissions.length; ++i) + { + int result = grantResults[i]; + String permission = permissions[i]; + if (permission.equals(WRITE_EXTERNAL_STORAGE) && result == PERMISSION_GRANTED) + isWriteGranted = true; + } + + if (isWriteGranted) + safeOnCreate(mSavedInstanceState); + + if (isWriteGranted && mView != null) + { + safeOnViewCreated(mView, mSavedInstanceState); + safeOnResume(); + } + } + public BaseMwmFragmentActivity getMwmActivity() { return (BaseMwmFragmentActivity) getActivity(); diff --git a/android/src/com/mapswithme/maps/base/BaseMwmFragment.java b/android/src/com/mapswithme/maps/base/BaseMwmFragment.java index a79049469d..5a01b91df7 100644 --- a/android/src/com/mapswithme/maps/base/BaseMwmFragment.java +++ b/android/src/com/mapswithme/maps/base/BaseMwmFragment.java @@ -1,15 +1,38 @@ package com.mapswithme.maps.base; +import android.os.Bundle; +import android.support.annotation.CallSuper; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.v4.app.Fragment; +import android.view.View; + +import com.mapswithme.maps.MwmApplication; +import com.mapswithme.util.Utils; + +import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; public class BaseMwmFragment extends Fragment { + @Nullable + private View mView; + @Nullable + private Bundle mSavedInstanceState; + @Override public void onResume() { super.onResume(); org.alohalytics.Statistics.logEvent("$onResume", this.getClass().getSimpleName() + ":" + com.mapswithme.util.UiUtils.deviceOrientationAsString(getActivity())); + + if (MwmApplication.get().isPlatformInitialized() && Utils.isWriteExternalGranted(getActivity())) + safeOnResume(); + } + + protected void safeOnResume() + { } @Override @@ -19,6 +42,53 @@ public class BaseMwmFragment extends Fragment org.alohalytics.Statistics.logEvent("$onPause", this.getClass().getSimpleName()); } + @CallSuper + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) + { + super.onViewCreated(view, savedInstanceState); + mView = view; + mSavedInstanceState = savedInstanceState; + if (MwmApplication.get().isPlatformInitialized() && Utils.isWriteExternalGranted(getActivity())) + safeOnViewCreated(view, savedInstanceState); + } + + protected void safeOnViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) + { + } + + @CallSuper + @Override + public void onDestroyView() + { + mView = null; + mSavedInstanceState = null; + super.onDestroyView(); + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) + { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (grantResults.length == 0) + return; + + boolean isWriteGranted = false; + for (int i = 0; i < permissions.length; ++i) + { + int result = grantResults[i]; + String permission = permissions[i]; + if (permission.equals(WRITE_EXTERNAL_STORAGE) && result == PERMISSION_GRANTED) + isWriteGranted = true; + } + + if (isWriteGranted && mView != null) + { + safeOnViewCreated(mView, mSavedInstanceState); + safeOnResume(); + } + } + public BaseMwmFragmentActivity getMwmActivity() { return (BaseMwmFragmentActivity) getActivity(); diff --git a/android/src/com/mapswithme/maps/base/BaseMwmFragmentActivity.java b/android/src/com/mapswithme/maps/base/BaseMwmFragmentActivity.java index 5fb29c0232..e73b965541 100644 --- a/android/src/com/mapswithme/maps/base/BaseMwmFragmentActivity.java +++ b/android/src/com/mapswithme/maps/base/BaseMwmFragmentActivity.java @@ -1,10 +1,10 @@ package com.mapswithme.maps.base; import android.app.Activity; -import android.content.Intent; import android.media.AudioManager; import android.os.Bundle; import android.support.annotation.ColorRes; +import android.support.annotation.CallSuper; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.StyleRes; @@ -16,17 +16,38 @@ import android.view.MenuItem; import com.mapswithme.maps.MwmApplication; import com.mapswithme.maps.R; import com.mapswithme.util.Config; +import com.mapswithme.maps.location.LocationHelper; import com.mapswithme.util.ThemeUtils; import com.mapswithme.util.UiUtils; import com.mapswithme.util.Utils; +import static android.Manifest.permission.ACCESS_COARSE_LOCATION; +import static android.Manifest.permission.ACCESS_FINE_LOCATION; +import static android.Manifest.permission.GET_ACCOUNTS; +import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; + public class BaseMwmFragmentActivity extends AppCompatActivity implements BaseActivity { + private static final int REQUEST_PERMISSIONS_START = 1; + private static final int REQUEST_PERMISSIONS_RESUME = 2; + + private static final String[] START_PERMISSIONS = new String[] + { + WRITE_EXTERNAL_STORAGE, + ACCESS_COARSE_LOCATION, + ACCESS_FINE_LOCATION, + GET_ACCOUNTS + }; + private static final String[] RESUME_PERMISSIONS = new String[] {WRITE_EXTERNAL_STORAGE}; + private final BaseActivityDelegate mBaseDelegate = new BaseActivityDelegate(this); @Nullable private Bundle mSavedInstanceState; + private boolean mRequestedFromOnCreate = false; + private boolean mFromInstanceState = false; @Override public Activity get() @@ -48,22 +69,38 @@ public class BaseMwmFragmentActivity extends AppCompatActivity } @Override - protected void onCreate(Bundle savedInstanceState) + protected void onCreate(@Nullable Bundle savedInstanceState) { + mFromInstanceState = savedInstanceState != null; + if (!Utils.checkPermissions(this, MwmApplication.get().isPlatformInitialized() + ? RESUME_PERMISSIONS : START_PERMISSIONS, + REQUEST_PERMISSIONS_START)) + { + mRequestedFromOnCreate = true; + super.onCreate(savedInstanceState); + return; + } + + MwmApplication.get().initNativePlatform(); mBaseDelegate.onCreate(); super.onCreate(savedInstanceState); + safeOnCreate(savedInstanceState); + } + + @CallSuper + protected void safeOnCreate(@Nullable Bundle savedInstanceState) + { + setVolumeControlStream(AudioManager.STREAM_MUSIC); + final int layoutId = getContentLayoutResId(); + if (layoutId != 0) + setContentView(layoutId); if (useTransparentStatusBar()) UiUtils.setupStatusBar(this); if (useColorStatusBar()) UiUtils.setupColorStatusBar(this, getStatusBarColor()); - setVolumeControlStream(AudioManager.STREAM_MUSIC); - final int layoutId = getContentLayoutResId(); - if (layoutId != 0) - setContentView(layoutId); - // Use full-screen on Kindle Fire only if (Utils.isAmazonDevice()) { @@ -74,6 +111,8 @@ public class BaseMwmFragmentActivity extends AppCompatActivity MwmApplication.get().initNativeCore(); MwmApplication.get().initCounters(); + LocationHelper.INSTANCE.init(); + attachDefaultFragment(); } @@ -119,6 +158,12 @@ public class BaseMwmFragmentActivity extends AppCompatActivity { super.onStart(); mBaseDelegate.onStart(); + if (MwmApplication.get().isPlatformInitialized()) + safeOnStart(); + } + + protected void safeOnStart() + { } @Override @@ -133,6 +178,12 @@ public class BaseMwmFragmentActivity extends AppCompatActivity { super.onRestoreInstanceState(savedInstanceState); mSavedInstanceState = savedInstanceState; + if (MwmApplication.get().isPlatformInitialized() && Utils.isWriteExternalGranted(this)) + safeOnRestoreInstanceState(savedInstanceState); + } + + protected void safeOnRestoreInstanceState(@NonNull Bundle savedInstanceState) + { } @Nullable @@ -156,15 +207,41 @@ public class BaseMwmFragmentActivity extends AppCompatActivity protected void onResume() { super.onResume(); + if (!mRequestedFromOnCreate && !Utils.checkPermissions(this, RESUME_PERMISSIONS, + REQUEST_PERMISSIONS_RESUME)) + { + return; + } + mBaseDelegate.onResume(); + if (MwmApplication.get().isPlatformInitialized() && Utils.isWriteExternalGranted(this)) + safeOnResume(); + } + + protected void safeOnResume() + { } @Override - protected void onPostResume() { + protected void onPostResume() + { super.onPostResume(); mBaseDelegate.onPostResume(); } + @CallSuper + @Override + protected void onResumeFragments() + { + super.onResumeFragments(); + if (MwmApplication.get().isPlatformInitialized() && Utils.isWriteExternalGranted(this)) + safeOnResumeFragments(); + } + + protected void safeOnResumeFragments() + { + } + @Override protected void onPause() { @@ -172,6 +249,48 @@ public class BaseMwmFragmentActivity extends AppCompatActivity mBaseDelegate.onPause(); } + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) + { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (grantResults.length == 0) + return; + + boolean isWriteGranted = false; + for (int i = 0; i < permissions.length; ++i) + { + int result = grantResults[i]; + String permission = permissions[i]; + if (permission.equals(WRITE_EXTERNAL_STORAGE) && result == PERMISSION_GRANTED) + isWriteGranted = true; + } + if (isWriteGranted) + { + if (requestCode == REQUEST_PERMISSIONS_START) + { + MwmApplication.get().initNativePlatform(); + mBaseDelegate.onCreate(); + safeOnCreate(mSavedInstanceState); + mBaseDelegate.onStart(); + if (mSavedInstanceState != null) + safeOnRestoreInstanceState(mSavedInstanceState); + mBaseDelegate.onResume(); + safeOnResume(); + if (!mFromInstanceState) + safeOnResumeFragments(); + } + else if (requestCode == REQUEST_PERMISSIONS_RESUME) + { + safeOnResume(); + safeOnResumeFragments(); + } + } + else + { + finish(); + } + } + protected Toolbar getToolbar() { return (Toolbar) findViewById(R.id.toolbar); diff --git a/android/src/com/mapswithme/maps/base/BaseMwmListFragment.java b/android/src/com/mapswithme/maps/base/BaseMwmListFragment.java index 2a715b2113..172571a922 100644 --- a/android/src/com/mapswithme/maps/base/BaseMwmListFragment.java +++ b/android/src/com/mapswithme/maps/base/BaseMwmListFragment.java @@ -1,24 +1,56 @@ package com.mapswithme.maps.base; import android.os.Bundle; +import android.support.annotation.CallSuper; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.v4.app.ListFragment; import android.support.v7.widget.Toolbar; import android.view.View; +import com.mapswithme.maps.MwmApplication; import com.mapswithme.maps.R; import com.mapswithme.util.UiUtils; import com.mapswithme.util.Utils; +import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; + @Deprecated public abstract class BaseMwmListFragment extends ListFragment { private Toolbar mToolbar; + @Nullable + private View mView; + @Nullable + private Bundle mSavedInstanceState; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + if (MwmApplication.get().isPlatformInitialized() && Utils.isWriteExternalGranted(getActivity())) + safeOnCreate(savedInstanceState); + } + + protected void safeOnCreate(@Nullable Bundle savedInstanceState) + { + } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); + mView = view; + mSavedInstanceState = savedInstanceState; + if (MwmApplication.get().isPlatformInitialized() && Utils.isWriteExternalGranted(getActivity())) + safeOnViewCreated(view, savedInstanceState); + } + + @CallSuper + protected void safeOnViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) + { mToolbar = (Toolbar) view.findViewById(R.id.toolbar); if (mToolbar != null) { @@ -34,6 +66,33 @@ public abstract class BaseMwmListFragment extends ListFragment } } + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) + { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (grantResults.length == 0) + return; + + boolean isWriteGranted = false; + for (int i = 0; i < permissions.length; ++i) + { + int result = grantResults[i]; + String permission = permissions[i]; + if (permission.equals(WRITE_EXTERNAL_STORAGE) && result == PERMISSION_GRANTED) + isWriteGranted = true; + } + + if (isWriteGranted) + { + safeOnCreate(mSavedInstanceState); + if (mView != null) + { + safeOnViewCreated(mView, mSavedInstanceState); + safeOnResume(); + } + } + } + public Toolbar getToolbar() { return mToolbar; @@ -45,6 +104,13 @@ public abstract class BaseMwmListFragment extends ListFragment super.onResume(); org.alohalytics.Statistics.logEvent("$onResume", getClass().getSimpleName() + ":" + UiUtils.deviceOrientationAsString(getActivity())); + + if (MwmApplication.get().isPlatformInitialized() && Utils.isWriteExternalGranted(getActivity())) + safeOnResume(); + } + + protected void safeOnResume() + { } @Override diff --git a/android/src/com/mapswithme/maps/base/BaseMwmRecyclerFragment.java b/android/src/com/mapswithme/maps/base/BaseMwmRecyclerFragment.java index f79b7cdc63..0438a2bb0a 100644 --- a/android/src/com/mapswithme/maps/base/BaseMwmRecyclerFragment.java +++ b/android/src/com/mapswithme/maps/base/BaseMwmRecyclerFragment.java @@ -1,8 +1,10 @@ package com.mapswithme.maps.base; import android.os.Bundle; +import android.support.annotation.CallSuper; import android.support.annotation.LayoutRes; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; @@ -11,17 +13,27 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import com.mapswithme.maps.MwmApplication; import com.mapswithme.maps.R; import com.mapswithme.maps.widget.PlaceholderView; import com.mapswithme.util.UiUtils; import com.mapswithme.util.Utils; +import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; + public abstract class BaseMwmRecyclerFragment extends Fragment { private Toolbar mToolbar; + @Nullable private RecyclerView mRecycler; private PlaceholderView mPlaceholder; + @Nullable + private View mView; + @Nullable + private Bundle mSavedInstanceState; + protected abstract RecyclerView.Adapter createAdapter(); protected @LayoutRes int getLayoutRes() @@ -29,9 +41,10 @@ public abstract class BaseMwmRecyclerFragment extends Fragment return R.layout.fragment_recycler; } + @Nullable protected RecyclerView.Adapter getAdapter() { - return mRecycler.getAdapter(); + return mRecycler != null ? mRecycler.getAdapter() : null; } @Override @@ -45,6 +58,15 @@ public abstract class BaseMwmRecyclerFragment extends Fragment { super.onViewCreated(view, savedInstanceState); + mView = view; + mSavedInstanceState = savedInstanceState; + if (MwmApplication.get().isPlatformInitialized() && Utils.isWriteExternalGranted(getActivity())) + safeOnViewCreated(view, savedInstanceState); + } + + @CallSuper + protected void safeOnViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) + { mToolbar = (Toolbar) view.findViewById(R.id.toolbar); if (mToolbar != null) { @@ -72,6 +94,50 @@ public abstract class BaseMwmRecyclerFragment extends Fragment setupPlaceholder(mPlaceholder); } + @CallSuper + @Override + public void onDestroyView() + { + mView = null; + mSavedInstanceState = null; + super.onDestroyView(); + } + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) + { + super.onActivityCreated(savedInstanceState); + if (MwmApplication.get().isPlatformInitialized() && Utils.isWriteExternalGranted(getActivity())) + safeOnActivityCreated(savedInstanceState); + } + + protected void safeOnActivityCreated(@Nullable Bundle savedInstanceState) + { + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) + { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (grantResults.length == 0) + return; + + boolean isWriteGranted = false; + for (int i = 0; i < permissions.length; ++i) + { + int result = grantResults[i]; + String permission = permissions[i]; + if (permission.equals(WRITE_EXTERNAL_STORAGE) && result == PERMISSION_GRANTED) + isWriteGranted = true; + } + + if (isWriteGranted && mView != null) + { + safeOnViewCreated(mView, mSavedInstanceState); + safeOnActivityCreated(mSavedInstanceState); + } + } + public Toolbar getToolbar() { return mToolbar; diff --git a/android/src/com/mapswithme/maps/base/BaseMwmToolbarFragment.java b/android/src/com/mapswithme/maps/base/BaseMwmToolbarFragment.java index 6113b363d9..a2548098c8 100644 --- a/android/src/com/mapswithme/maps/base/BaseMwmToolbarFragment.java +++ b/android/src/com/mapswithme/maps/base/BaseMwmToolbarFragment.java @@ -1,6 +1,7 @@ package com.mapswithme.maps.base; import android.os.Bundle; +import android.support.annotation.CallSuper; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.view.View; @@ -11,10 +12,10 @@ public class BaseMwmToolbarFragment extends BaseMwmFragment { protected ToolbarController mToolbarController; + @CallSuper @Override - public void onViewCreated(View view, @Nullable Bundle savedInstanceState) + protected void safeOnViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); mToolbarController = onCreateToolbarController(view); } diff --git a/android/src/com/mapswithme/maps/base/BaseToolbarActivity.java b/android/src/com/mapswithme/maps/base/BaseToolbarActivity.java index 6763a02378..c295c161ea 100644 --- a/android/src/com/mapswithme/maps/base/BaseToolbarActivity.java +++ b/android/src/com/mapswithme/maps/base/BaseToolbarActivity.java @@ -1,6 +1,8 @@ package com.mapswithme.maps.base; import android.os.Bundle; +import android.support.annotation.CallSuper; +import android.support.annotation.Nullable; import android.support.annotation.StringRes; import android.support.v4.app.Fragment; import android.support.v7.widget.Toolbar; @@ -10,10 +12,11 @@ import com.mapswithme.util.UiUtils; public abstract class BaseToolbarActivity extends BaseMwmFragmentActivity { + @CallSuper @Override - protected void onCreate(Bundle state) + protected void safeOnCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(state); + super.safeOnCreate(savedInstanceState); Toolbar toolbar = getToolbar(); UiUtils.extendViewWithStatusBar(toolbar); diff --git a/android/src/com/mapswithme/maps/bookmarks/BookmarkCategoriesFragment.java b/android/src/com/mapswithme/maps/bookmarks/BookmarkCategoriesFragment.java index 5b2807242f..b5931fa4cb 100644 --- a/android/src/com/mapswithme/maps/bookmarks/BookmarkCategoriesFragment.java +++ b/android/src/com/mapswithme/maps/bookmarks/BookmarkCategoriesFragment.java @@ -2,8 +2,10 @@ package com.mapswithme.maps.bookmarks; import android.content.Intent; import android.os.Bundle; +import android.support.annotation.CallSuper; import android.support.annotation.LayoutRes; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; import android.view.MenuItem; import android.view.View; @@ -39,39 +41,47 @@ public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment return new BookmarkCategoriesAdapter(getActivity()); } + @Nullable @Override protected BookmarkCategoriesAdapter getAdapter() { - return (BookmarkCategoriesAdapter)super.getAdapter(); + RecyclerView.Adapter adapter = super.getAdapter(); + return adapter != null ? (BookmarkCategoriesAdapter)adapter : null; } + @CallSuper @Override - public void onViewCreated(View view, Bundle savedInstanceState) + protected void safeOnViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); + super.safeOnViewCreated(view, savedInstanceState); - getAdapter().setOnClickListener(this); - getAdapter().setOnLongClickListener(this); - getAdapter().registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() + if (getAdapter() != null) { - @Override - public void onChanged() + getAdapter().setOnClickListener(this); + getAdapter().setOnLongClickListener(this); + getAdapter().registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() { - updateResultsPlaceholder(); - } - }); + @Override + public void onChanged() + { + updateResultsPlaceholder(); + } + }); + } } private void updateResultsPlaceholder() { - showPlaceholder(getAdapter().getItemCount() == 0); + if (getAdapter() != null) + showPlaceholder(getAdapter().getItemCount() == 0); } @Override public void onResume() { super.onResume(); - getAdapter().notifyDataSetChanged(); + if (getAdapter() != null) + getAdapter().notifyDataSetChanged(); } @Override @@ -86,7 +96,8 @@ public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment { final BookmarkCategory category = BookmarkManager.INSTANCE.getCategory(mSelectedPosition); category.setName(text); - getAdapter().notifyDataSetChanged(); + if (getAdapter() != null) + getAdapter().notifyDataSetChanged(); } @Override @@ -96,7 +107,8 @@ public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment { case R.id.set_show: BookmarkManager.INSTANCE.toggleCategoryVisibility(mSelectedPosition); - getAdapter().notifyDataSetChanged(); + if (getAdapter() != null) + getAdapter().notifyDataSetChanged(); break; case R.id.set_share: @@ -105,7 +117,8 @@ public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment case R.id.set_delete: BookmarkManager.INSTANCE.nativeDeleteCategory(mSelectedPosition); - getAdapter().notifyDataSetChanged(); + if (getAdapter() != null) + getAdapter().notifyDataSetChanged(); break; case R.id.set_edit: diff --git a/android/src/com/mapswithme/maps/bookmarks/BookmarksListFragment.java b/android/src/com/mapswithme/maps/bookmarks/BookmarksListFragment.java index a01cba32d4..b117183aa4 100644 --- a/android/src/com/mapswithme/maps/bookmarks/BookmarksListFragment.java +++ b/android/src/com/mapswithme/maps/bookmarks/BookmarksListFragment.java @@ -2,7 +2,10 @@ package com.mapswithme.maps.bookmarks; import android.content.Intent; import android.os.Bundle; +import android.support.annotation.CallSuper; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.v7.app.ActionBar; import android.support.v7.app.AppCompatActivity; import android.view.LayoutInflater; import android.view.Menu; @@ -13,7 +16,6 @@ import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ListView; -import com.mapswithme.maps.Framework; import com.mapswithme.maps.MwmActivity; import com.mapswithme.maps.R; import com.mapswithme.maps.base.BaseMwmListFragment; @@ -36,13 +38,13 @@ public class BookmarksListFragment extends BaseMwmListFragment private BookmarkCategory mCategory; private int mCategoryIndex; private int mSelectedPosition; + @Nullable private BookmarkListAdapter mAdapter; + @CallSuper @Override - public void onCreate(Bundle savedInstanceState) + protected void safeOnCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - mCategoryIndex = getArguments().getInt(ChooseBookmarkCategoryFragment.CATEGORY_ID, -1); mCategory = BookmarkManager.INSTANCE.getCategory(mCategoryIndex); } @@ -53,19 +55,23 @@ public class BookmarksListFragment extends BaseMwmListFragment return inflater.inflate(R.layout.simple_list, container, false); } + @CallSuper @Override - public void onViewCreated(View view, Bundle savedInstanceState) + protected void safeOnViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); + super.safeOnViewCreated(view, savedInstanceState); initList(); setHasOptionsMenu(true); - ((AppCompatActivity) getActivity()).getSupportActionBar().setTitle(mCategory.getName()); + ActionBar bar = ((AppCompatActivity) getActivity()).getSupportActionBar(); + if (bar != null) + bar.setTitle(mCategory.getName()); } @Override - public void onResume() + protected void safeOnResume() { - super.onResume(); + if (mAdapter == null) + return; mAdapter.startLocationUpdate(); mAdapter.notifyDataSetChanged(); @@ -76,7 +82,8 @@ public class BookmarksListFragment extends BaseMwmListFragment { super.onPause(); - mAdapter.stopLocationUpdate(); + if (mAdapter != null) + mAdapter.stopLocationUpdate(); } private void initList() @@ -92,20 +99,23 @@ public class BookmarksListFragment extends BaseMwmListFragment { final Intent i = new Intent(getActivity(), MwmActivity.class); - switch (mAdapter.getItemViewType(position)) + if (mAdapter != null) { - case BookmarkListAdapter.TYPE_SECTION: - return; - case BookmarkListAdapter.TYPE_BOOKMARK: - final Bookmark bookmark = (Bookmark) mAdapter.getItem(position); - i.putExtra(MwmActivity.EXTRA_TASK, - new MwmActivity.ShowBookmarkTask(mCategoryIndex, bookmark.getBookmarkId())); - break; - case BookmarkListAdapter.TYPE_TRACK: - final Track track = (Track) mAdapter.getItem(position); - i.putExtra(MwmActivity.EXTRA_TASK, - new MwmActivity.ShowTrackTask(track.getCategoryId(), track.getTrackId())); - break; + switch (mAdapter.getItemViewType(position)) + { + case BookmarkListAdapter.TYPE_SECTION: + return; + case BookmarkListAdapter.TYPE_BOOKMARK: + final Bookmark bookmark = (Bookmark) mAdapter.getItem(position); + i.putExtra(MwmActivity.EXTRA_TASK, + new MwmActivity.ShowBookmarkTask(mCategoryIndex, bookmark.getBookmarkId())); + break; + case BookmarkListAdapter.TYPE_TRACK: + final Track track = (Track) mAdapter.getItem(position); + i.putExtra(MwmActivity.EXTRA_TASK, + new MwmActivity.ShowTrackTask(track.getCategoryId(), track.getTrackId())); + break; + } } i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); @@ -115,6 +125,9 @@ public class BookmarksListFragment extends BaseMwmListFragment @Override public boolean onItemLongClick(AdapterView parent, View view, int position, long id) { + if (mAdapter == null) + return false; + mSelectedPosition = position; final Object item = mAdapter.getItem(mSelectedPosition); int type = mAdapter.getItemViewType(mSelectedPosition); @@ -160,6 +173,9 @@ public class BookmarksListFragment extends BaseMwmListFragment @Override public boolean onMenuItemClick(MenuItem menuItem) { + if (mAdapter == null) + return false; + Bookmark item = (Bookmark) mAdapter.getItem(mSelectedPosition); switch (menuItem.getItemId()) diff --git a/android/src/com/mapswithme/maps/bookmarks/data/Bookmark.java b/android/src/com/mapswithme/maps/bookmarks/data/Bookmark.java index b0349eec74..9343e432c2 100644 --- a/android/src/com/mapswithme/maps/bookmarks/data/Bookmark.java +++ b/android/src/com/mapswithme/maps/bookmarks/data/Bookmark.java @@ -137,7 +137,8 @@ public class Bookmark extends MapObject if (!title.equals(getTitle()) || icon != mIcon || !description.equals(getBookmarkDescription())) { - nativeSetBookmarkParams(mCategoryId, mBookmarkId, title, icon.getType(), description); + nativeSetBookmarkParams(mCategoryId, mBookmarkId, title, icon != null ? icon.getType() : "", + description); mTitle = title; } } diff --git a/android/src/com/mapswithme/maps/bookmarks/data/BookmarkManager.java b/android/src/com/mapswithme/maps/bookmarks/data/BookmarkManager.java index c237296e3d..5dd519822e 100644 --- a/android/src/com/mapswithme/maps/bookmarks/data/BookmarkManager.java +++ b/android/src/com/mapswithme/maps/bookmarks/data/BookmarkManager.java @@ -39,11 +39,6 @@ public enum BookmarkManager return ICONS.get(0); } - BookmarkManager() - { - nativeLoadBookmarks(); - } - public void deleteBookmark(Bookmark bmk) { nativeDeleteBookmark(bmk.getCategoryId(), bmk.getBookmarkId()); diff --git a/android/src/com/mapswithme/maps/downloader/BottomPanel.java b/android/src/com/mapswithme/maps/downloader/BottomPanel.java index a2f4fc51ac..feab04b563 100644 --- a/android/src/com/mapswithme/maps/downloader/BottomPanel.java +++ b/android/src/com/mapswithme/maps/downloader/BottomPanel.java @@ -82,7 +82,8 @@ class BottomPanel @Override public void onClick(View v) { - mFragment.getAdapter().setAvailableMapsMode(); + if (mFragment.getAdapter() != null ) + mFragment.getAdapter().setAvailableMapsMode(); update(); } }); @@ -114,15 +115,15 @@ class BottomPanel public void update() { DownloaderAdapter adapter = mFragment.getAdapter(); - boolean search = adapter.isSearchResultsMode(); + boolean search = adapter != null && adapter.isSearchResultsMode(); boolean show = !search; - UiUtils.showIf(show && adapter.isMyMapsMode(), mFab); + UiUtils.showIf(show && adapter != null && adapter.isMyMapsMode(), mFab); if (show) { - String root = adapter.getCurrentRootId(); - if (adapter.isMyMapsMode()) + String root = adapter != null ? adapter.getCurrentRootId() : ""; + if (adapter != null && adapter.isMyMapsMode()) { int status = MapManager.nativeGetStatus(root); switch (status) diff --git a/android/src/com/mapswithme/maps/downloader/DownloaderFragment.java b/android/src/com/mapswithme/maps/downloader/DownloaderFragment.java index 298aedb23d..12ff82a0d8 100644 --- a/android/src/com/mapswithme/maps/downloader/DownloaderFragment.java +++ b/android/src/com/mapswithme/maps/downloader/DownloaderFragment.java @@ -2,6 +2,7 @@ package com.mapswithme.maps.downloader; import android.content.Intent; import android.os.Bundle; +import android.support.annotation.CallSuper; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; @@ -17,7 +18,6 @@ import com.mapswithme.maps.base.OnBackPressListener; import com.mapswithme.maps.search.NativeMapSearchListener; import com.mapswithme.maps.search.SearchEngine; import com.mapswithme.maps.widget.PlaceholderView; -import com.mapswithme.util.UiUtils; public class DownloaderFragment extends BaseMwmRecyclerFragment implements OnBackPressListener @@ -25,6 +25,7 @@ public class DownloaderFragment extends BaseMwmRecyclerFragment private DownloaderToolbarController mToolbarController; private BottomPanel mBottomPanel; + @Nullable private DownloaderAdapter mAdapter; private long mCurrentSearch; @@ -57,7 +58,8 @@ public class DownloaderFragment extends BaseMwmRecyclerFragment rs.add(item); } - mAdapter.setSearchResultsMode(rs, mToolbarController.getQuery()); + if (mAdapter != null) + mAdapter.setSearchResultsMode(rs, mToolbarController.getQuery()); if (isLast) onSearchEnd(); @@ -75,7 +77,8 @@ public class DownloaderFragment extends BaseMwmRecyclerFragment mCurrentSearch = System.nanoTime(); SearchEngine.searchMaps(mToolbarController.getQuery(), mCurrentSearch); mToolbarController.showProgress(true); - mAdapter.clearAdsAndCancelMyTarget(); + if (mAdapter != null) + mAdapter.clearAdsAndCancelMyTarget(); } void clearSearchQuery() @@ -85,7 +88,7 @@ public class DownloaderFragment extends BaseMwmRecyclerFragment void cancelSearch() { - if (!mAdapter.isSearchResultsMode()) + if (mAdapter == null || !mAdapter.isSearchResultsMode()) return; mAdapter.resetSearchResultsMode(); @@ -105,6 +108,7 @@ public class DownloaderFragment extends BaseMwmRecyclerFragment mBottomPanel.update(); } + @CallSuper @Override public void onCreate(@Nullable Bundle savedInstanceState) { @@ -112,10 +116,9 @@ public class DownloaderFragment extends BaseMwmRecyclerFragment getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); } - @Override - public void onViewCreated(View view, Bundle savedInstanceState) + protected void safeOnViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); + super.safeOnViewCreated(view, savedInstanceState); mSubscriberSlot = MapManager.nativeSubscribe(new MapManager.StorageCallback() { @Override @@ -132,8 +135,11 @@ public class DownloaderFragment extends BaseMwmRecyclerFragment SearchEngine.INSTANCE.addMapListener(mSearchListener); getRecyclerView().addOnScrollListener(mScrollListener); - mAdapter.refreshData(); - mAdapter.attach(); + if (mAdapter != null) + { + mAdapter.refreshData(); + mAdapter.attach(); + } mBottomPanel = new BottomPanel(this, view); mToolbarController = new DownloaderToolbarController(view, getActivity(), this); @@ -145,7 +151,8 @@ public class DownloaderFragment extends BaseMwmRecyclerFragment public void onDestroyView() { super.onDestroyView(); - mAdapter.detach(); + if (mAdapter != null) + mAdapter.detach(); mAdapter = null; if (mSubscriberSlot != 0) @@ -174,7 +181,7 @@ public class DownloaderFragment extends BaseMwmRecyclerFragment return true; } - return mAdapter.goUpwards(); + return mAdapter != null && mAdapter.goUpwards(); } @Override @@ -200,20 +207,22 @@ public class DownloaderFragment extends BaseMwmRecyclerFragment } @Override + @Nullable public DownloaderAdapter getAdapter() { return mAdapter; } - @NonNull String getCurrentRoot() + @NonNull + String getCurrentRoot() { - return mAdapter.getCurrentRootId(); + return mAdapter != null ? mAdapter.getCurrentRootId() : ""; } @Override protected void setupPlaceholder(@NonNull PlaceholderView placeholder) { - if (mAdapter.isSearchResultsMode()) + if (mAdapter != null && mAdapter.isSearchResultsMode()) placeholder.setContent(R.drawable.img_search_nothing_found_light, R.string.search_not_found, R.string.search_not_found_query); else diff --git a/android/src/com/mapswithme/maps/downloader/OnmapDownloader.java b/android/src/com/mapswithme/maps/downloader/OnmapDownloader.java index fef316c9ff..4cf0617bc4 100644 --- a/android/src/com/mapswithme/maps/downloader/OnmapDownloader.java +++ b/android/src/com/mapswithme/maps/downloader/OnmapDownloader.java @@ -253,15 +253,18 @@ public class OnmapDownloader implements MwmActivity.LeftAnimationTrackListener { MapManager.nativeUnsubscribe(mStorageSubscriptionSlot); mStorageSubscriptionSlot = 0; - } - MapManager.nativeUnsubscribeOnCountryChanged(); + MapManager.nativeUnsubscribeOnCountryChanged(); + } } public void onResume() { - mStorageSubscriptionSlot = MapManager.nativeSubscribe(mStorageCallback); - MapManager.nativeSubscribeOnCountryChanged(mCountryChangedListener); + if (mStorageSubscriptionSlot == 0) + { + mStorageSubscriptionSlot = MapManager.nativeSubscribe(mStorageCallback); + MapManager.nativeSubscribeOnCountryChanged(mCountryChangedListener); + } } public static void setAutodownloadLocked(boolean locked) diff --git a/android/src/com/mapswithme/maps/editor/EditorFragment.java b/android/src/com/mapswithme/maps/editor/EditorFragment.java index 0e569818bc..f1d6aacd73 100644 --- a/android/src/com/mapswithme/maps/editor/EditorFragment.java +++ b/android/src/com/mapswithme/maps/editor/EditorFragment.java @@ -4,6 +4,7 @@ import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; import android.os.Bundle; +import android.support.annotation.CallSuper; import android.support.annotation.DrawableRes; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -114,6 +115,8 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe private EditorHostFragment mParent; + private boolean mIsViewCreated = false; + @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) @@ -121,10 +124,11 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe return inflater.inflate(R.layout.fragment_editor, container, false); } + @CallSuper @Override - public void onViewCreated(View view, @Nullable Bundle savedInstanceState) + protected void safeOnViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); + mIsViewCreated = true; mParent = (EditorHostFragment) getParentFragment(); @@ -206,7 +210,8 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); - setEdits(); + if (mIsViewCreated) + setEdits(); } boolean setEdits() diff --git a/android/src/com/mapswithme/maps/editor/EditorHostFragment.java b/android/src/com/mapswithme/maps/editor/EditorHostFragment.java index 6bc9f44f28..11fae484d3 100644 --- a/android/src/com/mapswithme/maps/editor/EditorHostFragment.java +++ b/android/src/com/mapswithme/maps/editor/EditorHostFragment.java @@ -4,6 +4,7 @@ import android.app.Activity; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; +import android.support.annotation.CallSuper; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.StringRes; @@ -118,10 +119,12 @@ public class EditorHostFragment extends BaseMwmToolbarFragment return inflater.inflate(R.layout.fragment_editor_host, container, false); } + @CallSuper @Override - public void onViewCreated(View view, @Nullable Bundle savedInstanceState) + protected void safeOnViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); + super.safeOnViewCreated(view, savedInstanceState); + mToolbarController.findViewById(R.id.save).setOnClickListener(this); mToolbarController.getToolbar().setNavigationOnClickListener(new View.OnClickListener() { @@ -153,7 +156,9 @@ public class EditorHostFragment extends BaseMwmToolbarFragment @Override protected void onTextChanged(String query) { - ((CuisineFragment) getChildFragmentManager().findFragmentByTag(CuisineFragment.class.getName())).setFilter(query); + Fragment fragment = getChildFragmentManager().findFragmentByTag(CuisineFragment.class.getName()); + if (fragment != null) + ((CuisineFragment) fragment).setFilter(query); } }; } diff --git a/android/src/com/mapswithme/maps/editor/FeatureCategoryFragment.java b/android/src/com/mapswithme/maps/editor/FeatureCategoryFragment.java index 46ea0001bd..7153d2e801 100644 --- a/android/src/com/mapswithme/maps/editor/FeatureCategoryFragment.java +++ b/android/src/com/mapswithme/maps/editor/FeatureCategoryFragment.java @@ -1,6 +1,9 @@ package com.mapswithme.maps.editor; import android.os.Bundle; +import android.support.annotation.CallSuper; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; @@ -29,10 +32,11 @@ public class FeatureCategoryFragment extends BaseMwmRecyclerFragment return inflater.inflate(R.layout.fragment_categories, container, false); } + @CallSuper @Override - public void onViewCreated(View view, Bundle savedInstanceState) + protected void safeOnViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); + super.safeOnViewCreated(view, savedInstanceState); if (getArguments() != null && getArguments().containsKey(FeatureCategoryActivity.EXTRA_FEATURE_CATEGORY)) mSelectedCategory = getArguments().getParcelable(FeatureCategoryActivity.EXTRA_FEATURE_CATEGORY); diff --git a/android/src/com/mapswithme/maps/editor/StreetFragment.java b/android/src/com/mapswithme/maps/editor/StreetFragment.java index 0d1ade85ea..c4a5addd03 100644 --- a/android/src/com/mapswithme/maps/editor/StreetFragment.java +++ b/android/src/com/mapswithme/maps/editor/StreetFragment.java @@ -1,7 +1,9 @@ package com.mapswithme.maps.editor; import android.os.Bundle; +import android.support.annotation.CallSuper; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; @@ -18,10 +20,17 @@ public class StreetFragment extends BaseMwmRecyclerFragment implements EditTextD @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - mSelectedString = Editor.nativeGetStreet(); return super.onCreateView(inflater, container, savedInstanceState); } + @CallSuper + @Override + protected void safeOnViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) + { + mSelectedString = Editor.nativeGetStreet(); + super.safeOnViewCreated(view, savedInstanceState); + } + @Override public void onSaveInstanceState(Bundle outState) { diff --git a/android/src/com/mapswithme/maps/location/AndroidNativeProvider.java b/android/src/com/mapswithme/maps/location/AndroidNativeProvider.java index 01191ec8f2..495f831994 100644 --- a/android/src/com/mapswithme/maps/location/AndroidNativeProvider.java +++ b/android/src/com/mapswithme/maps/location/AndroidNativeProvider.java @@ -51,7 +51,14 @@ class AndroidNativeProvider extends BaseLocationProvider 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); + try + { + mLocationManager.requestLocationUpdates(provider, interval, 0, listener); + } + catch (SecurityException e) + { + e.printStackTrace(); + } mListeners.add(listener); } @@ -110,14 +117,21 @@ class AndroidNativeProvider extends BaseLocationProvider private static Location findBestNotExpiredLocation(LocationManager manager, List providers, long expirationMillis) { Location res = null; - for (final String pr : providers) + try { - final Location last = manager.getLastKnownLocation(pr); - if (last == null || LocationUtils.isExpired(last, last.getTime(), expirationMillis)) - continue; + for (final String pr : providers) + { + final Location last = manager.getLastKnownLocation(pr); + if (last == null || LocationUtils.isExpired(last, last.getTime(), expirationMillis)) + continue; - if (res == null || res.getAccuracy() > last.getAccuracy()) - res = last; + if (res == null || res.getAccuracy() > last.getAccuracy()) + res = last; + } + } + catch (SecurityException e) + { + e.printStackTrace(); } return res; } diff --git a/android/src/com/mapswithme/maps/location/GoogleFusedLocationProvider.java b/android/src/com/mapswithme/maps/location/GoogleFusedLocationProvider.java index d45b16b58d..768f250d0a 100644 --- a/android/src/com/mapswithme/maps/location/GoogleFusedLocationProvider.java +++ b/android/src/com/mapswithme/maps/location/GoogleFusedLocationProvider.java @@ -128,11 +128,19 @@ class GoogleFusedLocationProvider extends BaseLocationProvider if (!mGoogleApiClient.isConnected()) return; - LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, mListener); - LocationHelper.INSTANCE.startSensors(); - Location last = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); - if (last != null) - mListener.onLocationChanged(last); + try + { + LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, mListener); + LocationHelper.INSTANCE.startSensors(); + Location last = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); + if (last != null) + mListener.onLocationChanged(last); + } + catch (SecurityException e) + { + e.printStackTrace(); + stop(); + } } @Override diff --git a/android/src/com/mapswithme/maps/location/LocationHelper.java b/android/src/com/mapswithme/maps/location/LocationHelper.java index dafac37106..d715da5636 100644 --- a/android/src/com/mapswithme/maps/location/LocationHelper.java +++ b/android/src/com/mapswithme/maps/location/LocationHelper.java @@ -159,7 +159,7 @@ public enum LocationHelper }; - LocationHelper() + public void init() { mLogger.d(LocationHelper.class.getSimpleName(), "ctor()"); } @@ -167,9 +167,12 @@ public enum LocationHelper @UiThread public void initialize() { - initProvider(); - LocationState.nativeSetListener(mMyPositionModeListener); - MwmApplication.backgroundTracker().addListener(mOnTransition); + if (MwmApplication.get().isFrameworkInitialized()) + { + initProvider(); + LocationState.nativeSetListener(mMyPositionModeListener); + MwmApplication.backgroundTracker().addListener(mOnTransition); + } } private void initProvider() diff --git a/android/src/com/mapswithme/maps/search/SearchCategoriesFragment.java b/android/src/com/mapswithme/maps/search/SearchCategoriesFragment.java index e0a546e062..d2cdc9b737 100644 --- a/android/src/com/mapswithme/maps/search/SearchCategoriesFragment.java +++ b/android/src/com/mapswithme/maps/search/SearchCategoriesFragment.java @@ -22,10 +22,9 @@ public class SearchCategoriesFragment extends BaseMwmRecyclerFragment return R.layout.fragment_search_categories; } - @Override - public void onActivityCreated(@Nullable Bundle savedInstanceState) + + protected void safeOnActivityCreated(@Nullable Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); ((SearchFragment) getParentFragment()).setRecyclerScrollListener(getRecyclerView()); } diff --git a/android/src/com/mapswithme/maps/search/SearchFragment.java b/android/src/com/mapswithme/maps/search/SearchFragment.java index 36c3cf50dd..627ab2bd6f 100644 --- a/android/src/com/mapswithme/maps/search/SearchFragment.java +++ b/android/src/com/mapswithme/maps/search/SearchFragment.java @@ -8,6 +8,7 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.design.widget.AppBarLayout; import android.support.design.widget.CollapsingToolbarLayout; +import android.support.annotation.CallSuper; import android.support.design.widget.TabLayout; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; @@ -19,7 +20,6 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import com.mapswithme.maps.Framework; import com.mapswithme.maps.MwmActivity; import com.mapswithme.maps.MwmApplication; import com.mapswithme.maps.R; @@ -286,10 +286,11 @@ public class SearchFragment extends BaseMwmFragment return inflater.inflate(R.layout.fragment_search, container, false); } + @CallSuper @Override - public void onViewCreated(View view, Bundle savedInstanceState) + protected void safeOnViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); + super.safeOnViewCreated(view, savedInstanceState); readArguments(); ViewGroup root = (ViewGroup) view; @@ -388,10 +389,9 @@ public class SearchFragment extends BaseMwmFragment mFilterController.onSaveState(outState); } - @Override - public void onResume() + + protected void safeOnResume() { - super.onResume(); LocationHelper.INSTANCE.addListener(mLocationListener, true); mAppBarLayout.addOnOffsetChangedListener(mOffsetListener); } diff --git a/android/src/com/mapswithme/maps/search/SearchHistoryAdapter.java b/android/src/com/mapswithme/maps/search/SearchHistoryAdapter.java index 2b022069e5..40843a69d3 100644 --- a/android/src/com/mapswithme/maps/search/SearchHistoryAdapter.java +++ b/android/src/com/mapswithme/maps/search/SearchHistoryAdapter.java @@ -35,6 +35,7 @@ class SearchHistoryAdapter extends RecyclerView.Adapter sRecents = new ArrayList<>(); - static - { - refresh(); - } - private SearchRecents() {} public static void refresh() diff --git a/android/src/com/mapswithme/maps/settings/AboutFragment.java b/android/src/com/mapswithme/maps/settings/AboutFragment.java index 4bf2e94014..0e4d397d93 100644 --- a/android/src/com/mapswithme/maps/settings/AboutFragment.java +++ b/android/src/com/mapswithme/maps/settings/AboutFragment.java @@ -42,12 +42,12 @@ public class AboutFragment extends BaseSettingsFragment return R.layout.about; } - @Override - protected BaseShadowController createShadowController() - { - clearPaddings(); - return new ScrollViewShadowController((ObservableScrollView) mFrame.findViewById(R.id.content_frame)); - } +// @Override +// protected BaseShadowController createShadowController() +// { +// clearPaddings(); +// return new ScrollViewShadowController((ObservableScrollView) mFrame.findViewById(R.id.content_frame)); +// } @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) @@ -127,7 +127,9 @@ public class AboutFragment extends BaseSettingsFragment case R.id.copyright: Statistics.INSTANCE.trackEvent(Statistics.EventName.Settings.COPYRIGHT); AlohaHelper.logClick(AlohaHelper.Settings.COPYRIGHT); - getSettingsActivity().switchToFragment(CopyrightFragment.class, R.string.copyright); +// getSettingsActivity().switchToFragment(CopyrightFragment.class, R.string.copyright); + getSettingsActivity().replaceFragment(CopyrightFragment.class, + getString(R.string.copyright), null); break; } } catch (ActivityNotFoundException e) diff --git a/android/src/com/mapswithme/maps/settings/BaseSettingsFragment.java b/android/src/com/mapswithme/maps/settings/BaseSettingsFragment.java index 87385a9b11..b68d384217 100644 --- a/android/src/com/mapswithme/maps/settings/BaseSettingsFragment.java +++ b/android/src/com/mapswithme/maps/settings/BaseSettingsFragment.java @@ -1,27 +1,21 @@ package com.mapswithme.maps.settings; -import android.app.Fragment; import android.graphics.Rect; import android.os.Bundle; -import android.preference.PreferenceActivity; import android.support.annotation.LayoutRes; import android.support.annotation.Nullable; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import com.mapswithme.maps.R; -import com.mapswithme.maps.widget.BaseShadowController; -import com.mapswithme.util.UiUtils; +import com.mapswithme.maps.base.BaseMwmFragment; -abstract class BaseSettingsFragment extends Fragment +abstract class BaseSettingsFragment extends BaseMwmFragment { protected View mFrame; - private BaseShadowController mShadowController; private final Rect mSavedPaddings = new Rect(); protected abstract @LayoutRes int getLayoutRes(); - protected abstract BaseShadowController createShadowController(); private void savePaddings() { @@ -53,12 +47,6 @@ abstract class BaseSettingsFragment extends Fragment super.onActivityCreated(savedInstanceState); savePaddings(); - if (((PreferenceActivity)getActivity()).onIsMultiPane()) - { - mShadowController = createShadowController(); - if (mShadowController != null) - mShadowController.attach(); - } } @Override @@ -67,33 +55,6 @@ abstract class BaseSettingsFragment extends Fragment super.onDestroyView(); restorePaddings(); - if (mShadowController != null) - mShadowController.detach(); - } - - @Override - public void onResume() - { - super.onResume(); - org.alohalytics.Statistics.logEvent("$onResume", getClass().getSimpleName() + ":" + - UiUtils.deviceOrientationAsString(getActivity())); - } - - @Override - public void onPause() - { - super.onPause(); - org.alohalytics.Statistics.logEvent("$onPause", getClass().getSimpleName() + ":" + - UiUtils.deviceOrientationAsString(getActivity())); - } - - protected static void adjustMargins(View view) - { - int margin = UiUtils.dimen(R.dimen.margin_half); - ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) view.getLayoutParams(); - lp.leftMargin = margin; - lp.rightMargin = margin; - view.setLayoutParams(lp); } protected SettingsActivity getSettingsActivity() diff --git a/android/src/com/mapswithme/maps/settings/BaseXmlSettingsFragment.java b/android/src/com/mapswithme/maps/settings/BaseXmlSettingsFragment.java index cb81146ae2..d7e6453e57 100644 --- a/android/src/com/mapswithme/maps/settings/BaseXmlSettingsFragment.java +++ b/android/src/com/mapswithme/maps/settings/BaseXmlSettingsFragment.java @@ -1,19 +1,25 @@ package com.mapswithme.maps.settings; import android.os.Bundle; -import android.preference.PreferenceFragment; +import android.support.annotation.Nullable; import android.support.annotation.XmlRes; +import android.support.v4.content.ContextCompat; +import android.support.v7.preference.PreferenceFragmentCompat; +import android.view.View; + +import com.mapswithme.maps.R; +import com.mapswithme.util.Config; +import com.mapswithme.util.ThemeUtils; import com.mapswithme.util.UiUtils; -abstract class BaseXmlSettingsFragment extends PreferenceFragment +abstract class BaseXmlSettingsFragment extends PreferenceFragmentCompat { protected abstract @XmlRes int getXmlResources(); @Override - public void onCreate(Bundle savedInstanceState) + public void onCreatePreferences(Bundle bundle, String root) { - super.onCreate(savedInstanceState); - addPreferencesFromResource(getXmlResources()); + setPreferencesFromResource(getXmlResources(), root); } @Override @@ -32,6 +38,20 @@ abstract class BaseXmlSettingsFragment extends PreferenceFragment UiUtils.deviceOrientationAsString(getActivity())); } + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) + { + super.onViewCreated(view, savedInstanceState); + + String theme = Config.getCurrentUiTheme(); + int color; + if (ThemeUtils.isDefaultTheme(theme)) + color = ContextCompat.getColor(getContext(), R.color.bg_cards); + else + color = ContextCompat.getColor(getContext(), R.color.bg_cards_night); + view.setBackgroundColor(color); + } + protected SettingsActivity getSettingsActivity() { return (SettingsActivity) getActivity(); diff --git a/android/src/com/mapswithme/maps/settings/CopyrightFragment.java b/android/src/com/mapswithme/maps/settings/CopyrightFragment.java index 0fcaa363b1..3a9bfe732d 100644 --- a/android/src/com/mapswithme/maps/settings/CopyrightFragment.java +++ b/android/src/com/mapswithme/maps/settings/CopyrightFragment.java @@ -9,9 +9,6 @@ import android.view.ViewGroup; import com.mapswithme.maps.R; import com.mapswithme.maps.WebContainerDelegate; import com.mapswithme.maps.base.OnBackPressListener; -import com.mapswithme.maps.widget.BaseShadowController; -import com.mapswithme.maps.widget.ObservableWebView; -import com.mapswithme.maps.widget.WebViewShadowController; import com.mapswithme.util.Constants; public class CopyrightFragment extends BaseSettingsFragment @@ -25,14 +22,6 @@ public class CopyrightFragment extends BaseSettingsFragment return R.layout.fragment_prefs_copyright; } - @Override - protected BaseShadowController createShadowController() - { - clearPaddings(); - adjustMargins(mDelegate.getWebView()); - return new WebViewShadowController((ObservableWebView)mDelegate.getWebView()); - } - @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { @@ -54,7 +43,8 @@ public class CopyrightFragment extends BaseSettingsFragment public boolean onBackPressed() { if (!mDelegate.onBackPressed()) - getSettingsActivity().switchToFragment(AboutFragment.class, R.string.about_menu_title); + getSettingsActivity().replaceFragment(AboutFragment.class, + getString(R.string.about_menu_title), null); return true; } diff --git a/android/src/com/mapswithme/maps/settings/HelpFragment.java b/android/src/com/mapswithme/maps/settings/HelpFragment.java index 2a6bc78853..3a8ed91cb4 100644 --- a/android/src/com/mapswithme/maps/settings/HelpFragment.java +++ b/android/src/com/mapswithme/maps/settings/HelpFragment.java @@ -13,9 +13,6 @@ import android.widget.TextView; import com.mapswithme.maps.BuildConfig; import com.mapswithme.maps.R; import com.mapswithme.maps.WebContainerDelegate; -import com.mapswithme.maps.widget.BaseShadowController; -import com.mapswithme.maps.widget.ObservableWebView; -import com.mapswithme.maps.widget.WebViewShadowController; import com.mapswithme.util.Constants; import com.mapswithme.util.Utils; import com.mapswithme.util.statistics.AlohaHelper; @@ -31,15 +28,6 @@ public class HelpFragment extends BaseSettingsFragment return R.layout.fragment_prefs_help; } - @Override - protected BaseShadowController createShadowController() - { - clearPaddings(); - adjustMargins(mDelegate.getWebView()); - return new WebViewShadowController((ObservableWebView)mDelegate.getWebView()) - .addBottomShadow(); - } - @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { diff --git a/android/src/com/mapswithme/maps/settings/MapPrefsFragment.java b/android/src/com/mapswithme/maps/settings/MapPrefsFragment.java deleted file mode 100644 index 20fdea77cc..0000000000 --- a/android/src/com/mapswithme/maps/settings/MapPrefsFragment.java +++ /dev/null @@ -1,235 +0,0 @@ -package com.mapswithme.maps.settings; - -import android.app.Activity; -import android.os.Bundle; -import android.preference.ListPreference; -import android.preference.Preference; -import android.preference.TwoStatePreference; -import android.support.v7.app.AlertDialog; - -import java.util.List; - -import com.mapswithme.maps.Framework; -import com.mapswithme.maps.R; -import com.mapswithme.maps.downloader.MapManager; -import com.mapswithme.maps.downloader.OnmapDownloader; -import com.mapswithme.maps.location.TrackRecorder; -import com.mapswithme.util.Config; -import com.mapswithme.util.ThemeSwitcher; -import com.mapswithme.util.concurrency.UiThread; -import com.mapswithme.util.statistics.AlohaHelper; -import com.mapswithme.util.statistics.Statistics; - -public class MapPrefsFragment extends BaseXmlSettingsFragment -{ - private final StoragePathManager mPathManager = new StoragePathManager(); - private Preference mStoragePref; - - private boolean singleStorageOnly() - { - return !mPathManager.hasMoreThanOneStorage(); - } - - private void updateStoragePrefs() - { - Preference old = findPreference(getString(R.string.pref_storage)); - - if (singleStorageOnly()) - { - if (old != null) - getPreferenceScreen().removePreference(old); - } - else - { - if (old == null) - getPreferenceScreen().addPreference(mStoragePref); - } - } - - @Override - protected int getXmlResources() - { - return R.xml.prefs_map; - } - - @Override - public void onCreate(Bundle savedInstanceState) - { - super.onCreate(savedInstanceState); - - mStoragePref = findPreference(getString(R.string.pref_storage)); - updateStoragePrefs(); - - mStoragePref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() - { - @Override - public boolean onPreferenceClick(Preference preference) - { - if (MapManager.nativeIsDownloading()) - new AlertDialog.Builder(getActivity()) - .setTitle(getString(R.string.downloading_is_active)) - .setMessage(getString(R.string.cant_change_this_setting)) - .setPositiveButton(getString(R.string.ok), null) - .show(); - else - getSettingsActivity().switchToFragment(StoragePathFragment.class, R.string.maps_storage); - - return true; - } - }); - - Preference pref = findPreference(getString(R.string.pref_munits)); - ((ListPreference)pref).setValue(String.valueOf(UnitLocale.getUnits())); - pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() - { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) - { - UnitLocale.setUnits(Integer.parseInt((String) newValue)); - Statistics.INSTANCE.trackEvent(Statistics.EventName.Settings.UNITS); - AlohaHelper.logClick(AlohaHelper.Settings.CHANGE_UNITS); - return true; - } - }); - - pref = findPreference(getString(R.string.pref_show_zoom_buttons)); - ((TwoStatePreference)pref).setChecked(Config.showZoomButtons()); - pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() - { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) - { - Statistics.INSTANCE.trackEvent(Statistics.EventName.Settings.ZOOM); - Config.setShowZoomButtons((Boolean) newValue); - return true; - } - }); - - String curTheme = Config.getUiThemeSettings(); - final ListPreference stylePref = (ListPreference)findPreference(getString(R.string.pref_map_style)); - stylePref.setValue(curTheme); - stylePref.setSummary(stylePref.getEntry()); - stylePref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() - { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) - { - String themeName = (String)newValue; - if (!Config.setUiThemeSettings(themeName)) - return true; - - ThemeSwitcher.restart(false); - Statistics.INSTANCE.trackEvent(Statistics.EventName.Settings.MAP_STYLE, - Statistics.params().add(Statistics.EventParam.NAME, themeName)); - - UiThread.runLater(new Runnable() - { - @Override - public void run() - { - stylePref.setSummary(stylePref.getEntry()); - } - }); - - return true; - } - }); - - TwoStatePreference prefAutodownload = (TwoStatePreference)findPreference(getString(R.string.pref_autodownload)); - prefAutodownload.setChecked(Config.isAutodownloadEnabled()); - prefAutodownload.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() - { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) - { - boolean value = (Boolean)newValue; - Config.setAutodownloadEnabled(value); - - if (value) - OnmapDownloader.setAutodownloadLocked(false); - - return true; - } - }); - - pref = findPreference(getString(R.string.pref_large_fonts_size)); - ((TwoStatePreference)pref).setChecked(Config.isLargeFontsSize()); - pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() - { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) - { - boolean oldVal = Config.isLargeFontsSize(); - boolean newVal = (Boolean) newValue; - if (oldVal != newVal) - Config.setLargeFontsSize(newVal); - - return true; - } - }); - - final Framework.Params3dMode _3d = new Framework.Params3dMode(); - Framework.nativeGet3dMode(_3d); - - final TwoStatePreference pref3dBuildings = (TwoStatePreference)findPreference(getString(R.string.pref_3d_buildings)); - pref3dBuildings.setChecked(_3d.buildings); - - pref3dBuildings.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() - { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) - { - Framework.nativeSet3dMode(_3d.enabled, (Boolean)newValue); - return true; - } - }); - - final ListPreference trackPref = (ListPreference)findPreference(getString(R.string.pref_track_record)); - String value = (TrackRecorder.isEnabled() ? String.valueOf(TrackRecorder.getDuration()) : "0"); - trackPref.setValue(value); - trackPref.setSummary(trackPref.getEntry()); - trackPref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() - { - @Override - public boolean onPreferenceChange(final Preference preference, Object newValue) - { - int value = Integer.valueOf((String)newValue); - TrackRecorder.setEnabled(value != 0); - - if (value != 0) - TrackRecorder.setDuration(value); - - UiThread.runLater(new Runnable() - { - @Override - public void run() - { - trackPref.setSummary(trackPref.getEntry()); - } - }); - return true; - } - }); - } - - @Override - public void onAttach(Activity activity) - { - super.onAttach(activity); - mPathManager.startExternalStorageWatching(activity, new StoragePathManager.OnStorageListChangedListener() - { - @Override - public void onStorageListChanged(List storageItems, int currentStorageIndex) - { - updateStoragePrefs(); - } - }, null); - } - - @Override - public void onDetach() - { - super.onDetach(); - mPathManager.stopExternalStorageWatching(); - } -} diff --git a/android/src/com/mapswithme/maps/settings/MiscPrefsFragment.java b/android/src/com/mapswithme/maps/settings/MiscPrefsFragment.java deleted file mode 100644 index bdf6631fd5..0000000000 --- a/android/src/com/mapswithme/maps/settings/MiscPrefsFragment.java +++ /dev/null @@ -1,146 +0,0 @@ -package com.mapswithme.maps.settings; - -import android.os.Bundle; -import android.preference.ListPreference; -import android.preference.Preference; -import android.preference.TwoStatePreference; - -import com.google.android.gms.common.ConnectionResult; -import com.google.android.gms.common.GoogleApiAvailability; -import com.mapswithme.maps.BuildConfig; -import com.mapswithme.maps.MwmApplication; -import com.mapswithme.maps.R; -import com.mapswithme.maps.location.LocationHelper; -import com.mapswithme.maps.search.SearchFragment; -import com.mapswithme.util.Config; -import com.mapswithme.util.log.LoggerFactory; -import com.mapswithme.util.NetworkPolicy; -import com.mapswithme.util.concurrency.UiThread; -import com.mapswithme.util.statistics.MytargetHelper; -import com.mapswithme.util.statistics.Statistics; - -public class MiscPrefsFragment extends BaseXmlSettingsFragment -{ - @Override - protected int getXmlResources() - { - return R.xml.prefs_misc; - } - - @Override - public void onCreate(Bundle savedInstanceState) - { - super.onCreate(savedInstanceState); - - Preference pref = findPreference(getString(R.string.pref_send_statistics)); - ((TwoStatePreference)pref).setChecked(Config.isStatisticsEnabled()); - pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() - { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) - { - Statistics.INSTANCE.setStatEnabled((Boolean) newValue); - return true; - } - }); - - pref = findPreference(getString(R.string.pref_play_services)); - - if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(MwmApplication.get()) != ConnectionResult.SUCCESS) - getPreferenceScreen().removePreference(pref); - else - { - ((TwoStatePreference) pref).setChecked(Config.useGoogleServices()); - pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() - { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) - { - boolean oldVal = Config.useGoogleServices(); - boolean newVal = ((Boolean) newValue).booleanValue(); - if (oldVal != newVal) - { - Config.setUseGoogleService(newVal); - LocationHelper.INSTANCE.restart(); - } - return true; - } - }); - } - - if (!MytargetHelper.isShowcaseSwitchedOnServer()) - getPreferenceScreen().removePreference(findPreference(getString(R.string.pref_showcase_switched_on))); - - pref = findPreference(getString(R.string.pref_enable_logging)); - if (!MwmApplication.prefs().getBoolean(SearchFragment.PREFS_SHOW_ENABLE_LOGGING_SETTING, - BuildConfig.BUILD_TYPE.equals("beta"))) - { - getPreferenceScreen().removePreference(pref); - } - else - { - final boolean isLoggingEnabled = LoggerFactory.INSTANCE.isFileLoggingEnabled(); - ((TwoStatePreference) pref).setChecked(isLoggingEnabled); - pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() - { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) - { - boolean oldVal = isLoggingEnabled; - boolean newVal = (Boolean) newValue; - if (oldVal != newVal) - { - LoggerFactory.INSTANCE.setFileLoggingEnabled(newVal); - } - return true; - } - }); - } - - int curValue = Config.getUseMobileDataSettings(); - final ListPreference mobilePref = (ListPreference)findPreference( - getString(R.string.pref_use_mobile_data)); - if (curValue != NetworkPolicy.NOT_TODAY && curValue != NetworkPolicy.TODAY) - { - mobilePref.setValue(String.valueOf(curValue)); - mobilePref.setSummary(mobilePref.getEntry()); - } - else - { - mobilePref.setSummary(getString(R.string.mobile_data_description)); - } - mobilePref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() - { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) - { - String valueStr = (String)newValue; - switch (Integer.parseInt(valueStr)) - { - case NetworkPolicy.ASK: - Config.setUseMobileDataSettings(NetworkPolicy.ASK); - break; - case NetworkPolicy.ALWAYS: - Config.setUseMobileDataSettings(NetworkPolicy.ALWAYS); - break; - case NetworkPolicy.NEVER: - Config.setUseMobileDataSettings(NetworkPolicy.NEVER); - break; - default: - throw new AssertionError("Wrong NetworkPolicy type!"); - } - - UiThread.runLater(new Runnable() - { - @Override - public void run() - { - mobilePref.setSummary(mobilePref.getEntry()); - } - }); - - return true; - } - }); - } -} diff --git a/android/src/com/mapswithme/maps/settings/RoutePrefsFragment.java b/android/src/com/mapswithme/maps/settings/RoutePrefsFragment.java deleted file mode 100644 index 30a2990c6c..0000000000 --- a/android/src/com/mapswithme/maps/settings/RoutePrefsFragment.java +++ /dev/null @@ -1,216 +0,0 @@ -package com.mapswithme.maps.settings; - -import android.content.Intent; -import android.os.Bundle; -import android.preference.ListPreference; -import android.preference.Preference; -import android.preference.PreferenceFragment; -import android.preference.TwoStatePreference; -import android.speech.tts.TextToSpeech; -import android.support.annotation.NonNull; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import com.mapswithme.maps.Framework; -import com.mapswithme.maps.R; -import com.mapswithme.maps.sound.LanguageData; -import com.mapswithme.maps.sound.TtsPlayer; -import com.mapswithme.util.Config; -import com.mapswithme.util.statistics.Statistics; - -public class RoutePrefsFragment extends PreferenceFragment -{ - private static final int REQUEST_INSTALL_DATA = 1; - - private TwoStatePreference mPrefEnabled; - private ListPreference mPrefLanguages; - - private final Map mLanguages = new HashMap<>(); - private LanguageData mCurrentLanguage; - private String mSelectedLanguage; - - private final Preference.OnPreferenceChangeListener mEnabledListener = new Preference.OnPreferenceChangeListener() - { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) - { - Statistics.INSTANCE.trackEvent(Statistics.EventName.Settings.VOICE_ENABLED, Statistics.params().add(Statistics.EventParam.ENABLED, newValue.toString())); - boolean set = (Boolean)newValue; - if (!set) - { - TtsPlayer.setEnabled(false); - mPrefLanguages.setEnabled(false); - return true; - } - - if (mCurrentLanguage != null && mCurrentLanguage.downloaded) - { - setLanguage(mCurrentLanguage); - return true; - } - - mPrefLanguages.setEnabled(true); - getPreferenceScreen().onItemClick(null, null, mPrefLanguages.getOrder(), 0); - mPrefLanguages.setEnabled(false); - return false; - } - }; - - private final Preference.OnPreferenceChangeListener mLangListener = new Preference.OnPreferenceChangeListener() - { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) - { - if (newValue == null) - return false; - - mSelectedLanguage = (String)newValue; - Statistics.INSTANCE.trackEvent(Statistics.EventName.Settings.VOICE_LANGUAGE, Statistics.params().add(Statistics.EventParam.LANGUAGE, mSelectedLanguage)); - LanguageData lang = mLanguages.get(mSelectedLanguage); - if (lang == null) - return false; - - if (lang.downloaded) - setLanguage(lang); - else - startActivityForResult(new Intent(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA), REQUEST_INSTALL_DATA); - - return false; - } - }; - - private void enableListeners(boolean enable) - { - mPrefEnabled.setOnPreferenceChangeListener(enable ? mEnabledListener : null); - mPrefLanguages.setOnPreferenceChangeListener(enable ? mLangListener : null); - } - - private void setLanguage(@NonNull LanguageData lang) - { - Config.setTtsEnabled(true); - TtsPlayer.INSTANCE.setLanguage(lang); - mPrefLanguages.setSummary(lang.name); - - update(); - } - - private void update() - { - enableListeners(false); - - List languages = TtsPlayer.INSTANCE.refreshLanguages(); - mLanguages.clear(); - mCurrentLanguage = null; - - if (languages.isEmpty()) - { - mPrefEnabled.setChecked(false); - mPrefEnabled.setEnabled(false); - mPrefEnabled.setSummary(R.string.pref_tts_unavailable); - mPrefLanguages.setEnabled(false); - mPrefLanguages.setSummary(null); - - enableListeners(true); - return; - } - - mPrefEnabled.setChecked(TtsPlayer.INSTANCE.isEnabled()); - mPrefEnabled.setSummary(null); - - final CharSequence[] entries = new CharSequence[languages.size()]; - final CharSequence[] values = new CharSequence[languages.size()]; - for (int i = 0; i < languages.size(); i++) - { - LanguageData lang = languages.get(i); - entries[i] = lang.name; - values[i] = lang.internalCode; - - mLanguages.put(lang.internalCode, lang); - } - - mPrefLanguages.setEntries(entries); - mPrefLanguages.setEntryValues(values); - - mCurrentLanguage = TtsPlayer.getSelectedLanguage(languages); - boolean available = (mCurrentLanguage != null && mCurrentLanguage.downloaded); - mPrefLanguages.setEnabled(available && TtsPlayer.INSTANCE.isEnabled()); - mPrefLanguages.setSummary(available ? mCurrentLanguage.name : null); - mPrefLanguages.setValue(available ? mCurrentLanguage.internalCode : null); - mPrefEnabled.setChecked(available && TtsPlayer.INSTANCE.isEnabled()); - - enableListeners(true); - } - - @Override - public void onCreate(Bundle savedInstanceState) - { - super.onCreate(savedInstanceState); - addPreferencesFromResource(R.xml.prefs_route); - - mPrefEnabled = (TwoStatePreference) findPreference(getString(R.string.pref_tts_enabled)); - mPrefLanguages = (ListPreference) findPreference(getString(R.string.pref_tts_language)); - - final Framework.Params3dMode _3d = new Framework.Params3dMode(); - Framework.nativeGet3dMode(_3d); - - final TwoStatePreference pref3d = (TwoStatePreference)findPreference(getString(R.string.pref_3d)); - pref3d.setChecked(_3d.enabled); - - pref3d.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() - { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) - { - Framework.nativeSet3dMode((Boolean) newValue, _3d.buildings); - return true; - } - }); - - boolean autozoomEnabled = Framework.nativeGetAutoZoomEnabled(); - final TwoStatePreference prefAutoZoom = (TwoStatePreference)findPreference(getString(R.string.pref_auto_zoom)); - prefAutoZoom.setChecked(autozoomEnabled); - prefAutoZoom.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() - { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) - { - Framework.nativeSetAutoZoomEnabled((Boolean)newValue); - return true; - } - }); - - boolean simplifiedColorsEnabled = Framework.nativeGetSimplifiedTrafficColorsEnabled(); - final TwoStatePreference prefSimplifiedColors = (TwoStatePreference)findPreference( - getString(R.string.pref_traffic_simplified_colors)); - prefSimplifiedColors.setChecked(simplifiedColorsEnabled); - prefSimplifiedColors.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() - { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) - { - Framework.nativeSetSimplifiedTrafficColorsEnabled((Boolean)newValue); - return true; - } - }); - - update(); - } - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) - { - // Do not check resultCode here as it is always RESULT_CANCELED - super.onActivityResult(requestCode, resultCode, data); - - if (requestCode == REQUEST_INSTALL_DATA) - { - update(); - - LanguageData lang = mLanguages.get(mSelectedLanguage); - if (lang != null && lang.downloaded) - setLanguage(lang); - } - } -} diff --git a/android/src/com/mapswithme/maps/settings/SettingsActivity.java b/android/src/com/mapswithme/maps/settings/SettingsActivity.java index 35c79307fd..bd55a918b6 100644 --- a/android/src/com/mapswithme/maps/settings/SettingsActivity.java +++ b/android/src/com/mapswithme/maps/settings/SettingsActivity.java @@ -1,303 +1,89 @@ package com.mapswithme.maps.settings; -import android.app.Activity; -import android.app.Fragment; -import android.content.Intent; -import android.content.res.Configuration; -import android.media.AudioManager; import android.os.Bundle; -import android.preference.PreferenceActivity; import android.support.annotation.NonNull; -import android.support.annotation.StringRes; -import android.support.annotation.StyleRes; -import android.support.v7.app.AppCompatDelegate; -import android.support.v7.widget.Toolbar; -import android.view.LayoutInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceFragmentCompat; +import android.support.v7.preference.PreferenceScreen; +import android.text.TextUtils; -import com.mapswithme.maps.MwmApplication; import com.mapswithme.maps.R; -import com.mapswithme.maps.base.BaseActivity; -import com.mapswithme.maps.base.BaseActivityDelegate; -import com.mapswithme.maps.base.OnBackPressListener; -import com.mapswithme.maps.editor.OsmOAuth; -import com.mapswithme.maps.editor.ProfileActivity; -import com.mapswithme.util.FragmentListHelper; -import com.mapswithme.util.ThemeUtils; -import com.mapswithme.util.UiUtils; -import com.mapswithme.util.statistics.AlohaHelper; -import com.mapswithme.util.statistics.Statistics; +import com.mapswithme.maps.base.BaseToolbarActivity; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class SettingsActivity extends PreferenceActivity - implements BaseActivity +public class SettingsActivity extends BaseToolbarActivity + implements PreferenceFragmentCompat.OnPreferenceStartFragmentCallback, + PreferenceFragmentCompat.OnPreferenceStartScreenCallback { - private final BaseActivityDelegate mActivityDelegate = new BaseActivityDelegate(this); - private final FragmentListHelper mFragmentListHelper = new FragmentListHelper(); - private AppCompatDelegate mDelegate; - private CharSequence mNextBreadcrumb; - private final Map mHeaders = new HashMap<>(); + @Nullable + private String mLastTitle; @Override - public Activity get() + protected int getContentLayoutResId() { - return this; + return R.layout.activity_settings; } @Override - @StyleRes - public int getThemeResourceId(@NonNull String theme) + protected Class getFragmentClass() { - if (ThemeUtils.isDefaultTheme(theme)) - return R.style.MwmTheme_Settings; - - if (ThemeUtils.isNightTheme(theme)) - return R.style.MwmTheme_Night_Settings; - - throw new IllegalArgumentException("Attempt to apply unsupported theme: " + theme); - } - - private AppCompatDelegate getAppDelegate() - { - if (mDelegate == null) - mDelegate = AppCompatDelegate.create(this, null); - - return mDelegate; + return SettingsPrefsFragment.class; } @Override - public void onAttachFragment(Fragment fragment) + @SuppressWarnings("unchecked") + public boolean onPreferenceStartFragment(PreferenceFragmentCompat caller, Preference pref) { - mFragmentListHelper.onAttachFragment(fragment); - } - - @Override - public void onBuildHeaders(List
target) - { - loadHeadersFromResource(R.xml.prefs_headers, target); - - mHeaders.clear(); - for (Header h : target) + String title = TextUtils.isEmpty(pref.getTitle()) ? null : pref.getTitle().toString(); + try { - mHeaders.put(h.id, h); - // Hack to change profile header to username, if user is logged in. - if (h.id == R.id.osm_profile && OsmOAuth.isAuthorized()) - { - h.titleRes = 0; - h.title = OsmOAuth.getUsername(); - } - } - } - - @Override - public void onHeaderClick(@NonNull Header header, int position) - { - if (header.id == R.id.group_map) - Statistics.INSTANCE.trackEvent(Statistics.EventName.Settings.GROUP_MAP); - else if (header.id == R.id.group_route) - Statistics.INSTANCE.trackEvent(Statistics.EventName.Settings.GROUP_ROUTE); - else if (header.id == R.id.group_misc) - Statistics.INSTANCE.trackEvent(Statistics.EventName.Settings.GROUP_MISC); - else if (header.id == R.id.help) + Class fragment = (Class) Class.forName(pref.getFragment()); + replaceFragment(fragment, title, pref.getExtras()); + } catch (ClassNotFoundException e) { - Statistics.INSTANCE.trackEvent(Statistics.EventName.Settings.HELP); - AlohaHelper.logClick(AlohaHelper.Settings.HELP); + e.printStackTrace(); } - else if (header.id == R.id.about) - { - Statistics.INSTANCE.trackEvent(Statistics.EventName.Settings.ABOUT); - AlohaHelper.logClick(AlohaHelper.Settings.ABOUT); - } - else if (header.id == R.id.osm_profile) - { - Statistics.INSTANCE.trackEvent(Statistics.EventName.Settings.OSM_PROFILE); - startActivity(new Intent(this, ProfileActivity.class)); - } - - super.onHeaderClick(header, position); - } - - @Override - protected void onCreate(Bundle savedInstanceState) - { - mActivityDelegate.onCreate(); - getAppDelegate().installViewFactory(); - getAppDelegate().onCreate(savedInstanceState); - - super.onCreate(savedInstanceState); - UiUtils.setupStatusBar(this); - setVolumeControlStream(AudioManager.STREAM_MUSIC); - - // Hack to attach Toolbar and make it work on native PreferenceActivity - ViewGroup root = (ViewGroup)findViewById(android.R.id.list).getParent().getParent().getParent(); - View toolbarHolder = LayoutInflater.from(this).inflate(R.layout.toolbar_default, root, false); - Toolbar toolbar = (Toolbar) toolbarHolder.findViewById(R.id.toolbar); - UiUtils.extendViewWithStatusBar(toolbar); - UiUtils.showHomeUpButton(toolbar); - - // First, add toolbar view to UI. - root.addView(toolbarHolder, 0); - // Second, attach it as ActionBar (it does not add view, so we need previous step). - getAppDelegate().setSupportActionBar(toolbar); - - MwmApplication.get().initNativeCore(); - MwmApplication.get().initCounters(); - } - - @Override - protected void onPostCreate(Bundle savedInstanceState) - { - super.onPostCreate(savedInstanceState); - mActivityDelegate.onPostCreate(); - getAppDelegate().onPostCreate(savedInstanceState); - } - - @Override - public void setContentView(int layoutResID) - { - getAppDelegate().setContentView(layoutResID); - } - - @Override - public void setContentView(View view) - { - getAppDelegate().setContentView(view); - } - - @Override - public void setContentView(View view, ViewGroup.LayoutParams params) - { - getAppDelegate().setContentView(view, params); - } - - @Override - public void addContentView(View view, ViewGroup.LayoutParams params) - { - getAppDelegate().addContentView(view, params); - } - - @Override - protected void onTitleChanged(CharSequence title, int color) - { - super.onTitleChanged(title, color); - getAppDelegate().setTitle(title); - } - - @Override - public void invalidateOptionsMenu() - { - super.invalidateOptionsMenu(); - getAppDelegate().invalidateOptionsMenu(); - } - - @Override - public void onConfigurationChanged(Configuration newConfig) - { - super.onConfigurationChanged(newConfig); - getAppDelegate().onConfigurationChanged(newConfig); - } - - @Override - protected void onDestroy() - { - super.onDestroy(); - mActivityDelegate.onDestroy(); - getAppDelegate().onDestroy(); - } - - @Override - protected boolean isValidFragment(String fragmentName) - { return true; } @Override - protected void onStart() + public boolean onPreferenceStartScreen(PreferenceFragmentCompat preferenceFragmentCompat, PreferenceScreen preferenceScreen) { - super.onStart(); - mActivityDelegate.onStart(); - invalidateHeaders(); + Bundle args = new Bundle(); + args.putString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT, preferenceScreen.getKey()); + replaceFragment(SettingsPrefsFragment.class, preferenceScreen.getTitle().toString(), args); + return true; } - @Override - protected void onStop() + public void replaceFragment(@NonNull Class fragmentClass, + @Nullable String title, @Nullable Bundle args) { - super.onStop(); - mActivityDelegate.onStop(); - getAppDelegate().onStop(); - } + final int resId = getFragmentContentResId(); + if (resId <= 0 || findViewById(resId) == null) + throw new IllegalStateException("Fragment can't be added, since getFragmentContentResId() isn't implemented or returns wrong resourceId."); - @Override - protected void onResume() - { - super.onResume(); - mActivityDelegate.onResume(); - } + String name = fragmentClass.getName(); + final Fragment fragment = Fragment.instantiate(this, name, args); + getSupportFragmentManager().beginTransaction() + .replace(resId, fragment, name) + .addToBackStack(null) + .commitAllowingStateLoss(); + getSupportFragmentManager().executePendingTransactions(); - @Override - protected void onPostResume() - { - super.onPostResume(); - mActivityDelegate.onPostResume(); - getAppDelegate().onPostResume(); - } - - @Override - protected void onPause() - { - super.onPause(); - mActivityDelegate.onPause(); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) - { - if (item.getItemId() == android.R.id.home) + if(title != null) { - super.onBackPressed(); - return true; + mLastTitle = getToolbar().getTitle().toString(); + getToolbar().setTitle(title); } - - return super.onOptionsItemSelected(item); } @Override public void onBackPressed() { - for (Fragment f : mFragmentListHelper.getFragments()) - if ((f instanceof OnBackPressListener) && ((OnBackPressListener)f).onBackPressed()) - return; + if (mLastTitle != null) + getToolbar().setTitle(mLastTitle); super.onBackPressed(); } - - @Override - public void showBreadCrumbs(CharSequence title, CharSequence shortTitle) - { - if (mNextBreadcrumb != null) - { - title = mNextBreadcrumb; - mNextBreadcrumb = null; - } - - super.showBreadCrumbs(title, shortTitle); - } - - public void switchToHeader(long id) - { - Header h = mHeaders.get(id); - if (h != null) - switchToHeader(h); - } - - public void switchToFragment(Class fragmentClass, @StringRes int breadcrumb) - { - mNextBreadcrumb = getString(breadcrumb); - switchToHeader(fragmentClass.getName(), null); - } } diff --git a/android/src/com/mapswithme/maps/settings/SettingsPrefsFragment.java b/android/src/com/mapswithme/maps/settings/SettingsPrefsFragment.java new file mode 100644 index 0000000000..faf492902e --- /dev/null +++ b/android/src/com/mapswithme/maps/settings/SettingsPrefsFragment.java @@ -0,0 +1,756 @@ +package com.mapswithme.maps.settings; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.speech.tts.TextToSpeech; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v7.app.AlertDialog; +import android.support.v7.preference.ListPreference; +import android.support.v7.preference.Preference; +import android.support.v7.preference.TwoStatePreference; + +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.GoogleApiAvailability; +import com.mapswithme.maps.BuildConfig; +import com.mapswithme.maps.Framework; +import com.mapswithme.maps.MwmApplication; +import com.mapswithme.maps.R; +import com.mapswithme.maps.downloader.MapManager; +import com.mapswithme.maps.downloader.OnmapDownloader; +import com.mapswithme.maps.editor.ProfileActivity; +import com.mapswithme.maps.location.LocationHelper; +import com.mapswithme.maps.location.TrackRecorder; +import com.mapswithme.maps.search.SearchFragment; +import com.mapswithme.maps.sound.LanguageData; +import com.mapswithme.maps.sound.TtsPlayer; +import com.mapswithme.util.Config; +import com.mapswithme.util.NetworkPolicy; +import com.mapswithme.util.ThemeSwitcher; +import com.mapswithme.util.concurrency.UiThread; +import com.mapswithme.util.log.LoggerFactory; +import com.mapswithme.util.statistics.AlohaHelper; +import com.mapswithme.util.statistics.MytargetHelper; +import com.mapswithme.util.statistics.Statistics; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class SettingsPrefsFragment extends BaseXmlSettingsFragment +{ + private static final int REQUEST_INSTALL_DATA = 1; + + @NonNull + private final StoragePathManager mPathManager = new StoragePathManager(); + @Nullable + private Preference mStoragePref; + + @Nullable + private TwoStatePreference mPrefEnabled; + @Nullable + private ListPreference mPrefLanguages; + @Nullable + private Preference mLangInfo; + + @NonNull + private final Map mLanguages = new HashMap<>(); + private LanguageData mCurrentLanguage; + private String mSelectedLanguage; + + private boolean singleStorageOnly() + { + return !mPathManager.hasMoreThanOneStorage(); + } + + private void updateStoragePrefs() + { + Preference old = findPreference(getString(R.string.pref_storage)); + + if (singleStorageOnly()) + { + if (old != null) + getPreferenceScreen().removePreference(old); + } + else + { + if (old == null && mStoragePref != null) + getPreferenceScreen().addPreference(mStoragePref); + } + } + + private final Preference.OnPreferenceChangeListener mEnabledListener = new Preference.OnPreferenceChangeListener() + { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) + { + Statistics.INSTANCE.trackEvent(Statistics.EventName.Settings.VOICE_ENABLED, Statistics.params().add(Statistics.EventParam.ENABLED, newValue.toString())); + Preference root = findPreference(getString(R.string.pref_tts_screen)); + boolean set = (Boolean)newValue; + if (!set) + { + TtsPlayer.setEnabled(false); + if (mPrefLanguages != null) + mPrefLanguages.setEnabled(false); + if (mLangInfo != null) + mLangInfo.setSummary(R.string.prefs_languages_information_off); + + if (root != null) + root.setSummary(R.string.off); + + if (mPrefEnabled != null) + mPrefEnabled.setTitle(R.string.off); + return true; + } + + if (mLangInfo != null) + mLangInfo.setSummary(R.string.prefs_languages_information); + if (root != null) + root.setSummary(R.string.on); + if (mPrefEnabled != null) + mPrefEnabled.setTitle(R.string.on); + + if (mCurrentLanguage != null && mCurrentLanguage.downloaded) + { + setLanguage(mCurrentLanguage); + return true; + } + + return false; + } + }; + + private final Preference.OnPreferenceChangeListener mLangListener = new Preference.OnPreferenceChangeListener() + { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) + { + if (newValue == null) + return false; + + mSelectedLanguage = (String)newValue; + Statistics.INSTANCE.trackEvent(Statistics.EventName.Settings.VOICE_LANGUAGE, Statistics.params().add(Statistics.EventParam.LANGUAGE, mSelectedLanguage)); + LanguageData lang = mLanguages.get(mSelectedLanguage); + if (lang == null) + return false; + + if (lang.downloaded) + setLanguage(lang); + else + startActivityForResult(new Intent(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA), REQUEST_INSTALL_DATA); + + return false; + } + }; + + private void enableListeners(boolean enable) + { + if (mPrefEnabled != null) + mPrefEnabled.setOnPreferenceChangeListener(enable ? mEnabledListener : null); + if (mPrefLanguages != null) + mPrefLanguages.setOnPreferenceChangeListener(enable ? mLangListener : null); + } + + private void setLanguage(@NonNull LanguageData lang) + { + Config.setTtsEnabled(true); + TtsPlayer.INSTANCE.setLanguage(lang); + if (mPrefLanguages != null) + mPrefLanguages.setSummary(lang.name); + + updateTts(); + } + + private void updateTts() + { + if (mPrefEnabled == null || mPrefLanguages == null || mLangInfo == null) + return; + + enableListeners(false); + + List languages = TtsPlayer.INSTANCE.refreshLanguages(); + mLanguages.clear(); + mCurrentLanguage = null; + + Preference root = findPreference(getString(R.string.pref_tts_screen)); + + if (languages.isEmpty()) + { + mPrefEnabled.setChecked(false); + mPrefEnabled.setEnabled(false); + mPrefEnabled.setSummary(R.string.pref_tts_unavailable); + mPrefEnabled.setTitle(R.string.off); + mPrefLanguages.setEnabled(false); + mPrefLanguages.setSummary(null); + mLangInfo.setSummary(R.string.prefs_languages_information_off); + if (root != null) + root.setSummary(R.string.off); + + enableListeners(true); + return; + } + + boolean enabled = TtsPlayer.INSTANCE.isEnabled(); + mPrefEnabled.setChecked(enabled); + mPrefEnabled.setSummary(null); + mPrefEnabled.setTitle(enabled ? R.string.on : R.string.off); + mLangInfo.setSummary(enabled ? R.string.prefs_languages_information + : R.string.prefs_languages_information_off); + + if (root != null) + root.setSummary(enabled ? R.string.on : R.string.off); + + final CharSequence[] entries = new CharSequence[languages.size()]; + final CharSequence[] values = new CharSequence[languages.size()]; + for (int i = 0; i < languages.size(); i++) + { + LanguageData lang = languages.get(i); + entries[i] = lang.name; + values[i] = lang.internalCode; + + mLanguages.put(lang.internalCode, lang); + } + + mPrefLanguages.setEntries(entries); + mPrefLanguages.setEntryValues(values); + + mCurrentLanguage = TtsPlayer.getSelectedLanguage(languages); + boolean available = (mCurrentLanguage != null && mCurrentLanguage.downloaded); + mPrefLanguages.setEnabled(available && TtsPlayer.INSTANCE.isEnabled()); + mPrefLanguages.setSummary(available ? mCurrentLanguage.name : null); + mPrefLanguages.setValue(available ? mCurrentLanguage.internalCode : null); + mPrefEnabled.setChecked(available && TtsPlayer.INSTANCE.isEnabled()); + + enableListeners(true); + } + + @Override + public Fragment getCallbackFragment() + { + return this; + } + + @Override + protected int getXmlResources() + { + return R.xml.prefs_main; + } + + @Override + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + + mStoragePref = findPreference(getString(R.string.pref_storage)); + mPrefEnabled = (TwoStatePreference) findPreference(getString(R.string.pref_tts_enabled)); + mPrefLanguages = (ListPreference) findPreference(getString(R.string.pref_tts_language)); + mLangInfo = findPreference(getString(R.string.pref_tts_info)); + updateStoragePrefs(); + initStoragePrefCallbacks(); + initMeasureUnitsPrefsCallbacks(); + initZoomPrefsCallbacks(); + initMapStylePrefsCallbacks(); + initAutoDownloadPrefsCallbacks(); + initLargeFontSizePrefsCallbacks(); + init3dModePrefsCallbacks(); + initPerspectivePrefsCallbacks(); + initTrackRecordPrefsCallbacks(); + initStatisticsPrefsCallback(); + initPlayServicesPrefsCallbacks(); + initAutoZoomPrefsCallbacks(); + initSimplifiedTrafficColorsPrefsCallbacks(); + + if (!MytargetHelper.isShowcaseSwitchedOnServer()) + getPreferenceScreen().removePreference(findPreference(getString(R.string.pref_showcase_switched_on))); + + initLoggingEnabledPrefsCallbacks(); + initUseMobileDataPrefsCallbacks(); + + updateTts(); + } + + @Override + public void onResume() + { + super.onResume(); + + initTrackRecordPrefsCallbacks(); + updateTts(); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) + { + // Do not check resultCode here as it is always RESULT_CANCELED + super.onActivityResult(requestCode, resultCode, data); + + if (requestCode == REQUEST_INSTALL_DATA) + { + updateTts(); + + LanguageData lang = mLanguages.get(mSelectedLanguage); + if (lang != null && lang.downloaded) + setLanguage(lang); + } + } + + @Override + public boolean onPreferenceTreeClick(Preference preference) + { + if (preference.getKey() != null && preference.getKey().equals(getString(R.string.pref_help))) + { + Statistics.INSTANCE.trackEvent(Statistics.EventName.Settings.HELP); + AlohaHelper.logClick(AlohaHelper.Settings.HELP); + } + else if (preference.getKey() != null && preference.getKey().equals(getString(R.string.pref_about))) + { + Statistics.INSTANCE.trackEvent(Statistics.EventName.Settings.ABOUT); + AlohaHelper.logClick(AlohaHelper.Settings.ABOUT); + } + else if (preference.getKey() != null && preference.getKey().equals(getString(R.string.pref_osm_profile))) + { + Statistics.INSTANCE.trackEvent(Statistics.EventName.Settings.OSM_PROFILE); + startActivity(new Intent(getActivity(), ProfileActivity.class)); + } + return super.onPreferenceTreeClick(preference); + } + + private void initSimplifiedTrafficColorsPrefsCallbacks() + { + boolean simplifiedColorsEnabled = Framework.nativeGetSimplifiedTrafficColorsEnabled(); + final TwoStatePreference prefSimplifiedColors = (TwoStatePreference)findPreference( + getString(R.string.pref_traffic_simplified_colors)); + prefSimplifiedColors.setChecked(simplifiedColorsEnabled); + prefSimplifiedColors.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() + { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) + { + Framework.nativeSetSimplifiedTrafficColorsEnabled((Boolean)newValue); + return true; + } + }); + } + + private void initLargeFontSizePrefsCallbacks() + { + Preference pref = findPreference(getString(R.string.pref_large_fonts_size)); + ((TwoStatePreference)pref).setChecked(Config.isLargeFontsSize()); + pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() + { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) + { + boolean oldVal = Config.isLargeFontsSize(); + boolean newVal = (Boolean) newValue; + if (oldVal != newVal) + Config.setLargeFontsSize(newVal); + + return true; + } + }); + } + + private void initUseMobileDataPrefsCallbacks() + { + int curValue = Config.getUseMobileDataSettings(); + final ListPreference mobilePref = (ListPreference)findPreference( + getString(R.string.pref_use_mobile_data)); + if (curValue != NetworkPolicy.NOT_TODAY && curValue != NetworkPolicy.TODAY) + { + mobilePref.setValue(String.valueOf(curValue)); + mobilePref.setSummary(mobilePref.getEntry()); + } + else + { + mobilePref.setSummary(getString(R.string.mobile_data_description)); + } + mobilePref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() + { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) + { + String valueStr = (String)newValue; + switch (Integer.parseInt(valueStr)) + { + case NetworkPolicy.ASK: + Config.setUseMobileDataSettings(NetworkPolicy.ASK); + break; + case NetworkPolicy.ALWAYS: + Config.setUseMobileDataSettings(NetworkPolicy.ALWAYS); + break; + case NetworkPolicy.NEVER: + Config.setUseMobileDataSettings(NetworkPolicy.NEVER); + break; + default: + throw new AssertionError("Wrong NetworkPolicy type!"); + } + + UiThread.runLater(new Runnable() + { + @Override + public void run() + { + mobilePref.setSummary(mobilePref.getEntry()); + } + }); + + return true; + } + }); + } + + private void initLoggingEnabledPrefsCallbacks() + { + Preference pref = findPreference(getString(R.string.pref_enable_logging)); + if (!MwmApplication.prefs().getBoolean(SearchFragment.PREFS_SHOW_ENABLE_LOGGING_SETTING, + BuildConfig.BUILD_TYPE.equals("beta"))) + { + getPreferenceScreen().removePreference(pref); + } + else + { + final boolean isLoggingEnabled = LoggerFactory.INSTANCE.isFileLoggingEnabled(); + ((TwoStatePreference) pref).setChecked(isLoggingEnabled); + pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() + { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) + { + boolean oldVal = isLoggingEnabled; + boolean newVal = (Boolean) newValue; + if (oldVal != newVal) + { + LoggerFactory.INSTANCE.setFileLoggingEnabled(newVal); + } + return true; + } + }); + } + } + + private void initAutoZoomPrefsCallbacks() + { + final TwoStatePreference pref = (TwoStatePreference)findPreference(getString(R.string.pref_auto_zoom)); + if (pref == null) + return; + + boolean autozoomEnabled = Framework.nativeGetAutoZoomEnabled(); + pref.setChecked(autozoomEnabled); + pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() + { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) + { + Framework.nativeSetAutoZoomEnabled((Boolean)newValue); + return true; + } + }); + } + + private void initPlayServicesPrefsCallbacks() + { + Preference pref = findPreference(getString(R.string.pref_play_services)); + if (pref == null) + return; + + if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(MwmApplication.get()) != ConnectionResult.SUCCESS) + getPreferenceScreen().removePreference(pref); + else + { + ((TwoStatePreference) pref).setChecked(Config.useGoogleServices()); + pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() + { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) + { + boolean oldVal = Config.useGoogleServices(); + boolean newVal = (Boolean) newValue; + if (oldVal != newVal) + { + Config.setUseGoogleService(newVal); + LocationHelper.INSTANCE.restart(); + } + return true; + } + }); + } + } + + private void initStatisticsPrefsCallback() + { + Preference pref = findPreference(getString(R.string.pref_send_statistics)); + if (pref == null) + return; + + ((TwoStatePreference)pref).setChecked(Config.isStatisticsEnabled()); + pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() + { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) + { + Statistics.INSTANCE.setStatEnabled((Boolean) newValue); + return true; + } + }); + } + + private void initTrackRecordPrefsCallbacks() + { + final ListPreference trackPref = (ListPreference)findPreference(getString(R.string.pref_track_record)); + final Preference pref = findPreference(getString(R.string.pref_track_record_time)); + final Preference root = findPreference(getString(R.string.pref_track_screen)); + if (trackPref == null || pref == null) + return; + + boolean enabled = TrackRecorder.isEnabled(); + ((TwoStatePreference)pref).setChecked(enabled); + trackPref.setEnabled(enabled); + if (root != null) + root.setSummary(enabled ? R.string.on : R.string.off); + pref.setTitle(enabled ? R.string.on : R.string.off); + pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() + { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) + { + boolean enabled = (Boolean) newValue; + TrackRecorder.setEnabled(enabled); + Statistics.INSTANCE.setStatEnabled(enabled); + trackPref.setEnabled(enabled); + if (root != null) + root.setSummary(enabled ? R.string.on : R.string.off); + pref.setTitle(enabled ? R.string.on : R.string.off); + trackPref.performClick(); + return true; + } + }); + + String value = (enabled ? String.valueOf(TrackRecorder.getDuration()) : "0"); + trackPref.setValue(value); + trackPref.setSummary(trackPref.getEntry()); + trackPref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() + { + @Override + public boolean onPreferenceChange(final Preference preference, Object newValue) + { + int value = Integer.valueOf((String)newValue); + boolean enabled = value != 0; + if (enabled) + TrackRecorder.setDuration(value); + TrackRecorder.setEnabled(enabled); + ((TwoStatePreference) pref).setChecked(enabled); + trackPref.setEnabled(enabled); + if (root != null) + root.setSummary(enabled ? R.string.on : R.string.off); + pref.setTitle(enabled ? R.string.on : R.string.off); + + UiThread.runLater(new Runnable() + { + @Override + public void run() + { + trackPref.setSummary(trackPref.getEntry()); + } + }); + return true; + } + }); + } + + private void init3dModePrefsCallbacks() + { + final TwoStatePreference pref = (TwoStatePreference)findPreference(getString(R.string.pref_3d_buildings)); + if (pref == null) + return; + + final Framework.Params3dMode _3d = new Framework.Params3dMode(); + Framework.nativeGet3dMode(_3d); + + pref.setChecked(_3d.buildings); + + pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() + { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) + { + Framework.nativeSet3dMode(_3d.enabled, (Boolean)newValue); + return true; + } + }); + } + + private void initPerspectivePrefsCallbacks() + { + final TwoStatePreference pref = (TwoStatePreference)findPreference(getString(R.string.pref_3d)); + if (pref == null) + return; + + final Framework.Params3dMode _3d = new Framework.Params3dMode(); + Framework.nativeGet3dMode(_3d); + + pref.setChecked(_3d.enabled); + + pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() + { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) + { + Framework.nativeSet3dMode((Boolean) newValue, _3d.buildings); + return true; + } + }); + } + + private void initAutoDownloadPrefsCallbacks() + { + TwoStatePreference pref = (TwoStatePreference)findPreference(getString(R.string.pref_autodownload)); + if (pref == null) + return; + + pref.setChecked(Config.isAutodownloadEnabled()); + pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() + { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) + { + boolean value = (Boolean)newValue; + Config.setAutodownloadEnabled(value); + + if (value) + OnmapDownloader.setAutodownloadLocked(false); + + return true; + } + }); + } + + private void initMapStylePrefsCallbacks() + { + final ListPreference pref = (ListPreference)findPreference(getString(R.string.pref_map_style)); + if (pref == null) + return; + + String curTheme = Config.getUiThemeSettings(); + pref.setValue(curTheme); + pref.setSummary(pref.getEntry()); + pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() + { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) + { + String themeName = (String)newValue; + if (!Config.setUiThemeSettings(themeName)) + return true; + + ThemeSwitcher.restart(false); + Statistics.INSTANCE.trackEvent(Statistics.EventName.Settings.MAP_STYLE, + Statistics.params().add(Statistics.EventParam.NAME, themeName)); + + UiThread.runLater(new Runnable() + { + @Override + public void run() + { + pref.setSummary(pref.getEntry()); + } + }); + + return true; + } + }); + } + + private void initZoomPrefsCallbacks() + { + Preference pref = findPreference(getString(R.string.pref_show_zoom_buttons)); + if (pref == null) + return; + + ((TwoStatePreference)pref).setChecked(Config.showZoomButtons()); + pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() + { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) + { + Statistics.INSTANCE.trackEvent(Statistics.EventName.Settings.ZOOM); + Config.setShowZoomButtons((Boolean) newValue); + return true; + } + }); + } + + private void initMeasureUnitsPrefsCallbacks() + { + Preference pref = findPreference(getString(R.string.pref_munits)); + if (pref == null) + return; + + ((ListPreference)pref).setValue(String.valueOf(UnitLocale.getUnits())); + pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() + { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) + { + UnitLocale.setUnits(Integer.parseInt((String) newValue)); + Statistics.INSTANCE.trackEvent(Statistics.EventName.Settings.UNITS); + AlohaHelper.logClick(AlohaHelper.Settings.CHANGE_UNITS); + return true; + } + }); + } + + private void initStoragePrefCallbacks() + { + if (mStoragePref == null) + return; + + mStoragePref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() + { + @Override + public boolean onPreferenceClick(Preference preference) + { + if (MapManager.nativeIsDownloading()) + new AlertDialog.Builder(getActivity()) + .setTitle(getString(R.string.downloading_is_active)) + .setMessage(getString(R.string.cant_change_this_setting)) + .setPositiveButton(getString(R.string.ok), null) + .show(); + else +// getSettingsActivity().switchToFragment(StoragePathFragment.class, R.string.maps_storage); + getSettingsActivity().replaceFragment(StoragePathFragment.class, + getString(R.string.maps_storage), null); + + return true; + } + }); + } + + @Override + public void onAttach(Context context) + { + super.onAttach(context); + + if (!(context instanceof Activity)) + return; + + mPathManager.startExternalStorageWatching((Activity) context, new StoragePathManager.OnStorageListChangedListener() + { + @Override + public void onStorageListChanged(List storageItems, int currentStorageIndex) + { + updateStoragePrefs(); + } + }, null); + } + + @Override + public void onDetach() + { + super.onDetach(); + mPathManager.stopExternalStorageWatching(); + } +} diff --git a/android/src/com/mapswithme/maps/settings/StoragePathFragment.java b/android/src/com/mapswithme/maps/settings/StoragePathFragment.java index 4a5a50ed83..3bbcb0eff5 100644 --- a/android/src/com/mapswithme/maps/settings/StoragePathFragment.java +++ b/android/src/com/mapswithme/maps/settings/StoragePathFragment.java @@ -16,7 +16,6 @@ import java.util.Locale; import com.mapswithme.maps.R; import com.mapswithme.maps.base.OnBackPressListener; -import com.mapswithme.maps.widget.BaseShadowController; import com.mapswithme.util.Constants; import com.mapswithme.util.Utils; @@ -36,12 +35,6 @@ public class StoragePathFragment extends BaseSettingsFragment return R.layout.fragment_prefs_storage; } - @Override - protected BaseShadowController createShadowController() - { - return null; - } - @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -148,13 +141,6 @@ public class StoragePathFragment extends BaseSettingsFragment @Override public boolean onBackPressed() { - SettingsActivity activity = (SettingsActivity)getActivity(); - if (activity.onIsMultiPane()) - { - activity.switchToHeader(R.id.group_map); - return true; - } - return false; } } diff --git a/android/src/com/mapswithme/maps/widget/placepage/EditBookmarkFragment.java b/android/src/com/mapswithme/maps/widget/placepage/EditBookmarkFragment.java index 6656f4c0c2..4357cf1f12 100644 --- a/android/src/com/mapswithme/maps/widget/placepage/EditBookmarkFragment.java +++ b/android/src/com/mapswithme/maps/widget/placepage/EditBookmarkFragment.java @@ -78,10 +78,8 @@ public class EditBookmarkFragment extends BaseMwmDialogFragment implements View. } @Override - public void onViewCreated(View view, Bundle savedInstanceState) + protected void safeOnViewCreated(@NonNull View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - final Bundle args = getArguments(); mCategoryId = args.getInt(EXTRA_CATEGORY_ID); int bookmarkId = args.getInt(EXTRA_BOOKMARK_ID); diff --git a/android/src/com/mapswithme/maps/widget/placepage/EditDescriptionFragment.java b/android/src/com/mapswithme/maps/widget/placepage/EditDescriptionFragment.java index 05e92ee566..ab2e584d85 100644 --- a/android/src/com/mapswithme/maps/widget/placepage/EditDescriptionFragment.java +++ b/android/src/com/mapswithme/maps/widget/placepage/EditDescriptionFragment.java @@ -1,6 +1,7 @@ package com.mapswithme.maps.widget.placepage; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.widget.Toolbar; import android.text.Html; @@ -49,14 +50,14 @@ public class EditDescriptionFragment extends BaseMwmDialogFragment } @Override - public void onViewCreated(View view, Bundle savedInstanceState) + protected void safeOnViewCreated(@NonNull View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - mBookmark = getArguments().getParcelable(EXTRA_BOOKMARK); - String description = mBookmark.getBookmarkDescription(); + String description = null; + if (mBookmark != null) + description = mBookmark.getBookmarkDescription(); - if (StringUtils.nativeIsHtml(description)) + if (description != null && StringUtils.nativeIsHtml(description)) { final String descriptionNoSimpleTags = StringUtils.removeEditTextHtmlTags(description); if (!StringUtils.nativeIsHtml(descriptionNoSimpleTags)) diff --git a/android/src/com/mapswithme/util/Utils.java b/android/src/com/mapswithme/util/Utils.java index 2f2e4fb4e5..e06afe70da 100644 --- a/android/src/com/mapswithme/util/Utils.java +++ b/android/src/com/mapswithme/util/Utils.java @@ -14,6 +14,7 @@ import android.support.annotation.DimenRes; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.StringRes; +import android.support.v4.app.ActivityCompat; import android.support.v4.app.NavUtils; import android.support.v7.app.AlertDialog; import android.text.SpannableStringBuilder; @@ -40,6 +41,8 @@ import java.util.Currency; import java.util.Locale; import java.util.Map; +import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE; + public class Utils { private static final Logger LOGGER = LoggerFactory.INSTANCE.getLogger(LoggerFactory.Type.MISC); @@ -400,7 +403,8 @@ public class Utils try { activity.startActivity(intent); - } catch (ActivityNotFoundException e) + } + catch (ActivityNotFoundException e) { AlohaHelper.logException(e); } @@ -408,4 +412,39 @@ public class Utils }); } } + + public static boolean checkPermissions(@NonNull Activity activity, @NonNull String[] permissions, + int requestCode) + { + if (Build.VERSION.SDK_INT >= 23) + { + boolean isGranted = false; + for (String permission: permissions) + { + isGranted = activity.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED; + if (!isGranted) + break; + } + if (isGranted) + { + return true; + } + else + { + ActivityCompat.requestPermissions(activity, permissions, requestCode); + return false; + } + } + + //permission is automatically granted on sdk<23 upon installation + return true; + } + + public static boolean isWriteExternalGranted(@NonNull Activity activity) + { + if (Build.VERSION.SDK_INT >= 23) + return activity.checkSelfPermission(WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED; + + return true; + } } diff --git a/iphone/Maps/LocalizedStrings/ar.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/ar.lproj/Localizable.strings index 105cc45e44..3a1ef44bf6 100644 --- a/iphone/Maps/LocalizedStrings/ar.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/ar.lproj/Localizable.strings @@ -467,6 +467,18 @@ "menu_search" = "بحث"; +/* Settings general group in settings screen */ +"prefs_group_general" = "General settings"; + +/* Settings information group in settings screen */ +"prefs_group_information" = "Information"; + +/* Settings languages information in voice instructions screen */ +"prefs_languages_information" = "Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.)."; + +/* Settings languages off information in voice instructions screen */ +"prefs_languages_information_off" = "For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device's settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine."; + /* Settings screen: "Map" category title */ "prefs_group_map" = "الخريطة"; @@ -1870,3 +1882,7 @@ "search_hotel_filter_resort" = "منتج"; "search_hotel_filter_motel" = "Motel"; + +"on" = "On"; + +"off" = "Off"; diff --git a/iphone/Maps/LocalizedStrings/cs.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/cs.lproj/Localizable.strings index 257fcc5475..014019656a 100644 --- a/iphone/Maps/LocalizedStrings/cs.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/cs.lproj/Localizable.strings @@ -467,6 +467,18 @@ "menu_search" = "Vyhledávání"; +/* Settings general group in settings screen */ +"prefs_group_general" = "General settings"; + +/* Settings information group in settings screen */ +"prefs_group_information" = "Information"; + +/* Settings languages information in voice instructions screen */ +"prefs_languages_information" = "Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.)."; + +/* Settings languages off information in voice instructions screen */ +"prefs_languages_information_off" = "For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device's settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine."; + /* Settings screen: "Map" category title */ "prefs_group_map" = "Mapa"; @@ -1870,3 +1882,7 @@ "search_hotel_filter_resort" = "Letovisko"; "search_hotel_filter_motel" = "Motel"; + +"on" = "On"; + +"off" = "Off"; diff --git a/iphone/Maps/LocalizedStrings/da.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/da.lproj/Localizable.strings index 58180ef40b..a91c7f5036 100644 --- a/iphone/Maps/LocalizedStrings/da.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/da.lproj/Localizable.strings @@ -467,6 +467,18 @@ "menu_search" = "Søg"; +/* Settings general group in settings screen */ +"prefs_group_general" = "General settings"; + +/* Settings information group in settings screen */ +"prefs_group_information" = "Information"; + +/* Settings languages information in voice instructions screen */ +"prefs_languages_information" = "Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.)."; + +/* Settings languages off information in voice instructions screen */ +"prefs_languages_information_off" = "For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device's settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine."; + /* Settings screen: "Map" category title */ "prefs_group_map" = "Kort"; @@ -1870,3 +1882,7 @@ "search_hotel_filter_resort" = "Resort"; "search_hotel_filter_motel" = "Motel"; + +"on" = "On"; + +"off" = "Off"; diff --git a/iphone/Maps/LocalizedStrings/de.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/de.lproj/Localizable.strings index f4ab6e1eca..a127f751cf 100644 --- a/iphone/Maps/LocalizedStrings/de.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/de.lproj/Localizable.strings @@ -467,6 +467,18 @@ "menu_search" = "Suche"; +/* Settings general group in settings screen */ +"prefs_group_general" = "General settings"; + +/* Settings information group in settings screen */ +"prefs_group_information" = "Information"; + +/* Settings languages information in voice instructions screen */ +"prefs_languages_information" = "Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.)."; + +/* Settings languages off information in voice instructions screen */ +"prefs_languages_information_off" = "For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device's settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine."; + /* Settings screen: "Map" category title */ "prefs_group_map" = "Karte"; @@ -1870,3 +1882,7 @@ "search_hotel_filter_resort" = "Resort"; "search_hotel_filter_motel" = "Motel"; + +"on" = "On"; + +"off" = "Off"; diff --git a/iphone/Maps/LocalizedStrings/en-GB.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/en-GB.lproj/Localizable.strings index 3360b3dc82..755b96c205 100644 --- a/iphone/Maps/LocalizedStrings/en-GB.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/en-GB.lproj/Localizable.strings @@ -467,6 +467,18 @@ "menu_search" = "Search"; +/* Settings general group in settings screen */ +"prefs_group_general" = "General settings"; + +/* Settings information group in settings screen */ +"prefs_group_information" = "Information"; + +/* Settings languages information in voice instructions screen */ +"prefs_languages_information" = "Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.)."; + +/* Settings languages off information in voice instructions screen */ +"prefs_languages_information_off" = "For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device's settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine."; + /* Settings screen: "Map" category title */ "prefs_group_map" = "Map"; @@ -1870,3 +1882,7 @@ "search_hotel_filter_resort" = "Resort"; "search_hotel_filter_motel" = "Motel"; + +"on" = "On"; + +"off" = "Off"; diff --git a/iphone/Maps/LocalizedStrings/en.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/en.lproj/Localizable.strings index 354ec24978..d12acbe404 100644 --- a/iphone/Maps/LocalizedStrings/en.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/en.lproj/Localizable.strings @@ -467,6 +467,18 @@ "menu_search" = "Search"; +/* Settings general group in settings screen */ +"prefs_group_general" = "General settings"; + +/* Settings information group in settings screen */ +"prefs_group_information" = "Information"; + +/* Settings languages information in voice instructions screen */ +"prefs_languages_information" = "Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.)."; + +/* Settings languages off information in voice instructions screen */ +"prefs_languages_information_off" = "For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device's settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine."; + /* Settings screen: "Map" category title */ "prefs_group_map" = "Map"; @@ -1870,3 +1882,7 @@ "search_hotel_filter_resort" = "Resort"; "search_hotel_filter_motel" = "Motel"; + +"on" = "On"; + +"off" = "Off"; diff --git a/iphone/Maps/LocalizedStrings/es.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/es.lproj/Localizable.strings index ab29ef75aa..a0e5081a9a 100644 --- a/iphone/Maps/LocalizedStrings/es.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/es.lproj/Localizable.strings @@ -467,6 +467,18 @@ "menu_search" = "Buscar"; +/* Settings general group in settings screen */ +"prefs_group_general" = "General settings"; + +/* Settings information group in settings screen */ +"prefs_group_information" = "Information"; + +/* Settings languages information in voice instructions screen */ +"prefs_languages_information" = "Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.)."; + +/* Settings languages off information in voice instructions screen */ +"prefs_languages_information_off" = "For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device's settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine."; + /* Settings screen: "Map" category title */ "prefs_group_map" = "Mapa"; @@ -1870,3 +1882,7 @@ "search_hotel_filter_resort" = "Resort"; "search_hotel_filter_motel" = "Motel"; + +"on" = "On"; + +"off" = "Off"; diff --git a/iphone/Maps/LocalizedStrings/fi.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/fi.lproj/Localizable.strings index c6638a399a..8c6a43368a 100644 --- a/iphone/Maps/LocalizedStrings/fi.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/fi.lproj/Localizable.strings @@ -467,6 +467,18 @@ "menu_search" = "Haku"; +/* Settings general group in settings screen */ +"prefs_group_general" = "General settings"; + +/* Settings information group in settings screen */ +"prefs_group_information" = "Information"; + +/* Settings languages information in voice instructions screen */ +"prefs_languages_information" = "Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.)."; + +/* Settings languages off information in voice instructions screen */ +"prefs_languages_information_off" = "For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device's settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine."; + /* Settings screen: "Map" category title */ "prefs_group_map" = "Kartta"; @@ -1870,3 +1882,7 @@ "search_hotel_filter_resort" = "Lomakohteet"; "search_hotel_filter_motel" = "Motel"; + +"on" = "On"; + +"off" = "Off"; diff --git a/iphone/Maps/LocalizedStrings/fr.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/fr.lproj/Localizable.strings index 6d95a9cde9..a9e081311a 100644 --- a/iphone/Maps/LocalizedStrings/fr.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/fr.lproj/Localizable.strings @@ -467,6 +467,18 @@ "menu_search" = "Rechercher"; +/* Settings general group in settings screen */ +"prefs_group_general" = "General settings"; + +/* Settings information group in settings screen */ +"prefs_group_information" = "Information"; + +/* Settings languages information in voice instructions screen */ +"prefs_languages_information" = "Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.)."; + +/* Settings languages off information in voice instructions screen */ +"prefs_languages_information_off" = "For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device's settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine."; + /* Settings screen: "Map" category title */ "prefs_group_map" = "Carte"; @@ -1870,3 +1882,7 @@ "search_hotel_filter_resort" = "Complexe touristique"; "search_hotel_filter_motel" = "Motel"; + +"on" = "On"; + +"off" = "Off"; diff --git a/iphone/Maps/LocalizedStrings/hu.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/hu.lproj/Localizable.strings index 001d4ab753..8d2c8f58d5 100644 --- a/iphone/Maps/LocalizedStrings/hu.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/hu.lproj/Localizable.strings @@ -467,6 +467,18 @@ "menu_search" = "Keresés"; +/* Settings general group in settings screen */ +"prefs_group_general" = "General settings"; + +/* Settings information group in settings screen */ +"prefs_group_information" = "Information"; + +/* Settings languages information in voice instructions screen */ +"prefs_languages_information" = "Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.)."; + +/* Settings languages off information in voice instructions screen */ +"prefs_languages_information_off" = "For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device's settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine."; + /* Settings screen: "Map" category title */ "prefs_group_map" = "Térkép"; @@ -1870,3 +1882,7 @@ "search_hotel_filter_resort" = "Resort hotel"; "search_hotel_filter_motel" = "Motel"; + +"on" = "On"; + +"off" = "Off"; diff --git a/iphone/Maps/LocalizedStrings/id.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/id.lproj/Localizable.strings index b69aba129e..f13a26539d 100644 --- a/iphone/Maps/LocalizedStrings/id.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/id.lproj/Localizable.strings @@ -467,6 +467,18 @@ "menu_search" = "Cari"; +/* Settings general group in settings screen */ +"prefs_group_general" = "General settings"; + +/* Settings information group in settings screen */ +"prefs_group_information" = "Information"; + +/* Settings languages information in voice instructions screen */ +"prefs_languages_information" = "Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.)."; + +/* Settings languages off information in voice instructions screen */ +"prefs_languages_information_off" = "For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device's settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine."; + /* Settings screen: "Map" category title */ "prefs_group_map" = "Peta"; @@ -1870,3 +1882,7 @@ "search_hotel_filter_resort" = "Sanggraloka"; "search_hotel_filter_motel" = "Motel"; + +"on" = "On"; + +"off" = "Off"; diff --git a/iphone/Maps/LocalizedStrings/it.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/it.lproj/Localizable.strings index 9848bfd2ce..b070b8851d 100644 --- a/iphone/Maps/LocalizedStrings/it.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/it.lproj/Localizable.strings @@ -467,6 +467,18 @@ "menu_search" = "Cerca"; +/* Settings general group in settings screen */ +"prefs_group_general" = "General settings"; + +/* Settings information group in settings screen */ +"prefs_group_information" = "Information"; + +/* Settings languages information in voice instructions screen */ +"prefs_languages_information" = "Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.)."; + +/* Settings languages off information in voice instructions screen */ +"prefs_languages_information_off" = "For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device's settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine."; + /* Settings screen: "Map" category title */ "prefs_group_map" = "Mappa"; @@ -1870,3 +1882,7 @@ "search_hotel_filter_resort" = "Resort"; "search_hotel_filter_motel" = "Motel"; + +"on" = "On"; + +"off" = "Off"; diff --git a/iphone/Maps/LocalizedStrings/ja.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/ja.lproj/Localizable.strings index dfabbc74ed..568735b60b 100644 --- a/iphone/Maps/LocalizedStrings/ja.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/ja.lproj/Localizable.strings @@ -467,6 +467,18 @@ "menu_search" = "検索"; +/* Settings general group in settings screen */ +"prefs_group_general" = "General settings"; + +/* Settings information group in settings screen */ +"prefs_group_information" = "Information"; + +/* Settings languages information in voice instructions screen */ +"prefs_languages_information" = "Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.)."; + +/* Settings languages off information in voice instructions screen */ +"prefs_languages_information_off" = "For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device's settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine."; + /* Settings screen: "Map" category title */ "prefs_group_map" = "地図"; @@ -1870,3 +1882,7 @@ "search_hotel_filter_resort" = "リゾート"; "search_hotel_filter_motel" = "Motel"; + +"on" = "On"; + +"off" = "Off"; diff --git a/iphone/Maps/LocalizedStrings/ko.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/ko.lproj/Localizable.strings index c8f0563e0b..117c84dcaf 100644 --- a/iphone/Maps/LocalizedStrings/ko.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/ko.lproj/Localizable.strings @@ -467,6 +467,18 @@ "menu_search" = "검색"; +/* Settings general group in settings screen */ +"prefs_group_general" = "General settings"; + +/* Settings information group in settings screen */ +"prefs_group_information" = "Information"; + +/* Settings languages information in voice instructions screen */ +"prefs_languages_information" = "Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.)."; + +/* Settings languages off information in voice instructions screen */ +"prefs_languages_information_off" = "For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device's settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine."; + /* Settings screen: "Map" category title */ "prefs_group_map" = "지도"; @@ -1870,3 +1882,7 @@ "search_hotel_filter_resort" = "리조트"; "search_hotel_filter_motel" = "Motel"; + +"on" = "On"; + +"off" = "Off"; diff --git a/iphone/Maps/LocalizedStrings/nb.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/nb.lproj/Localizable.strings index 96252709b6..bde13cb3e1 100644 --- a/iphone/Maps/LocalizedStrings/nb.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/nb.lproj/Localizable.strings @@ -467,6 +467,18 @@ "menu_search" = "Søk"; +/* Settings general group in settings screen */ +"prefs_group_general" = "General settings"; + +/* Settings information group in settings screen */ +"prefs_group_information" = "Information"; + +/* Settings languages information in voice instructions screen */ +"prefs_languages_information" = "Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.)."; + +/* Settings languages off information in voice instructions screen */ +"prefs_languages_information_off" = "For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device's settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine."; + /* Settings screen: "Map" category title */ "prefs_group_map" = "Kart"; @@ -1870,3 +1882,7 @@ "search_hotel_filter_resort" = "Ferieresort"; "search_hotel_filter_motel" = "Motel"; + +"on" = "On"; + +"off" = "Off"; diff --git a/iphone/Maps/LocalizedStrings/nl.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/nl.lproj/Localizable.strings index 362b44abf6..963a26c42b 100644 --- a/iphone/Maps/LocalizedStrings/nl.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/nl.lproj/Localizable.strings @@ -467,6 +467,18 @@ "menu_search" = "Zoek"; +/* Settings general group in settings screen */ +"prefs_group_general" = "General settings"; + +/* Settings information group in settings screen */ +"prefs_group_information" = "Information"; + +/* Settings languages information in voice instructions screen */ +"prefs_languages_information" = "Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.)."; + +/* Settings languages off information in voice instructions screen */ +"prefs_languages_information_off" = "For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device's settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine."; + /* Settings screen: "Map" category title */ "prefs_group_map" = "Kaart"; @@ -1870,3 +1882,7 @@ "search_hotel_filter_resort" = "Complex"; "search_hotel_filter_motel" = "Motel"; + +"on" = "On"; + +"off" = "Off"; diff --git a/iphone/Maps/LocalizedStrings/pl.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/pl.lproj/Localizable.strings index 92bf85cf6d..5c8aa19950 100644 --- a/iphone/Maps/LocalizedStrings/pl.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/pl.lproj/Localizable.strings @@ -467,6 +467,18 @@ "menu_search" = "Wyszukaj"; +/* Settings general group in settings screen */ +"prefs_group_general" = "General settings"; + +/* Settings information group in settings screen */ +"prefs_group_information" = "Information"; + +/* Settings languages information in voice instructions screen */ +"prefs_languages_information" = "Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.)."; + +/* Settings languages off information in voice instructions screen */ +"prefs_languages_information_off" = "For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device's settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine."; + /* Settings screen: "Map" category title */ "prefs_group_map" = "Mapa"; @@ -1870,3 +1882,7 @@ "search_hotel_filter_resort" = "Dom wczasowy"; "search_hotel_filter_motel" = "Motel"; + +"on" = "On"; + +"off" = "Off"; diff --git a/iphone/Maps/LocalizedStrings/pt.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/pt.lproj/Localizable.strings index bb33331cfd..3e24d2483c 100644 --- a/iphone/Maps/LocalizedStrings/pt.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/pt.lproj/Localizable.strings @@ -467,6 +467,18 @@ "menu_search" = "Pesquisar"; +/* Settings general group in settings screen */ +"prefs_group_general" = "General settings"; + +/* Settings information group in settings screen */ +"prefs_group_information" = "Information"; + +/* Settings languages information in voice instructions screen */ +"prefs_languages_information" = "Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.)."; + +/* Settings languages off information in voice instructions screen */ +"prefs_languages_information_off" = "For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device's settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine."; + /* Settings screen: "Map" category title */ "prefs_group_map" = "Mapa"; @@ -1870,3 +1882,7 @@ "search_hotel_filter_resort" = "Resort"; "search_hotel_filter_motel" = "Motel"; + +"on" = "On"; + +"off" = "Off"; diff --git a/iphone/Maps/LocalizedStrings/ro.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/ro.lproj/Localizable.strings index 366246c11a..11a461f482 100644 --- a/iphone/Maps/LocalizedStrings/ro.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/ro.lproj/Localizable.strings @@ -467,6 +467,18 @@ "menu_search" = "Căutare"; +/* Settings general group in settings screen */ +"prefs_group_general" = "General settings"; + +/* Settings information group in settings screen */ +"prefs_group_information" = "Information"; + +/* Settings languages information in voice instructions screen */ +"prefs_languages_information" = "Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.)."; + +/* Settings languages off information in voice instructions screen */ +"prefs_languages_information_off" = "For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device's settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine."; + /* Settings screen: "Map" category title */ "prefs_group_map" = "Hartă"; @@ -1870,3 +1882,7 @@ "search_hotel_filter_resort" = "Stațiuni"; "search_hotel_filter_motel" = "Motel"; + +"on" = "On"; + +"off" = "Off"; diff --git a/iphone/Maps/LocalizedStrings/ru.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/ru.lproj/Localizable.strings index e41a66518e..dac5301ed3 100644 --- a/iphone/Maps/LocalizedStrings/ru.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/ru.lproj/Localizable.strings @@ -467,6 +467,18 @@ "menu_search" = "Поиск"; +/* Settings general group in settings screen */ +"prefs_group_general" = "Общие настройки"; + +/* Settings information group in settings screen */ +"prefs_group_information" = "Информация"; + +/* Settings languages information in voice instructions screen */ +"prefs_languages_information" = "Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.)."; + +/* Settings languages off information in voice instructions screen */ +"prefs_languages_information_off" = "For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device's settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine."; + /* Settings screen: "Map" category title */ "prefs_group_map" = "Карта"; @@ -1870,3 +1882,7 @@ "search_hotel_filter_resort" = "Дом отдыха"; "search_hotel_filter_motel" = "Мотель"; + +"on" = "Вкл."; + +"off" = "Выкл."; diff --git a/iphone/Maps/LocalizedStrings/sk.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/sk.lproj/Localizable.strings index cfd9e7edb7..138799e784 100644 --- a/iphone/Maps/LocalizedStrings/sk.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/sk.lproj/Localizable.strings @@ -467,6 +467,18 @@ "menu_search" = "Vyhľadávanie"; +/* Settings general group in settings screen */ +"prefs_group_general" = "General settings"; + +/* Settings information group in settings screen */ +"prefs_group_information" = "Information"; + +/* Settings languages information in voice instructions screen */ +"prefs_languages_information" = "Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.)."; + +/* Settings languages off information in voice instructions screen */ +"prefs_languages_information_off" = "For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device's settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine."; + /* Settings screen: "Map" category title */ "prefs_group_map" = "Mapa"; @@ -1870,3 +1882,7 @@ "search_hotel_filter_resort" = "Rezort"; "search_hotel_filter_motel" = "Motel"; + +"on" = "On"; + +"off" = "Off"; diff --git a/iphone/Maps/LocalizedStrings/sv.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/sv.lproj/Localizable.strings index 7a6a7ac155..8f9f42f50e 100644 --- a/iphone/Maps/LocalizedStrings/sv.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/sv.lproj/Localizable.strings @@ -467,6 +467,18 @@ "menu_search" = "Sök"; +/* Settings general group in settings screen */ +"prefs_group_general" = "General settings"; + +/* Settings information group in settings screen */ +"prefs_group_information" = "Information"; + +/* Settings languages information in voice instructions screen */ +"prefs_languages_information" = "Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.)."; + +/* Settings languages off information in voice instructions screen */ +"prefs_languages_information_off" = "For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device's settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine."; + /* Settings screen: "Map" category title */ "prefs_group_map" = "Karta"; @@ -1870,3 +1882,7 @@ "search_hotel_filter_resort" = "Resorter"; "search_hotel_filter_motel" = "Motel"; + +"on" = "On"; + +"off" = "Off"; diff --git a/iphone/Maps/LocalizedStrings/th.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/th.lproj/Localizable.strings index c17d68a652..d120d388ca 100644 --- a/iphone/Maps/LocalizedStrings/th.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/th.lproj/Localizable.strings @@ -467,6 +467,18 @@ "menu_search" = "ค้นหา"; +/* Settings general group in settings screen */ +"prefs_group_general" = "General settings"; + +/* Settings information group in settings screen */ +"prefs_group_information" = "Information"; + +/* Settings languages information in voice instructions screen */ +"prefs_languages_information" = "Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.)."; + +/* Settings languages off information in voice instructions screen */ +"prefs_languages_information_off" = "For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device's settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine."; + /* Settings screen: "Map" category title */ "prefs_group_map" = "แผนที่"; @@ -1870,3 +1882,7 @@ "search_hotel_filter_resort" = "รีสอร์ต"; "search_hotel_filter_motel" = "Motel"; + +"on" = "On"; + +"off" = "Off"; diff --git a/iphone/Maps/LocalizedStrings/tr.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/tr.lproj/Localizable.strings index 23304911f0..15cd2d50fb 100644 --- a/iphone/Maps/LocalizedStrings/tr.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/tr.lproj/Localizable.strings @@ -467,6 +467,18 @@ "menu_search" = "Ara"; +/* Settings general group in settings screen */ +"prefs_group_general" = "General settings"; + +/* Settings information group in settings screen */ +"prefs_group_information" = "Information"; + +/* Settings languages information in voice instructions screen */ +"prefs_languages_information" = "Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.)."; + +/* Settings languages off information in voice instructions screen */ +"prefs_languages_information_off" = "For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device's settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine."; + /* Settings screen: "Map" category title */ "prefs_group_map" = "Harita"; @@ -1870,3 +1882,7 @@ "search_hotel_filter_resort" = "Tatil köyü"; "search_hotel_filter_motel" = "Motel"; + +"on" = "On"; + +"off" = "Off"; diff --git a/iphone/Maps/LocalizedStrings/uk.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/uk.lproj/Localizable.strings index fa357a9aa0..7292a3f6a4 100644 --- a/iphone/Maps/LocalizedStrings/uk.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/uk.lproj/Localizable.strings @@ -467,6 +467,18 @@ "menu_search" = "Пошук"; +/* Settings general group in settings screen */ +"prefs_group_general" = "General settings"; + +/* Settings information group in settings screen */ +"prefs_group_information" = "Information"; + +/* Settings languages information in voice instructions screen */ +"prefs_languages_information" = "Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.)."; + +/* Settings languages off information in voice instructions screen */ +"prefs_languages_information_off" = "For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device's settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine."; + /* Settings screen: "Map" category title */ "prefs_group_map" = "Карта"; @@ -1870,3 +1882,7 @@ "search_hotel_filter_resort" = "Будинок відпочинку"; "search_hotel_filter_motel" = "Motel"; + +"on" = "On"; + +"off" = "Off"; diff --git a/iphone/Maps/LocalizedStrings/vi.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/vi.lproj/Localizable.strings index bf599eeaf0..b2c263a551 100644 --- a/iphone/Maps/LocalizedStrings/vi.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/vi.lproj/Localizable.strings @@ -467,6 +467,18 @@ "menu_search" = "Tìm kiếm"; +/* Settings general group in settings screen */ +"prefs_group_general" = "General settings"; + +/* Settings information group in settings screen */ +"prefs_group_information" = "Information"; + +/* Settings languages information in voice instructions screen */ +"prefs_languages_information" = "Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.)."; + +/* Settings languages off information in voice instructions screen */ +"prefs_languages_information_off" = "For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device's settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine."; + /* Settings screen: "Map" category title */ "prefs_group_map" = "Bản đồ"; @@ -1870,3 +1882,7 @@ "search_hotel_filter_resort" = "Khu nghỉ dưỡng"; "search_hotel_filter_motel" = "Motel"; + +"on" = "On"; + +"off" = "Off"; diff --git a/iphone/Maps/LocalizedStrings/zh-Hans.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/zh-Hans.lproj/Localizable.strings index 530fd4d7d0..bffb9135a1 100644 --- a/iphone/Maps/LocalizedStrings/zh-Hans.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/zh-Hans.lproj/Localizable.strings @@ -467,6 +467,18 @@ "menu_search" = "搜索"; +/* Settings general group in settings screen */ +"prefs_group_general" = "General settings"; + +/* Settings information group in settings screen */ +"prefs_group_information" = "Information"; + +/* Settings languages information in voice instructions screen */ +"prefs_languages_information" = "Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.)."; + +/* Settings languages off information in voice instructions screen */ +"prefs_languages_information_off" = "For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device's settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine."; + /* Settings screen: "Map" category title */ "prefs_group_map" = "地图"; @@ -1870,3 +1882,7 @@ "search_hotel_filter_resort" = "度假村"; "search_hotel_filter_motel" = "Motel"; + +"on" = "On"; + +"off" = "Off"; diff --git a/iphone/Maps/LocalizedStrings/zh-Hant.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/zh-Hant.lproj/Localizable.strings index 6e00dafacf..ce1a3aadff 100644 --- a/iphone/Maps/LocalizedStrings/zh-Hant.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/zh-Hant.lproj/Localizable.strings @@ -467,6 +467,18 @@ "menu_search" = "搜尋"; +/* Settings general group in settings screen */ +"prefs_group_general" = "General settings"; + +/* Settings information group in settings screen */ +"prefs_group_information" = "Information"; + +/* Settings languages information in voice instructions screen */ +"prefs_languages_information" = "Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.)."; + +/* Settings languages off information in voice instructions screen */ +"prefs_languages_information_off" = "For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device's settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine."; + /* Settings screen: "Map" category title */ "prefs_group_map" = "地圖"; @@ -1870,3 +1882,7 @@ "search_hotel_filter_resort" = "度假酒店"; "search_hotel_filter_motel" = "Motel"; + +"on" = "On"; + +"off" = "Off"; diff --git a/strings.txt b/strings.txt index 210b7270e2..2591974923 100644 --- a/strings.txt +++ b/strings.txt @@ -5098,6 +5098,30 @@ he = חפוש sk = Vyhľadávanie + [prefs_group_general] + comment = Settings general group in settings screen + tags = android + en = General settings + ru = Общие настройки + + [prefs_group_information] + comment = Settings information group in settings screen + tags = android + en = Information + ru = Информация + + [prefs_languages_information] + comment = Settings languages information in voice instructions screen + tags = android + en = Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.). + ru = Написать о том когда вообще ничего не установлено\n\nНа Android голосовые подсказки доступны на 24 языках: русский, английский, арабский, венгерский, голландский, греческий, датский, индонезийский, испанский, итальянский, китайский (традиционный и упрощенный), корейский, немецкий, польский, португальский, румынский, тайский, турецкий, финский, французский, хинди, чешский, японский.\n\nВозможно, для некоторых языков вам необходимо будет установить сторонний синтезатор речи и дополнительный языковой пакет из магазина приложений (Google Play Маркет, Samsung Apps и др.). + + [prefs_languages_information_off] + comment = Settings languages off information in voice instructions screen + tags = android + en = For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device's settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine. + ru = For some languages, you will need to install a other speech synthesizer or an additional language pack from the app store (Google Play Market, Samsung Apps).\n\nOpen your device's settings –> Language and input –> Speech –> Text to speech output.*\n\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine. + [prefs_group_map] comment = Settings screen: "Map" category title tags = android @@ -23361,3 +23385,11 @@ [view_campaign_button] en = View ad campagain + + [on] + en = On + ru = Вкл. + + [off] + en = Off + ru = Выкл.