Refactored analytics, crash, rate us dialogs

This commit is contained in:
crimean 2019-06-10 16:39:04 +03:00
parent ff5900b8e5
commit 51466dbb68
35 changed files with 1049 additions and 128 deletions

View file

@ -901,5 +901,8 @@
android:name=".profiles.EditProfileActivity"
android:label="Application profiles"/>
</application>
<activity android:name=".activities.PrivacyAndSecurityActivity"
android:configChanges="keyboardHidden|orientation" />
</application>
</manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View file

@ -1,5 +1,5 @@
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/solid_ripple_color">
android:color="@color/active_buttons_and_links_pressed_dark">
<item android:id="@android:id/mask">
<shape android:shape="rectangle">
<solid android:color="@color/active_buttons_and_links_dark" />

View file

@ -1,5 +1,5 @@
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/solid_ripple_color">
android:color="@color/active_buttons_and_links_pressed_light">
<item android:id="@android:id/mask">
<shape android:shape="rectangle">
<solid android:color="@color/active_buttons_and_links_light" />

View file

@ -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"/>

View file

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:paddingStart="@dimen/content_padding"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding">
<net.osmand.plus.widgets.TextViewEx
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/content_padding_small"
android:text="Crash"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_medium" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Последний запуск OsmAnd завершился с ошибкой. Помогите нам улучшить OsmAnd. Пожалуйста, отправьте нам сообщение об ошибке."
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_desc_text_size" />
</LinearLayout>
<android.support.v7.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/content_padding_small"
android:src="@drawable/img_crash" />
</LinearLayout>

View file

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:paddingStart="@dimen/content_padding"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding">
<net.osmand.plus.widgets.TextViewEx
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/content_padding_small"
android:text="@string/user_hates_app_get_feedback"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_medium" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/user_hates_app_get_feedback_long"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_desc_text_size" />
</LinearLayout>
<android.support.v7.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/content_padding_small"
android:src="@drawable/img_get_feedback" />
</LinearLayout>

View file

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<android.support.v7.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="26dp"
android:layout_marginBottom="26dp"
android:src="@drawable/img_feedback" />
<net.osmand.plus.widgets.TextViewEx
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_small"
android:text="@string/help_us_make_osmand_better"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/dialog_header_text_size"
osmand:typeface="@string/font_roboto_medium" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:text="@string/make_osmand_better_descr"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_desc_text_size" />
<net.osmand.plus.widgets.TextViewEx
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dialog_content_margin"
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:text="@string/choose_data_to_share"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium" />
</LinearLayout>

View file

@ -0,0 +1,165 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:osmand="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/activity_background_basic"
android:orientation="vertical">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
app:theme="@style/ThemeOverlay.AppCompat.ActionBar">
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
<View
android:layout_width="match_parent"
android:layout_height="4dp" />
<include layout="@layout/card_top_divider" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/card_and_list_background_basic"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding_small"
android:paddingRight="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_small">
<net.osmand.plus.widgets.TextViewEx
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/colleted_data"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_medium" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/collected_data_descr"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_desc_text_size" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/dashboard_divider" />
<LinearLayout
android:id="@+id/downloaded_maps_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:gravity="center"
android:orientation="horizontal"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding_small"
android:paddingRight="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_small">
<TextView
android:id="@+id/downloaded_maps_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:layout_weight="1"
android:ellipsize="end"
android:text="@string/downloaded_maps"
android:textAppearance="@style/TextAppearance.ListItemTitle" />
<android.support.v7.widget.SwitchCompat
android:id="@+id/downloaded_maps_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:background="@null" />
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_small"
android:text="@string/downloaded_maps_collect_descr"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_desc_text_size" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginLeft="@dimen/content_padding"
android:background="?attr/dashboard_divider" />
<LinearLayout
android:id="@+id/visited_screens_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:gravity="center"
android:orientation="horizontal"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding_small"
android:paddingRight="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_small">
<TextView
android:id="@+id/visited_screens_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:layout_weight="1"
android:ellipsize="end"
android:text="@string/visited_screens"
android:textAppearance="@style/TextAppearance.ListItemTitle" />
<android.support.v7.widget.SwitchCompat
android:id="@+id/visited_screens_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:background="@null" />
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_small"
android:text="@string/visited_screens_collect_descr"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_desc_text_size" />
</LinearLayout>
<include layout="@layout/card_bottom_divider" />
</LinearLayout>

View file

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:paddingStart="@dimen/content_padding"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding">
<net.osmand.plus.widgets.TextViewEx
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/content_padding_small"
android:text="@string/do_you_like_osmand"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_medium" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/rate_dialog_descr"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_desc_text_size" />
</LinearLayout>
<android.support.v7.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/content_padding_small"
android:src="@drawable/img_rate_us" />
</LinearLayout>

View file

@ -491,7 +491,6 @@
<color name="settings_divider">#dcdcdc</color>
<color name="profile_button_gray">#EFEFEF</color>
<color name="profile_button_gray_pressed">#ababab</color>
<color name="solid_ripple_color">#505050</color>
<color name="active_buttons_and_links_text_disabled_light">#727272</color>
<color name="active_buttons_and_links_text_disabled_dark">#727272</color>

