From 51466dbb686e8d94764b909215d317e9b3b3b178 Mon Sep 17 00:00:00 2001 From: crimean Date: Mon, 10 Jun 2019 16:39:04 +0300 Subject: [PATCH] Refactored analytics, crash, rate us dialogs --- OsmAnd/AndroidManifest.xml | 5 +- .../res/drawable-hdpi/img_get_feedback.webp | Bin 0 -> 7036 bytes .../res/drawable-mdpi/img_get_feedback.webp | Bin 0 -> 4084 bytes .../res/drawable-xhdpi/img_get_feedback.webp | Bin 0 -> 9908 bytes .../res/drawable-xxhdpi/img_get_feedback.webp | Bin 0 -> 18874 bytes .../drawable-xxxhdpi/img_get_feedback.webp | Bin 0 -> 29614 bytes OsmAnd/res/drawable/ripple_solid_dark.xml | 2 +- OsmAnd/res/drawable/ripple_solid_light.xml | 2 +- .../bottom_sheet_item_description_long.xml | 1 + OsmAnd/res/layout/crash_title.xml | 42 ++++ OsmAnd/res/layout/dislike_title.xml | 42 ++++ OsmAnd/res/layout/make_better_title.xml | 48 +++++ OsmAnd/res/layout/privacy_settings_layout.xml | 165 +++++++++++++++ OsmAnd/res/layout/rate_us_title.xml | 42 ++++ OsmAnd/res/values/colors.xml | 1 - OsmAnd/res/values/strings.xml | 17 ++ OsmAnd/res/xml/settings_pref.xml | 1 + .../src/net/osmand/plus/AnalyticsHelper.java | 50 +++-- .../net/osmand/plus/OsmandApplication.java | 19 +- .../src/net/osmand/plus/OsmandSettings.java | 3 + .../osmand/plus/activities/MapActivity.java | 14 +- .../PrivacyAndSecurityActivity.java | 90 ++++++++ .../plus/activities/SettingsActivity.java | 7 + .../base/MenuBottomSheetDialogFragment.java | 40 +++- ...ottomSheetItemTitleWithDescrAndButton.java | 5 +- .../BottomSheetItemWithCompoundButton.java | 5 +- .../BottomSheetItemWithDescription.java | 28 ++- .../simpleitems/SubtitmeListDividerItem.java | 31 +++ .../plus/dashboard/DashErrorFragment.java | 12 +- .../CrashBottomSheetDialogFragment.java | 68 ++++++ ...islikeOsmAndBottomSheetDialogFragment.java | 85 ++++++++ .../plus/dialogs/ErrorBottomSheetDialog.java | 70 ------- .../plus/dialogs/RateUsBottomSheetDialog.java | 2 +- .../RateUsBottomSheetDialogFragment.java | 87 ++++++++ ...endAnalyticsBottomSheetDialogFragment.java | 193 ++++++++++++++++++ 35 files changed, 1049 insertions(+), 128 deletions(-) create mode 100644 OsmAnd/res/drawable-hdpi/img_get_feedback.webp create mode 100644 OsmAnd/res/drawable-mdpi/img_get_feedback.webp create mode 100644 OsmAnd/res/drawable-xhdpi/img_get_feedback.webp create mode 100644 OsmAnd/res/drawable-xxhdpi/img_get_feedback.webp create mode 100644 OsmAnd/res/drawable-xxxhdpi/img_get_feedback.webp create mode 100644 OsmAnd/res/layout/crash_title.xml create mode 100644 OsmAnd/res/layout/dislike_title.xml create mode 100644 OsmAnd/res/layout/make_better_title.xml create mode 100644 OsmAnd/res/layout/privacy_settings_layout.xml create mode 100644 OsmAnd/res/layout/rate_us_title.xml create mode 100644 OsmAnd/src/net/osmand/plus/activities/PrivacyAndSecurityActivity.java create mode 100644 OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/simpleitems/SubtitmeListDividerItem.java create mode 100644 OsmAnd/src/net/osmand/plus/dialogs/CrashBottomSheetDialogFragment.java create mode 100644 OsmAnd/src/net/osmand/plus/dialogs/DislikeOsmAndBottomSheetDialogFragment.java delete mode 100644 OsmAnd/src/net/osmand/plus/dialogs/ErrorBottomSheetDialog.java create mode 100644 OsmAnd/src/net/osmand/plus/dialogs/RateUsBottomSheetDialogFragment.java create mode 100644 OsmAnd/src/net/osmand/plus/dialogs/SendAnalyticsBottomSheetDialogFragment.java diff --git a/OsmAnd/AndroidManifest.xml b/OsmAnd/AndroidManifest.xml index 02776da9a6..0ff1017482 100644 --- a/OsmAnd/AndroidManifest.xml +++ b/OsmAnd/AndroidManifest.xml @@ -901,5 +901,8 @@ android:name=".profiles.EditProfileActivity" android:label="Application profiles"/> - + + + diff --git a/OsmAnd/res/drawable-hdpi/img_get_feedback.webp b/OsmAnd/res/drawable-hdpi/img_get_feedback.webp new file mode 100644 index 0000000000000000000000000000000000000000..54275e2b39abc0cc0684e7345ad2e2da50d49a23 GIT binary patch literal 7036 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 aKqL!92yi))ViU1RfTXvI%al&n-**C+2?qNB literal 0 HcmV?d00001 diff --git a/OsmAnd/res/drawable-mdpi/img_get_feedback.webp b/OsmAnd/res/drawable-mdpi/img_get_feedback.webp new file mode 100644 index 0000000000000000000000000000000000000000..c7f9d51f9f58b020d3402996393d060d290f4376 GIT binary patch literal 4084 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 literal 0 HcmV?d00001 diff --git a/OsmAnd/res/drawable-xxhdpi/img_get_feedback.webp b/OsmAnd/res/drawable-xxhdpi/img_get_feedback.webp new file mode 100644 index 0000000000000000000000000000000000000000..07c15526042c50abc36769d9cd482e7ee68cc003 GIT binary patch literal 18874 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 NhsusR)yf4$0{~B9tWW>| literal 0 HcmV?d00001 diff --git a/OsmAnd/res/drawable-xxxhdpi/img_get_feedback.webp b/OsmAnd/res/drawable-xxxhdpi/img_get_feedback.webp new file mode 100644 index 0000000000000000000000000000000000000000..73dfce7b577b1e9fea4c3adea22d9c021cb3e167 GIT binary patch literal 29614 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 + android:color="@color/active_buttons_and_links_pressed_dark"> diff --git a/OsmAnd/res/drawable/ripple_solid_light.xml b/OsmAnd/res/drawable/ripple_solid_light.xml index 69270d496e..b390b7cce7 100644 --- a/OsmAnd/res/drawable/ripple_solid_light.xml +++ b/OsmAnd/res/drawable/ripple_solid_light.xml @@ -1,5 +1,5 @@ + android:color="@color/active_buttons_and_links_pressed_light"> diff --git a/OsmAnd/res/layout/bottom_sheet_item_description_long.xml b/OsmAnd/res/layout/bottom_sheet_item_description_long.xml index 72c2da3171..d841ca0430 100644 --- a/OsmAnd/res/layout/bottom_sheet_item_description_long.xml +++ b/OsmAnd/res/layout/bottom_sheet_item_description_long.xml @@ -11,4 +11,5 @@ android:paddingRight="@dimen/content_padding" android:textColor="?android:textColorSecondary" android:textSize="@dimen/default_desc_text_size" + android:linksClickable="true" tools:text="Some long description"/> diff --git a/OsmAnd/res/layout/crash_title.xml b/OsmAnd/res/layout/crash_title.xml new file mode 100644 index 0000000000..7dea5a337d --- /dev/null +++ b/OsmAnd/res/layout/crash_title.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/dislike_title.xml b/OsmAnd/res/layout/dislike_title.xml new file mode 100644 index 0000000000..a5fb49608b --- /dev/null +++ b/OsmAnd/res/layout/dislike_title.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/make_better_title.xml b/OsmAnd/res/layout/make_better_title.xml new file mode 100644 index 0000000000..bd3d57e129 --- /dev/null +++ b/OsmAnd/res/layout/make_better_title.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/privacy_settings_layout.xml b/OsmAnd/res/layout/privacy_settings_layout.xml new file mode 100644 index 0000000000..a6587a6919 --- /dev/null +++ b/OsmAnd/res/layout/privacy_settings_layout.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/rate_us_title.xml b/OsmAnd/res/layout/rate_us_title.xml new file mode 100644 index 0000000000..9090a10b45 --- /dev/null +++ b/OsmAnd/res/layout/rate_us_title.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/values/colors.xml b/OsmAnd/res/values/colors.xml index e0d24ee9d8..cc70bf2be5 100644 --- a/OsmAnd/res/values/colors.xml +++ b/OsmAnd/res/values/colors.xml @@ -491,7 +491,6 @@ #dcdcdc #EFEFEF #ababab - #505050 #727272 #727272 diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 0fa36ba6fa..6c33f9bd58 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -11,6 +11,23 @@ Thx - Hardy --> + Please give us 30 seconds, share feedback and rate our work on Google Play. + Rate + Privacy Policy + Help us make OsmAnd better! + Allow OsmAnd to collect and process anonymous application usage data. We do not collect or store data about your location, or about the locations that you view on the map.\n\nYou can always change your selection in Settings > Privacy and Security. + Choose what type of data you want to share: + Downloaded Maps + Visited screens + Colleted Data + List of data you want to share with OsmAnd. + We collect this data to understand the maps of which regions and countries are the most popular. + We collect this data to understand the most popular features of OsmAnd. + By clicking \"Allow\" you agree with our %1$s + Privacy and Security + Choose your data for sharing with us + No, thank you + Allow Profile Name Navigation Type Taxi diff --git a/OsmAnd/res/xml/settings_pref.xml b/OsmAnd/res/xml/settings_pref.xml index 8f9e0c2fcc..22e47e3773 100644 --- a/OsmAnd/res/xml/settings_pref.xml +++ b/OsmAnd/res/xml/settings_pref.xml @@ -4,5 +4,6 @@ + diff --git a/OsmAnd/src/net/osmand/plus/AnalyticsHelper.java b/OsmAnd/src/net/osmand/plus/AnalyticsHelper.java index 9bbba55b9b..e906d7b9bb 100644 --- a/OsmAnd/src/net/osmand/plus/AnalyticsHelper.java +++ b/OsmAnd/src/net/osmand/plus/AnalyticsHelper.java @@ -49,10 +49,14 @@ public class AnalyticsHelper extends SQLiteOpenHelper { private final static String DATABASE_NAME = "analytics"; private final static int DATABASE_VERSION = 1; - private final static String TABLE_NAME = "events"; + private final static String TABLE_NAME = "app_events"; private final static String COL_DATE = "date"; + private final static String COL_TYPE = "event_type"; private final static String COL_EVENT = "event"; + public final static int EVENT_TYPE_APP_USAGE = 1; + public final static int EVENT_TYPE_MAP_DOWNLOAD = 2; + private OsmandApplication ctx; private String insertEventScript; private long lastSubmittedTime; @@ -62,6 +66,7 @@ public class AnalyticsHelper extends SQLiteOpenHelper { private static class AnalyticsItem { long date; + int type; String event; } @@ -74,7 +79,7 @@ public class AnalyticsHelper extends SQLiteOpenHelper { AnalyticsHelper(OsmandApplication ctx) { super(ctx, DATABASE_NAME, null, DATABASE_VERSION); this.ctx = ctx; - insertEventScript = "INSERT INTO " + TABLE_NAME + " VALUES (?, ?)"; + insertEventScript = "INSERT INTO " + TABLE_NAME + " VALUES (?, ?, ?)"; submitCollectedDataAsync(); } @@ -84,7 +89,7 @@ public class AnalyticsHelper extends SQLiteOpenHelper { } private void createTable(SQLiteDatabase db) { - db.execSQL("CREATE TABLE " + TABLE_NAME + " (" + COL_DATE + " long, " + COL_EVENT + " text )"); + db.execSQL("CREATE TABLE " + TABLE_NAME + " (" + COL_DATE + " long, " + COL_TYPE + " int, " + COL_EVENT + " text )"); } @Override @@ -108,7 +113,7 @@ public class AnalyticsHelper extends SQLiteOpenHelper { return res; } - private void clearDB( long finishDate) { + private void clearDB(long finishDate) { SQLiteDatabase db = getWritableDatabase(); if (db != null && db.isOpen()) { try { @@ -123,11 +128,18 @@ public class AnalyticsHelper extends SQLiteOpenHelper { if (ctx.getSettings().isInternetConnectionAvailable()) { long collectedRowsCount = getCollectedRowsCount(); if (collectedRowsCount > DATA_PARCEL_SIZE) { - if (submittingTask == null || submittingTask.isDone()) { + final List allowedTypes = new ArrayList<>(); + if (ctx.getSettings().SEND_ANONYMOUS_MAP_DOWNLOADS_DATA.get()) { + allowedTypes.add(EVENT_TYPE_MAP_DOWNLOAD); + } + if (ctx.getSettings().SEND_ANONYMOUS_APP_USAGE_DATA.get()) { + allowedTypes.add(EVENT_TYPE_APP_USAGE); + } + if ((submittingTask == null || submittingTask.isDone()) && allowedTypes.size() > 0) { submittingTask = executor.submit(new Runnable() { @Override public void run() { - submitCollectedData(); + submitCollectedData(allowedTypes); } }); return true; @@ -139,17 +151,19 @@ public class AnalyticsHelper extends SQLiteOpenHelper { @SuppressLint("HardwareIds") - private boolean submitCollectedData() { + private void submitCollectedData(List allowedTypes) { List data = collectRecordedData(); for (AnalyticsData d : data) { if (d.items != null && d.items.size() > 0) { try { JSONArray jsonItemsArray = new JSONArray(); for (AnalyticsItem item : d.items) { - JSONObject jsonItem = new JSONObject(); - jsonItem.put(JSON_DATE, item.date); - jsonItem.put(JSON_EVENT, item.event); - jsonItemsArray.put(jsonItem); + if (allowedTypes.contains(item.type)) { + JSONObject jsonItem = new JSONObject(); + jsonItem.put(JSON_DATE, item.date); + jsonItem.put(JSON_EVENT, item.event); + jsonItemsArray.put(jsonItem); + } } Map additionalData = new LinkedHashMap(); @@ -172,16 +186,15 @@ public class AnalyticsHelper extends SQLiteOpenHelper { InputStream inputStream = new ByteArrayInputStream(jsonStr.getBytes()); String res = AndroidNetworkUtils.uploadFile(ANALYTICS_UPLOAD_URL, inputStream, ANALYTICS_FILE_NAME, true, additionalData); if (res != null) { - return false; + return; } } catch (Exception e) { LOG.error(e); - return false; + return; } clearDB(d.finishDate); } } - return true; } private List collectRecordedData() { @@ -198,7 +211,7 @@ public class AnalyticsHelper extends SQLiteOpenHelper { } private void collectDBData(SQLiteDatabase db, List data) { - Cursor query = db.rawQuery("SELECT " + COL_DATE + "," + COL_EVENT + " FROM " + TABLE_NAME + " ORDER BY " + COL_DATE + " ASC", null); + Cursor query = db.rawQuery("SELECT " + COL_DATE + "," + COL_TYPE + "," + COL_EVENT + " FROM " + TABLE_NAME + " ORDER BY " + COL_DATE + " ASC", null); List items = new ArrayList<>(); int itemsCounter = 0; long startDate = Long.MAX_VALUE; @@ -208,7 +221,8 @@ public class AnalyticsHelper extends SQLiteOpenHelper { AnalyticsItem item = new AnalyticsItem(); long date = query.getLong(0); item.date = date; - item.event = query.getString(1); + item.type = query.getInt(1); + item.event = query.getString(2); items.add(item); itemsCounter++; @@ -244,11 +258,11 @@ public class AnalyticsHelper extends SQLiteOpenHelper { query.close(); } - public void addEvent(String event) { + public void addEvent(String event, int type) { SQLiteDatabase db = getWritableDatabase(); if (db != null && db.isOpen()) { try { - db.execSQL(insertEventScript, new Object[]{System.currentTimeMillis(), event}); + db.execSQL(insertEventScript, new Object[]{System.currentTimeMillis(), type, event}); } finally { db.close(); } diff --git a/OsmAnd/src/net/osmand/plus/OsmandApplication.java b/OsmAnd/src/net/osmand/plus/OsmandApplication.java index e1c69f6e9e..7d374dfa29 100644 --- a/OsmAnd/src/net/osmand/plus/OsmandApplication.java +++ b/OsmAnd/src/net/osmand/plus/OsmandApplication.java @@ -47,7 +47,7 @@ import net.osmand.plus.activities.SavingTrackHelper; import net.osmand.plus.api.SQLiteAPI; import net.osmand.plus.api.SQLiteAPIImpl; import net.osmand.plus.base.MapViewTrackingUtilities; -import net.osmand.plus.dialogs.ErrorBottomSheetDialog; +import net.osmand.plus.dialogs.CrashBottomSheetDialogFragment; import net.osmand.plus.dialogs.RateUsBottomSheetDialog; import net.osmand.plus.download.DownloadIndexesThread; import net.osmand.plus.download.IndexItem; @@ -85,7 +85,8 @@ import btools.routingapp.BRouterServiceConnection; import btools.routingapp.IBRouterService; public class OsmandApplication extends MultiDexApplication { - public static final String EXCEPTION_PATH = "exception.log"; + public static final String EXCEPTION_PATH = "exception.log"; + public static final String OSMAND_PRIVACY_POLICY_URL = "https://osmand.net/help-online/privacy-policy"; private static final org.apache.commons.logging.Log LOG = PlatformUtil.getLog(OsmandApplication.class); final AppInitializer appInitializer = new AppInitializer(this); @@ -942,9 +943,7 @@ public class OsmandApplication extends MultiDexApplication { public void logEvent(String event) { try { - if (osmandSettings.SEND_ANONYMOUS_APP_USAGE_DATA.get()) { - analyticsHelper.addEvent(event); - } + analyticsHelper.addEvent(event, AnalyticsHelper.EVENT_TYPE_APP_USAGE); } catch (Exception e) { LOG.error(e); } @@ -952,9 +951,7 @@ public class OsmandApplication extends MultiDexApplication { public void logMapDownloadEvent(String event, IndexItem item) { try { - if (osmandSettings.SEND_ANONYMOUS_MAP_DOWNLOADS_DATA.get()) { - analyticsHelper.addEvent("map_download_" + event + ": " + item.getFileName()); - } + analyticsHelper.addEvent("map_download_" + event + ": " + item.getFileName(), AnalyticsHelper.EVENT_TYPE_MAP_DOWNLOAD); } catch (Exception e) { LOG.error(e); } @@ -962,9 +959,7 @@ public class OsmandApplication extends MultiDexApplication { public void logMapDownloadEvent(String event, IndexItem item, long time) { try { - if (osmandSettings.SEND_ANONYMOUS_MAP_DOWNLOADS_DATA.get()) { - analyticsHelper.addEvent("map_download_" + event + ": " + item.getFileName() + " in " + time + " msec"); - } + analyticsHelper.addEvent("map_download_" + event + ": " + item.getFileName() + " in " + time + " msec", AnalyticsHelper.EVENT_TYPE_MAP_DOWNLOAD); } catch (Exception e) { LOG.error(e); } @@ -1009,7 +1004,7 @@ public class OsmandApplication extends MultiDexApplication { text.append("\nApk Version : ").append(info.versionName).append(" ").append(info.versionCode); } } catch (PackageManager.NameNotFoundException e) { - PlatformUtil.getLog(ErrorBottomSheetDialog.class).error("", e); + PlatformUtil.getLog(CrashBottomSheetDialogFragment.class).error("", e); } intent.putExtra(Intent.EXTRA_TEXT, text.toString()); Intent chooserIntent = Intent.createChooser(intent, getString(R.string.send_report)); diff --git a/OsmAnd/src/net/osmand/plus/OsmandSettings.java b/OsmAnd/src/net/osmand/plus/OsmandSettings.java index 3c513469ab..49df65dd53 100644 --- a/OsmAnd/src/net/osmand/plus/OsmandSettings.java +++ b/OsmAnd/src/net/osmand/plus/OsmandSettings.java @@ -1060,6 +1060,9 @@ public class OsmandSettings { public final OsmandPreference DO_NOT_USE_ANIMATIONS = new BooleanPreference("do_not_use_animations", false).makeGlobal().cache(); public final OsmandPreference SEND_ANONYMOUS_MAP_DOWNLOADS_DATA = new BooleanPreference("send_anonymous_map_downloads_data", false).makeGlobal().cache(); public final OsmandPreference SEND_ANONYMOUS_APP_USAGE_DATA = new BooleanPreference("send_anonymous_app_usage_data", false).makeGlobal().cache(); + public final OsmandPreference SEND_ANONYMOUS_DATA_REQUEST_PROCESSED = new BooleanPreference("send_anonymous_data_request_processed", false).makeGlobal().cache(); + public final OsmandPreference SEND_ANONYMOUS_DATA_REQUESTS_COUNT = new IntPreference("send_anonymous_data_requests_count", 0).makeGlobal().cache(); + public final OsmandPreference SEND_ANONYMOUS_DATA_LAST_REQUEST_NS = new IntPreference("send_anonymous_data_last_request_ns", -1).makeGlobal().cache(); public final OsmandPreference MAP_EMPTY_STATE_ALLOWED = new BooleanPreference("map_empty_state_allowed", true).makeGlobal().cache(); diff --git a/OsmAnd/src/net/osmand/plus/activities/MapActivity.java b/OsmAnd/src/net/osmand/plus/activities/MapActivity.java index 6cad542be5..3f56a6fac6 100644 --- a/OsmAnd/src/net/osmand/plus/activities/MapActivity.java +++ b/OsmAnd/src/net/osmand/plus/activities/MapActivity.java @@ -83,7 +83,9 @@ import net.osmand.plus.base.MapViewTrackingUtilities; import net.osmand.plus.chooseplan.OsmLiveCancelledDialog; import net.osmand.plus.dashboard.DashboardOnMap; import net.osmand.plus.dashboard.DashboardOnMap.DashboardType; -import net.osmand.plus.dialogs.ErrorBottomSheetDialog; +import net.osmand.plus.dialogs.CrashBottomSheetDialogFragment; +import net.osmand.plus.dialogs.RateUsBottomSheetDialogFragment; +import net.osmand.plus.dialogs.SendAnalyticsBottomSheetDialogFragment; import net.osmand.plus.dialogs.RateUsBottomSheetDialog; import net.osmand.plus.dialogs.WhatsNewDialogFragment; import net.osmand.plus.dialogs.XMasDialogFragment; @@ -680,12 +682,12 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven if (settings.SHOW_DASHBOARD_ON_START.get()) { dashboardOnMap.setDashboardVisibility(true, DashboardOnMap.staticVisibleType); } else { - if (ErrorBottomSheetDialog.shouldShow(settings, this)) { + if (CrashBottomSheetDialogFragment.shouldShow(settings, this)) { SecondSplashScreenFragment.SHOW = false; - new ErrorBottomSheetDialog().show(getSupportFragmentManager(), "dialog"); - } else if (RateUsBottomSheetDialog.shouldShow(app)) { + CrashBottomSheetDialogFragment.showInstance(getSupportFragmentManager()); + } else if (RateUsBottomSheetDialogFragment.shouldShow(app)) { SecondSplashScreenFragment.SHOW = false; - new RateUsBottomSheetDialog().show(getSupportFragmentManager(), "dialog"); + RateUsBottomSheetDialogFragment.showInstance(getSupportFragmentManager()); } } } else { @@ -860,6 +862,8 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven FirstUsageWelcomeFragment.TAG).commitAllowingStateLoss(); } else if (!isFirstScreenShowing() && OsmLiveCancelledDialog.shouldShowDialog(app)) { OsmLiveCancelledDialog.showInstance(getSupportFragmentManager()); + } else if (SendAnalyticsBottomSheetDialogFragment.shouldShowDialog(app)) { + SendAnalyticsBottomSheetDialogFragment.showInstance(app, getSupportFragmentManager()); } FirstUsageWelcomeFragment.SHOW = false; if (isFirstScreenShowing() && (!settings.SHOW_OSMAND_WELCOME_SCREEN.get() || !showOsmAndWelcomeScreen)) { diff --git a/OsmAnd/src/net/osmand/plus/activities/PrivacyAndSecurityActivity.java b/OsmAnd/src/net/osmand/plus/activities/PrivacyAndSecurityActivity.java new file mode 100644 index 0000000000..ce8e1da09c --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/activities/PrivacyAndSecurityActivity.java @@ -0,0 +1,90 @@ +package net.osmand.plus.activities; + +import android.app.Activity; +import android.os.Bundle; +import android.support.v7.widget.SwitchCompat; +import android.support.v7.widget.Toolbar; +import android.util.TypedValue; +import android.view.MenuItem; +import android.view.View; +import android.widget.CompoundButton; + +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; + +public class PrivacyAndSecurityActivity extends OsmandActionBarActivity { + + @Override + public void onCreate(Bundle savedInstanceState) { + OsmandApplication app = getMyApplication(); + int themeId = !app.getSettings().isLightContent() ? R.style.OsmandDarkTheme_NoActionbar : R.style.OsmandLightTheme_NoActionbar; + setTheme(themeId); + super.onCreate(savedInstanceState); + setContentView(R.layout.privacy_settings_layout); + Toolbar tb = (Toolbar) findViewById(R.id.toolbar); + tb.setTitle(R.string.settings_privacy_and_security); + + tb.setClickable(true); + tb.setNavigationIcon(((OsmandApplication) getApplication()).getUIUtilities().getIcon(R.drawable.ic_arrow_back)); + tb.setNavigationContentDescription(R.string.access_shared_string_navigate_up); + tb.setBackgroundColor(getResources().getColor(resolveResourceId(this, R.attr.pstsTabBackground))); + tb.setTitleTextColor(getResources().getColor(resolveResourceId(this, R.attr.pstsTextColor))); + tb.setNavigationOnClickListener(new View.OnClickListener() { + @Override + public void onClick(final View v) { + finish(); + } + }); + + View downloadedMapsContainer = findViewById(R.id.downloaded_maps_container); + final SwitchCompat downloadedMapsButton = (SwitchCompat) findViewById(R.id.downloaded_maps_button); + downloadedMapsButton.setChecked(app.getSettings().SEND_ANONYMOUS_MAP_DOWNLOADS_DATA.get()); + downloadedMapsButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + OsmandApplication app = getMyApplication(); + app.getSettings().SEND_ANONYMOUS_MAP_DOWNLOADS_DATA.set(isChecked); + } + }); + downloadedMapsContainer.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + downloadedMapsButton.setChecked(!downloadedMapsButton.isChecked()); + } + }); + + View visitedScreensContainer = findViewById(R.id.visited_screens_container); + final SwitchCompat visitedScreensButton = (SwitchCompat) findViewById(R.id.visited_screens_button); + visitedScreensButton.setChecked(app.getSettings().SEND_ANONYMOUS_APP_USAGE_DATA.get()); + visitedScreensButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + OsmandApplication app = getMyApplication(); + app.getSettings().SEND_ANONYMOUS_APP_USAGE_DATA.set(isChecked); + } + }); + visitedScreensContainer.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + visitedScreensButton.setChecked(!visitedScreensButton.isChecked()); + } + }); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + int itemId = item.getItemId(); + switch (itemId) { + case android.R.id.home: + finish(); + return true; + } + return false; + } + + private int resolveResourceId(final Activity activity, final int attr) { + final TypedValue typedvalueattr = new TypedValue(); + activity.getTheme().resolveAttribute(attr, typedvalueattr, true); + return typedvalueattr.resourceId; + } +} diff --git a/OsmAnd/src/net/osmand/plus/activities/SettingsActivity.java b/OsmAnd/src/net/osmand/plus/activities/SettingsActivity.java index db7df49a1c..7fc3caab0b 100644 --- a/OsmAnd/src/net/osmand/plus/activities/SettingsActivity.java +++ b/OsmAnd/src/net/osmand/plus/activities/SettingsActivity.java @@ -30,6 +30,7 @@ public class SettingsActivity extends SettingsBaseActivity { private Preference routing; private Preference subscription; private Preference profiles; + private Preference privacy; @Override @@ -46,6 +47,8 @@ public class SettingsActivity extends SettingsBaseActivity { profiles.setOnPreferenceClickListener(this); subscription = (Preference) screen.findPreference("subscription_settings"); subscription.setOnPreferenceClickListener(this); + privacy = (Preference) screen.findPreference("privacy_and_security"); + privacy.setOnPreferenceClickListener(this); getToolbar().setTitle(Version.getFullVersion(getMyApplication())); @@ -103,6 +106,10 @@ public class SettingsActivity extends SettingsBaseActivity { intent.putExtra(OsmLiveActivity.SHOW_SETTINGS_ONLY_INTENT_PARAM, true); startActivity(intent); return true; + } else if (preference == privacy) { + Intent intent = new Intent(this, PrivacyAndSecurityActivity.class); + startActivity(intent); + return true; } else { super.onPreferenceClick(preference); } diff --git a/OsmAnd/src/net/osmand/plus/base/MenuBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/base/MenuBottomSheetDialogFragment.java index 35bd35a350..c6ff3339ab 100644 --- a/OsmAnd/src/net/osmand/plus/base/MenuBottomSheetDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/base/MenuBottomSheetDialogFragment.java @@ -43,6 +43,8 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra protected boolean nightMode; protected int themeRes; + protected View dismissButton; + protected View rightButton; private LinearLayout itemsContainer; @@ -85,8 +87,8 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra inflateMenuItems(); - View dismissButton = mainView.findViewById(R.id.dismiss_button); - setupDialogButton(dismissButton, DialogButtonType.STROKED, getDismissButtonTextId()); + dismissButton = mainView.findViewById(R.id.dismiss_button); + setupDialogButton(dismissButton, getDismissByttonType(), getDismissButtonTextId()); dismissButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -100,8 +102,8 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra int rightBottomButtonTextId = getRightBottomButtonTextId(); if (rightBottomButtonTextId != DEFAULT_VALUE) { mainView.findViewById(R.id.buttons_divider).setVisibility(View.VISIBLE); - View rightButton = mainView.findViewById(R.id.right_bottom_button); - setupDialogButton(rightButton, DialogButtonType.PRIMARY, rightBottomButtonTextId); + rightButton = mainView.findViewById(R.id.right_bottom_button); + setupDialogButton(rightButton, getRightBottomByttonType(), rightBottomButtonTextId); rightButton.setVisibility(View.VISIBLE); rightButton.setOnClickListener(new View.OnClickListener() { @Override @@ -111,6 +113,7 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra }); } } + updateBottomButtons(); setupHeightAndBackground(mainView); return mainView; } @@ -283,6 +286,10 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra dismissButtonStringRes = stringRes; } + protected DialogButtonType getDismissByttonType() { + return DialogButtonType.SECONDARY; + } + protected void onDismissButtonClickAction() { } @@ -292,10 +299,35 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra return DEFAULT_VALUE; } + protected DialogButtonType getRightBottomByttonType() { + return DialogButtonType.PRIMARY; + } + protected void onRightBottomButtonClick() { } + protected boolean isDismissButtonEnabled() { + return true; + } + + protected boolean isRightBottomButtonEnabled() { + return true; + } + + protected void updateBottomButtons() { + if (dismissButton != null) { + boolean enabled = isDismissButtonEnabled(); + dismissButton.setEnabled(enabled); + dismissButton.findViewById(R.id.button_text).setEnabled(enabled); + } + if (rightButton != null) { + boolean enabled = isRightBottomButtonEnabled(); + rightButton.setEnabled(enabled); + rightButton.findViewById(R.id.button_text).setEnabled(enabled); + } + } + @ColorRes protected int getBgColorId() { return nightMode ? R.color.bg_color_dark : R.color.bg_color_light; diff --git a/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/BottomSheetItemTitleWithDescrAndButton.java b/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/BottomSheetItemTitleWithDescrAndButton.java index fc347554fd..9b17400b29 100644 --- a/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/BottomSheetItemTitleWithDescrAndButton.java +++ b/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/BottomSheetItemTitleWithDescrAndButton.java @@ -35,6 +35,7 @@ public class BottomSheetItemTitleWithDescrAndButton extends BottomSheetItemWithD CharSequence description, @ColorRes int descriptionColorId, int descriptionMaxLines, + boolean descriptionLinksClickable, String buttonTitle, View.OnClickListener onButtonClickListener, Drawable leftCompoundDrawable, @@ -51,7 +52,8 @@ public class BottomSheetItemTitleWithDescrAndButton extends BottomSheetItemWithD titleColorId, description, descriptionColorId, - descriptionMaxLines); + descriptionMaxLines, + descriptionLinksClickable); this.buttonTitle = buttonTitle; this.onButtonClickListener = onButtonClickListener; this.leftCompoundDrawable = leftCompoundDrawable; @@ -125,6 +127,7 @@ public class BottomSheetItemTitleWithDescrAndButton extends BottomSheetItemWithD description, descriptionColorId, descriptionMaxLines, + descriptionLinksClickable, buttonTitle, onButtonClickListener, leftCompoundDrawable, diff --git a/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/BottomSheetItemWithCompoundButton.java b/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/BottomSheetItemWithCompoundButton.java index 7722438cdb..4ad4613034 100644 --- a/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/BottomSheetItemWithCompoundButton.java +++ b/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/BottomSheetItemWithCompoundButton.java @@ -37,6 +37,7 @@ public class BottomSheetItemWithCompoundButton extends BottomSheetItemWithDescri CharSequence description, @ColorRes int descriptionColorId, int descriptionMaxLines, + boolean descriptionLinksClickable, boolean checked, ColorStateList buttonTintList, OnCheckedChangeListener onCheckedChangeListener) { @@ -51,7 +52,8 @@ public class BottomSheetItemWithCompoundButton extends BottomSheetItemWithDescri titleColorId, description, descriptionColorId, - descriptionMaxLines); + descriptionMaxLines, + descriptionLinksClickable); this.checked = checked; this.buttonTintList = buttonTintList; this.onCheckedChangeListener = onCheckedChangeListener; @@ -109,6 +111,7 @@ public class BottomSheetItemWithCompoundButton extends BottomSheetItemWithDescri description, descriptionColorId, descriptionMaxLines, + descriptionLinksClickable, checked, buttonTintList, onCheckedChangeListener); diff --git a/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/BottomSheetItemWithDescription.java b/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/BottomSheetItemWithDescription.java index fa26be10e7..ae08050abf 100644 --- a/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/BottomSheetItemWithDescription.java +++ b/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/BottomSheetItemWithDescription.java @@ -4,6 +4,7 @@ import android.graphics.drawable.Drawable; import android.support.annotation.ColorRes; import android.support.annotation.LayoutRes; import android.support.v4.content.ContextCompat; +import android.text.method.LinkMovementMethod; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; @@ -17,6 +18,7 @@ public class BottomSheetItemWithDescription extends SimpleBottomSheetItem { @ColorRes private int descriptionColorId = INVALID_ID; private int descriptionMaxLines = INVALID_VALUE; + private boolean descriptionLinksClickable = false; private TextView descriptionTv; @@ -31,11 +33,13 @@ public class BottomSheetItemWithDescription extends SimpleBottomSheetItem { @ColorRes int titleColorId, CharSequence description, @ColorRes int descriptionColorId, - int descriptionMaxLines) { + int descriptionMaxLines, + boolean descriptionLinksClickable) { super(customView, layoutId, tag, disabled, onClickListener, position, icon, title, titleColorId); this.description = description; this.descriptionColorId = descriptionColorId; this.descriptionMaxLines = descriptionMaxLines; + this.descriptionLinksClickable = descriptionLinksClickable; } protected BottomSheetItemWithDescription() { @@ -52,6 +56,17 @@ public class BottomSheetItemWithDescription extends SimpleBottomSheetItem { descriptionTv.setMaxLines(maxLines); } + public void setDescriptionLinksClickable(boolean descriptionLinksClickable) { + this.descriptionLinksClickable = descriptionLinksClickable; + if (descriptionTv != null) { + if (descriptionLinksClickable) { + descriptionTv.setMovementMethod(LinkMovementMethod.getInstance()); + } else { + descriptionTv.setMovementMethod(null); + } + } + } + @Override public void inflate(OsmandApplication app, ViewGroup container, boolean nightMode) { super.inflate(app, container, nightMode); @@ -64,6 +79,9 @@ public class BottomSheetItemWithDescription extends SimpleBottomSheetItem { if (descriptionMaxLines != INVALID_VALUE) { descriptionTv.setMaxLines(descriptionMaxLines); } + if (descriptionLinksClickable) { + descriptionTv.setMovementMethod(LinkMovementMethod.getInstance()); + } } } @@ -73,6 +91,7 @@ public class BottomSheetItemWithDescription extends SimpleBottomSheetItem { @ColorRes protected int descriptionColorId = INVALID_ID; protected int descriptionMaxLines = INVALID_POSITION; + protected boolean descriptionLinksClickable = false; public Builder setDescription(CharSequence description) { this.description = description; @@ -89,6 +108,10 @@ public class BottomSheetItemWithDescription extends SimpleBottomSheetItem { return this; } + public void setDescriptionLinksClickable(boolean descriptionLinksClickable) { + this.descriptionLinksClickable = descriptionLinksClickable; + } + public BottomSheetItemWithDescription create() { return new BottomSheetItemWithDescription(customView, layoutId, @@ -101,7 +124,8 @@ public class BottomSheetItemWithDescription extends SimpleBottomSheetItem { titleColorId, description, descriptionColorId, - descriptionMaxLines); + descriptionMaxLines, + descriptionLinksClickable); } } } diff --git a/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/simpleitems/SubtitmeListDividerItem.java b/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/simpleitems/SubtitmeListDividerItem.java new file mode 100644 index 0000000000..f429795bf1 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/simpleitems/SubtitmeListDividerItem.java @@ -0,0 +1,31 @@ +package net.osmand.plus.base.bottomsheetmenu.simpleitems; + +import android.content.Context; +import android.support.annotation.ColorRes; + +import net.osmand.plus.R; + +public class SubtitmeListDividerItem extends DividerItem { + + public SubtitmeListDividerItem(Context context) { + super(context); + } + + public SubtitmeListDividerItem(Context context, @ColorRes int colorId) { + super(context, colorId); + } + + public SubtitmeListDividerItem(Context context, @ColorRes int colorId, int position) { + super(context, colorId, position); + } + + @Override + protected int getBottomMargin(Context context) { + return 0; + } + + @Override + protected int getLeftMargin(Context context) { + return context.getResources().getDimensionPixelSize(R.dimen.list_content_padding); + } +} diff --git a/OsmAnd/src/net/osmand/plus/dashboard/DashErrorFragment.java b/OsmAnd/src/net/osmand/plus/dashboard/DashErrorFragment.java index 478c26b466..136e50deab 100644 --- a/OsmAnd/src/net/osmand/plus/dashboard/DashErrorFragment.java +++ b/OsmAnd/src/net/osmand/plus/dashboard/DashErrorFragment.java @@ -1,10 +1,6 @@ package net.osmand.plus.dashboard; -import android.content.Intent; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; import android.graphics.Typeface; -import android.os.Build; import android.os.Bundle; import android.support.design.widget.Snackbar; import android.support.v4.view.ViewCompat; @@ -15,19 +11,15 @@ import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; -import net.osmand.AndroidUtils; -import net.osmand.PlatformUtil; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandSettings; import net.osmand.plus.R; -import net.osmand.plus.Version; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.OsmandActionBarActivity; import net.osmand.plus.dashboard.tools.DashFragmentData; -import net.osmand.plus.dialogs.ErrorBottomSheetDialog; +import net.osmand.plus.dialogs.CrashBottomSheetDialogFragment; import net.osmand.plus.helpers.FontCache; -import java.io.File; import java.text.MessageFormat; public class DashErrorFragment extends DashBaseFragment { @@ -38,7 +30,7 @@ public class DashErrorFragment extends DashBaseFragment { // If settings null. No changes in setting will be made. @Override public boolean shouldShow(OsmandSettings settings, MapActivity activity, String tag) { - return ErrorBottomSheetDialog.shouldShow(settings, activity); + return CrashBottomSheetDialogFragment.shouldShow(settings, activity); } }; private DismissListener dismissCallback; diff --git a/OsmAnd/src/net/osmand/plus/dialogs/CrashBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/dialogs/CrashBottomSheetDialogFragment.java new file mode 100644 index 0000000000..ded8574cf3 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/dialogs/CrashBottomSheetDialogFragment.java @@ -0,0 +1,68 @@ +package net.osmand.plus.dialogs; + +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.FragmentManager; +import android.view.ContextThemeWrapper; +import android.view.View; + +import net.osmand.PlatformUtil; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.OsmandSettings; +import net.osmand.plus.R; +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.base.MenuBottomSheetDialogFragment; +import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; +import net.osmand.plus.base.bottomsheetmenu.simpleitems.SubtitleDividerItem; + +import org.apache.commons.logging.Log; + +public class CrashBottomSheetDialogFragment extends MenuBottomSheetDialogFragment { + public static final String TAG = "CrashBottomSheetDialogFragment"; + private static final Log LOG = PlatformUtil.getLog(CrashBottomSheetDialogFragment.class); + + @Override + public void createMenuItems(Bundle savedInstanceState) { + Context context = getContext(); + if (context == null) { + return; + } + + final View titleView = View.inflate(new ContextThemeWrapper(context, themeRes), R.layout.crash_title, null); + final SimpleBottomSheetItem titleItem = (SimpleBottomSheetItem) new SimpleBottomSheetItem.Builder() + .setCustomView(titleView) + .create(); + items.add(titleItem); + } + + @Override + protected int getRightBottomButtonTextId() { + return R.string.shared_string_send; + } + + @Override + protected void onRightBottomButtonClick() { + OsmandApplication app = getMyApplication(); + if (app != null) { + app.sendCrashLog(); + } + dismiss(); + } + + public static boolean shouldShow(OsmandSettings settings, MapActivity activity) { + return activity.getMyApplication().getAppInitializer() + .checkPreviousRunsForExceptions(activity, settings != null); + } + + public static void showInstance(@NonNull FragmentManager fm) { + try { + if (fm.findFragmentByTag(CrashBottomSheetDialogFragment.TAG) == null) { + CrashBottomSheetDialogFragment fragment = new CrashBottomSheetDialogFragment(); + fragment.show(fm, CrashBottomSheetDialogFragment.TAG); + } + } catch (RuntimeException e) { + LOG.error("showInstance", e); + } + } +} diff --git a/OsmAnd/src/net/osmand/plus/dialogs/DislikeOsmAndBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/dialogs/DislikeOsmAndBottomSheetDialogFragment.java new file mode 100644 index 0000000000..4e39a67038 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/dialogs/DislikeOsmAndBottomSheetDialogFragment.java @@ -0,0 +1,85 @@ +package net.osmand.plus.dialogs; + +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.FragmentManager; +import android.support.v7.view.ContextThemeWrapper; +import android.view.View; + +import net.osmand.PlatformUtil; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.OsmandSettings; +import net.osmand.plus.R; +import net.osmand.plus.base.MenuBottomSheetDialogFragment; +import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; + +import org.apache.commons.logging.Log; + +public class DislikeOsmAndBottomSheetDialogFragment extends MenuBottomSheetDialogFragment { + public static final String TAG = "DislikeOsmAndBottomSheetDialogFragment"; + private static final Log LOG = PlatformUtil.getLog(DislikeOsmAndBottomSheetDialogFragment.class); + + @Override + public void createMenuItems(Bundle savedInstanceState) { + Context context = getContext(); + if (context == null) { + return; + } + + final View titleView = View.inflate(new ContextThemeWrapper(context, themeRes), R.layout.dislike_title, null); + final SimpleBottomSheetItem titleItem = (SimpleBottomSheetItem) new SimpleBottomSheetItem.Builder() + .setCustomView(titleView) + .create(); + items.add(titleItem); + } + + @Override + protected int getDismissButtonTextId() { + return R.string.shared_string_cancel; + } + + @Override + protected void onDismissButtonClickAction() { + OsmandApplication app = getMyApplication(); + if (app != null) { + app.getSettings().RATE_US_STATE.set(RateUsBottomSheetDialog.RateUsState.DISLIKED_WITHOUT_MESSAGE); + } + } + + @Override + protected int getRightBottomButtonTextId() { + return R.string.shared_string_send; + } + + @Override + protected void onRightBottomButtonClick() { + OsmandApplication app = getMyApplication(); + if (app != null) { + OsmandSettings settings = app.getSettings(); + String email = getString(R.string.support_email); + settings.RATE_US_STATE.set(RateUsBottomSheetDialog.RateUsState.DISLIKED_WITH_MESSAGE); + settings.NUMBER_OF_APPLICATION_STARTS.set(0); + settings.LAST_DISPLAY_TIME.set(System.currentTimeMillis()); + Intent sendEmail = new Intent(Intent.ACTION_SENDTO); + sendEmail.setType("text/plain"); + sendEmail.setData(Uri.parse("mailto:" + email)); + sendEmail.putExtra(Intent.EXTRA_EMAIL, email); + startActivity(sendEmail); + dismiss(); + } + } + + public static void showInstance(@NonNull FragmentManager fm) { + try { + if (fm.findFragmentByTag(DislikeOsmAndBottomSheetDialogFragment.TAG) == null) { + DislikeOsmAndBottomSheetDialogFragment fragment = new DislikeOsmAndBottomSheetDialogFragment(); + fragment.show(fm, DislikeOsmAndBottomSheetDialogFragment.TAG); + } + } catch (RuntimeException e) { + LOG.error("showInstance", e); + } + } +} diff --git a/OsmAnd/src/net/osmand/plus/dialogs/ErrorBottomSheetDialog.java b/OsmAnd/src/net/osmand/plus/dialogs/ErrorBottomSheetDialog.java deleted file mode 100644 index 4d812da350..0000000000 --- a/OsmAnd/src/net/osmand/plus/dialogs/ErrorBottomSheetDialog.java +++ /dev/null @@ -1,70 +0,0 @@ -package net.osmand.plus.dialogs; - -import android.graphics.Typeface; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.FragmentActivity; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.TextView; - -import net.osmand.plus.OsmandApplication; -import net.osmand.plus.OsmandSettings; -import net.osmand.plus.R; -import net.osmand.plus.activities.MapActivity; -import net.osmand.plus.activities.OsmandActionBarActivity; -import net.osmand.plus.base.BottomSheetDialogFragment; -import net.osmand.plus.helpers.FontCache; - -import java.text.MessageFormat; - -public class ErrorBottomSheetDialog extends BottomSheetDialogFragment { - @Nullable - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - FragmentActivity activity = requireActivity(); - OsmandApplication app = (OsmandApplication) activity.getApplication(); - View view = activity.getLayoutInflater().inflate(R.layout.dash_error_fragment, container, false); - String msg = MessageFormat.format(getString(R.string.previous_run_crashed), OsmandApplication.EXCEPTION_PATH); - Typeface typeface = FontCache.getRobotoMedium(activity); - ImageView iv = ((ImageView) view.findViewById(R.id.error_icon)); - iv.setImageDrawable(app.getUIUtilities().getThemedIcon(R.drawable.ic_crashlog)); - TextView message = ((TextView) view.findViewById(R.id.error_header)); - message.setTypeface(typeface); - message.setText(msg); - Button errorBtn = ((Button) view.findViewById(R.id.error_btn)); - errorBtn.setTypeface(typeface); - errorBtn.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - OsmandApplication app = getMyApplication(); - if (app != null) { - app.sendCrashLog(); - } - dismiss(); - } - }); - - Button cancelBtn = ((Button) view.findViewById(R.id.error_cancel)); - cancelBtn.setTypeface(typeface); - cancelBtn.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - OsmandActionBarActivity dashboardActivity = ((OsmandActionBarActivity) getActivity()); - if (dashboardActivity != null) { - dismiss(); - } - } - }); - return view; - } - - public static boolean shouldShow(OsmandSettings settings, MapActivity activity) { - return activity.getMyApplication().getAppInitializer() - .checkPreviousRunsForExceptions(activity, settings != null); - } -} diff --git a/OsmAnd/src/net/osmand/plus/dialogs/RateUsBottomSheetDialog.java b/OsmAnd/src/net/osmand/plus/dialogs/RateUsBottomSheetDialog.java index c5663d87df..bd70893c37 100644 --- a/OsmAnd/src/net/osmand/plus/dialogs/RateUsBottomSheetDialog.java +++ b/OsmAnd/src/net/osmand/plus/dialogs/RateUsBottomSheetDialog.java @@ -83,7 +83,7 @@ public class RateUsBottomSheetDialog extends BottomSheetDialogFragment { } } // Initial state now - modifiedTime.add(Calendar.HOUR, -72); + modifiedTime.add(Calendar.MONTH, -1); bannerFreeRuns = 3; return modifiedTime.after(lastDisplayTime) && numberOfApplicationRuns >= bannerFreeRuns; } diff --git a/OsmAnd/src/net/osmand/plus/dialogs/RateUsBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/dialogs/RateUsBottomSheetDialogFragment.java new file mode 100644 index 0000000000..51b46fc143 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/dialogs/RateUsBottomSheetDialogFragment.java @@ -0,0 +1,87 @@ +package net.osmand.plus.dialogs; + +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.FragmentManager; +import android.view.ContextThemeWrapper; +import android.view.View; + +import net.osmand.PlatformUtil; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.OsmandSettings; +import net.osmand.plus.R; +import net.osmand.plus.Version; +import net.osmand.plus.base.MenuBottomSheetDialogFragment; +import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; +import net.osmand.plus.base.bottomsheetmenu.simpleitems.SubtitleDividerItem; + +import org.apache.commons.logging.Log; + +import java.util.Calendar; + +public class RateUsBottomSheetDialogFragment extends MenuBottomSheetDialogFragment { + public static final String TAG = "RateUsBottomSheetDialogFragment"; + private static final Log LOG = PlatformUtil.getLog(SendAnalyticsBottomSheetDialogFragment.class); + + @Override + public void createMenuItems(Bundle savedInstanceState) { + Context context = getContext(); + if (context == null) { + return; + } + + final View titleView = View.inflate(new ContextThemeWrapper(context, themeRes), R.layout.rate_us_title, null); + final SimpleBottomSheetItem titleItem = (SimpleBottomSheetItem) new SimpleBottomSheetItem.Builder() + .setCustomView(titleView) + .create(); + items.add(titleItem); + } + + @Override + protected int getDismissButtonTextId() { + return R.string.shared_string_no; + } + + @Override + protected void onDismissButtonClickAction() { + FragmentManager fm = getFragmentManager(); + if (fm != null) { + DislikeOsmAndBottomSheetDialogFragment.showInstance(fm); + } + } + + @Override + protected int getRightBottomButtonTextId() { + return R.string.button_rate; + } + + @Override + protected void onRightBottomButtonClick() { + OsmandApplication app = getMyApplication(); + if (app != null) { + app.getSettings().RATE_US_STATE.set(RateUsBottomSheetDialog.RateUsState.LIKED); + Uri uri = Uri.parse(Version.getUrlWithUtmRef(app, app.getPackageName())); + Intent goToMarket = new Intent(Intent.ACTION_VIEW, uri); + startActivity(goToMarket); + dismiss(); + } + } + + public static boolean shouldShow(OsmandApplication app) { + return RateUsBottomSheetDialog.shouldShow(app); + } + + public static void showInstance(@NonNull FragmentManager fm) { + try { + if (fm.findFragmentByTag(RateUsBottomSheetDialogFragment.TAG) == null) { + RateUsBottomSheetDialogFragment fragment = new RateUsBottomSheetDialogFragment(); + fragment.show(fm, RateUsBottomSheetDialogFragment.TAG); + } + } catch (RuntimeException e) { + LOG.error("showInstance", e); + } + } +} diff --git a/OsmAnd/src/net/osmand/plus/dialogs/SendAnalyticsBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/dialogs/SendAnalyticsBottomSheetDialogFragment.java new file mode 100644 index 0000000000..5de0ee13ca --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/dialogs/SendAnalyticsBottomSheetDialogFragment.java @@ -0,0 +1,193 @@ +package net.osmand.plus.dialogs; + +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.FragmentManager; +import android.support.v4.content.ContextCompat; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.TextPaint; +import android.text.style.ForegroundColorSpan; +import android.text.style.URLSpan; +import android.view.ContextThemeWrapper; +import android.view.View; + +import net.osmand.PlatformUtil; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.OsmandSettings; +import net.osmand.plus.OsmandSettings.OsmandPreference; +import net.osmand.plus.R; +import net.osmand.plus.base.MenuBottomSheetDialogFragment; +import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithCompoundButton; +import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; +import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerItem; +import net.osmand.plus.base.bottomsheetmenu.simpleitems.LongDescriptionItem; +import net.osmand.plus.base.bottomsheetmenu.simpleitems.SubtitleDividerItem; +import net.osmand.plus.base.bottomsheetmenu.simpleitems.SubtitmeListDividerItem; +import net.osmand.plus.chooseplan.OsmLiveCancelledDialog; + +import org.apache.commons.logging.Log; + +public class SendAnalyticsBottomSheetDialogFragment extends MenuBottomSheetDialogFragment { + + public static final String TAG = "SendAnalyticsBottomSheetDialogFragment"; + private static final Log LOG = PlatformUtil.getLog(SendAnalyticsBottomSheetDialogFragment.class); + + private boolean sendAnonymousMapDownloadsData; + private boolean sendAnonymousAppUsageData; + + @Override + public void createMenuItems(Bundle savedInstanceState) { + OsmandApplication app = getMyApplication(); + Context context = getContext(); + if (context == null || app == null) { + return; + } + + final View titleView = View.inflate(new ContextThemeWrapper(context, themeRes), R.layout.make_better_title, null); + final SimpleBottomSheetItem titleItem = (SimpleBottomSheetItem) new SimpleBottomSheetItem.Builder() + .setCustomView(titleView) + .create(); + items.add(titleItem); + + items.add(new SubtitleDividerItem(context)); + + sendAnonymousMapDownloadsData = app.getSettings().SEND_ANONYMOUS_MAP_DOWNLOADS_DATA.get(); + sendAnonymousAppUsageData = app.getSettings().SEND_ANONYMOUS_APP_USAGE_DATA.get(); + final BottomSheetItemWithCompoundButton[] downloadedMapsItem = new BottomSheetItemWithCompoundButton[1]; + downloadedMapsItem[0] = (BottomSheetItemWithCompoundButton) new BottomSheetItemWithCompoundButton.Builder() + .setChecked(sendAnonymousMapDownloadsData) + .setTitle(getString(R.string.downloaded_maps)) + .setLayoutId(R.layout.bottom_sheet_item_with_switch_no_icon) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + boolean checked = !downloadedMapsItem[0].isChecked(); + downloadedMapsItem[0].setChecked(checked); + sendAnonymousMapDownloadsData = checked; + updateBottomButtons(); + } + }) + .setTag("downloaded_maps") + .create(); + items.add(downloadedMapsItem[0]); + + items.add(new LongDescriptionItem(getString(R.string.downloaded_maps_collect_descr))); + + items.add(new SubtitmeListDividerItem(context)); + + final BottomSheetItemWithCompoundButton[] visitedScreensItem = new BottomSheetItemWithCompoundButton[1]; + visitedScreensItem[0] = (BottomSheetItemWithCompoundButton) new BottomSheetItemWithCompoundButton.Builder() + .setChecked(sendAnonymousAppUsageData) + .setTitle(getString(R.string.visited_screens)) + .setLayoutId(R.layout.bottom_sheet_item_with_switch_no_icon) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + boolean checked = !visitedScreensItem[0].isChecked(); + visitedScreensItem[0].setChecked(checked); + sendAnonymousAppUsageData = checked; + updateBottomButtons(); + } + }) + .setTag("visited_screens") + .create(); + items.add(visitedScreensItem[0]); + + items.add(new LongDescriptionItem(getString(R.string.visited_screens_collect_descr))); + + items.add(new DividerItem(context)); + + String privacyPolicyText = getString(R.string.shared_string_privacy_policy); + String text = getString(R.string.privacy_and_security_change_descr, privacyPolicyText); + + SpannableString spannable = new SpannableString(text); + int start = text.indexOf(privacyPolicyText); + int end = start + privacyPolicyText.length(); + spannable.setSpan(new URLSpan(OsmandApplication.OSMAND_PRIVACY_POLICY_URL) { + @Override + public void updateDrawState(@NonNull TextPaint ds) { + super.updateDrawState(ds); + ds.setUnderlineText(false); + } + }, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + int linkTextColor = ContextCompat.getColor(context, !nightMode ? R.color.ctx_menu_bottom_view_url_color_light : R.color.ctx_menu_bottom_view_url_color_dark); + spannable.setSpan(new ForegroundColorSpan(linkTextColor), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + + LongDescriptionItem descriptionItem = new LongDescriptionItem(spannable); + descriptionItem.setDescriptionLinksClickable(true); + items.add(descriptionItem); + } + + @Override + protected boolean isRightBottomButtonEnabled() { + return sendAnonymousMapDownloadsData || sendAnonymousAppUsageData; + } + + @Override + protected int getDismissButtonTextId() { + return R.string.shared_string_no_thank_you; + } + + @Override + protected int getRightBottomButtonTextId() { + return R.string.shared_string_allow; + } + + @Override + protected void onDismissButtonClickAction() { + OsmandApplication app = requiredMyApplication(); + OsmandSettings settings = app.getSettings(); + settings.SEND_ANONYMOUS_MAP_DOWNLOADS_DATA.set(false); + settings.SEND_ANONYMOUS_APP_USAGE_DATA.set(false); + settings.SEND_ANONYMOUS_DATA_REQUEST_PROCESSED.set(true); + } + + @Override + protected void onRightBottomButtonClick() { + OsmandApplication app = requiredMyApplication(); + OsmandSettings settings = app.getSettings(); + settings.SEND_ANONYMOUS_MAP_DOWNLOADS_DATA.set(sendAnonymousMapDownloadsData); + settings.SEND_ANONYMOUS_APP_USAGE_DATA.set(sendAnonymousAppUsageData); + settings.SEND_ANONYMOUS_DATA_REQUEST_PROCESSED.set(true); + dismiss(); + } + + public static boolean shouldShowDialog(@NonNull OsmandApplication app) { + OsmandSettings settings = app.getSettings(); + int requestsCount = settings.SEND_ANONYMOUS_DATA_REQUESTS_COUNT.get(); + long firstInstalledDays = app.getAppInitializer().getFirstInstalledDays(); + boolean requestProcessed = settings.SEND_ANONYMOUS_DATA_REQUEST_PROCESSED.get(); + if (!requestProcessed && firstInstalledDays >= 5 && firstInstalledDays <= 30 && requestsCount < 3) { + if (requestsCount == 0) { + return true; + } else { + int numberOfStarts = app.getAppInitializer().getNumberOfStarts(); + int lastRequestNS = settings.SEND_ANONYMOUS_DATA_LAST_REQUEST_NS.get(); + return numberOfStarts - lastRequestNS > 2; + } + } + return false; + } + + public static void showInstance(@NonNull OsmandApplication app, @NonNull FragmentManager fm) { + try { + if (fm.findFragmentByTag(SendAnalyticsBottomSheetDialogFragment.TAG) == null) { + SendAnalyticsBottomSheetDialogFragment fragment = new SendAnalyticsBottomSheetDialogFragment(); + fragment.show(fm, SendAnalyticsBottomSheetDialogFragment.TAG); + + OsmandSettings settings = app.getSettings(); + int numberOfStarts = app.getAppInitializer().getNumberOfStarts(); + OsmandPreference lastRequestNS = settings.SEND_ANONYMOUS_DATA_LAST_REQUEST_NS; + if (numberOfStarts != lastRequestNS.get()) { + OsmandPreference counter = settings.SEND_ANONYMOUS_DATA_REQUESTS_COUNT; + counter.set(counter.get() + 1); + lastRequestNS.set(numberOfStarts); + } + } + } catch (RuntimeException e) { + LOG.error("showInstance", e); + } + } +}