View file

@ -11,6 +11,23 @@
Thx - Hardy
-->
<string name="rate_dialog_descr">Please give us 30 seconds, share feedback and rate our work on Google Play.</string>
<string name="button_rate">Rate</string>
<string name="shared_string_privacy_policy">Privacy Policy</string>
<string name="help_us_make_osmand_better">Help us make OsmAnd better!</string>
<string name="make_osmand_better_descr">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.</string>
<string name="choose_data_to_share">Choose what type of data you want to share:</string>
<string name="downloaded_maps">Downloaded Maps</string>
<string name="visited_screens">Visited screens</string>
<string name="colleted_data">Colleted Data</string>
<string name="collected_data_descr">List of data you want to share with OsmAnd.</string>
<string name="downloaded_maps_collect_descr">We collect this data to understand the maps of which regions and countries are the most popular.</string>
<string name="visited_screens_collect_descr">We collect this data to understand the most popular features of OsmAnd.</string>
<string name="privacy_and_security_change_descr">By clicking \"Allow\" you agree with our %1$s</string>
<string name="settings_privacy_and_security">Privacy and Security</string>
<string name="settings_privacy_and_security_desc">Choose your data for sharing with us</string>
<string name="shared_string_no_thank_you">No, thank you</string>
<string name="shared_string_allow">Allow</string>
<string name="profile_name_hint">Profile Name</string>
<string name="nav_type_hint">Navigation Type</string>
<string name="app_mode_taxi">Taxi</string>

View file

@ -4,5 +4,6 @@
<Preference android:key="application_profiles" android:title="@string/application_profiles" android:summary="@string/application_profiles_descr"/>
<Preference android:key="routing_settings" android:title="@string/routing_settings_2" android:summary="@string/routing_settings_descr"/>
<Preference android:key="subscription_settings" android:title="@string/osm_live_subscription" android:summary="@string/osm_live_subscription_desc"/>
<Preference android:key="privacy_and_security" android:title="@string/settings_privacy_and_security" android:summary="@string/settings_privacy_and_security_desc"/>
<PreferenceCategory android:key="plugin_settings" android:title="@string/plugin_settings" />
</PreferenceScreen>

View file

@ -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<Integer> 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<Integer> allowedTypes) {
List<AnalyticsData> 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<String, String> additionalData = new LinkedHashMap<String, String>();
@ -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<AnalyticsData> collectRecordedData() {
@ -198,7 +211,7 @@ public class AnalyticsHelper extends SQLiteOpenHelper {
}
private void collectDBData(SQLiteDatabase db, List<AnalyticsData> 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<AnalyticsItem> 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();
}

View file

@ -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));

View file

@ -1060,6 +1060,9 @@ public class OsmandSettings {
public final OsmandPreference<Boolean> DO_NOT_USE_ANIMATIONS = new BooleanPreference("do_not_use_animations", false).makeGlobal().cache();
public final OsmandPreference<Boolean> SEND_ANONYMOUS_MAP_DOWNLOADS_DATA = new BooleanPreference("send_anonymous_map_downloads_data", false).makeGlobal().cache();
public final OsmandPreference<Boolean> SEND_ANONYMOUS_APP_USAGE_DATA = new BooleanPreference("send_anonymous_app_usage_data", false).makeGlobal().cache();
public final OsmandPreference<Boolean> SEND_ANONYMOUS_DATA_REQUEST_PROCESSED = new BooleanPreference("send_anonymous_data_request_processed", false).makeGlobal().cache();
public final OsmandPreference<Integer> SEND_ANONYMOUS_DATA_REQUESTS_COUNT = new IntPreference("send_anonymous_data_requests_count", 0).makeGlobal().cache();
public final OsmandPreference<Integer> SEND_ANONYMOUS_DATA_LAST_REQUEST_NS = new IntPreference("send_anonymous_data_last_request_ns", -1).makeGlobal().cache();
public final OsmandPreference<Boolean> MAP_EMPTY_STATE_ALLOWED = new BooleanPreference("map_empty_state_allowed", true).makeGlobal().cache();

View file

@ -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)) {

View file

@ -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;
}
}

View file

@ -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);
}

View file

@ -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;

View file

@ -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,

View file

@ -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);

View file

@ -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);
}
}
}

View file

@ -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);
}
}

View file

@ -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;

View file

@ -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);
}
}
}

View file

@ -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);
}
}
}

View file

@ -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);
}
}

View file

@ -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;
}

View file

@ -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);
}
}
}

View file

@ -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<Integer> lastRequestNS = settings.SEND_ANONYMOUS_DATA_LAST_REQUEST_NS;
if (numberOfStarts != lastRequestNS.get()) {
OsmandPreference<Integer> counter = settings.SEND_ANONYMOUS_DATA_REQUESTS_COUNT;
counter.set(counter.get() + 1);
lastRequestNS.set(numberOfStarts);
}
}
} catch (RuntimeException e) {
LOG.error("showInstance", e);
}
}
}