commit
1d08fc6155
84 changed files with 4875 additions and 5277 deletions
|
@ -247,6 +247,7 @@
|
|||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="content"/>
|
||||
<data android:scheme="file"/>
|
||||
<data android:host="*"/>
|
||||
<data android:pathPattern=".*\\.obf" />
|
||||
|
@ -262,6 +263,7 @@
|
|||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="content"/>
|
||||
<data android:scheme="file"/>
|
||||
<data android:host="*"/>
|
||||
<data android:mimeType="*/*"/>
|
||||
|
@ -466,6 +468,13 @@
|
|||
<data android:mimeType="text/plain" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="osmand-oauth" />
|
||||
</intent-filter>
|
||||
|
||||
</activity>
|
||||
|
||||
<receiver android:name="net.osmand.plus.audionotes.MediaRemoteControlReceiver">
|
||||
|
@ -478,28 +487,11 @@
|
|||
<activity android:name="net.osmand.plus.activities.SettingsActivity" android:label="@string/shared_string_settings" android:configChanges="keyboardHidden|orientation" />
|
||||
<activity android:name="net.osmand.plus.activities.SettingsGeneralActivity" android:configChanges="keyboardHidden|orientation" />
|
||||
<activity android:name="net.osmand.plus.activities.SettingsNavigationActivity" android:configChanges="keyboardHidden|orientation" />
|
||||
<activity android:name="net.osmand.plus.monitoring.SettingsMonitoringActivity" android:configChanges="keyboardHidden|orientation" />
|
||||
|
||||
<activity android:name="net.osmand.plus.osmedit.SettingsOsmEditingActivity"
|
||||
android:launchMode="singleInstance"
|
||||
android:configChanges="keyboardHidden|orientation">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="osmand-oauth" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="net.osmand.plus.development.SettingsDevelopmentActivity" android:configChanges="keyboardHidden|orientation" />
|
||||
<activity android:name="net.osmand.plus.audionotes.SettingsAudioVideoActivity" android:configChanges="keyboardHidden|orientation" />
|
||||
<activity android:name="net.osmand.access.SettingsAccessibilityActivity" android:configChanges="keyboardHidden|orientation" />
|
||||
|
||||
<activity android:name="net.osmand.plus.activities.search.SearchActivity" android:label="@string/search_activity" />
|
||||
<activity android:name="net.osmand.plus.activities.FavoritesListActivity" android:label="@string/favourites_list_activity" />
|
||||
<activity android:name=".myplaces.FavoritesActivity" android:windowSoftInputMode="adjustPan" />
|
||||
<activity android:name="net.osmand.plus.activities.TrackActivity"/>
|
||||
<activity android:name="net.osmand.plus.activities.PluginsActivity" />
|
||||
<activity android:name="net.osmand.plus.activities.PluginActivity" />
|
||||
<activity android:name="net.osmand.plus.activities.ContributionVersionActivity" android:configChanges="keyboardHidden|orientation" android:label="@string/contribution_activity" />
|
||||
|
||||
|
||||
|
|
|
@ -1,17 +1,29 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:osmand="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/bg_color"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<include layout="@layout/global_preference_toolbar" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/bg_color"
|
||||
android:orientation="vertical"
|
||||
tools:context=".activities.PluginActivity">
|
||||
android:orientation="vertical" >
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
|
@ -22,10 +34,10 @@
|
|||
android:layout_width="360dp"
|
||||
android:layout_height="144dp"
|
||||
android:layout_gravity="center"
|
||||
android:scaleType="center"
|
||||
android:background="@color/osmand_orange"
|
||||
osmand:srcCompat="@drawable/ic_extension_dark"
|
||||
android:visibility="gone"/>
|
||||
android:scaleType="center"
|
||||
android:visibility="gone"
|
||||
osmand:srcCompat="@drawable/ic_extension_dark" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/plugin_image"
|
||||
|
@ -44,39 +56,39 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="66dp"
|
||||
android:background="?attr/expandable_list_item_background"
|
||||
android:paddingStart="@dimen/content_padding"
|
||||
android:paddingLeft="@dimen/content_padding"
|
||||
android:paddingRight="@dimen/content_padding"
|
||||
android:paddingEnd="@dimen/content_padding"
|
||||
android:paddingStart="@dimen/content_padding">
|
||||
android:paddingRight="@dimen/content_padding">
|
||||
|
||||
<net.osmand.plus.widgets.ButtonEx
|
||||
android:id="@+id/plugin_settings"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical|start"
|
||||
android:layout_marginBottom="9dp"
|
||||
android:layout_marginTop="9dp"
|
||||
android:layout_marginBottom="9dp"
|
||||
android:background="?attr/expandable_list_item_background"
|
||||
android:drawablePadding="10dp"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:maxLines="1"
|
||||
android:paddingStart="0dp"
|
||||
android:paddingLeft="0dp"
|
||||
android:paddingEnd="@dimen/content_padding"
|
||||
android:paddingRight="@dimen/content_padding"
|
||||
android:text="@string/shared_string_settings"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="@dimen/default_sub_text_size"
|
||||
osmand:textAllCapsCompat="true"
|
||||
osmand:typeface="@string/font_roboto_medium"
|
||||
android:paddingEnd="@dimen/content_padding"
|
||||
android:paddingStart="0dp" />
|
||||
osmand:typeface="@string/font_roboto_medium" />
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="139dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:layout_marginBottom="@dimen/content_padding"
|
||||
android:layout_marginTop="@dimen/content_padding">
|
||||
android:layout_marginTop="@dimen/content_padding"
|
||||
android:layout_marginBottom="@dimen/content_padding">
|
||||
|
||||
<net.osmand.plus.widgets.SwitchEx
|
||||
android:id="@+id/plugin_enable_disable"
|
||||
|
@ -86,18 +98,18 @@
|
|||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:maxLines="1"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingStart="9.5dp"
|
||||
android:paddingLeft="9.5dp"
|
||||
android:paddingRight="9.5dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="9.5dp"
|
||||
android:paddingRight="9.5dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:textColor="?attr/switch_ex_text_color"
|
||||
android:textOff="@string/shared_string_off"
|
||||
android:textOn="@string/shared_string_on"
|
||||
android:textSize="@dimen/default_sub_text_size"
|
||||
osmand:textAllCapsCompat="true"
|
||||
osmand:typeface="@string/font_roboto_medium"
|
||||
android:paddingStart="9.5dp"
|
||||
android:paddingEnd="9.5dp" />
|
||||
osmand:typeface="@string/font_roboto_medium" />
|
||||
|
||||
<net.osmand.plus.widgets.ButtonEx
|
||||
android:id="@+id/plugin_get"
|
||||
|
@ -107,19 +119,21 @@
|
|||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:maxLines="1"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingStart="9.5dp"
|
||||
android:paddingLeft="9.5dp"
|
||||
android:paddingRight="9.5dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="9.5dp"
|
||||
android:paddingRight="9.5dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:text="@string/get_plugin"
|
||||
android:textColor="@color/color_white"
|
||||
android:textSize="@dimen/default_sub_text_size"
|
||||
android:visibility="gone"
|
||||
osmand:textAllCapsCompat="true"
|
||||
osmand:typeface="@string/font_roboto_medium"
|
||||
android:paddingStart="9.5dp"
|
||||
android:paddingEnd="9.5dp" />
|
||||
osmand:typeface="@string/font_roboto_medium" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
|
@ -129,58 +143,62 @@
|
|||
android:background="?attr/plugin_details_install_header_bg"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="@dimen/content_padding"
|
||||
android:paddingLeft="@dimen/content_padding"
|
||||
android:paddingEnd="@dimen/content_padding"
|
||||
android:paddingRight="@dimen/content_padding"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
android:paddingEnd="@dimen/content_padding"
|
||||
android:paddingStart="@dimen/content_padding">
|
||||
tools:visibility="visible">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/ic_world_globe"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
tools:background="@drawable/ic_world_globe_dark"/>
|
||||
tools:background="@drawable/ic_world_globe_dark" />
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="@dimen/content_padding"
|
||||
android:paddingLeft="@dimen/content_padding"
|
||||
android:paddingEnd="@dimen/content_padding"
|
||||
android:paddingRight="@dimen/content_padding"
|
||||
android:text="@string/plugin_install_needs_network"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
osmand:typeface="@string/font_roboto_regular"
|
||||
android:paddingStart="@dimen/content_padding"
|
||||
android:paddingEnd="@dimen/content_padding" />
|
||||
osmand:typeface="@string/font_roboto_regular" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/content_padding"
|
||||
android:layout_marginLeft="@dimen/content_padding"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
android:layout_marginTop="@dimen/content_padding"
|
||||
android:layout_marginEnd="@dimen/content_padding"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
android:text="@string/shared_string_description"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="@dimen/default_desc_text_size"
|
||||
osmand:textAllCapsCompat="true"
|
||||
osmand:typeface="@string/font_roboto_medium"
|
||||
android:layout_marginStart="@dimen/content_padding"
|
||||
android:layout_marginEnd="@dimen/content_padding" />
|
||||
osmand:typeface="@string/font_roboto_medium" />
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/plugin_description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/content_padding"
|
||||
android:layout_marginLeft="@dimen/content_padding"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
android:layout_marginTop="14dp"
|
||||
android:layout_marginEnd="@dimen/content_padding"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
osmand:typeface="@string/font_roboto_regular"
|
||||
tools:text="@string/lorem_ipsum"
|
||||
android:layout_marginEnd="@dimen/content_padding"
|
||||
android:layout_marginStart="@dimen/content_padding" />
|
||||
tools:text="@string/lorem_ipsum" />
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
</LinearLayout>
|
|
@ -1,14 +1,24 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/bg_color"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<include layout="@layout/global_preference_toolbar" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<ListView
|
||||
android:id="@android:id/list"
|
||||
android:id="@+id/plugins_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:listitem="@layout/plugins_list_item"/>
|
||||
android:dividerHeight="1dp"
|
||||
android:drawSelectorOnTop="true" />
|
||||
|
||||
</LinearLayout>
|
|
@ -52,6 +52,7 @@
|
|||
android:ellipsize="end"
|
||||
android:lines="2"
|
||||
android:maxLines="2"
|
||||
android:scrollbars="none"
|
||||
android:text="@string/lorem_ipsum"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="@dimen/default_desc_text_size"
|
||||
|
|
|
@ -64,6 +64,13 @@
|
|||
tools:text="Some description" />
|
||||
</LinearLayout>
|
||||
|
||||
<include
|
||||
layout="@layout/profile_button_small"
|
||||
android:layout_width="@dimen/list_header_height"
|
||||
android:layout_height="@dimen/list_header_height"
|
||||
android:layout_marginLeft="@dimen/content_padding_half"
|
||||
android:layout_marginRight="@dimen/content_padding_half" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.appcompat.widget.Toolbar>
|
|
@ -8,9 +8,9 @@ import androidx.annotation.NonNull;
|
|||
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.OsmandPlugin;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.settings.fragments.BaseSettingsFragment;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.plus.settings.fragments.BaseSettingsFragment.SettingsScreenType;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
@ -66,13 +66,8 @@ public class AccessibilityPlugin extends OsmandPlugin {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Activity> getSettingsActivity() {
|
||||
return SettingsAccessibilityActivity.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends BaseSettingsFragment> getSettingsFragment() {
|
||||
return AccessibilitySettingsFragment.class;
|
||||
public SettingsScreenType getSettingsScreenType() {
|
||||
return SettingsScreenType.ACCESSIBILITY_SETTINGS;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -4,6 +4,8 @@ import android.content.Context;
|
|||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener;
|
||||
import android.widget.ImageView;
|
||||
|
@ -13,21 +15,24 @@ import androidx.preference.Preference;
|
|||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.OsmandPlugin;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.access.AccessibilityMode;
|
||||
import net.osmand.plus.access.RelativeDirectionStyle;
|
||||
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||
import net.osmand.plus.monitoring.OsmandMonitoringPlugin;
|
||||
import net.osmand.plus.profiles.SelectCopyAppModeBottomSheet;
|
||||
import net.osmand.plus.profiles.SelectCopyAppModeBottomSheet.CopyAppModePrefsListener;
|
||||
import net.osmand.plus.settings.fragments.BaseSettingsFragment;
|
||||
import net.osmand.plus.settings.fragments.OnPreferenceChanged;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.settings.bottomsheets.ResetProfilePrefsBottomSheet;
|
||||
import net.osmand.plus.settings.bottomsheets.ResetProfilePrefsBottomSheet.ResetAppModePrefsListener;
|
||||
import net.osmand.plus.settings.fragments.BaseSettingsFragment;
|
||||
import net.osmand.plus.settings.fragments.OnPreferenceChanged;
|
||||
import net.osmand.plus.settings.preferences.ListPreferenceEx;
|
||||
import net.osmand.plus.settings.preferences.SwitchPreferenceEx;
|
||||
|
||||
import static net.osmand.plus.activities.PluginInfoFragment.PLUGIN_INFO;
|
||||
|
||||
public class AccessibilitySettingsFragment extends BaseSettingsFragment implements OnPreferenceChanged, CopyAppModePrefsListener, ResetAppModePrefsListener {
|
||||
|
||||
private static final String ACCESSIBILITY_OPTIONS = "accessibility_options";
|
||||
|
@ -36,6 +41,8 @@ public class AccessibilitySettingsFragment extends BaseSettingsFragment implemen
|
|||
|
||||
private AccessibilityStateChangeListener accessibilityListener;
|
||||
|
||||
boolean showSwitchProfile = false;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
@ -47,6 +54,28 @@ public class AccessibilitySettingsFragment extends BaseSettingsFragment implemen
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
Bundle args = getArguments();
|
||||
if (args != null) {
|
||||
showSwitchProfile = args.getBoolean(PLUGIN_INFO, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createToolbar(LayoutInflater inflater, View view) {
|
||||
super.createToolbar(inflater, view);
|
||||
|
||||
View switchProfile = view.findViewById(R.id.profile_button);
|
||||
if (switchProfile != null) {
|
||||
AndroidUiHelper.updateVisibility(switchProfile, showSwitchProfile);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle buildArguments() {
|
||||
Bundle args = super.buildArguments();
|
||||
args.putBoolean(PLUGIN_INFO, showSwitchProfile);
|
||||
return args;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,128 +0,0 @@
|
|||
package net.osmand.access;
|
||||
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.preference.ListPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.Preference.OnPreferenceChangeListener;
|
||||
import android.preference.PreferenceCategory;
|
||||
import android.preference.PreferenceGroup;
|
||||
import android.preference.PreferenceScreen;
|
||||
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.access.AccessibilityMode;
|
||||
import net.osmand.plus.access.RelativeDirectionStyle;
|
||||
import net.osmand.plus.activities.SettingsBaseActivity;
|
||||
|
||||
public class SettingsAccessibilityActivity extends SettingsBaseActivity {
|
||||
|
||||
private ListPreference accessibilityModePreference;
|
||||
private ListPreference directionStylePreference;
|
||||
private ListPreference autoannouncePeriodPreference;
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
((OsmandApplication) getApplication()).applyTheme(this);
|
||||
super.onCreate(savedInstanceState);
|
||||
getToolbar().setTitle(R.string.shared_string_accessibility);
|
||||
PreferenceScreen grp = getPreferenceScreen();
|
||||
|
||||
String[] entries = new String[AccessibilityMode.values().length];
|
||||
for (int i = 0; i < entries.length; i++) {
|
||||
entries[i] = AccessibilityMode.values()[i].toHumanString(getMyApplication());
|
||||
}
|
||||
accessibilityModePreference = createListPreference(settings.ACCESSIBILITY_MODE, entries, AccessibilityMode.values(),
|
||||
R.string.accessibility_mode, R.string.accessibility_mode_descr);
|
||||
accessibilityModePreference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
|
||||
private final OnPreferenceChangeListener committer = accessibilityModePreference.getOnPreferenceChangeListener();
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
if (committer != null)
|
||||
committer.onPreferenceChange(preference, newValue);
|
||||
updateAllSettings();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
addSpeechRateSetting(grp);
|
||||
|
||||
grp.addPreference(accessibilityModePreference);
|
||||
PreferenceCategory cat = new PreferenceCategory(this);
|
||||
cat.setKey("accessibility_options");
|
||||
cat.setTitle(R.string.accessibility_options);
|
||||
cat.setEnabled(getMyApplication().accessibilityEnabled());
|
||||
grp.addPreference(cat);
|
||||
|
||||
entries = new String[RelativeDirectionStyle.values().length];
|
||||
for (int i = 0; i < entries.length; i++) {
|
||||
entries[i] = RelativeDirectionStyle.values()[i].toHumanString(getMyApplication());
|
||||
}
|
||||
directionStylePreference = createListPreference(settings.DIRECTION_STYLE, entries, RelativeDirectionStyle.values(),
|
||||
R.string.settings_direction_style, R.string.settings_direction_style_descr);
|
||||
directionStylePreference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
|
||||
private final OnPreferenceChangeListener committer = directionStylePreference.getOnPreferenceChangeListener();
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
if (committer != null)
|
||||
committer.onPreferenceChange(preference, newValue);
|
||||
updateAllSettings();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
cat.addPreference(directionStylePreference);
|
||||
|
||||
cat.addPreference(createCheckBoxPreference(settings.ACCESSIBILITY_SMART_AUTOANNOUNCE, R.string.access_smart_autoannounce,
|
||||
R.string.access_smart_autoannounce_descr));
|
||||
|
||||
final int[] seconds = new int[] {5, 10, 15, 20, 30, 45, 60, 90};
|
||||
final int[] minutes = new int[] {2, 3, 5};
|
||||
autoannouncePeriodPreference = createTimeListPreference(settings.ACCESSIBILITY_AUTOANNOUNCE_PERIOD, seconds, minutes, 1000,
|
||||
R.string.access_autoannounce_period, R.string.access_autoannounce_period_descr);
|
||||
autoannouncePeriodPreference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
|
||||
private final OnPreferenceChangeListener committer = autoannouncePeriodPreference.getOnPreferenceChangeListener();
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
if (committer != null)
|
||||
committer.onPreferenceChange(preference, newValue);
|
||||
updateAllSettings();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
cat.addPreference(autoannouncePeriodPreference);
|
||||
cat.addPreference(createCheckBoxPreference(settings.DIRECTION_AUDIO_FEEDBACK, R.string.access_direction_audio_feedback,
|
||||
R.string.access_direction_audio_feedback_descr));
|
||||
cat.addPreference(createCheckBoxPreference(settings.DIRECTION_HAPTIC_FEEDBACK, R.string.access_direction_haptic_feedback,
|
||||
R.string.access_direction_haptic_feedback_descr));
|
||||
|
||||
}
|
||||
|
||||
|
||||
protected void addSpeechRateSetting(PreferenceGroup grp) {
|
||||
Float[] sprValues = new Float[] {0.5f, 0.75f, 1f, 1.25f, 1.5f, 2f} ;
|
||||
String[] sprNames = new String[sprValues.length];
|
||||
for(int i = 0; i < sprNames.length; i++) {
|
||||
sprNames[i] = (int)(sprValues[i] * 100) + " %";
|
||||
}
|
||||
grp.addPreference(createListPreference(settings.SPEECH_RATE, sprNames, sprValues, R.string.speech_rate, R.string.speech_rate_descr));
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void updateAllSettings() {
|
||||
super.updateAllSettings();
|
||||
PreferenceCategory accessibilityOptions = ((PreferenceCategory)(getPreferenceScreen().findPreference("accessibility_options")));
|
||||
if (accessibilityOptions != null)
|
||||
accessibilityOptions.setEnabled(getMyApplication().accessibilityEnabled());
|
||||
if(accessibilityModePreference != null) {
|
||||
accessibilityModePreference.setSummary(getString(R.string.accessibility_mode_descr) + " [" + settings.ACCESSIBILITY_MODE.get().toHumanString(getMyApplication()) + "]");
|
||||
}
|
||||
if(directionStylePreference != null) {
|
||||
directionStylePreference.setSummary(getString(R.string.settings_direction_style_descr) + " [" + settings.DIRECTION_STYLE.get().toHumanString(getMyApplication()) + "]");
|
||||
}
|
||||
if(autoannouncePeriodPreference != null) {
|
||||
autoannouncePeriodPreference.setSummary(getString(R.string.access_autoannounce_period_descr) + " [" + autoannouncePeriodPreference.getEntry() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -81,8 +81,10 @@ import net.osmand.plus.routing.VoiceRouter;
|
|||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.settings.backend.OsmAndAppCustomization;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper;
|
||||
import net.osmand.plus.settings.backend.backup.ProfileSettingsItem;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsHelper;
|
||||
import net.osmand.plus.settings.backend.ExportSettingsType;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsItem;
|
||||
import net.osmand.plus.views.OsmandMapLayer;
|
||||
import net.osmand.plus.views.OsmandMapTileView;
|
||||
import net.osmand.plus.views.layers.AidlMapLayer;
|
||||
|
@ -138,7 +140,7 @@ import static net.osmand.plus.helpers.ExternalApiHelper.PARAM_NT_DIRECTION_NAME;
|
|||
import static net.osmand.plus.helpers.ExternalApiHelper.PARAM_NT_DIRECTION_TURN;
|
||||
import static net.osmand.plus.helpers.ExternalApiHelper.PARAM_NT_DISTANCE;
|
||||
import static net.osmand.plus.helpers.ExternalApiHelper.PARAM_NT_IMMINENT;
|
||||
import static net.osmand.plus.settings.backend.SettingsHelper.REPLACE_KEY;
|
||||
import static net.osmand.plus.settings.backend.backup.SettingsHelper.REPLACE_KEY;
|
||||
|
||||
public class OsmandAidlApi {
|
||||
|
||||
|
@ -2305,8 +2307,8 @@ public class OsmandAidlApi {
|
|||
for (String key : settingsTypesKeys) {
|
||||
settingsTypes.add(ExportSettingsType.valueOf(key));
|
||||
}
|
||||
List<SettingsHelper.SettingsItem> settingsItems = new ArrayList<>();
|
||||
settingsItems.add(new SettingsHelper.ProfileSettingsItem(app, appMode));
|
||||
List<SettingsItem> settingsItems = new ArrayList<>();
|
||||
settingsItems.add(new ProfileSettingsItem(app, appMode));
|
||||
File exportDir = app.getSettings().getExternalStorageDirectory();
|
||||
String fileName = appMode.toHumanString();
|
||||
SettingsHelper settingsHelper = app.getSettingsHelper();
|
||||
|
|
|
@ -55,7 +55,7 @@ import net.osmand.plus.routing.TransportRoutingHelper;
|
|||
import net.osmand.plus.search.QuickSearchHelper;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsHelper;
|
||||
import net.osmand.plus.views.corenative.NativeCoreContext;
|
||||
import net.osmand.plus.voice.CommandPlayer;
|
||||
import net.osmand.plus.voice.CommandPlayerException;
|
||||
|
|
|
@ -18,15 +18,15 @@ import net.osmand.data.LatLon;
|
|||
import net.osmand.map.ITileSource;
|
||||
import net.osmand.map.WorldRegion;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.AvoidRoadsSettingsItem;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.MapSourcesSettingsItem;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.PluginSettingsItem;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.PoiUiFiltersSettingsItem;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.ProfileSettingsItem;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.QuickActionsSettingsItem;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.SettingsCollectListener;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.SettingsItem;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsHelper;
|
||||
import net.osmand.plus.settings.backend.backup.AvoidRoadsSettingsItem;
|
||||
import net.osmand.plus.settings.backend.backup.MapSourcesSettingsItem;
|
||||
import net.osmand.plus.settings.backend.backup.PluginSettingsItem;
|
||||
import net.osmand.plus.settings.backend.backup.PoiUiFiltersSettingsItem;
|
||||
import net.osmand.plus.settings.backend.backup.ProfileSettingsItem;
|
||||
import net.osmand.plus.settings.backend.backup.QuickActionsSettingsItem;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsHelper.SettingsCollectListener;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsItem;
|
||||
import net.osmand.plus.download.DownloadActivityType;
|
||||
import net.osmand.plus.download.DownloadIndexesThread;
|
||||
import net.osmand.plus.download.DownloadResources;
|
||||
|
|
|
@ -75,7 +75,7 @@ import net.osmand.plus.search.QuickSearchHelper;
|
|||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.settings.backend.OsmAndAppCustomization;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsHelper;
|
||||
import net.osmand.plus.voice.CommandPlayer;
|
||||
import net.osmand.plus.wikivoyage.data.TravelDbHelper;
|
||||
import net.osmand.router.GeneralRouter;
|
||||
|
|
|
@ -48,7 +48,7 @@ import net.osmand.plus.search.QuickSearchDialogFragment;
|
|||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.settings.backend.CommonPreference;
|
||||
import net.osmand.plus.settings.backend.OsmandPreference;
|
||||
import net.osmand.plus.settings.fragments.BaseSettingsFragment;
|
||||
import net.osmand.plus.settings.fragments.BaseSettingsFragment.SettingsScreenType;
|
||||
import net.osmand.plus.skimapsplugin.SkiMapsPlugin;
|
||||
import net.osmand.plus.srtmplugin.SRTMPlugin;
|
||||
import net.osmand.plus.views.OsmandMapTileView;
|
||||
|
@ -111,11 +111,7 @@ public abstract class OsmandPlugin {
|
|||
return app.getUIUtilities().getIcon(getLogoResourceId());
|
||||
}
|
||||
|
||||
public Class<? extends Activity> getSettingsActivity() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Class<? extends BaseSettingsFragment> getSettingsFragment() {
|
||||
public SettingsScreenType getSettingsScreenType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -118,6 +118,7 @@ import net.osmand.plus.measurementtool.GpxData;
|
|||
import net.osmand.plus.measurementtool.MeasurementEditingContext;
|
||||
import net.osmand.plus.measurementtool.MeasurementToolFragment;
|
||||
import net.osmand.plus.measurementtool.SnapTrackWarningFragment;
|
||||
import net.osmand.plus.osmedit.OsmEditingFragment;
|
||||
import net.osmand.plus.render.RendererRegistry;
|
||||
import net.osmand.plus.resources.ResourceManager;
|
||||
import net.osmand.plus.routepreparationmenu.ChooseRouteFragment;
|
||||
|
@ -2216,6 +2217,10 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
|
|||
return getFragment(GpxApproximationFragment.TAG);
|
||||
}
|
||||
|
||||
public OsmEditingFragment getOsmEditingFragment() {
|
||||
return getFragment(SettingsScreenType.OPEN_STREET_MAP_EDITING.fragmentName);
|
||||
}
|
||||
|
||||
public SnapTrackWarningFragment getSnapTrackWarningBottomSheet() {
|
||||
return getFragment(SnapTrackWarningFragment.TAG);
|
||||
}
|
||||
|
|
|
@ -974,10 +974,7 @@ public class MapActivityActions implements DialogProvider {
|
|||
@Override
|
||||
public boolean onContextMenuClick(ArrayAdapter<ContextMenuItem> adapter, int itemId, int pos, boolean isChecked, int[] viewCoordinates) {
|
||||
app.logEvent("drawer_plugins_open");
|
||||
Intent newIntent = new Intent(mapActivity, mapActivity.getMyApplication().getAppCustomization()
|
||||
.getPluginsActivity());
|
||||
newIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
|
||||
mapActivity.startActivity(newIntent);
|
||||
PluginsFragment.showInstance(mapActivity.getSupportFragmentManager());
|
||||
return true;
|
||||
}
|
||||
}).createItem());
|
||||
|
|
|
@ -1,241 +0,0 @@
|
|||
package net.osmand.plus.activities;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.util.Log;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.content.res.AppCompatResources;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.OsmandPlugin;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.chooseplan.ChoosePlanDialogFragment;
|
||||
import net.osmand.plus.dialogs.PluginInstalledBottomSheetDialog;
|
||||
import net.osmand.plus.download.DownloadIndexesThread;
|
||||
import net.osmand.plus.srtmplugin.SRTMPlugin;
|
||||
|
||||
public class PluginActivity extends OsmandActionBarActivity implements DownloadIndexesThread.DownloadEvents, PluginInstalledBottomSheetDialog.PluginStateListener {
|
||||
private static final String TAG = "PluginActivity";
|
||||
public static final String EXTRA_PLUGIN_ID = "plugin_id";
|
||||
|
||||
private OsmandPlugin plugin;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
((OsmandApplication) getApplication()).applyTheme(this);
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Intent intent = getIntent();
|
||||
if (intent == null || !intent.hasExtra(EXTRA_PLUGIN_ID)) {
|
||||
Log.e(TAG, "Required extra '" + EXTRA_PLUGIN_ID + "' is missing");
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
String pluginId = intent.getStringExtra(EXTRA_PLUGIN_ID);
|
||||
if (pluginId == null) {
|
||||
Log.e(TAG, "Extra '" + EXTRA_PLUGIN_ID + "' is null");
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
for (OsmandPlugin plugin : OsmandPlugin.getAvailablePlugins()) {
|
||||
if (!plugin.getId().equals(pluginId))
|
||||
continue;
|
||||
|
||||
this.plugin = plugin;
|
||||
break;
|
||||
}
|
||||
if (plugin == null) {
|
||||
Log.e(TAG, "Plugin '" + EXTRA_PLUGIN_ID + "' not found");
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
setContentView(R.layout.plugin);
|
||||
//noinspection ConstantConditions
|
||||
getSupportActionBar().setTitle(plugin.getName());
|
||||
Drawable pluginImage = plugin.getAssetResourceImage();
|
||||
if (pluginImage != null) {
|
||||
ImageView img = (ImageView) findViewById(R.id.plugin_image);
|
||||
img.setImageDrawable(pluginImage);
|
||||
} else {
|
||||
findViewById(R.id.plugin_image_placeholder).setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
TextView descriptionView = (TextView) findViewById(R.id.plugin_description);
|
||||
descriptionView.setText(plugin.getDescription());
|
||||
|
||||
boolean light = getMyApplication().getSettings().isLightContent();
|
||||
int linkTextColor = ContextCompat.getColor(this,
|
||||
light ? R.color.ctx_menu_bottom_view_url_color_light : R.color.ctx_menu_bottom_view_url_color_dark);
|
||||
|
||||
descriptionView.setLinkTextColor(linkTextColor);
|
||||
descriptionView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
AndroidUtils.removeLinkUnderline(descriptionView);
|
||||
|
||||
Button settingsButton = (Button) findViewById(R.id.plugin_settings);
|
||||
settingsButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
startActivity(new Intent(PluginActivity.this, plugin.getSettingsActivity()));
|
||||
}
|
||||
});
|
||||
|
||||
CompoundButton enableDisableButton = (CompoundButton)findViewById(
|
||||
R.id.plugin_enable_disable);
|
||||
enableDisableButton.setOnCheckedChangeListener(
|
||||
new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
if (plugin.isActive() == isChecked) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean ok = OsmandPlugin.enablePlugin(PluginActivity.this, (OsmandApplication)getApplication(),
|
||||
plugin, isChecked);
|
||||
if (!ok) {
|
||||
return;
|
||||
}
|
||||
updateState();
|
||||
}
|
||||
});
|
||||
Button getButton = (Button)findViewById(R.id.plugin_get);
|
||||
getButton.setText(plugin.isPaid() ? R.string.get_plugin : R.string.shared_string_install);
|
||||
getButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
try {
|
||||
if (plugin instanceof SRTMPlugin) {
|
||||
FragmentManager fragmentManager = getSupportFragmentManager();
|
||||
if (fragmentManager != null) {
|
||||
ChoosePlanDialogFragment.showHillshadeSrtmPluginInstance(fragmentManager);
|
||||
}
|
||||
} else {
|
||||
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(plugin.getInstallURL())));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
//ignored
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
updateState();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
OsmandApplication app = getMyApplication();
|
||||
OsmandPlugin.checkInstalledMarketPlugins(app, this);
|
||||
app.getDownloadThread().setUiActivity(this);
|
||||
updateState();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
getMyApplication().getDownloadThread().resetUiActivity(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int itemId = item.getItemId();
|
||||
switch (itemId) {
|
||||
case android.R.id.home:
|
||||
finish();
|
||||
return true;
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
private void updateState() {
|
||||
CompoundButton enableDisableButton = (CompoundButton)findViewById(
|
||||
R.id.plugin_enable_disable);
|
||||
Button getButton = (Button)findViewById(R.id.plugin_get);
|
||||
Button settingsButton = (Button)findViewById(R.id.plugin_settings);
|
||||
settingsButton.setCompoundDrawablesWithIntrinsicBounds(
|
||||
getMyApplication().getUIUtilities().getThemedIcon(R.drawable.ic_action_settings),
|
||||
null, null, null);
|
||||
View installHeader = findViewById(R.id.plugin_install_header);
|
||||
|
||||
if (plugin.needsInstallation()) {
|
||||
getButton.setVisibility(View.VISIBLE);
|
||||
enableDisableButton.setVisibility(View.GONE);
|
||||
settingsButton.setVisibility(View.GONE);
|
||||
installHeader.setVisibility(View.VISIBLE);
|
||||
View worldGlobeIcon = installHeader.findViewById(R.id.ic_world_globe);
|
||||
Drawable worldGlobeDrawable = getMyApplication().getUIUtilities().getThemedIcon(
|
||||
R.drawable.ic_world_globe_dark);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
worldGlobeIcon.setBackground(worldGlobeDrawable);
|
||||
} else {
|
||||
//noinspection deprecation
|
||||
worldGlobeIcon.setBackgroundDrawable(worldGlobeDrawable);
|
||||
}
|
||||
} else {
|
||||
getButton.setVisibility(View.GONE);
|
||||
enableDisableButton.setVisibility(View.VISIBLE);
|
||||
enableDisableButton.setChecked(plugin.isActive());
|
||||
|
||||
final Class<? extends Activity> settingsActivity = plugin.getSettingsActivity();
|
||||
if (settingsActivity == null || !plugin.isActive()) {
|
||||
settingsButton.setVisibility(View.GONE);
|
||||
} else {
|
||||
settingsButton.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
installHeader.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
// DownloadEvents
|
||||
@Override
|
||||
public void newDownloadIndexes() {
|
||||
for (Fragment fragment : getSupportFragmentManager().getFragments()) {
|
||||
if (fragment instanceof DownloadIndexesThread.DownloadEvents && fragment.isAdded()) {
|
||||
((DownloadIndexesThread.DownloadEvents) fragment).newDownloadIndexes();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void downloadInProgress() {
|
||||
for (Fragment fragment : getSupportFragmentManager().getFragments()) {
|
||||
if (fragment instanceof DownloadIndexesThread.DownloadEvents && fragment.isAdded()) {
|
||||
((DownloadIndexesThread.DownloadEvents) fragment).downloadInProgress();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void downloadHasFinished() {
|
||||
for (Fragment fragment : getSupportFragmentManager().getFragments()) {
|
||||
if (fragment instanceof DownloadIndexesThread.DownloadEvents && fragment.isAdded()) {
|
||||
((DownloadIndexesThread.DownloadEvents) fragment).downloadHasFinished();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPluginStateChanged(OsmandPlugin plugin) {
|
||||
updateState();
|
||||
}
|
||||
}
|
258
OsmAnd/src/net/osmand/plus/activities/PluginInfoFragment.java
Normal file
258
OsmAnd/src/net/osmand/plus/activities/PluginInfoFragment.java
Normal file
|
@ -0,0 +1,258 @@
|
|||
package net.osmand.plus.activities;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.activity.OnBackPressedCallback;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.OsmandPlugin;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.base.BaseOsmAndFragment;
|
||||
import net.osmand.plus.chooseplan.ChoosePlanDialogFragment;
|
||||
import net.osmand.plus.dialogs.PluginInstalledBottomSheetDialog.PluginStateListener;
|
||||
import net.osmand.plus.settings.fragments.BaseSettingsFragment;
|
||||
import net.osmand.plus.settings.fragments.BaseSettingsFragment.SettingsScreenType;
|
||||
import net.osmand.plus.srtmplugin.SRTMPlugin;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
public class PluginInfoFragment extends BaseOsmAndFragment implements PluginStateListener {
|
||||
|
||||
private static final Log log = PlatformUtil.getLog(PluginInfoFragment.class);
|
||||
|
||||
private static final String TAG = PluginInfoFragment.class.getName();
|
||||
|
||||
public static final String EXTRA_PLUGIN_ID = "plugin_id";
|
||||
public static final String PLUGIN_INFO = "plugin_info";
|
||||
|
||||
private OsmandPlugin plugin;
|
||||
private OsmandApplication app;
|
||||
|
||||
private View mainView;
|
||||
private boolean nightMode;
|
||||
|
||||
@Override
|
||||
public int getStatusBarColorId() {
|
||||
return nightMode ? R.color.status_bar_color_dark : R.color.status_bar_color_light;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
FragmentActivity activity = requireMyActivity();
|
||||
activity.getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
|
||||
public void handleOnBackPressed() {
|
||||
dismiss();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
app = requireMyApplication();
|
||||
|
||||
Bundle args = getArguments();
|
||||
if (args == null || !args.containsKey(EXTRA_PLUGIN_ID)) {
|
||||
log.error("Required extra '" + EXTRA_PLUGIN_ID + "' is missing");
|
||||
return null;
|
||||
}
|
||||
String pluginId = args.getString(EXTRA_PLUGIN_ID);
|
||||
if (pluginId == null) {
|
||||
log.error("Extra '" + EXTRA_PLUGIN_ID + "' is null");
|
||||
return null;
|
||||
}
|
||||
plugin = OsmandPlugin.getPlugin(pluginId);
|
||||
if (plugin == null) {
|
||||
log.error("Plugin '" + EXTRA_PLUGIN_ID + "' not found");
|
||||
return null;
|
||||
}
|
||||
|
||||
Context context = requireContext();
|
||||
nightMode = !app.getSettings().isLightContent();
|
||||
LayoutInflater themedInflater = UiUtilities.getInflater(context, nightMode);
|
||||
mainView = themedInflater.inflate(R.layout.plugin, container, false);
|
||||
AndroidUtils.addStatusBarPadding21v(context, mainView);
|
||||
|
||||
TextView toolbarTitle = mainView.findViewById(R.id.toolbar_title);
|
||||
toolbarTitle.setText(plugin.getName());
|
||||
|
||||
ImageView closeButton = mainView.findViewById(R.id.close_button);
|
||||
closeButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Activity activity = getMyActivity();
|
||||
if (activity != null) {
|
||||
activity.onBackPressed();
|
||||
}
|
||||
}
|
||||
});
|
||||
UiUtilities.rotateImageByLayoutDirection(closeButton, AndroidUtils.getLayoutDirection(app));
|
||||
|
||||
Drawable pluginImage = plugin.getAssetResourceImage();
|
||||
if (pluginImage != null) {
|
||||
ImageView img = mainView.findViewById(R.id.plugin_image);
|
||||
img.setImageDrawable(pluginImage);
|
||||
} else {
|
||||
mainView.findViewById(R.id.plugin_image_placeholder).setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
TextView descriptionView = mainView.findViewById(R.id.plugin_description);
|
||||
descriptionView.setText(plugin.getDescription());
|
||||
|
||||
int linkTextColorId = nightMode ? R.color.ctx_menu_bottom_view_url_color_dark : R.color.ctx_menu_bottom_view_url_color_light;
|
||||
int linkTextColor = ContextCompat.getColor(context, linkTextColorId);
|
||||
|
||||
descriptionView.setLinkTextColor(linkTextColor);
|
||||
descriptionView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
AndroidUtils.removeLinkUnderline(descriptionView);
|
||||
|
||||
Button settingsButton = mainView.findViewById(R.id.plugin_settings);
|
||||
settingsButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity != null) {
|
||||
SettingsScreenType settingsScreenType = plugin.getSettingsScreenType();
|
||||
if (settingsScreenType != null) {
|
||||
Bundle args = new Bundle();
|
||||
args.putBoolean(PLUGIN_INFO, true);
|
||||
BaseSettingsFragment.showInstance(activity, settingsScreenType, null, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
CompoundButton enableDisableButton = mainView.findViewById(R.id.plugin_enable_disable);
|
||||
enableDisableButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
if (plugin.isActive() == isChecked) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean ok = OsmandPlugin.enablePlugin(getActivity(), app, plugin, isChecked);
|
||||
if (!ok) {
|
||||
return;
|
||||
}
|
||||
updateState();
|
||||
}
|
||||
});
|
||||
Button getButton = mainView.findViewById(R.id.plugin_get);
|
||||
getButton.setText(plugin.isPaid() ? R.string.get_plugin : R.string.shared_string_install);
|
||||
getButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
try {
|
||||
if (plugin instanceof SRTMPlugin) {
|
||||
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
|
||||
if (fragmentManager != null) {
|
||||
ChoosePlanDialogFragment.showHillshadeSrtmPluginInstance(fragmentManager);
|
||||
}
|
||||
} else {
|
||||
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(plugin.getInstallURL())));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
//ignored
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
updateState();
|
||||
return mainView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
OsmandPlugin.checkInstalledMarketPlugins(app, getActivity());
|
||||
updateState();
|
||||
}
|
||||
|
||||
private void updateState() {
|
||||
CompoundButton enableDisableButton = mainView.findViewById(R.id.plugin_enable_disable);
|
||||
Button getButton = mainView.findViewById(R.id.plugin_get);
|
||||
Button settingsButton = mainView.findViewById(R.id.plugin_settings);
|
||||
settingsButton.setCompoundDrawablesWithIntrinsicBounds(app.getUIUtilities().getThemedIcon(R.drawable.ic_action_settings), null, null, null);
|
||||
View installHeader = mainView.findViewById(R.id.plugin_install_header);
|
||||
|
||||
if (plugin.needsInstallation()) {
|
||||
getButton.setVisibility(View.VISIBLE);
|
||||
enableDisableButton.setVisibility(View.GONE);
|
||||
settingsButton.setVisibility(View.GONE);
|
||||
installHeader.setVisibility(View.VISIBLE);
|
||||
View worldGlobeIcon = installHeader.findViewById(R.id.ic_world_globe);
|
||||
Drawable worldGlobeDrawable = app.getUIUtilities().getThemedIcon(R.drawable.ic_world_globe_dark);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
worldGlobeIcon.setBackground(worldGlobeDrawable);
|
||||
} else {
|
||||
worldGlobeIcon.setBackgroundDrawable(worldGlobeDrawable);
|
||||
}
|
||||
} else {
|
||||
getButton.setVisibility(View.GONE);
|
||||
enableDisableButton.setVisibility(View.VISIBLE);
|
||||
enableDisableButton.setChecked(plugin.isActive());
|
||||
|
||||
if (plugin.getSettingsScreenType() == null || !plugin.isActive()) {
|
||||
settingsButton.setVisibility(View.GONE);
|
||||
} else {
|
||||
settingsButton.setVisibility(View.VISIBLE);
|
||||
}
|
||||
installHeader.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPluginStateChanged(OsmandPlugin plugin) {
|
||||
updateState();
|
||||
}
|
||||
|
||||
public void dismiss() {
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity != null) {
|
||||
try {
|
||||
activity.getSupportFragmentManager().popBackStack(TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE);
|
||||
} catch (Exception e) {
|
||||
log.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean showInstance(FragmentManager fragmentManager, OsmandPlugin plugin) {
|
||||
try {
|
||||
Bundle args = new Bundle();
|
||||
args.putString(EXTRA_PLUGIN_ID, plugin.getId());
|
||||
|
||||
PluginInfoFragment fragment = new PluginInfoFragment();
|
||||
fragment.setArguments(args);
|
||||
fragmentManager.beginTransaction()
|
||||
.add(R.id.fragmentContainer, fragment, TAG)
|
||||
.addToBackStack(TAG)
|
||||
.commitAllowingStateLoss();
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,296 +0,0 @@
|
|||
package net.osmand.plus.activities;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.res.TypedArray;
|
||||
import android.os.Bundle;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.PopupMenu;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.aidl.ConnectedApp;
|
||||
import net.osmand.plus.CustomOsmandPlugin;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.OsmandPlugin;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.dialogs.PluginInstalledBottomSheetDialog;
|
||||
import net.osmand.plus.download.DownloadIndexesThread;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class PluginsActivity extends OsmandListActivity implements DownloadIndexesThread.DownloadEvents, PluginInstalledBottomSheetDialog.PluginStateListener {
|
||||
|
||||
public static final int ACTIVE_PLUGINS_LIST_MODIFIED = 1;
|
||||
|
||||
private boolean listModified = false;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
getMyApplication().applyTheme(this);
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.plugins);
|
||||
getSupportActionBar().setTitle(R.string.plugins_screen);
|
||||
setListAdapter(new PluginsListAdapter());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginsListAdapter getListAdapter() {
|
||||
return (PluginsListAdapter) super.getListAdapter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
Object tag = view.getTag();
|
||||
if (tag instanceof OsmandPlugin) {
|
||||
Intent intent = new Intent(this, PluginActivity.class);
|
||||
intent.putExtra(PluginActivity.EXTRA_PLUGIN_ID, ((OsmandPlugin) tag).getId());
|
||||
startActivity(intent);
|
||||
} else if (tag instanceof ConnectedApp) {
|
||||
switchEnabled((ConnectedApp) tag);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
OsmandApplication app = getMyApplication();
|
||||
OsmandPlugin.checkInstalledMarketPlugins(app, this);
|
||||
app.getDownloadThread().setUiActivity(this);
|
||||
getListAdapter().notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
getMyApplication().getDownloadThread().resetUiActivity(this);
|
||||
}
|
||||
|
||||
private void enableDisablePlugin(OsmandPlugin plugin, boolean enable) {
|
||||
OsmandApplication app = getMyApplication();
|
||||
if (OsmandPlugin.enablePlugin(this, app, plugin, enable)) {
|
||||
if (!listModified) {
|
||||
setResult(ACTIVE_PLUGINS_LIST_MODIFIED);
|
||||
listModified = true;
|
||||
}
|
||||
getListAdapter().notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void switchEnabled(@NonNull ConnectedApp app) {
|
||||
getMyApplication().getAidlApi().switchEnabled(app);
|
||||
getListAdapter().notifyDataSetChanged();
|
||||
}
|
||||
|
||||
// DownloadEvents
|
||||
@Override
|
||||
public void newDownloadIndexes() {
|
||||
for (Fragment fragment : getSupportFragmentManager().getFragments()) {
|
||||
if (fragment instanceof DownloadIndexesThread.DownloadEvents && fragment.isAdded()) {
|
||||
((DownloadIndexesThread.DownloadEvents) fragment).newDownloadIndexes();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void downloadInProgress() {
|
||||
for (Fragment fragment : getSupportFragmentManager().getFragments()) {
|
||||
if (fragment instanceof DownloadIndexesThread.DownloadEvents && fragment.isAdded()) {
|
||||
((DownloadIndexesThread.DownloadEvents) fragment).downloadInProgress();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void downloadHasFinished() {
|
||||
for (Fragment fragment : getSupportFragmentManager().getFragments()) {
|
||||
if (fragment instanceof DownloadIndexesThread.DownloadEvents && fragment.isAdded()) {
|
||||
((DownloadIndexesThread.DownloadEvents) fragment).downloadHasFinished();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPluginStateChanged(OsmandPlugin plugin) {
|
||||
getListAdapter().notifyDataSetChanged();
|
||||
}
|
||||
|
||||
protected class PluginsListAdapter extends ArrayAdapter<Object> {
|
||||
PluginsListAdapter() {
|
||||
super(PluginsActivity.this, R.layout.plugins_list_item, new ArrayList<>());
|
||||
addAll(getMyApplication().getAidlApi().getConnectedApps());
|
||||
addAll(OsmandPlugin.getVisiblePlugins());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public View getView(int position, View convertView, @NonNull ViewGroup parent) {
|
||||
View view = convertView;
|
||||
if (view == null) {
|
||||
view = getLayoutInflater().inflate(R.layout.plugins_list_item, parent, false);
|
||||
}
|
||||
|
||||
final Object item = getItem(position);
|
||||
|
||||
boolean active = false;
|
||||
int logoContDescId = R.string.shared_string_disable;
|
||||
String name = "";
|
||||
boolean isLightTheme = getMyApplication().getSettings().isLightContent();
|
||||
|
||||
ImageButton pluginLogo = (ImageButton) view.findViewById(R.id.plugin_logo);
|
||||
ImageView pluginOptions = (ImageView) view.findViewById(R.id.plugin_options);
|
||||
TextView pluginDescription = (TextView) view.findViewById(R.id.plugin_description);
|
||||
|
||||
if (item instanceof ConnectedApp) {
|
||||
final ConnectedApp app = (ConnectedApp) item;
|
||||
active = app.isEnabled();
|
||||
if (!active) {
|
||||
logoContDescId = R.string.shared_string_enable;
|
||||
}
|
||||
name = app.getName();
|
||||
pluginDescription.setText(R.string.third_party_application);
|
||||
pluginLogo.setImageDrawable(app.getIcon());
|
||||
pluginLogo.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
switchEnabled(app);
|
||||
}
|
||||
});
|
||||
pluginOptions.setVisibility(View.GONE);
|
||||
pluginOptions.setOnClickListener(null);
|
||||
view.setTag(app);
|
||||
} else if (item instanceof OsmandPlugin) {
|
||||
final OsmandPlugin plugin = (OsmandPlugin) item;
|
||||
active = plugin.isActive();
|
||||
if (!active) {
|
||||
logoContDescId = plugin.needsInstallation()
|
||||
? R.string.access_shared_string_not_installed : R.string.shared_string_enable;
|
||||
}
|
||||
name = plugin.getName();
|
||||
pluginDescription.setText(plugin.getDescription());
|
||||
|
||||
boolean light = getMyApplication().getSettings().isLightContent();
|
||||
int linkTextColor = ContextCompat.getColor(PluginsActivity.this,
|
||||
light ? R.color.ctx_menu_bottom_view_url_color_light : R.color.ctx_menu_bottom_view_url_color_dark);
|
||||
|
||||
pluginDescription.setLinkTextColor(linkTextColor);
|
||||
pluginDescription.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
AndroidUtils.removeLinkUnderline(pluginDescription);
|
||||
|
||||
OsmandApplication app = getMyApplication();
|
||||
int color = AndroidUtils.getColorFromAttr(PluginsActivity.this, R.attr.list_background_color);
|
||||
pluginLogo.setImageDrawable(UiUtilities.tintDrawable(plugin.getLogoResource(), color));
|
||||
pluginLogo.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (plugin.isActive() || !plugin.needsInstallation()) {
|
||||
enableDisablePlugin(plugin, !plugin.isActive());
|
||||
}
|
||||
}
|
||||
});
|
||||
pluginOptions.setVisibility(View.VISIBLE);
|
||||
pluginOptions.setImageDrawable(getMyApplication().getUIUtilities().getThemedIcon(R.drawable.ic_overflow_menu_white));
|
||||
pluginOptions.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
showOptionsMenu(v, plugin);
|
||||
}
|
||||
});
|
||||
view.setTag(plugin);
|
||||
}
|
||||
|
||||
pluginLogo.setContentDescription(getString(logoContDescId));
|
||||
if (active) {
|
||||
pluginLogo.setBackgroundResource(isLightTheme ? R.drawable.bg_plugin_logo_enabled_light : R.drawable.bg_plugin_logo_enabled_dark);
|
||||
} else {
|
||||
TypedArray attributes = getTheme().obtainStyledAttributes(new int[] {R.attr.bg_plugin_logo_disabled});
|
||||
pluginLogo.setBackgroundDrawable(attributes.getDrawable(0));
|
||||
attributes.recycle();
|
||||
}
|
||||
|
||||
TextView pluginName = (TextView) view.findViewById(R.id.plugin_name);
|
||||
pluginName.setText(name);
|
||||
pluginName.setContentDescription(name + " " + getString(active
|
||||
? R.string.item_checked
|
||||
: R.string.item_unchecked));
|
||||
|
||||
return view;
|
||||
}
|
||||
}
|
||||
|
||||
private void showOptionsMenu(View v, final OsmandPlugin plugin) {
|
||||
final Class<? extends Activity> settingsActivity = plugin.getSettingsActivity();
|
||||
|
||||
final PopupMenu optionsMenu = new PopupMenu(this, v);
|
||||
if (plugin.isActive() || !plugin.needsInstallation()) {
|
||||
MenuItem enableDisableItem = optionsMenu.getMenu().add(
|
||||
plugin.isActive() ? R.string.shared_string_disable
|
||||
: R.string.shared_string_enable);
|
||||
enableDisableItem
|
||||
.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
enableDisablePlugin(plugin, !plugin.isActive());
|
||||
optionsMenu.dismiss();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (settingsActivity != null && plugin.isActive()) {
|
||||
MenuItem settingsItem = optionsMenu.getMenu().add(R.string.shared_string_settings);
|
||||
settingsItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
startActivity(new Intent(PluginsActivity.this, settingsActivity));
|
||||
optionsMenu.dismiss();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (plugin instanceof CustomOsmandPlugin) {
|
||||
MenuItem settingsItem = optionsMenu.getMenu().add(R.string.shared_string_delete);
|
||||
settingsItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
showDeletePluginDialog((CustomOsmandPlugin) plugin);
|
||||
optionsMenu.dismiss();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
optionsMenu.show();
|
||||
}
|
||||
|
||||
private void showDeletePluginDialog(final CustomOsmandPlugin plugin) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(PluginsActivity.this);
|
||||
builder.setTitle(getString(R.string.delete_confirmation_msg, plugin.getName()));
|
||||
builder.setMessage(R.string.are_you_sure);
|
||||
builder.setNegativeButton(R.string.shared_string_cancel, null);
|
||||
builder.setPositiveButton(R.string.shared_string_ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
OsmandApplication app = getMyApplication();
|
||||
OsmandPlugin.removeCustomPlugin(app, plugin);
|
||||
getListAdapter().remove(plugin);
|
||||
}
|
||||
});
|
||||
builder.show();
|
||||
}
|
||||
}
|
338
OsmAnd/src/net/osmand/plus/activities/PluginsFragment.java
Normal file
338
OsmAnd/src/net/osmand/plus/activities/PluginsFragment.java
Normal file
|
@ -0,0 +1,338 @@
|
|||
package net.osmand.plus.activities;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.res.TypedArray;
|
||||
import android.os.Bundle;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.activity.OnBackPressedCallback;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.PopupMenu;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.aidl.ConnectedApp;
|
||||
import net.osmand.plus.CustomOsmandPlugin;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.OsmandPlugin;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.base.BaseOsmAndFragment;
|
||||
import net.osmand.plus.dialogs.PluginInstalledBottomSheetDialog.PluginStateListener;
|
||||
import net.osmand.plus.settings.fragments.BaseSettingsFragment;
|
||||
import net.osmand.plus.settings.fragments.BaseSettingsFragment.SettingsScreenType;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class PluginsFragment extends BaseOsmAndFragment implements PluginStateListener {
|
||||
|
||||
private static final Log log = PlatformUtil.getLog(PluginsFragment.class);
|
||||
|
||||
public static final String TAG = PluginsFragment.class.getName();
|
||||
|
||||
public static final String OPEN_PLUGINS = "open_plugins";
|
||||
|
||||
private OsmandApplication app;
|
||||
private PluginsListAdapter adapter;
|
||||
|
||||
private LayoutInflater themedInflater;
|
||||
private boolean nightMode;
|
||||
|
||||
@Override
|
||||
public int getStatusBarColorId() {
|
||||
return nightMode ? R.color.status_bar_color_dark : R.color.status_bar_color_light;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
FragmentActivity activity = requireMyActivity();
|
||||
activity.getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
|
||||
public void handleOnBackPressed() {
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity instanceof MapActivity) {
|
||||
dismissImmediate();
|
||||
MapActivity mapActivity = (MapActivity) activity;
|
||||
mapActivity.launchPrevActivityIntent();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
app = requireMyApplication();
|
||||
nightMode = !app.getSettings().isLightContent();
|
||||
|
||||
themedInflater = UiUtilities.getInflater(getContext(), nightMode);
|
||||
View view = themedInflater.inflate(R.layout.plugins, container, false);
|
||||
AndroidUtils.addStatusBarPadding21v(getContext(), view);
|
||||
|
||||
TextView toolbarTitle = view.findViewById(R.id.toolbar_title);
|
||||
toolbarTitle.setText(R.string.plugins_screen);
|
||||
|
||||
ImageView closeButton = view.findViewById(R.id.close_button);
|
||||
closeButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Activity activity = getMyActivity();
|
||||
if (activity != null) {
|
||||
activity.onBackPressed();
|
||||
}
|
||||
}
|
||||
});
|
||||
UiUtilities.rotateImageByLayoutDirection(closeButton, AndroidUtils.getLayoutDirection(app));
|
||||
|
||||
adapter = new PluginsListAdapter(requireContext());
|
||||
|
||||
ListView listView = view.findViewById(R.id.plugins_list);
|
||||
listView.setAdapter(adapter);
|
||||
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
Object tag = view.getTag();
|
||||
if (tag instanceof OsmandPlugin) {
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity != null) {
|
||||
PluginInfoFragment.showInstance(activity.getSupportFragmentManager(), (OsmandPlugin) tag);
|
||||
}
|
||||
} else if (tag instanceof ConnectedApp) {
|
||||
switchEnabled((ConnectedApp) tag);
|
||||
}
|
||||
}
|
||||
});
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
OsmandPlugin.checkInstalledMarketPlugins(app, getActivity());
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private void enableDisablePlugin(OsmandPlugin plugin, boolean enable) {
|
||||
if (OsmandPlugin.enablePlugin(getActivity(), app, plugin, enable)) {
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void switchEnabled(@NonNull ConnectedApp connectedApp) {
|
||||
app.getAidlApi().switchEnabled(connectedApp);
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPluginStateChanged(OsmandPlugin plugin) {
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
protected class PluginsListAdapter extends ArrayAdapter<Object> {
|
||||
|
||||
PluginsListAdapter(Context context) {
|
||||
super(context, R.layout.plugins_list_item, new ArrayList<>());
|
||||
addAll(app.getAidlApi().getConnectedApps());
|
||||
addAll(OsmandPlugin.getVisiblePlugins());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public View getView(int position, View convertView, @NonNull ViewGroup parent) {
|
||||
View view = convertView;
|
||||
if (view == null) {
|
||||
view = themedInflater.inflate(R.layout.plugins_list_item, parent, false);
|
||||
}
|
||||
Context context = view.getContext();
|
||||
|
||||
boolean active = false;
|
||||
int logoContDescId = R.string.shared_string_disable;
|
||||
String name = "";
|
||||
|
||||
ImageButton pluginLogo = view.findViewById(R.id.plugin_logo);
|
||||
ImageView pluginOptions = view.findViewById(R.id.plugin_options);
|
||||
TextView pluginDescription = view.findViewById(R.id.plugin_description);
|
||||
|
||||
Object item = getItem(position);
|
||||
if (item instanceof ConnectedApp) {
|
||||
final ConnectedApp app = (ConnectedApp) item;
|
||||
active = app.isEnabled();
|
||||
if (!active) {
|
||||
logoContDescId = R.string.shared_string_enable;
|
||||
}
|
||||
name = app.getName();
|
||||
pluginDescription.setText(R.string.third_party_application);
|
||||
pluginLogo.setImageDrawable(app.getIcon());
|
||||
pluginLogo.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
switchEnabled(app);
|
||||
}
|
||||
});
|
||||
pluginOptions.setVisibility(View.GONE);
|
||||
pluginOptions.setOnClickListener(null);
|
||||
view.setTag(app);
|
||||
} else if (item instanceof OsmandPlugin) {
|
||||
final OsmandPlugin plugin = (OsmandPlugin) item;
|
||||
active = plugin.isActive();
|
||||
if (!active) {
|
||||
logoContDescId = plugin.needsInstallation()
|
||||
? R.string.access_shared_string_not_installed : R.string.shared_string_enable;
|
||||
}
|
||||
name = plugin.getName();
|
||||
pluginDescription.setText(plugin.getDescription());
|
||||
|
||||
int linkTextColorId = nightMode ? R.color.ctx_menu_bottom_view_url_color_dark : R.color.ctx_menu_bottom_view_url_color_light;
|
||||
int linkTextColor = ContextCompat.getColor(context, linkTextColorId);
|
||||
|
||||
pluginDescription.setLinkTextColor(linkTextColor);
|
||||
pluginDescription.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
AndroidUtils.removeLinkUnderline(pluginDescription);
|
||||
|
||||
int color = AndroidUtils.getColorFromAttr(context, R.attr.list_background_color);
|
||||
pluginLogo.setImageDrawable(UiUtilities.tintDrawable(plugin.getLogoResource(), color));
|
||||
pluginLogo.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (plugin.isActive() || !plugin.needsInstallation()) {
|
||||
enableDisablePlugin(plugin, !plugin.isActive());
|
||||
}
|
||||
}
|
||||
});
|
||||
pluginOptions.setVisibility(View.VISIBLE);
|
||||
pluginOptions.setImageDrawable(app.getUIUtilities().getThemedIcon(R.drawable.ic_overflow_menu_white));
|
||||
pluginOptions.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
showOptionsMenu(v, plugin);
|
||||
}
|
||||
});
|
||||
view.setTag(plugin);
|
||||
}
|
||||
|
||||
pluginLogo.setContentDescription(getString(logoContDescId));
|
||||
if (active) {
|
||||
pluginLogo.setBackgroundResource(nightMode ? R.drawable.bg_plugin_logo_enabled_dark : R.drawable.bg_plugin_logo_enabled_light);
|
||||
} else {
|
||||
TypedArray attributes = context.getTheme().obtainStyledAttributes(new int[] {R.attr.bg_plugin_logo_disabled});
|
||||
pluginLogo.setBackgroundDrawable(attributes.getDrawable(0));
|
||||
attributes.recycle();
|
||||
}
|
||||
|
||||
TextView pluginName = view.findViewById(R.id.plugin_name);
|
||||
pluginName.setText(name);
|
||||
pluginName.setContentDescription(name + " " + getString(active
|
||||
? R.string.item_checked
|
||||
: R.string.item_unchecked));
|
||||
|
||||
return view;
|
||||
}
|
||||
}
|
||||
|
||||
private void showOptionsMenu(View view, final OsmandPlugin plugin) {
|
||||
final PopupMenu optionsMenu = new PopupMenu(view.getContext(), view);
|
||||
if (plugin.isActive() || !plugin.needsInstallation()) {
|
||||
MenuItem enableDisableItem = optionsMenu.getMenu().add(
|
||||
plugin.isActive() ? R.string.shared_string_disable
|
||||
: R.string.shared_string_enable);
|
||||
enableDisableItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
enableDisablePlugin(plugin, !plugin.isActive());
|
||||
optionsMenu.dismiss();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
final SettingsScreenType settingsScreenType = plugin.getSettingsScreenType();
|
||||
if (settingsScreenType != null && plugin.isActive()) {
|
||||
MenuItem settingsItem = optionsMenu.getMenu().add(R.string.shared_string_settings);
|
||||
settingsItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity != null) {
|
||||
BaseSettingsFragment.showInstance(activity, settingsScreenType);
|
||||
}
|
||||
optionsMenu.dismiss();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (plugin instanceof CustomOsmandPlugin) {
|
||||
MenuItem settingsItem = optionsMenu.getMenu().add(R.string.shared_string_delete);
|
||||
settingsItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
showDeletePluginDialog((CustomOsmandPlugin) plugin);
|
||||
optionsMenu.dismiss();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
optionsMenu.show();
|
||||
}
|
||||
|
||||
private void showDeletePluginDialog(final CustomOsmandPlugin plugin) {
|
||||
Context context = getContext();
|
||||
if (context != null) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
builder.setTitle(getString(R.string.delete_confirmation_msg, plugin.getName()));
|
||||
builder.setMessage(R.string.are_you_sure);
|
||||
builder.setNegativeButton(R.string.shared_string_cancel, null);
|
||||
builder.setPositiveButton(R.string.shared_string_ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
OsmandPlugin.removeCustomPlugin(app, plugin);
|
||||
adapter.remove(plugin);
|
||||
}
|
||||
});
|
||||
builder.show();
|
||||
}
|
||||
}
|
||||
|
||||
public void dismissImmediate() {
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity != null) {
|
||||
try {
|
||||
activity.getSupportFragmentManager().popBackStackImmediate(TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE);
|
||||
} catch (Exception e) {
|
||||
log.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean showInstance(FragmentManager fragmentManager) {
|
||||
try {
|
||||
PluginsFragment fragment = new PluginsFragment();
|
||||
fragmentManager.beginTransaction()
|
||||
.add(R.id.fragmentContainer, fragment, TAG)
|
||||
.addToBackStack(TAG)
|
||||
.commitAllowingStateLoss();
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +1,9 @@
|
|||
package net.osmand.plus.activities;
|
||||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.preference.Preference;
|
||||
import android.preference.Preference.OnPreferenceClickListener;
|
||||
import android.preference.PreferenceCategory;
|
||||
import android.preference.PreferenceScreen;
|
||||
|
||||
|
@ -59,30 +57,21 @@ public class SettingsActivity extends SettingsBaseActivity {
|
|||
}
|
||||
PreferenceCategory plugins = (PreferenceCategory) screen.findPreference("plugin_settings");
|
||||
for(OsmandPlugin op : OsmandPlugin.getEnabledPlugins()) {
|
||||
final Class<? extends Activity> sa = op.getSettingsActivity();
|
||||
if(sa != null) {
|
||||
Preference preference = new Preference(this);
|
||||
preference.setTitle(op.getName());
|
||||
preference.setKey(op.getId());
|
||||
preference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
startActivity(new Intent(SettingsActivity.this, sa));
|
||||
return false;
|
||||
}
|
||||
});
|
||||
plugins.addPreference(preference);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if ((requestCode == PLUGINS_SELECTION_REQUEST) && (resultCode == PluginsActivity.ACTIVE_PLUGINS_LIST_MODIFIED)) {
|
||||
finish();
|
||||
startActivity(getIntent());
|
||||
// final Class<? extends Activity> sa = op.getSettingsActivity();
|
||||
// if(sa != null) {
|
||||
// Preference preference = new Preference(this);
|
||||
// preference.setTitle(op.getName());
|
||||
// preference.setKey(op.getId());
|
||||
// preference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||
//
|
||||
// @Override
|
||||
// public boolean onPreferenceClick(Preference preference) {
|
||||
// startActivity(new Intent(SettingsActivity.this, sa));
|
||||
// return false;
|
||||
// }
|
||||
// });
|
||||
// plugins.addPreference(preference);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -96,13 +96,11 @@ public class AudioVideoNoteMenuController extends MenuController {
|
|||
|
||||
@Override
|
||||
public Drawable getRightIcon() {
|
||||
if (mRecording.isPhoto()) {
|
||||
return getIcon(R.drawable.ic_action_photo_dark, R.color.audio_video_icon_color);
|
||||
} else if (mRecording.isAudio()) {
|
||||
return getIcon(R.drawable.ic_action_micro_dark, R.color.audio_video_icon_color);
|
||||
} else {
|
||||
return getIcon(R.drawable.ic_action_video_dark, R.color.audio_video_icon_color);
|
||||
int iconId = AudioVideoNotesPlugin.getIconIdForRecordingFile(mRecording.getFile());
|
||||
if (iconId == -1) {
|
||||
iconId = R.drawable.ic_action_photo_dark;
|
||||
}
|
||||
return getIcon(iconId, R.color.audio_video_icon_color);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
|
|
@ -47,14 +47,11 @@ import net.osmand.PlatformUtil;
|
|||
import net.osmand.data.DataTileManager;
|
||||
import net.osmand.data.LatLon;
|
||||
import net.osmand.data.PointDescription;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.ContextMenuAdapter;
|
||||
import net.osmand.plus.ContextMenuAdapter.ItemClickListener;
|
||||
import net.osmand.plus.ContextMenuItem;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.OsmandPlugin;
|
||||
import net.osmand.plus.settings.backend.CommonPreference;
|
||||
import net.osmand.plus.settings.backend.OsmandPreference;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
|
@ -66,12 +63,15 @@ import net.osmand.plus.mapcontextmenu.MapContextMenu;
|
|||
import net.osmand.plus.monitoring.OsmandMonitoringPlugin;
|
||||
import net.osmand.plus.myplaces.FavoritesActivity;
|
||||
import net.osmand.plus.quickaction.QuickActionType;
|
||||
import net.osmand.plus.settings.fragments.BaseSettingsFragment;
|
||||
import net.osmand.plus.views.layers.MapInfoLayer;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.settings.backend.CommonPreference;
|
||||
import net.osmand.plus.settings.backend.OsmandPreference;
|
||||
import net.osmand.plus.settings.fragments.BaseSettingsFragment.SettingsScreenType;
|
||||
import net.osmand.plus.views.OsmandMapLayer.DrawSettings;
|
||||
import net.osmand.plus.views.OsmandMapTileView;
|
||||
import net.osmand.plus.views.mapwidgets.widgetstates.WidgetState;
|
||||
import net.osmand.plus.views.layers.MapInfoLayer;
|
||||
import net.osmand.plus.views.mapwidgets.widgets.TextInfoWidget;
|
||||
import net.osmand.plus.views.mapwidgets.widgetstates.WidgetState;
|
||||
import net.osmand.util.Algorithms;
|
||||
import net.osmand.util.GeoPointParserUtil.GeoParsedPoint;
|
||||
import net.osmand.util.MapUtils;
|
||||
|
@ -517,7 +517,18 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
|
|||
}
|
||||
return additional.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static int getIconIdForRecordingFile(@NonNull File file) {
|
||||
String fileName = file.getName();
|
||||
if (fileName.endsWith(IMG_EXTENSION)) {
|
||||
return R.drawable.ic_action_photo_dark;
|
||||
} else if (fileName.endsWith(MPEG4_EXTENSION)) {
|
||||
return R.drawable.ic_action_video_dark;
|
||||
} else if (fileName.endsWith(THREEGP_EXTENSION)) {
|
||||
return R.drawable.ic_action_micro_dark;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// private static void initializeRemoteControlRegistrationMethods() {
|
||||
|
@ -1800,13 +1811,8 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Activity> getSettingsActivity() {
|
||||
return SettingsAudioVideoActivity.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends BaseSettingsFragment> getSettingsFragment() {
|
||||
return MultimediaNotesFragment.class;
|
||||
public SettingsScreenType getSettingsScreenType() {
|
||||
return SettingsScreenType.MULTIMEDIA_NOTES;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -13,6 +13,8 @@ import android.os.Build;
|
|||
import android.os.Bundle;
|
||||
import android.os.StatFs;
|
||||
import android.text.SpannableString;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
|
@ -22,17 +24,18 @@ import androidx.preference.PreferenceViewHolder;
|
|||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.settings.backend.OsmAndAppCustomization;
|
||||
import net.osmand.plus.OsmandPlugin;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||
import net.osmand.plus.helpers.FontCache;
|
||||
import net.osmand.plus.profiles.SelectCopyAppModeBottomSheet;
|
||||
import net.osmand.plus.profiles.SelectCopyAppModeBottomSheet.CopyAppModePrefsListener;
|
||||
import net.osmand.plus.settings.fragments.BaseSettingsFragment;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.settings.backend.OsmAndAppCustomization;
|
||||
import net.osmand.plus.settings.bottomsheets.ResetProfilePrefsBottomSheet;
|
||||
import net.osmand.plus.settings.bottomsheets.ResetProfilePrefsBottomSheet.ResetAppModePrefsListener;
|
||||
import net.osmand.plus.settings.fragments.BaseSettingsFragment;
|
||||
import net.osmand.plus.settings.preferences.ListPreferenceEx;
|
||||
import net.osmand.plus.settings.preferences.SwitchPreferenceEx;
|
||||
import net.osmand.plus.widgets.style.CustomTypefaceSpan;
|
||||
|
@ -43,6 +46,7 @@ import java.io.File;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static net.osmand.plus.activities.PluginInfoFragment.PLUGIN_INFO;
|
||||
import static net.osmand.plus.audionotes.AudioVideoNotesPlugin.AUDIO_BITRATE_DEFAULT;
|
||||
import static net.osmand.plus.audionotes.AudioVideoNotesPlugin.AV_CAMERA_FOCUS_AUTO;
|
||||
import static net.osmand.plus.audionotes.AudioVideoNotesPlugin.AV_CAMERA_FOCUS_CONTINUOUS;
|
||||
|
@ -66,6 +70,35 @@ public class MultimediaNotesFragment extends BaseSettingsFragment implements Cop
|
|||
private static final String RESET_TO_DEFAULT = "reset_to_default";
|
||||
private static final String OPEN_NOTES = "open_notes";
|
||||
|
||||
boolean showSwitchProfile = false;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Bundle args = getArguments();
|
||||
if (args != null) {
|
||||
showSwitchProfile = args.getBoolean(PLUGIN_INFO, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createToolbar(LayoutInflater inflater, View view) {
|
||||
super.createToolbar(inflater, view);
|
||||
|
||||
View switchProfile = view.findViewById(R.id.profile_button);
|
||||
if (switchProfile != null) {
|
||||
AndroidUiHelper.updateVisibility(switchProfile, showSwitchProfile);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle buildArguments() {
|
||||
Bundle args = super.buildArguments();
|
||||
args.putBoolean(PLUGIN_INFO, showSwitchProfile);
|
||||
return args;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupPreferences() {
|
||||
AudioVideoNotesPlugin plugin = OsmandPlugin.getPlugin(AudioVideoNotesPlugin.class);
|
||||
|
|
|
@ -1,334 +0,0 @@
|
|||
package net.osmand.plus.audionotes;
|
||||
|
||||
import android.hardware.Camera;
|
||||
import android.hardware.Camera.Parameters;
|
||||
import android.media.CamcorderProfile;
|
||||
import android.media.MediaRecorder;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.StatFs;
|
||||
import android.preference.ListPreference;
|
||||
import android.preference.PreferenceCategory;
|
||||
import android.preference.PreferenceScreen;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.OsmandPlugin;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.activities.SettingsBaseActivity;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static net.osmand.plus.audionotes.AudioVideoNotesPlugin.AUDIO_BITRATE_DEFAULT;
|
||||
import static net.osmand.plus.audionotes.AudioVideoNotesPlugin.AV_CAMERA_FOCUS_AUTO;
|
||||
import static net.osmand.plus.audionotes.AudioVideoNotesPlugin.AV_CAMERA_FOCUS_CONTINUOUS;
|
||||
import static net.osmand.plus.audionotes.AudioVideoNotesPlugin.AV_CAMERA_FOCUS_EDOF;
|
||||
import static net.osmand.plus.audionotes.AudioVideoNotesPlugin.AV_CAMERA_FOCUS_HIPERFOCAL;
|
||||
import static net.osmand.plus.audionotes.AudioVideoNotesPlugin.AV_CAMERA_FOCUS_INFINITY;
|
||||
import static net.osmand.plus.audionotes.AudioVideoNotesPlugin.AV_CAMERA_FOCUS_MACRO;
|
||||
import static net.osmand.plus.audionotes.AudioVideoNotesPlugin.AV_DEFAULT_ACTION_AUDIO;
|
||||
import static net.osmand.plus.audionotes.AudioVideoNotesPlugin.AV_DEFAULT_ACTION_CHOOSE;
|
||||
import static net.osmand.plus.audionotes.AudioVideoNotesPlugin.AV_DEFAULT_ACTION_TAKEPICTURE;
|
||||
import static net.osmand.plus.audionotes.AudioVideoNotesPlugin.AV_DEFAULT_ACTION_VIDEO;
|
||||
import static net.osmand.plus.audionotes.AudioVideoNotesPlugin.cameraPictureSizeDefault;
|
||||
|
||||
// camera picture size:
|
||||
// support camera focus select:
|
||||
////
|
||||
|
||||
public class SettingsAudioVideoActivity extends SettingsBaseActivity {
|
||||
|
||||
private static final Log log = PlatformUtil.getLog(AudioVideoNotesPlugin.class);
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
((OsmandApplication) getApplication()).applyTheme(this);
|
||||
super.onCreate(savedInstanceState);
|
||||
getToolbar().setTitle(R.string.av_settings);
|
||||
PreferenceScreen grp = getPreferenceScreen();
|
||||
AudioVideoNotesPlugin p = OsmandPlugin.getEnabledPlugin(AudioVideoNotesPlugin.class);
|
||||
if (p != null) {
|
||||
String[] entries;
|
||||
Integer[] intValues;
|
||||
|
||||
entries = new String[]{getString(R.string.av_def_action_choose), getString(R.string.av_def_action_audio),
|
||||
getString(R.string.av_def_action_video), getString(R.string.av_def_action_picture)};
|
||||
intValues = new Integer[]{AV_DEFAULT_ACTION_CHOOSE, AV_DEFAULT_ACTION_AUDIO, AV_DEFAULT_ACTION_VIDEO,
|
||||
AV_DEFAULT_ACTION_TAKEPICTURE};
|
||||
ListPreference defAct = createListPreference(p.AV_DEFAULT_ACTION, entries, intValues, R.string.av_widget_action,
|
||||
R.string.av_widget_action_descr);
|
||||
grp.addPreference(defAct);
|
||||
|
||||
PreferenceCategory photo = new PreferenceCategory(this);
|
||||
photo.setTitle(R.string.shared_string_photo);
|
||||
grp.addPreference(photo);
|
||||
|
||||
final Camera cam = openCamera();
|
||||
if (cam != null) {
|
||||
// camera type settings
|
||||
photo.addPreference(createCheckBoxPreference(p.AV_EXTERNAL_PHOTO_CAM, R.string.av_use_external_camera,
|
||||
R.string.av_use_external_camera_descr));
|
||||
|
||||
Parameters parameters = cam.getParameters();
|
||||
createCameraPictureSizesPref(p, photo, parameters);
|
||||
createCameraFocusModesPref(p, photo, parameters);
|
||||
|
||||
// play sound on success photo
|
||||
photo.addPreference(createCheckBoxPreference(p.AV_PHOTO_PLAY_SOUND, R.string.av_photo_play_sound,
|
||||
R.string.av_photo_play_sound_descr));
|
||||
|
||||
cam.release();
|
||||
}
|
||||
|
||||
// video settings
|
||||
PreferenceCategory video = new PreferenceCategory(this);
|
||||
video.setTitle(R.string.shared_string_video);
|
||||
grp.addPreference(video);
|
||||
|
||||
video.addPreference(createCheckBoxPreference(p.AV_EXTERNAL_RECORDER, R.string.av_use_external_recorder,
|
||||
R.string.av_use_external_recorder_descr));
|
||||
|
||||
// entries = new String[] { "3GP", "MP4" };
|
||||
// intValues = new Integer[] { VIDEO_OUTPUT_3GP, VIDEO_OUTPUT_MP4 };
|
||||
// ListPreference lp = createListPreference(p.AV_VIDEO_FORMAT, entries, intValues, R.string.av_video_format,
|
||||
// R.string.av_video_format_descr);
|
||||
// video.addPreference(lp);
|
||||
|
||||
List<String> qNames = new ArrayList<>();
|
||||
List<Integer> qValues = new ArrayList<>();
|
||||
if (Build.VERSION.SDK_INT < 11 || CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_LOW)) {
|
||||
qNames.add(getString(R.string.av_video_quality_low));
|
||||
qValues.add(CamcorderProfile.QUALITY_LOW);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 11 && CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_480P)) {
|
||||
qNames.add("720 x 480 (480p)");
|
||||
qValues.add(CamcorderProfile.QUALITY_480P);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 11 && CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_720P)) {
|
||||
qNames.add("1280 x 720 (720p)");
|
||||
qValues.add(CamcorderProfile.QUALITY_720P);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 11 && CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_1080P)) {
|
||||
qNames.add("1920 x 1080 (1080p)");
|
||||
qValues.add(CamcorderProfile.QUALITY_1080P);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 21 && CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_2160P)) {
|
||||
qNames.add("3840x2160 (2160p)");
|
||||
qValues.add(CamcorderProfile.QUALITY_2160P);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT < 11 || CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_HIGH)) {
|
||||
qNames.add(getString(R.string.av_video_quality_high));
|
||||
qValues.add(CamcorderProfile.QUALITY_HIGH);
|
||||
}
|
||||
|
||||
ListPreference lp = createListPreference(p.AV_VIDEO_QUALITY,
|
||||
qNames.toArray(new String[qNames.size()]),
|
||||
qValues.toArray(new Integer[qValues.size()]),
|
||||
R.string.av_video_quality,
|
||||
R.string.av_video_quality_descr);
|
||||
video.addPreference(lp);
|
||||
|
||||
// Recorder Split settings
|
||||
PreferenceCategory recSplit = new PreferenceCategory(this);
|
||||
recSplit.setTitle(R.string.rec_split);
|
||||
grp.addPreference(recSplit);
|
||||
|
||||
recSplit.addPreference(createCheckBoxPreference(p.AV_RECORDER_SPLIT, R.string.rec_split_title,
|
||||
R.string.rec_split_desc));
|
||||
|
||||
intValues = new Integer[]{1, 2, 3, 4, 5, 7, 10, 15, 20, 25, 30};
|
||||
entries = new String[intValues.length];
|
||||
int i = 0;
|
||||
String minStr = getString(R.string.int_min);
|
||||
for (int v : intValues) {
|
||||
entries[i++] = String.valueOf(v) + " " + minStr;
|
||||
}
|
||||
lp = createListPreference(p.AV_RS_CLIP_LENGTH, entries, intValues,
|
||||
R.string.rec_split_clip_length,
|
||||
R.string.rec_split_clip_length_desc);
|
||||
recSplit.addPreference(lp);
|
||||
|
||||
File dir = getMyApplication().getAppPath("").getParentFile();
|
||||
long size = 0;
|
||||
if (dir.canRead()) {
|
||||
StatFs fs = new StatFs(dir.getAbsolutePath());
|
||||
size = ((long) fs.getBlockSize() * (long) fs.getBlockCount()) / (1 << 30);
|
||||
}
|
||||
if (size > 0) {
|
||||
int value = 1;
|
||||
ArrayList<Integer> gbList = new ArrayList<>();
|
||||
while (value < size) {
|
||||
gbList.add(value);
|
||||
if (value < 5) {
|
||||
value++;
|
||||
} else {
|
||||
value += 5;
|
||||
}
|
||||
}
|
||||
if (value != size) {
|
||||
gbList.add((int) size);
|
||||
}
|
||||
entries = new String[gbList.size()];
|
||||
intValues = new Integer[gbList.size()];
|
||||
i = 0;
|
||||
for (int v : gbList) {
|
||||
intValues[i] = v;
|
||||
entries[i] = AndroidUtils.formatSize(this, v * (1l << 30));
|
||||
i++;
|
||||
}
|
||||
|
||||
lp = createListPreference(p.AV_RS_STORAGE_SIZE, entries, intValues,
|
||||
R.string.rec_split_storage_size,
|
||||
R.string.rec_split_storage_size_desc);
|
||||
recSplit.addPreference(lp);
|
||||
}
|
||||
|
||||
// audio settings
|
||||
PreferenceCategory audio = new PreferenceCategory(this);
|
||||
audio.setTitle(R.string.shared_string_audio);
|
||||
grp.addPreference(audio);
|
||||
|
||||
entries = new String[]{"Default", "AAC"};
|
||||
intValues = new Integer[]{MediaRecorder.AudioEncoder.DEFAULT, MediaRecorder.AudioEncoder.AAC};
|
||||
lp = createListPreference(p.AV_AUDIO_FORMAT, entries, intValues,
|
||||
R.string.av_audio_format,
|
||||
R.string.av_audio_format_descr);
|
||||
audio.addPreference(lp);
|
||||
|
||||
entries = new String[]{"Default", "16 kbps", "32 kbps", "48 kbps", "64 kbps", "96 kbps", "128 kbps"};
|
||||
intValues = new Integer[]{AUDIO_BITRATE_DEFAULT, 16 * 1024, 32 * 1024, 48 * 1024, 64 * 1024, 96 * 1024, 128 * 1024};
|
||||
lp = createListPreference(p.AV_AUDIO_BITRATE, entries, intValues,
|
||||
R.string.av_audio_bitrate,
|
||||
R.string.av_audio_bitrate_descr);
|
||||
audio.addPreference(lp);
|
||||
}
|
||||
}
|
||||
|
||||
private void createCameraPictureSizesPref(AudioVideoNotesPlugin p, PreferenceCategory photo, Parameters parameters) {
|
||||
String[] entries;
|
||||
Integer[] intValues;
|
||||
// Photo picture size
|
||||
// get supported sizes
|
||||
List<Camera.Size> psps = parameters.getSupportedPictureSizes();
|
||||
if (psps == null) {
|
||||
return;
|
||||
}
|
||||
// list of megapixels of each resolution
|
||||
List<Integer> mpix = new ArrayList<Integer>();
|
||||
// list of index each resolution in list, returned by getSupportedPictureSizes()
|
||||
List<Integer> picSizesValues = new ArrayList<Integer>();
|
||||
// fill lists for sort
|
||||
for (int index = 0; index < psps.size(); index++) {
|
||||
mpix.add((psps.get(index)).width * (psps.get(index)).height);
|
||||
picSizesValues.add(index);
|
||||
}
|
||||
// sort list for max resolution in begining of list
|
||||
for (int i = 0; i < mpix.size(); i++) {
|
||||
for (int j = 0; j < mpix.size() - i - 1; j++) {
|
||||
if (mpix.get(j) < mpix.get(j + 1)) {
|
||||
// change elements
|
||||
int tmp = mpix.get(j + 1);
|
||||
mpix.set(j + 1, mpix.get(j));
|
||||
mpix.set(j, tmp);
|
||||
|
||||
tmp = picSizesValues.get(j + 1);
|
||||
picSizesValues.set(j + 1, picSizesValues.get(j));
|
||||
picSizesValues.set(j, tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
// set default photo size to max resolution (set index of element with max resolution in List, returned by getSupportedPictureSizes() )
|
||||
cameraPictureSizeDefault = picSizesValues.get(0);
|
||||
log.debug("onCreate() set cameraPictureSizeDefault=" + cameraPictureSizeDefault);
|
||||
|
||||
List<String> itemsPicSizes = new ArrayList<String>();
|
||||
String prefix;
|
||||
for (int index = 0; index < psps.size(); index++) {
|
||||
float px = (float) ((psps.get(picSizesValues.get(index))).width * (psps.get(picSizesValues.get(index))).height);
|
||||
if (px > 102400) // 100 K
|
||||
{
|
||||
px = px / 1048576;
|
||||
prefix = "Mpx";
|
||||
} else {
|
||||
px = px / 1024;
|
||||
prefix = "Kpx";
|
||||
}
|
||||
|
||||
itemsPicSizes.add((psps.get(picSizesValues.get(index))).width +
|
||||
"x" +
|
||||
(psps.get(picSizesValues.get(index))).height +
|
||||
" ( " +
|
||||
String.format("%.2f", px) +
|
||||
" " +
|
||||
prefix +
|
||||
" )");
|
||||
}
|
||||
log.debug("onCreate() set default size: width=" + psps.get(cameraPictureSizeDefault).width + " height="
|
||||
+ psps.get(cameraPictureSizeDefault).height + " index in ps=" + cameraPictureSizeDefault);
|
||||
|
||||
entries = itemsPicSizes.toArray(new String[itemsPicSizes.size()]);
|
||||
intValues = picSizesValues.toArray(new Integer[picSizesValues.size()]);
|
||||
if (entries.length > 0) {
|
||||
ListPreference camSizes = createListPreference(p.AV_CAMERA_PICTURE_SIZE, entries, intValues, R.string.av_camera_pic_size,
|
||||
R.string.av_camera_pic_size_descr);
|
||||
photo.addPreference(camSizes);
|
||||
}
|
||||
}
|
||||
|
||||
private void createCameraFocusModesPref(AudioVideoNotesPlugin p, PreferenceCategory photo, Parameters parameters) {
|
||||
String[] entries;
|
||||
Integer[] intValues;
|
||||
// focus mode settings
|
||||
// show in menu only suppoted modes
|
||||
List<String> sfm = parameters.getSupportedFocusModes();
|
||||
if (sfm == null) {
|
||||
return;
|
||||
}
|
||||
List<String> items = new ArrayList<String>();
|
||||
List<Integer> itemsValues = new ArrayList<Integer>();
|
||||
// filtering known types for translate and set index
|
||||
for (int index = 0; index < sfm.size(); index++) {
|
||||
if (sfm.get(index).equals("auto")) {
|
||||
items.add(getString(R.string.av_camera_focus_auto));
|
||||
itemsValues.add(AV_CAMERA_FOCUS_AUTO);
|
||||
} else if (sfm.get(index).equals("fixed")) {
|
||||
items.add(getString(R.string.av_camera_focus_hiperfocal));
|
||||
itemsValues.add(AV_CAMERA_FOCUS_HIPERFOCAL);
|
||||
} else if (sfm.get(index).equals("edof")) {
|
||||
items.add(getString(R.string.av_camera_focus_edof));
|
||||
itemsValues.add(AV_CAMERA_FOCUS_EDOF);
|
||||
} else if (sfm.get(index).equals("infinity")) {
|
||||
items.add(getString(R.string.av_camera_focus_infinity));
|
||||
itemsValues.add(AV_CAMERA_FOCUS_INFINITY);
|
||||
} else if (sfm.get(index).equals("macro")) {
|
||||
items.add(getString(R.string.av_camera_focus_macro));
|
||||
itemsValues.add(AV_CAMERA_FOCUS_MACRO);
|
||||
} else if (sfm.get(index).equals("continuous-picture")) {
|
||||
items.add(getString(R.string.av_camera_focus_continuous));
|
||||
itemsValues.add(AV_CAMERA_FOCUS_CONTINUOUS);
|
||||
}
|
||||
}
|
||||
entries = items.toArray(new String[items.size()]);
|
||||
intValues = itemsValues.toArray(new Integer[itemsValues.size()]);
|
||||
if (entries.length > 0) {
|
||||
ListPreference camFocus = createListPreference(p.AV_CAMERA_FOCUS_TYPE, entries, intValues, R.string.av_camera_focus,
|
||||
R.string.av_camera_focus_descr);
|
||||
photo.addPreference(camFocus);
|
||||
}
|
||||
}
|
||||
|
||||
protected Camera openCamera() {
|
||||
try {
|
||||
return Camera.open();
|
||||
} catch (Exception e) {
|
||||
log.error("Error open camera", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,11 +14,12 @@ import android.widget.LinearLayout;
|
|||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import net.osmand.plus.OsmandPlugin;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.activities.PluginActivity;
|
||||
import net.osmand.plus.activities.PluginsFragment;
|
||||
import net.osmand.plus.chooseplan.ChoosePlanDialogFragment;
|
||||
import net.osmand.plus.dashboard.tools.DashFragmentData;
|
||||
import net.osmand.plus.development.OsmandDevelopmentPlugin;
|
||||
|
@ -68,9 +69,10 @@ public class DashPluginsFragment extends DashBaseFragment {
|
|||
return new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Intent intent = new Intent(getActivity(), PluginActivity.class);
|
||||
intent.putExtra(PluginActivity.EXTRA_PLUGIN_ID, plugin.getId());
|
||||
startActivity(intent);
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity != null) {
|
||||
PluginsFragment.showInstance(activity.getSupportFragmentManager());
|
||||
}
|
||||
closeDashboard();
|
||||
}
|
||||
};
|
||||
|
@ -84,7 +86,10 @@ public class DashPluginsFragment extends DashBaseFragment {
|
|||
view.findViewById(R.id.show_all).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
startActivity(new Intent(getActivity(), getMyApplication().getAppCustomization().getPluginsActivity()));
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity != null) {
|
||||
PluginsFragment.showInstance(activity.getSupportFragmentManager());
|
||||
}
|
||||
closeDashboard();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -14,7 +14,7 @@ import net.osmand.plus.Version;
|
|||
import net.osmand.plus.activities.ContributionVersionActivity;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.dashboard.tools.DashFragmentData;
|
||||
import net.osmand.plus.settings.fragments.BaseSettingsFragment;
|
||||
import net.osmand.plus.settings.fragments.BaseSettingsFragment.SettingsScreenType;
|
||||
import net.osmand.plus.views.layers.MapInfoLayer;
|
||||
import net.osmand.plus.views.OsmandMapLayer.DrawSettings;
|
||||
import net.osmand.plus.views.OsmandMapTileView;
|
||||
|
@ -122,13 +122,8 @@ public class OsmandDevelopmentPlugin extends OsmandPlugin {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Activity> getSettingsActivity() {
|
||||
return SettingsDevelopmentActivity.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends BaseSettingsFragment> getSettingsFragment() {
|
||||
return DevelopmentSettingsFragment.class;
|
||||
public SettingsScreenType getSettingsScreenType() {
|
||||
return SettingsScreenType.DEVELOPMENT_SETTINGS;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,212 +0,0 @@
|
|||
package net.osmand.plus.development;
|
||||
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Debug;
|
||||
import android.os.Debug.MemoryInfo;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.Preference.OnPreferenceClickListener;
|
||||
import android.preference.PreferenceCategory;
|
||||
import android.preference.PreferenceScreen;
|
||||
|
||||
import net.osmand.plus.OsmAndLocationSimulation;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.Version;
|
||||
import net.osmand.plus.activities.SettingsBaseActivity;
|
||||
import net.osmand.plus.render.NativeOsmandLibrary;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.util.SunriseSunset;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
//import net.osmand.plus.development.OsmandDevelopmentPlugin;
|
||||
|
||||
public class SettingsDevelopmentActivity extends SettingsBaseActivity {
|
||||
|
||||
@SuppressLint("SimpleDateFormat")
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
OsmandApplication app = getMyApplication();
|
||||
app.applyTheme(this);
|
||||
super.onCreate(savedInstanceState);
|
||||
getToolbar().setTitle(R.string.debugging_and_development);
|
||||
PreferenceScreen category = getPreferenceScreen();
|
||||
Preference pref;
|
||||
|
||||
if (Version.isOpenGlAvailable(app)) {
|
||||
category.addPreference(createCheckBoxPreference(settings.USE_OPENGL_RENDER,
|
||||
R.string.use_opengl_render, R.string.use_opengl_render_descr));
|
||||
}
|
||||
|
||||
if (!Version.isBlackberry(app)) {
|
||||
CheckBoxPreference nativeCheckbox = createCheckBoxPreference(settings.SAFE_MODE, R.string.safe_mode, R.string.safe_mode_description);
|
||||
// disable the checkbox if the library cannot be used
|
||||
if ((NativeOsmandLibrary.isLoaded() && !NativeOsmandLibrary.isSupported()) || settings.NATIVE_RENDERING_FAILED.get()) {
|
||||
nativeCheckbox.setEnabled(false);
|
||||
nativeCheckbox.setChecked(true);
|
||||
}
|
||||
category.addPreference(nativeCheckbox);
|
||||
}
|
||||
|
||||
PreferenceCategory navigation = new PreferenceCategory(this);
|
||||
navigation.setTitle(R.string.routing_settings);
|
||||
category.addPreference(navigation);
|
||||
pref = new Preference(this);
|
||||
final Preference simulate = pref;
|
||||
final OsmAndLocationSimulation sim = getMyApplication().getLocationProvider().getLocationSimulation();
|
||||
final Runnable updateTitle = new Runnable(){
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
simulate.setSummary(sim.isRouteAnimating() ?
|
||||
R.string.simulate_your_location_stop_descr : R.string.simulate_your_location_gpx_descr);
|
||||
}
|
||||
};
|
||||
pref.setTitle(R.string.simulate_your_location);
|
||||
updateTitle.run();
|
||||
pref.setKey("simulate_your_location");
|
||||
pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
updateTitle.run();
|
||||
sim.startStopRouteAnimation(SettingsDevelopmentActivity.this, true, updateTitle);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
navigation.addPreference(pref);
|
||||
|
||||
PreferenceCategory debug = new PreferenceCategory(this);
|
||||
debug.setTitle(R.string.debugging_and_development);
|
||||
category.addPreference(debug);
|
||||
|
||||
CheckBoxPreference dbg = createCheckBoxPreference(settings.DEBUG_RENDERING_INFO,
|
||||
R.string.trace_rendering, R.string.trace_rendering_descr);
|
||||
debug.addPreference(dbg);
|
||||
|
||||
|
||||
final Preference firstRunPreference = new Preference(this);
|
||||
firstRunPreference.setTitle(R.string.simulate_initial_startup);
|
||||
firstRunPreference.setSummary(R.string.simulate_initial_startup_descr);
|
||||
firstRunPreference.setSelectable(true);
|
||||
firstRunPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
getMyApplication().getAppInitializer().resetFirstTimeRun();
|
||||
OsmandSettings settings = getMyApplication().getSettings();
|
||||
settings.FIRST_MAP_IS_DOWNLOADED.set(false);
|
||||
settings.MAPILLARY_FIRST_DIALOG_SHOWN.set(false);
|
||||
settings.WEBGL_SUPPORTED.set(true);
|
||||
settings.WIKI_ARTICLE_SHOW_IMAGES_ASKED.set(false);
|
||||
|
||||
getMyApplication().showToastMessage(R.string.shared_string_ok);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
debug.addPreference(firstRunPreference);
|
||||
|
||||
debug.addPreference(createCheckBoxPreference(settings.SHOULD_SHOW_FREE_VERSION_BANNER,
|
||||
R.string.show_free_version_banner,
|
||||
R.string.show_free_version_banner_description));
|
||||
|
||||
pref = new Preference(this);
|
||||
pref.setTitle(R.string.test_voice_prompts);
|
||||
pref.setSummary(R.string.play_commands_of_currently_selected_voice);
|
||||
pref.setKey("test_voice_commands");
|
||||
pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
startActivity(new Intent(SettingsDevelopmentActivity.this, TestVoiceActivity.class));
|
||||
return true;
|
||||
}
|
||||
});
|
||||
category.addPreference(pref);
|
||||
|
||||
pref = new Preference(this);
|
||||
pref.setTitle(R.string.logcat_buffer);
|
||||
pref.setSummary(R.string.logcat_buffer_descr);
|
||||
pref.setKey("logcat_buffer");
|
||||
pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
startActivity(new Intent(SettingsDevelopmentActivity.this, LogcatActivity.class));
|
||||
return true;
|
||||
}
|
||||
});
|
||||
category.addPreference(pref);
|
||||
|
||||
PreferenceCategory info = new PreferenceCategory(this);
|
||||
info.setTitle(R.string.info_button);
|
||||
category.addPreference(info);
|
||||
|
||||
pref = new Preference(this);
|
||||
pref.setTitle(R.string.global_app_allocated_memory);
|
||||
|
||||
long javaAvailMem = (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())/ (1024*1024l);
|
||||
long javaTotal = Runtime.getRuntime().totalMemory() / (1024*1024l);
|
||||
long dalvikSize = android.os.Debug.getNativeHeapAllocatedSize() / (1024*1024l);
|
||||
pref.setSummary(getString(R.string.global_app_allocated_memory_descr, javaAvailMem, javaTotal, dalvikSize));
|
||||
pref.setSelectable(false);
|
||||
//setEnabled(false) creates bad readability on some devices
|
||||
//pref.setEnabled(false);
|
||||
info.addPreference(pref);
|
||||
|
||||
// ActivityManager activityManager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
|
||||
// ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
|
||||
// activityManager.getMemoryInfo(memoryInfo);
|
||||
// long totalSize = memoryInfo.availMem / (1024*1024l);
|
||||
MemoryInfo mem = new Debug.MemoryInfo();
|
||||
Debug.getMemoryInfo(mem);
|
||||
pref = new Preference(this);
|
||||
pref.setTitle(R.string.native_app_allocated_memory);
|
||||
pref.setSummary(getString(R.string.native_app_allocated_memory_descr
|
||||
, mem.nativePrivateDirty / 1024, mem.dalvikPrivateDirty / 1024 , mem.otherPrivateDirty / 1024
|
||||
, mem.nativePss / 1024, mem.dalvikPss / 1024 , mem.otherPss / 1024));
|
||||
pref.setSelectable(false);
|
||||
//setEnabled(false) creates bad readability on some devices
|
||||
//pref.setEnabled(false);
|
||||
info.addPreference(pref);
|
||||
|
||||
final Preference agpspref = new Preference(this);
|
||||
agpspref.setTitle(R.string.agps_info);
|
||||
if (settings.AGPS_DATA_LAST_TIME_DOWNLOADED.get() != 0L) {
|
||||
SimpleDateFormat prt = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
||||
agpspref.setSummary(getString(R.string.agps_data_last_downloaded, prt.format(settings.AGPS_DATA_LAST_TIME_DOWNLOADED.get())));
|
||||
} else {
|
||||
agpspref.setSummary(getString(R.string.agps_data_last_downloaded, "--"));
|
||||
}
|
||||
agpspref.setSelectable(true);
|
||||
//setEnabled(false) creates bad readability on some devices
|
||||
//pref.setEnabled(false);
|
||||
agpspref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
if(getMyApplication().getSettings().isInternetConnectionAvailable(true)) {
|
||||
getMyApplication().getLocationProvider().redownloadAGPS();
|
||||
SimpleDateFormat prt = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
||||
agpspref.setSummary(getString(R.string.agps_data_last_downloaded, prt.format(settings.AGPS_DATA_LAST_TIME_DOWNLOADED.get())));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
info.addPreference(agpspref);
|
||||
|
||||
SunriseSunset sunriseSunset = getMyApplication().getDaynightHelper().getSunriseSunset();
|
||||
pref = new Preference(this);
|
||||
pref.setTitle(R.string.day_night_info);
|
||||
if (sunriseSunset != null && sunriseSunset.getSunrise() != null && sunriseSunset.getSunset() != null) {
|
||||
SimpleDateFormat prt = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
||||
pref.setSummary(getString(R.string.day_night_info_description, prt.format(sunriseSunset.getSunrise()),
|
||||
prt.format(sunriseSunset.getSunset())));
|
||||
} else {
|
||||
pref.setSummary(getString(R.string.day_night_info_description, "null", "null"));
|
||||
}
|
||||
pref.setSelectable(false);
|
||||
//setEnabled(false) creates bad readability on some devices
|
||||
//pref.setEnabled(false);
|
||||
info.addPreference(pref);
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
package net.osmand.plus.dialogs;
|
||||
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.view.View;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.CompoundButton;
|
||||
|
@ -20,7 +19,7 @@ import net.osmand.plus.OsmandPlugin;
|
|||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.activities.MapActivityLayers;
|
||||
import net.osmand.plus.activities.PluginActivity;
|
||||
import net.osmand.plus.activities.PluginsFragment;
|
||||
import net.osmand.plus.helpers.GpxUiHelper;
|
||||
import net.osmand.plus.poi.PoiFiltersHelper;
|
||||
import net.osmand.plus.poi.PoiUIFilter;
|
||||
|
@ -149,9 +148,7 @@ final class MapLayerMenuListener extends OnRowItemClick {
|
|||
settings.SHOW_MAP_MARKERS.set(isChecked);
|
||||
} else if (itemId == R.string.layer_map) {
|
||||
if (OsmandPlugin.getEnabledPlugin(OsmandRasterMapsPlugin.class) == null) {
|
||||
Intent intent = new Intent(mapActivity, PluginActivity.class);
|
||||
intent.putExtra(PluginActivity.EXTRA_PLUGIN_ID, OsmandRasterMapsPlugin.ID);
|
||||
mapActivity.startActivity(intent);
|
||||
PluginsFragment.showInstance(mapActivity.getSupportFragmentManager());
|
||||
} else {
|
||||
ContextMenuItem it = adapter.getItem(pos);
|
||||
mapActivity.getMapLayers().selectMapLayer(mapActivity.getMapView(), it, adapter);
|
||||
|
|
|
@ -6,6 +6,7 @@ import android.content.Intent;
|
|||
import android.content.res.Resources;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.util.TypedValue;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
|
@ -25,6 +26,8 @@ import net.osmand.plus.R;
|
|||
import net.osmand.plus.Version;
|
||||
import net.osmand.plus.activities.LocalIndexHelper.LocalIndexType;
|
||||
import net.osmand.plus.activities.LocalIndexInfo;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.activities.PluginsFragment;
|
||||
import net.osmand.plus.chooseplan.ChoosePlanDialogFragment;
|
||||
import net.osmand.plus.download.CityItem;
|
||||
import net.osmand.plus.download.CustomIndexItem;
|
||||
|
@ -343,8 +346,7 @@ public class ItemViewHolder {
|
|||
ChoosePlanDialogFragment.showSeaDepthMapsInstance(context.getSupportFragmentManager());
|
||||
break;
|
||||
case ASK_FOR_SEAMARKS_PLUGIN:
|
||||
context.startActivity(new Intent(context, context.getMyApplication().getAppCustomization()
|
||||
.getPluginsActivity()));
|
||||
showPluginsScreen();
|
||||
Toast.makeText(context.getApplicationContext(),
|
||||
context.getString(R.string.activate_seamarks_plugin), Toast.LENGTH_SHORT).show();
|
||||
break;
|
||||
|
@ -352,8 +354,7 @@ public class ItemViewHolder {
|
|||
ChoosePlanDialogFragment.showHillshadeSrtmPluginInstance(context.getSupportFragmentManager());
|
||||
break;
|
||||
case ASK_FOR_SRTM_PLUGIN_ENABLE:
|
||||
context.startActivity(new Intent(context, context.getMyApplication().getAppCustomization()
|
||||
.getPluginsActivity()));
|
||||
showPluginsScreen();
|
||||
Toast.makeText(context, context.getString(R.string.activate_srtm_plugin),
|
||||
Toast.LENGTH_SHORT).show();
|
||||
break;
|
||||
|
@ -361,6 +362,13 @@ public class ItemViewHolder {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void showPluginsScreen() {
|
||||
Bundle params = new Bundle();
|
||||
params.putBoolean(PluginsFragment.OPEN_PLUGINS, true);
|
||||
Intent intent = context.getIntent();
|
||||
MapActivity.launchMapActivityMoveToTop(context, intent != null ? intent.getExtras() : null, null, params);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
final boolean isDownloading = context.getDownloadThread().isDownloading(item);
|
||||
|
|
|
@ -13,6 +13,7 @@ import android.graphics.Typeface;
|
|||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.SpannableString;
|
||||
import android.text.style.StyleSpan;
|
||||
import android.view.ContextThemeWrapper;
|
||||
|
@ -80,6 +81,7 @@ import net.osmand.plus.OsmAndConstants;
|
|||
import net.osmand.plus.OsmAndFormatter;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.OsmandPlugin;
|
||||
import net.osmand.plus.activities.PluginsFragment;
|
||||
import net.osmand.plus.helpers.enums.MetricsConstants;
|
||||
import net.osmand.plus.helpers.enums.SpeedConstants;
|
||||
import net.osmand.plus.settings.backend.CommonPreference;
|
||||
|
@ -90,7 +92,6 @@ import net.osmand.plus.Version;
|
|||
import net.osmand.plus.activities.ActivityResultListener;
|
||||
import net.osmand.plus.activities.ActivityResultListener.OnActivityResultListener;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.activities.PluginActivity;
|
||||
import net.osmand.plus.activities.SettingsActivity;
|
||||
import net.osmand.plus.dialogs.ConfigureMapMenu;
|
||||
import net.osmand.plus.dialogs.GpxAppearanceAdapter;
|
||||
|
@ -649,9 +650,9 @@ public class GpxUiHelper {
|
|||
confirm.setPositiveButton(R.string.shared_string_ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Intent intent = new Intent(activity, PluginActivity.class);
|
||||
intent.putExtra(PluginActivity.EXTRA_PLUGIN_ID, OsmandMonitoringPlugin.ID);
|
||||
activity.startActivity(intent);
|
||||
Bundle params = new Bundle();
|
||||
params.putBoolean(PluginsFragment.OPEN_PLUGINS, true);
|
||||
MapActivity.launchMapActivityMoveToTop(activity, null, null, params);
|
||||
}
|
||||
});
|
||||
confirm.setNegativeButton(R.string.shared_string_cancel, null);
|
||||
|
|
|
@ -11,16 +11,18 @@ import net.osmand.PlatformUtil;
|
|||
import net.osmand.data.LatLon;
|
||||
import net.osmand.data.PointDescription;
|
||||
import net.osmand.map.TileSourceManager;
|
||||
import net.osmand.plus.mapsource.EditMapSourceDialogFragment;
|
||||
import net.osmand.plus.search.QuickSearchDialogFragment;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.MapMarkersHelper;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.activities.PluginsFragment;
|
||||
import net.osmand.plus.dashboard.DashboardOnMap.DashboardType;
|
||||
import net.osmand.plus.mapmarkers.MapMarkersDialogFragment;
|
||||
import net.osmand.plus.mapsource.EditMapSourceDialogFragment;
|
||||
import net.osmand.plus.osmedit.OsmEditingFragment;
|
||||
import net.osmand.plus.search.QuickSearchDialogFragment;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.plus.settings.fragments.BaseSettingsFragment;
|
||||
import net.osmand.plus.settings.fragments.BaseSettingsFragment.SettingsScreenType;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
@ -58,6 +60,9 @@ public class IntentHelper {
|
|||
if (!applied) {
|
||||
applied = parseSendIntent();
|
||||
}
|
||||
if (!applied) {
|
||||
applied = parseOAuthIntent();
|
||||
}
|
||||
return applied;
|
||||
}
|
||||
|
||||
|
@ -207,10 +212,22 @@ public class IntentHelper {
|
|||
mapActivity.setIntent(null);
|
||||
}
|
||||
if (intent.hasExtra(BaseSettingsFragment.OPEN_SETTINGS)) {
|
||||
String settingsType = intent.getStringExtra(BaseSettingsFragment.OPEN_SETTINGS);
|
||||
String appMode = intent.getStringExtra(BaseSettingsFragment.APP_MODE_KEY);
|
||||
if (BaseSettingsFragment.OPEN_CONFIG_PROFILE.equals(settingsType)) {
|
||||
BaseSettingsFragment.showInstance(mapActivity, SettingsScreenType.CONFIGURE_PROFILE, ApplicationMode.valueOfStringKey(appMode, null));
|
||||
String settingsTypeName = intent.getStringExtra(BaseSettingsFragment.OPEN_SETTINGS);
|
||||
if (!Algorithms.isEmpty(settingsTypeName)) {
|
||||
try {
|
||||
SettingsScreenType screenType = SettingsScreenType.valueOf(settingsTypeName);
|
||||
BaseSettingsFragment.showInstance(mapActivity, screenType, ApplicationMode.valueOfStringKey(appMode, null));
|
||||
} catch (IllegalArgumentException e) {
|
||||
LOG.error("error", e);
|
||||
}
|
||||
}
|
||||
mapActivity.setIntent(null);
|
||||
}
|
||||
if (intent.hasExtra(PluginsFragment.OPEN_PLUGINS)) {
|
||||
boolean openPlugins = intent.getBooleanExtra(PluginsFragment.OPEN_PLUGINS, false);
|
||||
if (openPlugins) {
|
||||
PluginsFragment.showInstance(mapActivity.getSupportFragmentManager());
|
||||
}
|
||||
mapActivity.setIntent(null);
|
||||
}
|
||||
|
@ -271,6 +288,23 @@ public class IntentHelper {
|
|||
return false;
|
||||
}
|
||||
|
||||
private boolean parseOAuthIntent() {
|
||||
Intent intent = mapActivity.getIntent();
|
||||
if (intent != null && intent.getData() != null) {
|
||||
Uri uri = intent.getData();
|
||||
if (uri.toString().startsWith("osmand-oauth")) {
|
||||
OsmEditingFragment fragment = mapActivity.getOsmEditingFragment();
|
||||
if (fragment != null) {
|
||||
String oauthVerifier = uri.getQueryParameter("oauth_verifier");
|
||||
fragment.authorize(oauthVerifier);
|
||||
mapActivity.setIntent(null);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean handleSendText(Intent intent) {
|
||||
String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
|
||||
if (!Algorithms.isEmpty(sharedText)) {
|
||||
|
|
|
@ -34,8 +34,8 @@ import net.osmand.plus.dialogs.ImportGpxBottomSheetDialogFragment;
|
|||
import net.osmand.plus.helpers.GpxUiHelper;
|
||||
import net.osmand.plus.helpers.GpxUiHelper.GPXInfo;
|
||||
import net.osmand.plus.measurementtool.MeasurementToolFragment;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.SettingsItem;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsHelper;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsItem;
|
||||
import net.osmand.plus.views.OsmandMapTileView;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
|
|
|
@ -13,12 +13,12 @@ import net.osmand.FileUtils;
|
|||
import net.osmand.IndexConstants;
|
||||
import net.osmand.plus.CustomOsmandPlugin;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.CheckDuplicatesListener;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.PluginSettingsItem;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.ProfileSettingsItem;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.SettingsCollectListener;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.SettingsImportListener;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.SettingsItem;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsHelper.CheckDuplicatesListener;
|
||||
import net.osmand.plus.settings.backend.backup.PluginSettingsItem;
|
||||
import net.osmand.plus.settings.backend.backup.ProfileSettingsItem;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsHelper.SettingsCollectListener;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsHelper.SettingsImportListener;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsItem;
|
||||
import net.osmand.plus.settings.fragments.ImportSettingsFragment;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import net.osmand.plus.activities.LocalIndexHelper;
|
|||
import net.osmand.plus.activities.LocalIndexHelper.LocalIndexType;
|
||||
import net.osmand.plus.activities.LocalIndexInfo;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.activities.PluginsFragment;
|
||||
import net.osmand.plus.download.DownloadActivityType;
|
||||
import net.osmand.plus.download.DownloadIndexesThread;
|
||||
import net.osmand.plus.download.DownloadValidationManager;
|
||||
|
@ -110,8 +111,7 @@ public class MapDataMenuController extends MenuController {
|
|||
activity.getString(R.string.activate_srtm_plugin), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
} else {
|
||||
activity.startActivity(new Intent(activity, activity.getMyApplication().getAppCustomization()
|
||||
.getPluginsActivity()));
|
||||
PluginsFragment.showInstance(activity.getSupportFragmentManager());
|
||||
Toast.makeText(activity, activity.getString(R.string.activate_srtm_plugin),
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
|
|
@ -6,10 +6,13 @@ import android.graphics.drawable.Drawable;
|
|||
import android.os.Bundle;
|
||||
import android.text.SpannableString;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.settings.backend.OsmAndAppCustomization;
|
||||
import net.osmand.plus.OsmandPlugin;
|
||||
|
@ -32,6 +35,7 @@ import net.osmand.plus.widgets.style.CustomTypefaceSpan;
|
|||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
import static net.osmand.plus.activities.PluginInfoFragment.PLUGIN_INFO;
|
||||
import static net.osmand.plus.settings.backend.OsmandSettings.MONTHLY_DIRECTORY;
|
||||
import static net.osmand.plus.settings.backend.OsmandSettings.REC_DIRECTORY;
|
||||
import static net.osmand.plus.monitoring.OsmandMonitoringPlugin.MINUTES;
|
||||
|
@ -46,6 +50,35 @@ public class MonitoringSettingsFragment extends BaseSettingsFragment
|
|||
private static final String OPEN_TRACKS = "open_tracks";
|
||||
private static final String SAVE_GLOBAL_TRACK_INTERVAL = "save_global_track_interval";
|
||||
|
||||
boolean showSwitchProfile = false;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Bundle args = getArguments();
|
||||
if (args != null) {
|
||||
showSwitchProfile = args.getBoolean(PLUGIN_INFO, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createToolbar(LayoutInflater inflater, View view) {
|
||||
super.createToolbar(inflater, view);
|
||||
|
||||
View switchProfile = view.findViewById(R.id.profile_button);
|
||||
if (switchProfile != null) {
|
||||
AndroidUiHelper.updateVisibility(switchProfile, showSwitchProfile);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle buildArguments() {
|
||||
Bundle args = super.buildArguments();
|
||||
args.putBoolean(PLUGIN_INFO, showSwitchProfile);
|
||||
return args;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupPreferences() {
|
||||
setupSaveTrackToGpxPref();
|
||||
|
|
|
@ -42,7 +42,7 @@ import net.osmand.plus.activities.SavingTrackHelper.SaveGpxResult;
|
|||
import net.osmand.plus.dashboard.tools.DashFragmentData;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.plus.settings.fragments.BaseSettingsFragment;
|
||||
import net.osmand.plus.settings.fragments.BaseSettingsFragment.SettingsScreenType;
|
||||
import net.osmand.plus.views.OsmandMapLayer.DrawSettings;
|
||||
import net.osmand.plus.views.OsmandMapTileView;
|
||||
import net.osmand.plus.views.layers.MapInfoLayer;
|
||||
|
@ -166,15 +166,9 @@ public class OsmandMonitoringPlugin extends OsmandPlugin {
|
|||
public static final int[] MINUTES = new int[] {2, 3, 5};
|
||||
public static final int[] MAX_INTERVAL_TO_SEND_MINUTES = new int[] {1, 2, 5, 10, 15, 20, 30, 60, 90, 2 * 60, 3 * 60, 4 * 60, 6 * 60, 12 * 60, 24 * 60};
|
||||
|
||||
|
||||
@Override
|
||||
public Class<? extends Activity> getSettingsActivity() {
|
||||
return SettingsMonitoringActivity.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends BaseSettingsFragment> getSettingsFragment() {
|
||||
return MonitoringSettingsFragment.class;
|
||||
public SettingsScreenType getSettingsScreenType() {
|
||||
return SettingsScreenType.MONITORING_SETTINGS;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,325 +0,0 @@
|
|||
package net.osmand.plus.monitoring;
|
||||
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.preference.EditTextPreference;
|
||||
import android.preference.ListPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.Preference.OnPreferenceClickListener;
|
||||
import android.preference.PreferenceCategory;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.text.SpannableString;
|
||||
import android.text.style.StyleSpan;
|
||||
import android.util.TypedValue;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
|
||||
import net.osmand.plus.OsmAndFormatter;
|
||||
import net.osmand.plus.OsmAndTaskManager.OsmAndTaskRunnable;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.activities.SavingTrackHelper;
|
||||
import net.osmand.plus.activities.SettingsBaseActivity;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static net.osmand.plus.settings.backend.OsmandSettings.MONTHLY_DIRECTORY;
|
||||
import static net.osmand.plus.settings.backend.OsmandSettings.REC_DIRECTORY;
|
||||
|
||||
public class SettingsMonitoringActivity extends SettingsBaseActivity {
|
||||
|
||||
public static final String PROFILE_STRING_KEY = "string_key";
|
||||
|
||||
private CheckBoxPreference routeServiceEnabled;
|
||||
private BroadcastReceiver broadcastReceiver;
|
||||
|
||||
public static final int[] BG_SECONDS = new int[]{0, 30, 60, 90};
|
||||
public static final int[] BG_MINUTES = new int[]{2, 3, 5, 10, 15, 30, 60, 90};
|
||||
private static final int[] SECONDS = OsmandMonitoringPlugin.SECONDS;
|
||||
private static final int[] MINUTES = OsmandMonitoringPlugin.MINUTES;
|
||||
private static final int[] MAX_INTERVAL_TO_SEND_MINUTES = OsmandMonitoringPlugin.MAX_INTERVAL_TO_SEND_MINUTES;
|
||||
|
||||
public SettingsMonitoringActivity() {
|
||||
super(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
((OsmandApplication) getApplication()).applyTheme(this);
|
||||
requestWindowFeature(Window.FEATURE_PROGRESS);
|
||||
super.onCreate(savedInstanceState);
|
||||
setProgressVisibility(false);
|
||||
getToolbar().setTitle(R.string.monitoring_settings);
|
||||
PreferenceScreen grp = getPreferenceScreen();
|
||||
|
||||
createLoggingSection(grp);
|
||||
createLiveSection(grp);
|
||||
createNotificationSection(grp);
|
||||
|
||||
Intent intent = getIntent();
|
||||
if (intent != null && intent.hasExtra(PROFILE_STRING_KEY)) {
|
||||
String modeName = intent.getStringExtra(PROFILE_STRING_KEY);
|
||||
selectedAppMode = ApplicationMode.valueOfStringKey(modeName, ApplicationMode.CAR);
|
||||
} else {
|
||||
selectAppModeDialog().show();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void createLoggingSection(PreferenceScreen grp) {
|
||||
PreferenceCategory cat = new PreferenceCategory(this);
|
||||
cat.setTitle(R.string.save_track_to_gpx_globally);
|
||||
grp.addPreference(cat);
|
||||
|
||||
Preference globalrecord = new Preference(this);
|
||||
globalrecord.setTitle(R.string.save_track_to_gpx_globally_headline);
|
||||
globalrecord.setSummary(R.string.save_track_to_gpx_globally_descr);
|
||||
globalrecord.setSelectable(false);
|
||||
//setEnabled(false) creates bad readability on some devices
|
||||
//globalrecord.setEnabled(false);
|
||||
cat.addPreference(globalrecord);
|
||||
|
||||
if(settings.SAVE_GLOBAL_TRACK_REMEMBER.get()) {
|
||||
cat.addPreference(createTimeListPreference(settings.SAVE_GLOBAL_TRACK_INTERVAL, SECONDS,
|
||||
MINUTES, 1000, settings.SAVE_GLOBAL_TRACK_REMEMBER, R.string.save_global_track_interval, R.string.save_global_track_interval_descr));
|
||||
}
|
||||
|
||||
Preference pref = new Preference(this);
|
||||
pref.setTitle(R.string.save_current_track);
|
||||
pref.setSummary(getMyApplication().getString(R.string.save_current_track_descr)
|
||||
+ " (" + OsmAndFormatter.getFormattedDistance(getMyApplication().getSavingTrackHelper().getDistance(), getMyApplication()) + ")");
|
||||
pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
SavingTrackHelper helper = getMyApplication().getSavingTrackHelper();
|
||||
if (helper.hasDataToSave()) {
|
||||
saveCurrentTracks(helper);
|
||||
} else {
|
||||
helper.close();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
cat.addPreference(pref);
|
||||
|
||||
cat.addPreference(createCheckBoxPreference(settings.SAVE_TRACK_TO_GPX, R.string.save_track_to_gpx,
|
||||
R.string.save_track_to_gpx_descrp));
|
||||
cat.addPreference(createTimeListPreference(settings.SAVE_TRACK_INTERVAL, SECONDS,
|
||||
MINUTES, 1000, R.string.save_track_interval, R.string.save_track_interval_descr));
|
||||
String[] names;
|
||||
Float[] floatValues;
|
||||
floatValues = new Float[] {0.f, 2.0f, 5.0f, 10.0f, 20.0f, 30.0f, 50.0f};
|
||||
names = new String[floatValues.length];
|
||||
names[0] = getString(R.string.shared_string_not_selected);
|
||||
for(int i = 1; i < floatValues.length; i++) {
|
||||
names[i] = floatValues[i].intValue() + " " + getString(R.string.m);
|
||||
}
|
||||
cat.addPreference(createListPreference(settings.SAVE_TRACK_MIN_DISTANCE, names, floatValues,
|
||||
R.string.save_track_min_distance, R.string.save_track_min_distance_descr));
|
||||
floatValues = new Float[] {0.f, 1.0f, 2.0f, 5.0f, 10.0f, 15.0f, 20.0f, 50.0f, 100.0f};
|
||||
names = new String[floatValues.length];
|
||||
names[0] = getString(R.string.shared_string_not_selected);
|
||||
for(int i = 1; i < floatValues.length; i++) {
|
||||
names[i] = floatValues[i].intValue() + " " + getString(R.string.m) + " (" + Math.round(floatValues[i]/0.3048f) + " " + getString(R.string.foot) + ")";
|
||||
}
|
||||
cat.addPreference(createListPreference(settings.SAVE_TRACK_PRECISION, names, floatValues,
|
||||
R.string.save_track_precision, R.string.save_track_precision_descr));
|
||||
floatValues = new Float[] {0.f, 0.000001f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f};
|
||||
names = new String[floatValues.length];
|
||||
names[0] = getString(R.string.shared_string_not_selected);
|
||||
names[1] = "> 0"; // This option for the GPS chipset motion detection
|
||||
for(int i = 2; i < floatValues.length; i++) {
|
||||
names[i] = floatValues[i].intValue() + " " + getString(R.string.km_h);
|
||||
floatValues[i] = floatValues[i] / 3.6f;
|
||||
}
|
||||
cat.addPreference(createListPreference(settings.SAVE_TRACK_MIN_SPEED, names, floatValues,
|
||||
R.string.save_track_min_speed, R.string.save_track_min_speed_descr));
|
||||
cat.addPreference(createCheckBoxPreference(settings.AUTO_SPLIT_RECORDING, R.string.auto_split_recording_title,
|
||||
R.string.auto_split_recording_descr));
|
||||
cat.addPreference(createCheckBoxPreference(settings.DISABLE_RECORDING_ONCE_APP_KILLED, R.string.disable_recording_once_app_killed,
|
||||
R.string.disable_recording_once_app_killed_descrp));
|
||||
cat.addPreference(createCheckBoxPreference(settings.SAVE_HEADING_TO_GPX, R.string.save_heading,
|
||||
R.string.save_heading_descr));
|
||||
|
||||
Integer[] intValues = new Integer[]{REC_DIRECTORY, MONTHLY_DIRECTORY};
|
||||
names = new String[intValues.length];
|
||||
names[0] = getString(R.string.store_tracks_in_rec_directory);
|
||||
names[1] = getString(R.string.store_tracks_in_monthly_directories);
|
||||
// names[2] = getString(R.string.store_tracks_in_daily_directories);
|
||||
cat.addPreference(createListPreference(settings.TRACK_STORAGE_DIRECTORY, names, intValues,
|
||||
R.string.track_storage_directory, R.string.track_storage_directory_descrp));
|
||||
}
|
||||
|
||||
|
||||
private void createLiveSection(PreferenceScreen grp) {
|
||||
PreferenceCategory cat;
|
||||
cat = new PreferenceCategory(this);
|
||||
cat.setTitle(R.string.live_monitoring_m);
|
||||
grp.addPreference(cat);
|
||||
|
||||
EditTextPreference urlPreference = createEditTextPreference(settings.LIVE_MONITORING_URL, R.string.live_monitoring_url,
|
||||
R.string.live_monitoring_url_descr);
|
||||
urlPreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
if (Algorithms.isValidMessageFormat((String) newValue)) {
|
||||
return SettingsMonitoringActivity.super.onPreferenceChange(preference, newValue);
|
||||
} else {
|
||||
Toast.makeText(SettingsMonitoringActivity.this, R.string.wrong_format, Toast.LENGTH_SHORT).show();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
cat.addPreference(urlPreference);
|
||||
final CheckBoxPreference liveMonitoring = createCheckBoxPreference(settings.LIVE_MONITORING, R.string.live_monitoring_m,
|
||||
R.string.live_monitoring_m_descr);
|
||||
cat.addPreference(liveMonitoring);
|
||||
cat.addPreference(createTimeListPreference(settings.LIVE_MONITORING_INTERVAL, SECONDS,
|
||||
MINUTES, 1000, R.string.live_monitoring_interval, R.string.live_monitoring_interval_descr));
|
||||
cat.addPreference(createTimeListPreference(settings.LIVE_MONITORING_MAX_INTERVAL_TO_SEND, null,
|
||||
MAX_INTERVAL_TO_SEND_MINUTES, 1000, R.string.live_monitoring_max_interval_to_send, R.string.live_monitoring_max_interval_to_send_desrc));
|
||||
}
|
||||
|
||||
private void createNotificationSection(PreferenceScreen grp) {
|
||||
PreferenceCategory cat;
|
||||
cat = new PreferenceCategory(this);
|
||||
cat.setTitle(R.string.shared_string_notifications);
|
||||
grp.addPreference(cat);
|
||||
|
||||
final CheckBoxPreference tripRecording = createCheckBoxPreference(settings.SHOW_TRIP_REC_NOTIFICATION, R.string.trip_rec_notification_settings,
|
||||
R.string.trip_rec_notification_settings_desc);
|
||||
cat.addPreference(tripRecording);
|
||||
}
|
||||
|
||||
public void updateAllSettings() {
|
||||
super.updateAllSettings();
|
||||
|
||||
if(routeServiceEnabled != null) {
|
||||
routeServiceEnabled.setChecked(getMyApplication().getNavigationService() != null);
|
||||
}
|
||||
}
|
||||
|
||||
private void saveCurrentTracks(final SavingTrackHelper helper) {
|
||||
setProgressVisibility(true);
|
||||
getMyApplication().getTaskManager().runInBackground(new OsmAndTaskRunnable<Void, Void, Void>() {
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
SavingTrackHelper helper = getMyApplication().getSavingTrackHelper();
|
||||
helper.saveDataToGpx(getMyApplication().getAppCustomization().getTracksDir());
|
||||
helper.close();
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
protected void onPostExecute(Void result) {
|
||||
setProgressVisibility(false);
|
||||
}
|
||||
|
||||
}, (Void) null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if(broadcastReceiver != null) {
|
||||
unregisterReceiver(broadcastReceiver);
|
||||
broadcastReceiver = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
String prefId = preference.getKey();
|
||||
if (preference instanceof ListPreference) {
|
||||
int ind = ((ListPreference) preference).findIndexOfValue((String) newValue);
|
||||
CharSequence entry = ((ListPreference) preference).getEntries()[ind];
|
||||
Map<String, ?> map = getListPrefValues().get(prefId);
|
||||
if (map != null) {
|
||||
newValue = map.get(entry);
|
||||
}
|
||||
}
|
||||
showConfirmDialog(prefId, newValue);
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void showConfirmDialog(final String prefId, final Object newValue) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
|
||||
String appModeName = selectedAppMode.toHumanString();
|
||||
String currentModeText = getString(R.string.apply_to_current_profile, appModeName);
|
||||
int start = currentModeText.indexOf(appModeName);
|
||||
|
||||
SpannableString[] strings = new SpannableString[2];
|
||||
strings[0] = new SpannableString(getString(R.string.apply_to_all_profiles));
|
||||
strings[1] = new SpannableString(currentModeText);
|
||||
strings[1].setSpan(new StyleSpan(Typeface.BOLD), start, start + appModeName.length(), 0);
|
||||
|
||||
final int[] icons = new int[2];
|
||||
icons[0] = R.drawable.ic_action_copy;
|
||||
icons[1] = selectedAppMode.getIconRes();
|
||||
|
||||
final boolean nightMode = !settings.isLightContent();
|
||||
final OsmandApplication app = getMyApplication();
|
||||
final LayoutInflater themedInflater = UiUtilities.getInflater(this, nightMode);
|
||||
|
||||
//set up dialog title
|
||||
View dialogTitle = themedInflater.inflate(R.layout.bottom_sheet_item_simple, null);
|
||||
dialogTitle.findViewById(R.id.icon).setVisibility(View.GONE);
|
||||
TextView tvTitle = dialogTitle.findViewById(R.id.title);
|
||||
tvTitle.setText(R.string.change_default_settings);
|
||||
int textSize = (int) app.getResources().getDimension(R.dimen.dialog_header_text_size);
|
||||
tvTitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
|
||||
builder.setCustomTitle(dialogTitle);
|
||||
|
||||
final ArrayAdapter<SpannableString> singleChoiceAdapter = new ArrayAdapter<SpannableString>(this, R.layout.bottom_sheet_item_simple, R.id.title, strings) {
|
||||
@NonNull
|
||||
@Override
|
||||
public View getView(int position, View convertView, @NonNull ViewGroup parent) {
|
||||
View v = convertView;
|
||||
if (v == null) {
|
||||
v = themedInflater.inflate(R.layout.bottom_sheet_item_simple, parent, false);
|
||||
}
|
||||
int activeColor = nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light;
|
||||
Drawable icon = app.getUIUtilities().getIcon(icons[position], activeColor);
|
||||
((TextView) v.findViewById(R.id.title)).setText(getItem(position));
|
||||
((ImageView) v.findViewById(R.id.icon)).setImageDrawable(icon);
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
builder.setAdapter(singleChoiceAdapter, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
if (which == 0) {
|
||||
settings.setPreferenceForAllModes(prefId, newValue);
|
||||
} else {
|
||||
settings.setPreference(prefId, newValue);
|
||||
}
|
||||
updateAllSettings();
|
||||
}
|
||||
});
|
||||
|
||||
builder.setNegativeButton(R.string.discard_changes, null);
|
||||
AlertDialog dialog = builder.create();
|
||||
dialog.getListView().setDividerHeight(0);
|
||||
dialog.show();
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package net.osmand.plus.osmedit;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
@ -7,31 +8,50 @@ import android.os.Bundle;
|
|||
import android.text.SpannableString;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
|
||||
import net.osmand.plus.settings.backend.OsmAndAppCustomization;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||
import net.osmand.plus.helpers.FontCache;
|
||||
import net.osmand.plus.osmedit.oauth.OsmOAuthAuthorizationAdapter;
|
||||
import net.osmand.plus.settings.backend.OsmAndAppCustomization;
|
||||
import net.osmand.plus.settings.bottomsheets.OsmLoginDataBottomSheet;
|
||||
import net.osmand.plus.settings.fragments.BaseSettingsFragment;
|
||||
import net.osmand.plus.settings.fragments.OnPreferenceChanged;
|
||||
import net.osmand.plus.settings.bottomsheets.OsmLoginDataBottomSheet;
|
||||
import net.osmand.plus.settings.preferences.SwitchPreferenceEx;
|
||||
import net.osmand.plus.widgets.style.CustomTypefaceSpan;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import static net.osmand.plus.myplaces.FavoritesActivity.TAB_ID;
|
||||
import static net.osmand.plus.osmedit.OsmEditingPlugin.OSM_EDIT_TAB;
|
||||
|
||||
public class OsmEditingFragment extends BaseSettingsFragment implements OnPreferenceChanged {
|
||||
|
||||
private static final Log log = PlatformUtil.getLog(OsmEditingFragment.class);
|
||||
|
||||
private static final String OSM_EDITING_INFO = "osm_editing_info";
|
||||
private static final String OPEN_OSM_EDITS = "open_osm_edits";
|
||||
private static final String OSM_LOGIN_DATA = "osm_login_data";
|
||||
private static final String OSM_OAUTH_SUCCESS = "osm_oauth_success";
|
||||
private static final String OSM_OAUTH_CLEAR = "osm_oauth_clear";
|
||||
private static final String OSM_OAUTH_LOGIN = "osm_oauth_login";
|
||||
|
||||
private OsmOAuthAuthorizationAdapter client;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
client = new OsmOAuthAuthorizationAdapter(app);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupPreferences() {
|
||||
|
@ -42,6 +62,7 @@ public class OsmEditingFragment extends BaseSettingsFragment implements OnPrefer
|
|||
setupOfflineEditingPref();
|
||||
setupOsmEditsDescrPref();
|
||||
setupOsmEditsPref();
|
||||
setupOAuthPrefs();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -73,7 +94,7 @@ public class OsmEditingFragment extends BaseSettingsFragment implements OnPrefer
|
|||
Drawable enabled = getActiveIcon(R.drawable.ic_world_globe_dark);
|
||||
Drawable icon = getPersistentPrefIcon(enabled, disabled);
|
||||
|
||||
SwitchPreferenceEx offlineEditingPref = (SwitchPreferenceEx) findPreference(settings.OFFLINE_EDITION.getId());
|
||||
SwitchPreferenceEx offlineEditingPref = findPreference(settings.OFFLINE_EDITION.getId());
|
||||
offlineEditingPref.setDescription(getString(R.string.offline_edition_descr));
|
||||
offlineEditingPref.setIcon(icon);
|
||||
}
|
||||
|
@ -101,9 +122,37 @@ public class OsmEditingFragment extends BaseSettingsFragment implements OnPrefer
|
|||
createProfile.setIcon(getActiveIcon(R.drawable.ic_action_folder));
|
||||
}
|
||||
|
||||
private void setupOAuthPrefs() {
|
||||
Context ctx = getContext();
|
||||
if (ctx != null) {
|
||||
PreferenceScreen screen = getPreferenceScreen();
|
||||
if (client.isValidToken()) {
|
||||
Preference prefOAuth = new Preference(ctx);
|
||||
prefOAuth.setTitle(R.string.osm_authorization_success);
|
||||
prefOAuth.setSummary(R.string.osm_authorization_success);
|
||||
prefOAuth.setKey(OSM_OAUTH_SUCCESS);
|
||||
|
||||
Preference prefClearToken = new Preference(ctx);
|
||||
prefClearToken.setTitle(R.string.shared_string_logoff);
|
||||
prefClearToken.setSummary(R.string.clear_osm_token);
|
||||
prefClearToken.setKey(OSM_OAUTH_CLEAR);
|
||||
|
||||
screen.addPreference(prefOAuth);
|
||||
screen.addPreference(prefClearToken);
|
||||
} else {
|
||||
Preference prefOAuth = new Preference(ctx);
|
||||
prefOAuth.setTitle(R.string.perform_oauth_authorization);
|
||||
prefOAuth.setSummary(R.string.perform_oauth_authorization_description);
|
||||
prefOAuth.setKey(OSM_OAUTH_LOGIN);
|
||||
screen.addPreference(prefOAuth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
if (OPEN_OSM_EDITS.equals(preference.getKey())) {
|
||||
String prefId = preference.getKey();
|
||||
if (OPEN_OSM_EDITS.equals(prefId)) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putInt(TAB_ID, OSM_EDIT_TAB);
|
||||
|
||||
|
@ -113,12 +162,29 @@ public class OsmEditingFragment extends BaseSettingsFragment implements OnPrefer
|
|||
favorites.putExtra(MapActivity.INTENT_PARAMS, bundle);
|
||||
startActivity(favorites);
|
||||
return true;
|
||||
} else if (OSM_LOGIN_DATA.equals(preference.getKey())) {
|
||||
} else if (OSM_LOGIN_DATA.equals(prefId)) {
|
||||
FragmentManager fragmentManager = getFragmentManager();
|
||||
if (fragmentManager != null) {
|
||||
OsmLoginDataBottomSheet.showInstance(fragmentManager, OSM_LOGIN_DATA, this, false, getSelectedAppMode());
|
||||
return true;
|
||||
}
|
||||
} else if (OSM_OAUTH_CLEAR.equals(prefId)) {
|
||||
settings.USER_ACCESS_TOKEN.set("");
|
||||
settings.USER_ACCESS_TOKEN_SECRET.set("");
|
||||
|
||||
client.resetToken();
|
||||
client = new OsmOAuthAuthorizationAdapter(app);
|
||||
|
||||
app.showShortToastMessage(R.string.osm_edit_logout_success);
|
||||
updateAllSettings();
|
||||
return true;
|
||||
} else if (OSM_OAUTH_LOGIN.equals(prefId)) {
|
||||
View view = getView();
|
||||
if (view != null) {
|
||||
ViewGroup appBarLayout = view.findViewById(R.id.appbar);
|
||||
client.startOAuth(appBarLayout);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return super.onPreferenceClick(preference);
|
||||
}
|
||||
|
@ -130,4 +196,11 @@ public class OsmEditingFragment extends BaseSettingsFragment implements OnPrefer
|
|||
nameAndPasswordPref.setSummary(settings.USER_NAME.get());
|
||||
}
|
||||
}
|
||||
|
||||
public void authorize(String oauthVerifier) {
|
||||
if (client != null) {
|
||||
client.authorize(oauthVerifier);
|
||||
}
|
||||
updateAllSettings();
|
||||
}
|
||||
}
|
|
@ -13,9 +13,11 @@ import android.widget.ArrayAdapter;
|
|||
import android.widget.EditText;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.data.Amenity;
|
||||
|
@ -23,13 +25,11 @@ import net.osmand.data.MapObject;
|
|||
import net.osmand.data.TransportStop;
|
||||
import net.osmand.osm.PoiType;
|
||||
import net.osmand.osm.edit.Entity;
|
||||
import net.osmand.plus.*;
|
||||
import net.osmand.plus.ContextMenuAdapter;
|
||||
import net.osmand.plus.ContextMenuAdapter.ItemClickListener;
|
||||
import net.osmand.plus.ContextMenuItem;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.OsmandPlugin;
|
||||
import net.osmand.plus.settings.backend.OsmandPreference;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.activities.EnumAdapter;
|
||||
import net.osmand.plus.activities.EnumAdapter.IEnumWithResource;
|
||||
|
@ -42,16 +42,21 @@ import net.osmand.plus.myplaces.AvailableGPXFragment.GpxInfo;
|
|||
import net.osmand.plus.myplaces.FavoritesActivity;
|
||||
import net.osmand.plus.osmedit.OsmPoint.Action;
|
||||
import net.osmand.plus.quickaction.QuickActionType;
|
||||
import net.osmand.plus.settings.backend.OsmandPreference;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.plus.settings.fragments.BaseSettingsFragment;
|
||||
import net.osmand.plus.settings.fragments.BaseSettingsFragment.SettingsScreenType;
|
||||
import net.osmand.plus.views.OsmandMapTileView;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static net.osmand.aidlapi.OsmAndCustomizationConstants.*;
|
||||
import static net.osmand.aidlapi.OsmAndCustomizationConstants.MAP_CONTEXT_MENU_CREATE_POI;
|
||||
import static net.osmand.aidlapi.OsmAndCustomizationConstants.MAP_CONTEXT_MENU_OPEN_OSM_NOTE;
|
||||
import static net.osmand.aidlapi.OsmAndCustomizationConstants.OSM_EDITS;
|
||||
import static net.osmand.aidlapi.OsmAndCustomizationConstants.OSM_NOTES;
|
||||
import static net.osmand.plus.ContextMenuAdapter.makeDeleteAction;
|
||||
|
||||
|
||||
|
@ -193,13 +198,8 @@ public class OsmEditingPlugin extends OsmandPlugin {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Activity> getSettingsActivity() {
|
||||
return SettingsOsmEditingActivity.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends BaseSettingsFragment> getSettingsFragment() {
|
||||
return OsmEditingFragment.class;
|
||||
public SettingsScreenType getSettingsScreenType() {
|
||||
return SettingsScreenType.OPEN_STREET_MAP_EDITING;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,189 +0,0 @@
|
|||
package net.osmand.plus.osmedit;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.StrictMode;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.preference.DialogPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.Preference.OnPreferenceClickListener;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import com.github.scribejava.core.model.OAuthAsyncRequestCallback;
|
||||
import com.github.scribejava.core.model.Response;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.OsmandPlugin;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.activities.SettingsBaseActivity;
|
||||
import net.osmand.plus.osmedit.oauth.OsmOAuthAuthorizationAdapter;
|
||||
import net.osmand.plus.settings.backend.OsmAndAppCustomization;
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class SettingsOsmEditingActivity extends SettingsBaseActivity {
|
||||
private OsmOAuthAuthorizationAdapter client;
|
||||
private static final Log log = PlatformUtil.getLog(SettingsOsmEditingActivity.class);
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
|
||||
.detectDiskReads()
|
||||
.detectDiskWrites()
|
||||
.detectNetwork()
|
||||
.penaltyLog()
|
||||
.build());
|
||||
|
||||
((OsmandApplication) getApplication()).applyTheme(this);
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
client = new OsmOAuthAuthorizationAdapter(getMyApplication());
|
||||
|
||||
getToolbar().setTitle(R.string.osm_settings);
|
||||
@SuppressWarnings("deprecation")
|
||||
PreferenceScreen grp = getPreferenceScreen();
|
||||
|
||||
DialogPreference loginDialogPreference = new OsmLoginDataDialogPreference(this, null);
|
||||
grp.addPreference(loginDialogPreference);
|
||||
|
||||
CheckBoxPreference poiEdit = createCheckBoxPreference(settings.OFFLINE_EDITION,
|
||||
R.string.offline_edition, R.string.offline_edition_descr);
|
||||
grp.addPreference(poiEdit);
|
||||
|
||||
final Preference pref = new Preference(this);
|
||||
pref.setTitle(R.string.local_openstreetmap_settings);
|
||||
pref.setSummary(R.string.local_openstreetmap_settings_descr);
|
||||
pref.setKey("local_openstreetmap_points");
|
||||
pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
OsmAndAppCustomization appCustomization = getMyApplication().getAppCustomization();
|
||||
final Intent favorites = new Intent(SettingsOsmEditingActivity.this,
|
||||
appCustomization.getFavoritesActivity());
|
||||
favorites.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
|
||||
getMyApplication().getSettings().FAVORITES_TAB.set(R.string.osm_edits);
|
||||
startActivity(favorites);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
grp.addPreference(pref);
|
||||
|
||||
final Preference prefOAuth = new Preference(this);
|
||||
if (client.isValidToken()){
|
||||
prefOAuth.setTitle(R.string.osm_authorization_success);
|
||||
prefOAuth.setSummary(R.string.osm_authorization_success);
|
||||
prefOAuth.setKey("local_openstreetmap_oauth_success");
|
||||
final Preference prefClearToken = new Preference(this);
|
||||
prefClearToken.setTitle(R.string.shared_string_logoff);
|
||||
prefClearToken.setSummary(R.string.clear_osm_token);
|
||||
prefClearToken.setKey("local_openstreetmap_oauth_clear");
|
||||
prefClearToken.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
settings.USER_ACCESS_TOKEN.set("");
|
||||
settings.USER_ACCESS_TOKEN_SECRET.set("");
|
||||
client.resetToken();
|
||||
Toast.makeText(SettingsOsmEditingActivity.this, R.string.osm_edit_logout_success, Toast.LENGTH_SHORT).show();
|
||||
finish();
|
||||
startActivity(getIntent());
|
||||
return true;
|
||||
}
|
||||
});
|
||||
grp.addPreference(prefClearToken);
|
||||
}
|
||||
else {
|
||||
prefOAuth.setTitle(R.string.perform_oauth_authorization);
|
||||
prefOAuth.setSummary(R.string.perform_oauth_authorization_description);
|
||||
prefOAuth.setKey("local_openstreetmap_oauth_login");
|
||||
prefOAuth.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
ViewGroup preferenceView = (ViewGroup)getListView().getChildAt(preference.getOrder());
|
||||
client.startOAuth(preferenceView);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
grp.addPreference(prefOAuth);
|
||||
}
|
||||
|
||||
public class OsmLoginDataDialogPreference extends DialogPreference {
|
||||
private TextView userNameEditText;
|
||||
private TextView passwordEditText;
|
||||
|
||||
public OsmLoginDataDialogPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
setDialogLayoutResource(R.layout.osm_user_login_details);
|
||||
setPositiveButtonText(android.R.string.ok);
|
||||
setNegativeButtonText(android.R.string.cancel);
|
||||
setDialogTitle(R.string.open_street_map_login_and_pass);
|
||||
|
||||
setTitle(R.string.open_street_map_login_and_pass);
|
||||
setSummary(R.string.open_street_map_login_descr);
|
||||
|
||||
setDialogIcon(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBindDialogView(View view) {
|
||||
userNameEditText = (TextView) view.findViewById(R.id.user_name_field);
|
||||
userNameEditText.setText(settings.USER_NAME.get());
|
||||
passwordEditText = (TextView) view.findViewById(R.id.password_field);
|
||||
passwordEditText.setText(settings.USER_PASSWORD.get());
|
||||
super.onBindDialogView(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDialogClosed(boolean positiveResult) {
|
||||
if (positiveResult) {
|
||||
settings.USER_NAME.set(userNameEditText.getText().toString());
|
||||
settings.USER_PASSWORD.set(passwordEditText.getText().toString());
|
||||
new ValidateOsmLoginDetailsTask(SettingsOsmEditingActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class ValidateOsmLoginDetailsTask extends AsyncTask<Void, Void, OsmBugsUtil.OsmBugResult> {
|
||||
private final Context context;
|
||||
|
||||
public ValidateOsmLoginDetailsTask(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OsmBugsUtil.OsmBugResult doInBackground(Void... params) {
|
||||
OsmEditingPlugin plugin = OsmandPlugin.getPlugin(OsmEditingPlugin.class);
|
||||
assert plugin != null;
|
||||
OsmBugsRemoteUtil remoteUtil = plugin.getOsmNotesRemoteUtil();
|
||||
return remoteUtil.validateLoginDetails();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(OsmBugsUtil.OsmBugResult osmBugResult) {
|
||||
String text = osmBugResult.warning != null ? osmBugResult.warning : context.getString(R.string.osm_authorization_success);
|
||||
Toast.makeText(context, text, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
Uri uri = intent.getData();
|
||||
if (uri != null && uri.toString().startsWith("osmand-oauth")) {
|
||||
String oauthVerifier = uri.getQueryParameter("oauth_verifier");
|
||||
client.authorize(oauthVerifier);
|
||||
finish();
|
||||
startActivity(getIntent());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package net.osmand.plus.osmedit;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.OsmandPlugin;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.osmedit.OsmBugsUtil.OsmBugResult;
|
||||
|
||||
public class ValidateOsmLoginDetailsTask extends AsyncTask<Void, Void, OsmBugResult> {
|
||||
|
||||
private OsmandApplication app;
|
||||
|
||||
public ValidateOsmLoginDetailsTask(OsmandApplication app) {
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OsmBugResult doInBackground(Void... params) {
|
||||
OsmEditingPlugin plugin = OsmandPlugin.getPlugin(OsmEditingPlugin.class);
|
||||
assert plugin != null;
|
||||
OsmBugsRemoteUtil remoteUtil = plugin.getOsmNotesRemoteUtil();
|
||||
return remoteUtil.validateLoginDetails();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(OsmBugResult osmBugResult) {
|
||||
if (osmBugResult.warning != null) {
|
||||
app.showToastMessage(osmBugResult.warning);
|
||||
} else {
|
||||
app.showToastMessage(R.string.osm_authorization_success);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,5 +7,7 @@ public enum ExportSettingsType {
|
|||
MAP_SOURCES,
|
||||
CUSTOM_RENDER_STYLE,
|
||||
CUSTOM_ROUTING,
|
||||
AVOID_ROADS
|
||||
AVOID_ROADS,
|
||||
TRACKS,
|
||||
MULTIMEDIA_NOTES
|
||||
}
|
||||
|
|
|
@ -27,12 +27,11 @@ import net.osmand.plus.OsmandApplication;
|
|||
import net.osmand.plus.OsmandPlugin;
|
||||
import net.osmand.plus.Version;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.activities.PluginsActivity;
|
||||
import net.osmand.plus.activities.SettingsActivity;
|
||||
import net.osmand.plus.activities.TrackActivity;
|
||||
import net.osmand.plus.download.DownloadActivity;
|
||||
import net.osmand.plus.importfiles.ImportHelper;
|
||||
import net.osmand.plus.helpers.WaypointHelper;
|
||||
import net.osmand.plus.importfiles.ImportHelper;
|
||||
import net.osmand.plus.myplaces.FavoritesActivity;
|
||||
import net.osmand.plus.routing.RouteCalculationResult;
|
||||
import net.osmand.plus.views.OsmandMapTileView;
|
||||
|
@ -195,10 +194,6 @@ public class OsmAndAppCustomization {
|
|||
return DownloadActivity.class;
|
||||
}
|
||||
|
||||
public Class<? extends Activity> getPluginsActivity() {
|
||||
return PluginsActivity.class;
|
||||
}
|
||||
|
||||
public Class<? extends Activity> getDownloadActivity() {
|
||||
return DownloadActivity.class;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,179 @@
|
|||
package net.osmand.plus.settings.backend.backup;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import net.osmand.data.LatLon;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.helpers.AvoidSpecificRoads;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class AvoidRoadsSettingsItem extends CollectionSettingsItem<AvoidSpecificRoads.AvoidRoadInfo> {
|
||||
|
||||
private OsmandSettings settings;
|
||||
private AvoidSpecificRoads specificRoads;
|
||||
|
||||
public AvoidRoadsSettingsItem(@NonNull OsmandApplication app, @NonNull List<AvoidSpecificRoads.AvoidRoadInfo> items) {
|
||||
super(app, null, items);
|
||||
}
|
||||
|
||||
public AvoidRoadsSettingsItem(@NonNull OsmandApplication app, @Nullable AvoidRoadsSettingsItem baseItem, @NonNull List<AvoidSpecificRoads.AvoidRoadInfo> items) {
|
||||
super(app, baseItem, items);
|
||||
}
|
||||
|
||||
AvoidRoadsSettingsItem(@NonNull OsmandApplication app, @NonNull JSONObject json) throws JSONException {
|
||||
super(app, json);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
settings = app.getSettings();
|
||||
specificRoads = app.getAvoidSpecificRoads();
|
||||
existingItems = new ArrayList<>(specificRoads.getImpassableRoads().values());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public SettingsItemType getType() {
|
||||
return SettingsItemType.AVOID_ROADS;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return "avoid_roads";
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getPublicName(@NonNull Context ctx) {
|
||||
return "avoid_roads";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply() {
|
||||
List<AvoidSpecificRoads.AvoidRoadInfo> newItems = getNewItems();
|
||||
if (!newItems.isEmpty() || !duplicateItems.isEmpty()) {
|
||||
appliedItems = new ArrayList<>(newItems);
|
||||
for (AvoidSpecificRoads.AvoidRoadInfo duplicate : duplicateItems) {
|
||||
if (shouldReplace) {
|
||||
LatLon latLon = new LatLon(duplicate.latitude, duplicate.longitude);
|
||||
if (settings.removeImpassableRoad(latLon)) {
|
||||
settings.addImpassableRoad(duplicate);
|
||||
}
|
||||
} else {
|
||||
settings.addImpassableRoad(renameItem(duplicate));
|
||||
}
|
||||
}
|
||||
for (AvoidSpecificRoads.AvoidRoadInfo avoidRoad : appliedItems) {
|
||||
settings.addImpassableRoad(avoidRoad);
|
||||
}
|
||||
specificRoads.loadImpassableRoads();
|
||||
specificRoads.initRouteObjects(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDuplicate(@NonNull AvoidSpecificRoads.AvoidRoadInfo item) {
|
||||
return existingItems.contains(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldReadOnCollecting() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public AvoidSpecificRoads.AvoidRoadInfo renameItem(@NonNull AvoidSpecificRoads.AvoidRoadInfo item) {
|
||||
int number = 0;
|
||||
while (true) {
|
||||
number++;
|
||||
AvoidSpecificRoads.AvoidRoadInfo renamedItem = new AvoidSpecificRoads.AvoidRoadInfo();
|
||||
renamedItem.name = item.name + "_" + number;
|
||||
if (!isDuplicate(renamedItem)) {
|
||||
renamedItem.id = item.id;
|
||||
renamedItem.latitude = item.latitude;
|
||||
renamedItem.longitude = item.longitude;
|
||||
renamedItem.appModeKey = item.appModeKey;
|
||||
return renamedItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void readItemsFromJson(@NonNull JSONObject json) throws IllegalArgumentException {
|
||||
try {
|
||||
if (!json.has("items")) {
|
||||
return;
|
||||
}
|
||||
JSONArray jsonArray = json.getJSONArray("items");
|
||||
for (int i = 0; i < jsonArray.length(); i++) {
|
||||
JSONObject object = jsonArray.getJSONObject(i);
|
||||
double latitude = object.optDouble("latitude");
|
||||
double longitude = object.optDouble("longitude");
|
||||
String name = object.optString("name");
|
||||
String appModeKey = object.optString("appModeKey");
|
||||
AvoidSpecificRoads.AvoidRoadInfo roadInfo = new AvoidSpecificRoads.AvoidRoadInfo();
|
||||
roadInfo.id = 0;
|
||||
roadInfo.latitude = latitude;
|
||||
roadInfo.longitude = longitude;
|
||||
roadInfo.name = name;
|
||||
if (ApplicationMode.valueOfStringKey(appModeKey, null) != null) {
|
||||
roadInfo.appModeKey = appModeKey;
|
||||
} else {
|
||||
roadInfo.appModeKey = app.getRoutingHelper().getAppMode().getStringKey();
|
||||
}
|
||||
items.add(roadInfo);
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
warnings.add(app.getString(R.string.settings_item_read_error, String.valueOf(getType())));
|
||||
throw new IllegalArgumentException("Json parse error", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void writeItemsToJson(@NonNull JSONObject json) {
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
if (!items.isEmpty()) {
|
||||
try {
|
||||
for (AvoidSpecificRoads.AvoidRoadInfo avoidRoad : items) {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("latitude", avoidRoad.latitude);
|
||||
jsonObject.put("longitude", avoidRoad.longitude);
|
||||
jsonObject.put("name", avoidRoad.name);
|
||||
jsonObject.put("appModeKey", avoidRoad.appModeKey);
|
||||
jsonArray.put(jsonObject);
|
||||
}
|
||||
json.put("items", jsonArray);
|
||||
} catch (JSONException e) {
|
||||
warnings.add(app.getString(R.string.settings_item_write_error, String.valueOf(getType())));
|
||||
SettingsHelper.LOG.error("Failed write to json", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
SettingsItemReader<? extends SettingsItem> getReader() {
|
||||
return getJsonReader();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
SettingsItemWriter<? extends SettingsItem> getWriter() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
package net.osmand.plus.settings.backend.backup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class CollectionSettingsItem<T> extends SettingsItem {
|
||||
|
||||
protected List<T> items;
|
||||
protected List<T> appliedItems;
|
||||
protected List<T> duplicateItems;
|
||||
protected List<T> existingItems;
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
items = new ArrayList<>();
|
||||
appliedItems = new ArrayList<>();
|
||||
duplicateItems = new ArrayList<>();
|
||||
}
|
||||
|
||||
CollectionSettingsItem(@NonNull OsmandApplication app, @Nullable CollectionSettingsItem<T> baseItem, @NonNull List<T> items) {
|
||||
super(app, baseItem);
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
CollectionSettingsItem(@NonNull OsmandApplication app, @NonNull JSONObject json) throws JSONException {
|
||||
super(app, json);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<T> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<T> getAppliedItems() {
|
||||
return appliedItems;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<T> getDuplicateItems() {
|
||||
return duplicateItems;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<T> processDuplicateItems() {
|
||||
if (!items.isEmpty()) {
|
||||
for (T item : items) {
|
||||
if (isDuplicate(item)) {
|
||||
duplicateItems.add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
return duplicateItems;
|
||||
}
|
||||
|
||||
public List<T> getNewItems() {
|
||||
List<T> res = new ArrayList<>(items);
|
||||
res.removeAll(duplicateItems);
|
||||
return res;
|
||||
}
|
||||
|
||||
public abstract boolean isDuplicate(@NonNull T item);
|
||||
|
||||
@NonNull
|
||||
public abstract T renameItem(@NonNull T item);
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
package net.osmand.plus.settings.backend.backup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class DataSettingsItem extends StreamSettingsItem {
|
||||
|
||||
@Nullable
|
||||
private byte[] data;
|
||||
|
||||
public DataSettingsItem(@NonNull OsmandApplication app, @NonNull String name) {
|
||||
super(app, name);
|
||||
}
|
||||
|
||||
DataSettingsItem(@NonNull OsmandApplication app, @NonNull JSONObject json) throws JSONException {
|
||||
super(app, json);
|
||||
}
|
||||
|
||||
public DataSettingsItem(@NonNull OsmandApplication app, @NonNull byte[] data, @NonNull String name) {
|
||||
super(app, name);
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public SettingsItemType getType() {
|
||||
return SettingsItemType.DATA;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getDefaultFileExtension() {
|
||||
return ".dat";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public byte[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
void readFromJson(@NonNull JSONObject json) throws JSONException {
|
||||
super.readFromJson(json);
|
||||
String fileName = getFileName();
|
||||
if (!Algorithms.isEmpty(fileName)) {
|
||||
name = Algorithms.getFileNameWithoutExtension(new File(fileName));
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
SettingsItemReader<? extends SettingsItem> getReader() {
|
||||
return new StreamSettingsItemReader(this) {
|
||||
@Override
|
||||
public void readFromStream(@NonNull InputStream inputStream) throws IOException, IllegalArgumentException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
int nRead;
|
||||
byte[] data = new byte[SettingsHelper.BUFFER];
|
||||
while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
|
||||
buffer.write(data, 0, nRead);
|
||||
}
|
||||
|
||||
buffer.flush();
|
||||
DataSettingsItem.this.data = buffer.toByteArray();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public SettingsItemWriter<? extends SettingsItem> getWriter() {
|
||||
setInputStream(new ByteArrayInputStream(data));
|
||||
return super.getWriter();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
package net.osmand.plus.settings.backend.backup;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import net.osmand.map.WorldRegion;
|
||||
import net.osmand.plus.CustomOsmandPlugin;
|
||||
import net.osmand.plus.CustomRegion;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class DownloadsItem extends SettingsItem {
|
||||
|
||||
private List<WorldRegion> items;
|
||||
|
||||
DownloadsItem(@NonNull OsmandApplication app, @NonNull JSONObject json) throws JSONException {
|
||||
super(app, json);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
items = new ArrayList<>();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public SettingsItemType getType() {
|
||||
return SettingsItemType.DOWNLOADS;
|
||||
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return "downloads";
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getPublicName(@NonNull Context ctx) {
|
||||
return "downloads";
|
||||
}
|
||||
|
||||
public List<WorldRegion> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
@Override
|
||||
void readItemsFromJson(@NonNull JSONObject json) throws IllegalArgumentException {
|
||||
try {
|
||||
if (!json.has("items")) {
|
||||
return;
|
||||
}
|
||||
JSONArray jsonArray = json.getJSONArray("items");
|
||||
items.addAll(CustomOsmandPlugin.collectRegionsFromJson(app, jsonArray));
|
||||
} catch (JSONException e) {
|
||||
warnings.add(app.getString(R.string.settings_item_read_error, String.valueOf(getType())));
|
||||
throw new IllegalArgumentException("Json parse error", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void writeItemsToJson(@NonNull JSONObject json) {
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
if (!items.isEmpty()) {
|
||||
try {
|
||||
for (WorldRegion region : items) {
|
||||
if (region instanceof CustomRegion) {
|
||||
JSONObject regionJson = ((CustomRegion) region).toJson();
|
||||
jsonArray.put(regionJson);
|
||||
}
|
||||
}
|
||||
json.put("items", jsonArray);
|
||||
} catch (JSONException e) {
|
||||
warnings.add(app.getString(R.string.settings_item_write_error, String.valueOf(getType())));
|
||||
SettingsHelper.LOG.error("Failed write to json", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
SettingsItemReader<? extends SettingsItem> getReader() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
SettingsItemWriter<? extends SettingsItem> getWriter() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,242 @@
|
|||
package net.osmand.plus.settings.backend.backup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import net.osmand.IndexConstants;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class FileSettingsItem extends StreamSettingsItem {
|
||||
|
||||
public enum FileSubtype {
|
||||
UNKNOWN("", null),
|
||||
OTHER("other", ""),
|
||||
ROUTING_CONFIG("routing_config", IndexConstants.ROUTING_PROFILES_DIR),
|
||||
RENDERING_STYLE("rendering_style", IndexConstants.RENDERERS_DIR),
|
||||
OBF_MAP("obf_map", IndexConstants.MAPS_PATH),
|
||||
TILES_MAP("tiles_map", IndexConstants.TILES_INDEX_DIR),
|
||||
GPX("gpx", IndexConstants.GPX_INDEX_DIR),
|
||||
VOICE("voice", IndexConstants.VOICE_INDEX_DIR),
|
||||
TRAVEL("travel", IndexConstants.WIKIVOYAGE_INDEX_DIR),
|
||||
MULTIMEDIA_NOTES("multimedia_notes", IndexConstants.AV_INDEX_DIR);
|
||||
|
||||
private String subtypeName;
|
||||
private String subtypeFolder;
|
||||
|
||||
FileSubtype(String subtypeName, String subtypeFolder) {
|
||||
this.subtypeName = subtypeName;
|
||||
this.subtypeFolder = subtypeFolder;
|
||||
}
|
||||
|
||||
public String getSubtypeName() {
|
||||
return subtypeName;
|
||||
}
|
||||
|
||||
public String getSubtypeFolder() {
|
||||
return subtypeFolder;
|
||||
}
|
||||
|
||||
public static FileSubtype getSubtypeByName(@NonNull String name) {
|
||||
for (FileSubtype subtype : FileSubtype.values()) {
|
||||
if (name.equals(subtype.subtypeName)) {
|
||||
return subtype;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static FileSubtype getSubtypeByFileName(@NonNull String fileName) {
|
||||
String name = fileName;
|
||||
if (fileName.startsWith(File.separator)) {
|
||||
name = fileName.substring(1);
|
||||
}
|
||||
for (FileSubtype subtype : FileSubtype.values()) {
|
||||
switch (subtype) {
|
||||
case UNKNOWN:
|
||||
case OTHER:
|
||||
break;
|
||||
case OBF_MAP:
|
||||
if (name.endsWith(IndexConstants.BINARY_MAP_INDEX_EXT)) {
|
||||
return subtype;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (name.startsWith(subtype.subtypeFolder)) {
|
||||
return subtype;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return subtypeName;
|
||||
}
|
||||
}
|
||||
|
||||
protected File file;
|
||||
private File appPath;
|
||||
protected FileSubtype subtype;
|
||||
|
||||
public FileSettingsItem(@NonNull OsmandApplication app, @NonNull File file) throws IllegalArgumentException {
|
||||
super(app, file.getPath().replace(app.getAppPath(null).getPath(), ""));
|
||||
this.file = file;
|
||||
this.appPath = app.getAppPath(null);
|
||||
String fileName = getFileName();
|
||||
if (fileName != null) {
|
||||
this.subtype = FileSubtype.getSubtypeByFileName(fileName);
|
||||
}
|
||||
if (subtype == FileSubtype.UNKNOWN || subtype == null) {
|
||||
throw new IllegalArgumentException("Unknown file subtype: " + fileName);
|
||||
}
|
||||
}
|
||||
|
||||
FileSettingsItem(@NonNull OsmandApplication app, @NonNull JSONObject json) throws JSONException {
|
||||
super(app, json);
|
||||
this.appPath = app.getAppPath(null);
|
||||
if (subtype == FileSubtype.OTHER) {
|
||||
this.file = new File(appPath, name);
|
||||
} else if (subtype == FileSubtype.UNKNOWN || subtype == null) {
|
||||
throw new IllegalArgumentException("Unknown file subtype: " + getFileName());
|
||||
} else {
|
||||
String subtypeFolder = subtype.subtypeFolder;
|
||||
int nameIndex = fileName.indexOf(name);
|
||||
int folderIndex = fileName.indexOf(subtype.subtypeFolder);
|
||||
if (nameIndex != -1 && folderIndex != -1) {
|
||||
String subfolderPath = fileName.substring(folderIndex + subtype.subtypeFolder.length(), nameIndex);
|
||||
subtypeFolder = subtypeFolder + subfolderPath;
|
||||
}
|
||||
this.file = new File(app.getAppPath(subtypeFolder), name);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public SettingsItemType getType() {
|
||||
return SettingsItemType.FILE;
|
||||
}
|
||||
|
||||
public File getPluginPath() {
|
||||
String pluginId = getPluginId();
|
||||
if (!Algorithms.isEmpty(pluginId)) {
|
||||
return new File(appPath, IndexConstants.PLUGINS_DIR + pluginId);
|
||||
}
|
||||
return appPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
void readFromJson(@NonNull JSONObject json) throws JSONException {
|
||||
super.readFromJson(json);
|
||||
String fileName = getFileName();
|
||||
if (subtype == null) {
|
||||
String subtypeStr = json.has("subtype") ? json.getString("subtype") : null;
|
||||
if (!Algorithms.isEmpty(subtypeStr)) {
|
||||
subtype = FileSubtype.getSubtypeByName(subtypeStr);
|
||||
} else if (!Algorithms.isEmpty(fileName)) {
|
||||
subtype = FileSubtype.getSubtypeByFileName(fileName);
|
||||
} else {
|
||||
subtype = FileSubtype.UNKNOWN;
|
||||
}
|
||||
}
|
||||
if (!Algorithms.isEmpty(fileName)) {
|
||||
if (subtype == FileSubtype.OTHER) {
|
||||
name = fileName;
|
||||
} else if (subtype != null && subtype != FileSubtype.UNKNOWN) {
|
||||
name = Algorithms.getFileWithoutDirs(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void writeToJson(@NonNull JSONObject json) throws JSONException {
|
||||
super.writeToJson(json);
|
||||
if (subtype != null) {
|
||||
json.put("subtype", subtype.getSubtypeName());
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public File getFile() {
|
||||
return file;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public FileSubtype getSubtype() {
|
||||
return subtype;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists() {
|
||||
return file.exists();
|
||||
}
|
||||
|
||||
private File renameFile(File file) {
|
||||
int number = 0;
|
||||
String path = file.getAbsolutePath();
|
||||
while (true) {
|
||||
number++;
|
||||
String copyName = path.replaceAll(file.getName(), file.getName().replaceFirst("[.]", "_" + number + "."));
|
||||
File copyFile = new File(copyName);
|
||||
if (!copyFile.exists()) {
|
||||
return copyFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
SettingsItemReader<? extends SettingsItem> getReader() {
|
||||
return new StreamSettingsItemReader(this) {
|
||||
@Override
|
||||
public void readFromStream(@NonNull InputStream inputStream) throws IOException, IllegalArgumentException {
|
||||
OutputStream output;
|
||||
File dest = FileSettingsItem.this.file;
|
||||
if (dest.exists() && !shouldReplace) {
|
||||
dest = renameFile(dest);
|
||||
}
|
||||
if (dest.getParentFile() != null && !dest.getParentFile().exists()) {
|
||||
dest.getParentFile().mkdirs();
|
||||
}
|
||||
output = new FileOutputStream(dest);
|
||||
byte[] buffer = new byte[SettingsHelper.BUFFER];
|
||||
int count;
|
||||
try {
|
||||
while ((count = inputStream.read(buffer)) != -1) {
|
||||
output.write(buffer, 0, count);
|
||||
}
|
||||
output.flush();
|
||||
} finally {
|
||||
Algorithms.closeStream(output);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public SettingsItemWriter<? extends SettingsItem> getWriter() {
|
||||
try {
|
||||
setInputStream(new FileInputStream(file));
|
||||
} catch (FileNotFoundException e) {
|
||||
warnings.add(app.getString(R.string.settings_item_read_error, file.getName()));
|
||||
SettingsHelper.LOG.error("Failed to set input stream from file: " + file.getName(), e);
|
||||
}
|
||||
return super.getWriter();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package net.osmand.plus.settings.backend.backup;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.settings.backend.OsmandPreference;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class GlobalSettingsItem extends OsmandSettingsItem {
|
||||
|
||||
public GlobalSettingsItem(@NonNull OsmandSettings settings) {
|
||||
super(settings);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public SettingsItemType getType() {
|
||||
return SettingsItemType.GLOBAL;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return "general_settings";
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getPublicName(@NonNull Context ctx) {
|
||||
return ctx.getString(R.string.general_settings_2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
SettingsItemReader<? extends SettingsItem> getReader() {
|
||||
return new OsmandSettingsItemReader<OsmandSettingsItem>(this, getSettings()) {
|
||||
@Override
|
||||
protected void readPreferenceFromJson(@NonNull OsmandPreference<?> preference, @NonNull JSONObject json) throws JSONException {
|
||||
preference.readFromJson(json, null);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
SettingsItemWriter<? extends SettingsItem> getWriter() {
|
||||
return new OsmandSettingsItemWriter<OsmandSettingsItem>(this, getSettings()) {
|
||||
@Override
|
||||
protected void writePreferenceToJson(@NonNull OsmandPreference<?> preference, @NonNull JSONObject json) throws JSONException {
|
||||
preference.writeToJson(json, null);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,241 @@
|
|||
package net.osmand.plus.settings.backend.backup;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import net.osmand.IndexConstants;
|
||||
import net.osmand.map.ITileSource;
|
||||
import net.osmand.map.TileSourceManager;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.SQLiteTileSource;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class MapSourcesSettingsItem extends CollectionSettingsItem<ITileSource> {
|
||||
|
||||
private List<String> existingItemsNames;
|
||||
|
||||
public MapSourcesSettingsItem(@NonNull OsmandApplication app, @NonNull List<ITileSource> items) {
|
||||
super(app, null, items);
|
||||
}
|
||||
|
||||
public MapSourcesSettingsItem(@NonNull OsmandApplication app, @Nullable MapSourcesSettingsItem baseItem, @NonNull List<ITileSource> items) {
|
||||
super(app, baseItem, items);
|
||||
}
|
||||
|
||||
MapSourcesSettingsItem(@NonNull OsmandApplication app, @NonNull JSONObject json) throws JSONException {
|
||||
super(app, json);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
existingItemsNames = new ArrayList<>(app.getSettings().getTileSourceEntries().values());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public SettingsItemType getType() {
|
||||
return SettingsItemType.MAP_SOURCES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply() {
|
||||
List<ITileSource> newItems = getNewItems();
|
||||
if (!newItems.isEmpty() || !duplicateItems.isEmpty()) {
|
||||
appliedItems = new ArrayList<>(newItems);
|
||||
if (shouldReplace) {
|
||||
for (ITileSource tileSource : duplicateItems) {
|
||||
if (tileSource instanceof SQLiteTileSource) {
|
||||
File f = app.getAppPath(IndexConstants.TILES_INDEX_DIR + tileSource.getName() + IndexConstants.SQLITE_EXT);
|
||||
if (f != null && f.exists() && Algorithms.removeAllFiles(f)) {
|
||||
appliedItems.add(tileSource);
|
||||
}
|
||||
} else if (tileSource instanceof TileSourceManager.TileSourceTemplate) {
|
||||
File f = app.getAppPath(IndexConstants.TILES_INDEX_DIR + tileSource.getName());
|
||||
if (f != null && f.exists() && f.isDirectory() && Algorithms.removeAllFiles(f)) {
|
||||
appliedItems.add(tileSource);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (ITileSource tileSource : duplicateItems) {
|
||||
appliedItems.add(renameItem(tileSource));
|
||||
}
|
||||
}
|
||||
for (ITileSource tileSource : appliedItems) {
|
||||
if (tileSource instanceof TileSourceManager.TileSourceTemplate) {
|
||||
app.getSettings().installTileSource((TileSourceManager.TileSourceTemplate) tileSource);
|
||||
} else if (tileSource instanceof SQLiteTileSource) {
|
||||
((SQLiteTileSource) tileSource).createDataBase();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ITileSource renameItem(@NonNull ITileSource item) {
|
||||
int number = 0;
|
||||
while (true) {
|
||||
number++;
|
||||
if (item instanceof SQLiteTileSource) {
|
||||
SQLiteTileSource oldItem = (SQLiteTileSource) item;
|
||||
SQLiteTileSource renamedItem = new SQLiteTileSource(
|
||||
oldItem,
|
||||
oldItem.getName() + "_" + number,
|
||||
app);
|
||||
if (!isDuplicate(renamedItem)) {
|
||||
return renamedItem;
|
||||
}
|
||||
} else if (item instanceof TileSourceManager.TileSourceTemplate) {
|
||||
TileSourceManager.TileSourceTemplate oldItem = (TileSourceManager.TileSourceTemplate) item;
|
||||
oldItem.setName(oldItem.getName() + "_" + number);
|
||||
if (!isDuplicate(oldItem)) {
|
||||
return oldItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDuplicate(@NonNull ITileSource item) {
|
||||
for (String name : existingItemsNames) {
|
||||
if (name.equals(item.getName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return "map_sources";
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getPublicName(@NonNull Context ctx) {
|
||||
return "map_sources";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldReadOnCollecting() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
void readItemsFromJson(@NonNull JSONObject json) throws IllegalArgumentException {
|
||||
try {
|
||||
if (!json.has("items")) {
|
||||
return;
|
||||
}
|
||||
JSONArray jsonArray = json.getJSONArray("items");
|
||||
for (int i = 0; i < jsonArray.length(); i++) {
|
||||
JSONObject object = jsonArray.getJSONObject(i);
|
||||
boolean sql = object.optBoolean("sql");
|
||||
String name = object.optString("name");
|
||||
int minZoom = object.optInt("minZoom");
|
||||
int maxZoom = object.optInt("maxZoom");
|
||||
String url = object.optString("url");
|
||||
String randoms = object.optString("randoms");
|
||||
boolean ellipsoid = object.optBoolean("ellipsoid", false);
|
||||
boolean invertedY = object.optBoolean("inverted_y", false);
|
||||
String referer = object.optString("referer");
|
||||
String userAgent = object.optString("userAgent");
|
||||
boolean timeSupported = object.optBoolean("timesupported", false);
|
||||
long expire = object.optLong("expire", -1);
|
||||
boolean inversiveZoom = object.optBoolean("inversiveZoom", false);
|
||||
String ext = object.optString("ext");
|
||||
int tileSize = object.optInt("tileSize");
|
||||
int bitDensity = object.optInt("bitDensity");
|
||||
int avgSize = object.optInt("avgSize");
|
||||
String rule = object.optString("rule");
|
||||
|
||||
if (expire > 0 && expire < 3600000) {
|
||||
expire = expire * 60 * 1000L;
|
||||
}
|
||||
|
||||
ITileSource template;
|
||||
if (!sql) {
|
||||
TileSourceManager.TileSourceTemplate tileSourceTemplate = new TileSourceManager.TileSourceTemplate(name, url, ext, maxZoom, minZoom, tileSize, bitDensity, avgSize);
|
||||
tileSourceTemplate.setRule(rule);
|
||||
tileSourceTemplate.setRandoms(randoms);
|
||||
tileSourceTemplate.setReferer(referer);
|
||||
tileSourceTemplate.setUserAgent(userAgent);
|
||||
tileSourceTemplate.setEllipticYTile(ellipsoid);
|
||||
tileSourceTemplate.setInvertedYTile(invertedY);
|
||||
tileSourceTemplate.setExpirationTimeMillis(timeSupported ? expire : -1);
|
||||
|
||||
template = tileSourceTemplate;
|
||||
} else {
|
||||
template = new SQLiteTileSource(app, name, minZoom, maxZoom, url, randoms, ellipsoid, invertedY, referer, userAgent, timeSupported, expire, inversiveZoom, rule);
|
||||
}
|
||||
items.add(template);
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
warnings.add(app.getString(R.string.settings_item_read_error, String.valueOf(getType())));
|
||||
throw new IllegalArgumentException("Json parse error", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void writeItemsToJson(@NonNull JSONObject json) {
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
if (!items.isEmpty()) {
|
||||
try {
|
||||
for (ITileSource template : items) {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
boolean sql = template instanceof SQLiteTileSource;
|
||||
jsonObject.put("sql", sql);
|
||||
jsonObject.put("name", template.getName());
|
||||
jsonObject.put("minZoom", template.getMinimumZoomSupported());
|
||||
jsonObject.put("maxZoom", template.getMaximumZoomSupported());
|
||||
jsonObject.put("url", template.getUrlTemplate());
|
||||
jsonObject.put("randoms", template.getRandoms());
|
||||
jsonObject.put("ellipsoid", template.isEllipticYTile());
|
||||
jsonObject.put("inverted_y", template.isInvertedYTile());
|
||||
jsonObject.put("referer", template.getReferer());
|
||||
jsonObject.put("userAgent", template.getUserAgent());
|
||||
jsonObject.put("timesupported", template.isTimeSupported());
|
||||
jsonObject.put("expire", template.getExpirationTimeMinutes());
|
||||
jsonObject.put("inversiveZoom", template.getInversiveZoom());
|
||||
jsonObject.put("ext", template.getTileFormat());
|
||||
jsonObject.put("tileSize", template.getTileSize());
|
||||
jsonObject.put("bitDensity", template.getBitDensity());
|
||||
jsonObject.put("avgSize", template.getAvgSize());
|
||||
jsonObject.put("rule", template.getRule());
|
||||
jsonArray.put(jsonObject);
|
||||
}
|
||||
json.put("items", jsonArray);
|
||||
|
||||
} catch (JSONException e) {
|
||||
warnings.add(app.getString(R.string.settings_item_write_error, String.valueOf(getType())));
|
||||
SettingsHelper.LOG.error("Failed write to json", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
SettingsItemReader<? extends SettingsItem> getReader() {
|
||||
return getJsonReader();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
SettingsItemWriter<? extends SettingsItem> getWriter() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package net.osmand.plus.settings.backend.backup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public abstract class OsmandSettingsItem extends SettingsItem {
|
||||
|
||||
private OsmandSettings settings;
|
||||
|
||||
protected OsmandSettingsItem(@NonNull OsmandSettings settings) {
|
||||
super(settings.getContext());
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
protected OsmandSettingsItem(@NonNull OsmandSettings settings, @Nullable OsmandSettingsItem baseItem) {
|
||||
super(settings.getContext(), baseItem);
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
protected OsmandSettingsItem(@NonNull SettingsItemType type, @NonNull OsmandSettings settings, @NonNull JSONObject json) throws JSONException {
|
||||
super(settings.getContext(), json);
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
public OsmandSettings getSettings() {
|
||||
return settings;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
package net.osmand.plus.settings.backend.backup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import net.osmand.plus.settings.backend.OsmandPreference;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class OsmandSettingsItemReader<T extends OsmandSettingsItem> extends SettingsItemReader<T> {
|
||||
|
||||
private OsmandSettings settings;
|
||||
|
||||
public OsmandSettingsItemReader(@NonNull T item, @NonNull OsmandSettings settings) {
|
||||
super(item);
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
protected abstract void readPreferenceFromJson(@NonNull OsmandPreference<?> preference,
|
||||
@NonNull JSONObject json) throws JSONException;
|
||||
|
||||
@Override
|
||||
public void readFromStream(@NonNull InputStream inputStream) throws IOException, IllegalArgumentException {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
try {
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
|
||||
String str;
|
||||
while ((str = in.readLine()) != null) {
|
||||
buf.append(str);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new IOException("Cannot read json body", e);
|
||||
}
|
||||
String jsonStr = buf.toString();
|
||||
if (Algorithms.isEmpty(jsonStr)) {
|
||||
throw new IllegalArgumentException("Cannot find json body");
|
||||
}
|
||||
final JSONObject json;
|
||||
try {
|
||||
json = new JSONObject(jsonStr);
|
||||
} catch (JSONException e) {
|
||||
throw new IllegalArgumentException("Json parse error", e);
|
||||
}
|
||||
readPreferencesFromJson(json);
|
||||
}
|
||||
|
||||
void readPreferencesFromJson(final JSONObject json) {
|
||||
settings.getContext().runInUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Map<String, OsmandPreference<?>> prefs = settings.getRegisteredPreferences();
|
||||
Iterator<String> iter = json.keys();
|
||||
while (iter.hasNext()) {
|
||||
String key = iter.next();
|
||||
OsmandPreference<?> p = prefs.get(key);
|
||||
if (p != null) {
|
||||
try {
|
||||
readPreferenceFromJson(p, json);
|
||||
} catch (Exception e) {
|
||||
SettingsHelper.LOG.error("Failed to read preference: " + key, e);
|
||||
}
|
||||
} else {
|
||||
SettingsHelper.LOG.warn("No preference while importing settings: " + key);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package net.osmand.plus.settings.backend.backup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import net.osmand.plus.settings.backend.OsmandPreference;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class OsmandSettingsItemWriter<T extends OsmandSettingsItem> extends SettingsItemWriter<T> {
|
||||
|
||||
private OsmandSettings settings;
|
||||
|
||||
public OsmandSettingsItemWriter(@NonNull T item, @NonNull OsmandSettings settings) {
|
||||
super(item);
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
protected abstract void writePreferenceToJson(@NonNull OsmandPreference<?> preference,
|
||||
@NonNull JSONObject json) throws JSONException;
|
||||
|
||||
@Override
|
||||
public boolean writeToStream(@NonNull OutputStream outputStream) throws IOException {
|
||||
JSONObject json = new JSONObject();
|
||||
Map<String, OsmandPreference<?>> prefs = settings.getRegisteredPreferences();
|
||||
for (OsmandPreference<?> pref : prefs.values()) {
|
||||
try {
|
||||
writePreferenceToJson(pref, json);
|
||||
} catch (JSONException e) {
|
||||
SettingsHelper.LOG.error("Failed to write preference: " + pref.getId(), e);
|
||||
}
|
||||
}
|
||||
if (json.length() > 0) {
|
||||
try {
|
||||
String s = json.toString(2);
|
||||
outputStream.write(s.getBytes("UTF-8"));
|
||||
} catch (JSONException e) {
|
||||
SettingsHelper.LOG.error("Failed to write json to stream", e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
package net.osmand.plus.settings.backend.backup;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import net.osmand.plus.CustomOsmandPlugin;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.OsmandPlugin;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PluginSettingsItem extends SettingsItem {
|
||||
|
||||
private CustomOsmandPlugin plugin;
|
||||
private List<SettingsItem> pluginDependentItems;
|
||||
|
||||
PluginSettingsItem(@NonNull OsmandApplication app, @NonNull JSONObject json) throws JSONException {
|
||||
super(app, json);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
pluginDependentItems = new ArrayList<>();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public SettingsItemType getType() {
|
||||
return SettingsItemType.PLUGIN;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return plugin.getId();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getPublicName(@NonNull Context ctx) {
|
||||
return plugin.getName();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getDefaultFileName() {
|
||||
return getName();
|
||||
}
|
||||
|
||||
public CustomOsmandPlugin getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
public List<SettingsItem> getPluginDependentItems() {
|
||||
return pluginDependentItems;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists() {
|
||||
return OsmandPlugin.getPlugin(getPluginId()) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply() {
|
||||
if (shouldReplace || !exists()) {
|
||||
for (SettingsItem item : pluginDependentItems) {
|
||||
if (item instanceof FileSettingsItem) {
|
||||
FileSettingsItem fileItem = (FileSettingsItem) item;
|
||||
if (fileItem.getSubtype() == FileSettingsItem.FileSubtype.RENDERING_STYLE) {
|
||||
plugin.addRenderer(fileItem.getName());
|
||||
} else if (fileItem.getSubtype() == FileSettingsItem.FileSubtype.ROUTING_CONFIG) {
|
||||
plugin.addRouter(fileItem.getName());
|
||||
} else if (fileItem.getSubtype() == FileSettingsItem.FileSubtype.OTHER) {
|
||||
plugin.setResourceDirName(item.getFileName());
|
||||
}
|
||||
} else if (item instanceof SuggestedDownloadsItem) {
|
||||
plugin.updateSuggestedDownloads(((SuggestedDownloadsItem) item).getItems());
|
||||
} else if (item instanceof DownloadsItem) {
|
||||
plugin.updateDownloadItems(((DownloadsItem) item).getItems());
|
||||
}
|
||||
}
|
||||
OsmandPlugin.addCustomPlugin(app, plugin);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void readFromJson(@NonNull JSONObject json) throws JSONException {
|
||||
super.readFromJson(json);
|
||||
plugin = new CustomOsmandPlugin(app, json);
|
||||
}
|
||||
|
||||
@Override
|
||||
void writeToJson(@NonNull JSONObject json) throws JSONException {
|
||||
super.writeToJson(json);
|
||||
plugin.writeAdditionalDataToJson(json);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
SettingsItemReader<? extends SettingsItem> getReader() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
SettingsItemWriter<? extends SettingsItem> getWriter() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,178 @@
|
|||
package net.osmand.plus.settings.backend.backup;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import net.osmand.osm.MapPoiTypes;
|
||||
import net.osmand.osm.PoiCategory;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.poi.PoiUIFilter;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class PoiUiFiltersSettingsItem extends CollectionSettingsItem<PoiUIFilter> {
|
||||
|
||||
public PoiUiFiltersSettingsItem(@NonNull OsmandApplication app, @NonNull List<PoiUIFilter> items) {
|
||||
super(app, null, items);
|
||||
}
|
||||
|
||||
public PoiUiFiltersSettingsItem(@NonNull OsmandApplication app, @Nullable PoiUiFiltersSettingsItem baseItem, @NonNull List<PoiUIFilter> items) {
|
||||
super(app, baseItem, items);
|
||||
}
|
||||
|
||||
PoiUiFiltersSettingsItem(@NonNull OsmandApplication app, @NonNull JSONObject json) throws JSONException {
|
||||
super(app, json);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
existingItems = app.getPoiFilters().getUserDefinedPoiFilters(false);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public SettingsItemType getType() {
|
||||
return SettingsItemType.POI_UI_FILTERS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply() {
|
||||
List<PoiUIFilter> newItems = getNewItems();
|
||||
if (!newItems.isEmpty() || !duplicateItems.isEmpty()) {
|
||||
appliedItems = new ArrayList<>(newItems);
|
||||
|
||||
for (PoiUIFilter duplicate : duplicateItems) {
|
||||
appliedItems.add(shouldReplace ? duplicate : renameItem(duplicate));
|
||||
}
|
||||
for (PoiUIFilter filter : appliedItems) {
|
||||
app.getPoiFilters().createPoiFilter(filter, false);
|
||||
}
|
||||
app.getSearchUICore().refreshCustomPoiFilters();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDuplicate(@NonNull PoiUIFilter item) {
|
||||
String savedName = item.getName();
|
||||
for (PoiUIFilter filter : existingItems) {
|
||||
if (filter.getName().equals(savedName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public PoiUIFilter renameItem(@NonNull PoiUIFilter item) {
|
||||
int number = 0;
|
||||
while (true) {
|
||||
number++;
|
||||
PoiUIFilter renamedItem = new PoiUIFilter(item,
|
||||
item.getName() + "_" + number,
|
||||
item.getFilterId() + "_" + number);
|
||||
if (!isDuplicate(renamedItem)) {
|
||||
return renamedItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return "poi_ui_filters";
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getPublicName(@NonNull Context ctx) {
|
||||
return "poi_ui_filters";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldReadOnCollecting() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
void readItemsFromJson(@NonNull JSONObject json) throws IllegalArgumentException {
|
||||
try {
|
||||
if (!json.has("items")) {
|
||||
return;
|
||||
}
|
||||
JSONArray jsonArray = json.getJSONArray("items");
|
||||
Gson gson = new Gson();
|
||||
Type type = new TypeToken<HashMap<String, LinkedHashSet<String>>>() {
|
||||
}.getType();
|
||||
MapPoiTypes poiTypes = app.getPoiTypes();
|
||||
for (int i = 0; i < jsonArray.length(); i++) {
|
||||
JSONObject object = jsonArray.getJSONObject(i);
|
||||
String name = object.getString("name");
|
||||
String filterId = object.getString("filterId");
|
||||
String acceptedTypesString = object.getString("acceptedTypes");
|
||||
HashMap<String, LinkedHashSet<String>> acceptedTypes = gson.fromJson(acceptedTypesString, type);
|
||||
Map<PoiCategory, LinkedHashSet<String>> acceptedTypesDone = new HashMap<>();
|
||||
for (Map.Entry<String, LinkedHashSet<String>> mapItem : acceptedTypes.entrySet()) {
|
||||
final PoiCategory a = poiTypes.getPoiCategoryByName(mapItem.getKey());
|
||||
acceptedTypesDone.put(a, mapItem.getValue());
|
||||
}
|
||||
PoiUIFilter filter = new PoiUIFilter(name, filterId, acceptedTypesDone, app);
|
||||
items.add(filter);
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
warnings.add(app.getString(R.string.settings_item_read_error, String.valueOf(getType())));
|
||||
throw new IllegalArgumentException("Json parse error", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void writeItemsToJson(@NonNull JSONObject json) {
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
Gson gson = new Gson();
|
||||
Type type = new TypeToken<HashMap<PoiCategory, LinkedHashSet<String>>>() {
|
||||
}.getType();
|
||||
if (!items.isEmpty()) {
|
||||
try {
|
||||
for (PoiUIFilter filter : items) {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("name", filter.getName());
|
||||
jsonObject.put("filterId", filter.getFilterId());
|
||||
jsonObject.put("acceptedTypes", gson.toJson(filter.getAcceptedTypes(), type));
|
||||
jsonArray.put(jsonObject);
|
||||
}
|
||||
json.put("items", jsonArray);
|
||||
} catch (JSONException e) {
|
||||
warnings.add(app.getString(R.string.settings_item_write_error, String.valueOf(getType())));
|
||||
SettingsHelper.LOG.error("Failed write to json", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
SettingsItemReader<? extends SettingsItem> getReader() {
|
||||
return getJsonReader();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
SettingsItemWriter<? extends SettingsItem> getWriter() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,312 @@
|
|||
package net.osmand.plus.settings.backend.backup;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import net.osmand.IndexConstants;
|
||||
import net.osmand.plus.CustomOsmandPlugin;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.OsmandPlugin;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.settings.backend.OsmandPreference;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.router.GeneralRouter;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class ProfileSettingsItem extends OsmandSettingsItem {
|
||||
|
||||
private ApplicationMode appMode;
|
||||
private ApplicationMode.ApplicationModeBuilder builder;
|
||||
private ApplicationMode.ApplicationModeBean modeBean;
|
||||
|
||||
private JSONObject additionalPrefsJson;
|
||||
private Set<String> appModeBeanPrefsIds;
|
||||
|
||||
public ProfileSettingsItem(@NonNull OsmandApplication app, @NonNull ApplicationMode appMode) {
|
||||
super(app.getSettings());
|
||||
this.appMode = appMode;
|
||||
}
|
||||
|
||||
public ProfileSettingsItem(@NonNull OsmandApplication app, @Nullable ProfileSettingsItem baseItem, @NonNull ApplicationMode.ApplicationModeBean modeBean) {
|
||||
super(app.getSettings(), baseItem);
|
||||
this.modeBean = modeBean;
|
||||
builder = ApplicationMode.fromModeBean(app, modeBean);
|
||||
appMode = builder.getApplicationMode();
|
||||
}
|
||||
|
||||
public ProfileSettingsItem(@NonNull OsmandApplication app, @NonNull JSONObject json) throws JSONException {
|
||||
super(SettingsItemType.PROFILE, app.getSettings(), json);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
appModeBeanPrefsIds = new HashSet<>(Arrays.asList(getAppModeBeanPrefsIds()));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public SettingsItemType getType() {
|
||||
return SettingsItemType.PROFILE;
|
||||
}
|
||||
|
||||
public ApplicationMode getAppMode() {
|
||||
return appMode;
|
||||
}
|
||||
|
||||
public ApplicationMode.ApplicationModeBean getModeBean() {
|
||||
return modeBean;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return appMode.getStringKey();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getPublicName(@NonNull Context ctx) {
|
||||
if (appMode.isCustomProfile()) {
|
||||
return modeBean.userProfileName;
|
||||
} else if (appMode.getNameKeyResource() != -1) {
|
||||
return ctx.getString(appMode.getNameKeyResource());
|
||||
} else {
|
||||
return getName();
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getDefaultFileName() {
|
||||
return "profile_" + getName() + getDefaultFileExtension();
|
||||
}
|
||||
|
||||
@Override
|
||||
void readFromJson(@NonNull JSONObject json) throws JSONException {
|
||||
super.readFromJson(json);
|
||||
String appModeJson = json.getString("appMode");
|
||||
modeBean = ApplicationMode.fromJson(appModeJson);
|
||||
builder = ApplicationMode.fromModeBean(app, modeBean);
|
||||
ApplicationMode appMode = builder.getApplicationMode();
|
||||
if (!appMode.isCustomProfile()) {
|
||||
appMode = ApplicationMode.valueOfStringKey(appMode.getStringKey(), appMode);
|
||||
}
|
||||
this.appMode = appMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
void readItemsFromJson(@NonNull JSONObject json) throws IllegalArgumentException {
|
||||
additionalPrefsJson = json.optJSONObject("prefs");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists() {
|
||||
return builder != null && ApplicationMode.valueOfStringKey(getName(), null) != null;
|
||||
}
|
||||
|
||||
private void renameProfile() {
|
||||
List<ApplicationMode> values = ApplicationMode.allPossibleValues();
|
||||
if (Algorithms.isEmpty(modeBean.userProfileName)) {
|
||||
ApplicationMode appMode = ApplicationMode.valueOfStringKey(modeBean.stringKey, null);
|
||||
if (appMode != null) {
|
||||
modeBean.userProfileName = app.getString(appMode.getNameKeyResource());
|
||||
}
|
||||
}
|
||||
int number = 0;
|
||||
while (true) {
|
||||
number++;
|
||||
String key = modeBean.stringKey + "_" + number;
|
||||
String name = modeBean.userProfileName + '_' + number;
|
||||
if (ApplicationMode.valueOfStringKey(key, null) == null && isNameUnique(values, name)) {
|
||||
modeBean.userProfileName = name;
|
||||
modeBean.stringKey = key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isNameUnique(List<ApplicationMode> values, String name) {
|
||||
for (ApplicationMode mode : values) {
|
||||
if (mode.getUserProfileName().equals(name)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply() {
|
||||
if (!appMode.isCustomProfile() && !shouldReplace) {
|
||||
ApplicationMode parent = ApplicationMode.valueOfStringKey(modeBean.stringKey, null);
|
||||
renameProfile();
|
||||
ApplicationMode.ApplicationModeBuilder builder = ApplicationMode
|
||||
.createCustomMode(parent, modeBean.stringKey, app)
|
||||
.setIconResName(modeBean.iconName)
|
||||
.setUserProfileName(modeBean.userProfileName)
|
||||
.setRoutingProfile(modeBean.routingProfile)
|
||||
.setRouteService(modeBean.routeService)
|
||||
.setIconColor(modeBean.iconColor)
|
||||
.setLocationIcon(modeBean.locIcon)
|
||||
.setNavigationIcon(modeBean.navIcon);
|
||||
app.getSettings().copyPreferencesFromProfile(parent, builder.getApplicationMode());
|
||||
appMode = ApplicationMode.saveProfile(builder, app);
|
||||
} else if (!shouldReplace && exists()) {
|
||||
renameProfile();
|
||||
builder = ApplicationMode.fromModeBean(app, modeBean);
|
||||
appMode = ApplicationMode.saveProfile(builder, app);
|
||||
} else {
|
||||
builder = ApplicationMode.fromModeBean(app, modeBean);
|
||||
appMode = ApplicationMode.saveProfile(builder, app);
|
||||
}
|
||||
ApplicationMode.changeProfileAvailability(appMode, true, app);
|
||||
}
|
||||
|
||||
public void applyAdditionalPrefs() {
|
||||
if (additionalPrefsJson != null) {
|
||||
updatePluginResPrefs();
|
||||
|
||||
SettingsItemReader<? extends SettingsItem> reader = getReader();
|
||||
if (reader instanceof OsmandSettingsItemReader) {
|
||||
((OsmandSettingsItemReader) reader).readPreferencesFromJson(additionalPrefsJson);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePluginResPrefs() {
|
||||
String pluginId = getPluginId();
|
||||
if (Algorithms.isEmpty(pluginId)) {
|
||||
return;
|
||||
}
|
||||
OsmandPlugin plugin = OsmandPlugin.getPlugin(pluginId);
|
||||
if (plugin instanceof CustomOsmandPlugin) {
|
||||
CustomOsmandPlugin customPlugin = (CustomOsmandPlugin) plugin;
|
||||
String resDirPath = IndexConstants.PLUGINS_DIR + pluginId + "/" + customPlugin.getResourceDirName();
|
||||
|
||||
for (Iterator<String> it = additionalPrefsJson.keys(); it.hasNext(); ) {
|
||||
try {
|
||||
String prefId = it.next();
|
||||
Object value = additionalPrefsJson.get(prefId);
|
||||
if (value instanceof JSONObject) {
|
||||
JSONObject jsonObject = (JSONObject) value;
|
||||
for (Iterator<String> iterator = jsonObject.keys(); iterator.hasNext(); ) {
|
||||
String key = iterator.next();
|
||||
Object val = jsonObject.get(key);
|
||||
if (val instanceof String) {
|
||||
val = checkPluginResPath((String) val, resDirPath);
|
||||
}
|
||||
jsonObject.put(key, val);
|
||||
}
|
||||
} else if (value instanceof String) {
|
||||
value = checkPluginResPath((String) value, resDirPath);
|
||||
additionalPrefsJson.put(prefId, value);
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
SettingsHelper.LOG.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String checkPluginResPath(String path, String resDirPath) {
|
||||
if (path.startsWith("@")) {
|
||||
return resDirPath + "/" + path.substring(1);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
void writeToJson(@NonNull JSONObject json) throws JSONException {
|
||||
super.writeToJson(json);
|
||||
json.put("appMode", new JSONObject(appMode.toJson()));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
SettingsItemReader<? extends SettingsItem> getReader() {
|
||||
return new OsmandSettingsItemReader<ProfileSettingsItem>(this, getSettings()) {
|
||||
@Override
|
||||
protected void readPreferenceFromJson(@NonNull OsmandPreference<?> preference, @NonNull JSONObject json) throws JSONException {
|
||||
if (!appModeBeanPrefsIds.contains(preference.getId())) {
|
||||
preference.readFromJson(json, appMode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void readPreferencesFromJson(final JSONObject json) {
|
||||
getSettings().getContext().runInUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
OsmandSettings settings = getSettings();
|
||||
Map<String, OsmandPreference<?>> prefs = settings.getRegisteredPreferences();
|
||||
Iterator<String> iter = json.keys();
|
||||
while (iter.hasNext()) {
|
||||
String key = iter.next();
|
||||
OsmandPreference<?> p = prefs.get(key);
|
||||
if (p == null) {
|
||||
if (OsmandSettings.isRoutingPreference(key)) {
|
||||
p = settings.registerStringPreference(key, "");
|
||||
}
|
||||
}
|
||||
if (p != null) {
|
||||
try {
|
||||
readPreferenceFromJson(p, json);
|
||||
if (OsmandSettings.isRoutingPreference(p.getId())) {
|
||||
if (p.getId().endsWith(GeneralRouter.USE_SHORTEST_WAY)) {
|
||||
settings.FAST_ROUTE_MODE.setModeValue(appMode,
|
||||
!settings.getCustomRoutingBooleanProperty(GeneralRouter.USE_SHORTEST_WAY, false).getModeValue(appMode));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
SettingsHelper.LOG.error("Failed to read preference: " + key, e);
|
||||
}
|
||||
} else {
|
||||
SettingsHelper.LOG.warn("No preference while importing settings: " + key);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
SettingsItemWriter<? extends SettingsItem> getWriter() {
|
||||
return new OsmandSettingsItemWriter<ProfileSettingsItem>(this, getSettings()) {
|
||||
@Override
|
||||
protected void writePreferenceToJson(@NonNull OsmandPreference<?> preference, @NonNull JSONObject json) throws JSONException {
|
||||
if (!appModeBeanPrefsIds.contains(preference.getId())) {
|
||||
preference.writeToJson(json, appMode);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private String[] getAppModeBeanPrefsIds() {
|
||||
OsmandSettings settings = app.getSettings();
|
||||
return new String[] {
|
||||
settings.ICON_COLOR.getId(),
|
||||
settings.ICON_RES_NAME.getId(),
|
||||
settings.PARENT_APP_MODE.getId(),
|
||||
settings.ROUTING_PROFILE.getId(),
|
||||
settings.ROUTE_SERVICE.getId(),
|
||||
settings.USER_PROFILE_NAME.getId(),
|
||||
settings.LOCATION_ICON.getId(),
|
||||
settings.NAVIGATION_ICON.getId(),
|
||||
settings.APP_MODE_ORDER.getId()
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,183 @@
|
|||
package net.osmand.plus.settings.backend.backup;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.quickaction.QuickAction;
|
||||
import net.osmand.plus.quickaction.QuickActionRegistry;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class QuickActionsSettingsItem extends CollectionSettingsItem<QuickAction> {
|
||||
|
||||
private QuickActionRegistry actionRegistry;
|
||||
|
||||
public QuickActionsSettingsItem(@NonNull OsmandApplication app, @NonNull List<QuickAction> items) {
|
||||
super(app, null, items);
|
||||
}
|
||||
|
||||
public QuickActionsSettingsItem(@NonNull OsmandApplication app, @Nullable QuickActionsSettingsItem baseItem, @NonNull List<QuickAction> items) {
|
||||
super(app, baseItem, items);
|
||||
}
|
||||
|
||||
QuickActionsSettingsItem(@NonNull OsmandApplication app, @NonNull JSONObject json) throws JSONException {
|
||||
super(app, json);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
actionRegistry = app.getQuickActionRegistry();
|
||||
existingItems = actionRegistry.getQuickActions();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public SettingsItemType getType() {
|
||||
return SettingsItemType.QUICK_ACTIONS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDuplicate(@NonNull QuickAction item) {
|
||||
return !actionRegistry.isNameUnique(item, app);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public QuickAction renameItem(@NonNull QuickAction item) {
|
||||
return actionRegistry.generateUniqueName(item, app);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply() {
|
||||
List<QuickAction> newItems = getNewItems();
|
||||
if (!newItems.isEmpty() || !duplicateItems.isEmpty()) {
|
||||
appliedItems = new ArrayList<>(newItems);
|
||||
List<QuickAction> newActions = new ArrayList<>(existingItems);
|
||||
if (!duplicateItems.isEmpty()) {
|
||||
if (shouldReplace) {
|
||||
for (QuickAction duplicateItem : duplicateItems) {
|
||||
for (QuickAction savedAction : existingItems) {
|
||||
if (duplicateItem.getName(app).equals(savedAction.getName(app))) {
|
||||
newActions.remove(savedAction);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (QuickAction duplicateItem : duplicateItems) {
|
||||
renameItem(duplicateItem);
|
||||
}
|
||||
}
|
||||
appliedItems.addAll(duplicateItems);
|
||||
}
|
||||
newActions.addAll(appliedItems);
|
||||
actionRegistry.updateQuickActions(newActions);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldReadOnCollecting() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return "quick_actions";
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getPublicName(@NonNull Context ctx) {
|
||||
return "quick_actions";
|
||||
}
|
||||
|
||||
@Override
|
||||
void readItemsFromJson(@NonNull JSONObject json) throws IllegalArgumentException {
|
||||
try {
|
||||
if (!json.has("items")) {
|
||||
return;
|
||||
}
|
||||
Gson gson = new Gson();
|
||||
Type type = new TypeToken<HashMap<String, String>>() {
|
||||
}.getType();
|
||||
QuickActionRegistry quickActionRegistry = app.getQuickActionRegistry();
|
||||
JSONArray itemsJson = json.getJSONArray("items");
|
||||
for (int i = 0; i < itemsJson.length(); i++) {
|
||||
JSONObject object = itemsJson.getJSONObject(i);
|
||||
String name = object.getString("name");
|
||||
QuickAction quickAction = null;
|
||||
if (object.has("actionType")) {
|
||||
quickAction = quickActionRegistry.newActionByStringType(object.getString("actionType"));
|
||||
} else if (object.has("type")) {
|
||||
quickAction = quickActionRegistry.newActionByType(object.getInt("type"));
|
||||
}
|
||||
if (quickAction != null) {
|
||||
String paramsString = object.getString("params");
|
||||
HashMap<String, String> params = gson.fromJson(paramsString, type);
|
||||
|
||||
if (!name.isEmpty()) {
|
||||
quickAction.setName(name);
|
||||
}
|
||||
quickAction.setParams(params);
|
||||
items.add(quickAction);
|
||||
} else {
|
||||
warnings.add(app.getString(R.string.settings_item_read_error, name));
|
||||
}
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
warnings.add(app.getString(R.string.settings_item_read_error, String.valueOf(getType())));
|
||||
throw new IllegalArgumentException("Json parse error", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void writeItemsToJson(@NonNull JSONObject json) {
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
Gson gson = new Gson();
|
||||
Type type = new TypeToken<HashMap<String, String>>() {
|
||||
}.getType();
|
||||
if (!items.isEmpty()) {
|
||||
try {
|
||||
for (QuickAction action : items) {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("name", action.hasCustomName(app)
|
||||
? action.getName(app) : "");
|
||||
jsonObject.put("actionType", action.getActionType().getStringId());
|
||||
jsonObject.put("params", gson.toJson(action.getParams(), type));
|
||||
jsonArray.put(jsonObject);
|
||||
}
|
||||
json.put("items", jsonArray);
|
||||
} catch (JSONException e) {
|
||||
warnings.add(app.getString(R.string.settings_item_write_error, String.valueOf(getType())));
|
||||
SettingsHelper.LOG.error("Failed write to json", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
SettingsItemReader<? extends SettingsItem> getReader() {
|
||||
return getJsonReader();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
SettingsItemWriter<? extends SettingsItem> getWriter() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package net.osmand.plus.settings.backend.backup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class ResourcesSettingsItem extends FileSettingsItem {
|
||||
|
||||
ResourcesSettingsItem(@NonNull OsmandApplication app, @NonNull JSONObject json) throws JSONException {
|
||||
super(app, json);
|
||||
shouldReplace = true;
|
||||
String fileName = getFileName();
|
||||
if (!Algorithms.isEmpty(fileName) && !fileName.endsWith(File.separator)) {
|
||||
this.fileName = fileName + File.separator;
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public SettingsItemType getType() {
|
||||
return SettingsItemType.RESOURCES;
|
||||
}
|
||||
|
||||
@Override
|
||||
void readFromJson(@NonNull JSONObject json) throws JSONException {
|
||||
subtype = FileSubtype.OTHER;
|
||||
super.readFromJson(json);
|
||||
}
|
||||
|
||||
@Override
|
||||
void writeToJson(@NonNull JSONObject json) throws JSONException {
|
||||
super.writeToJson(json);
|
||||
String fileName = getFileName();
|
||||
if (!Algorithms.isEmpty(fileName)) {
|
||||
if (fileName.endsWith(File.separator)) {
|
||||
fileName = fileName.substring(0, fileName.length() - 1);
|
||||
}
|
||||
json.put("file", fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applyFileName(@NonNull String fileName) {
|
||||
if (fileName.endsWith(File.separator)) {
|
||||
return false;
|
||||
}
|
||||
String itemFileName = getFileName();
|
||||
if (itemFileName != null && itemFileName.endsWith(File.separator)) {
|
||||
if (fileName.startsWith(itemFileName)) {
|
||||
this.file = new File(getPluginPath(), fileName);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return super.applyFileName(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public SettingsItemWriter<? extends SettingsItem> getWriter() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
package net.osmand.plus.settings.backend.backup;
|
||||
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
class SettingsExporter {
|
||||
|
||||
private Map<String, SettingsItem> items;
|
||||
private Map<String, String> additionalParams;
|
||||
private boolean exportItemsFiles;
|
||||
|
||||
SettingsExporter(boolean exportItemsFiles) {
|
||||
this.exportItemsFiles = exportItemsFiles;
|
||||
items = new LinkedHashMap<>();
|
||||
additionalParams = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
void addSettingsItem(SettingsItem item) throws IllegalArgumentException {
|
||||
if (items.containsKey(item.getName())) {
|
||||
throw new IllegalArgumentException("Already has such item: " + item.getName());
|
||||
}
|
||||
items.put(item.getName(), item);
|
||||
}
|
||||
|
||||
void addAdditionalParam(String key, String value) {
|
||||
additionalParams.put(key, value);
|
||||
}
|
||||
|
||||
void exportSettings(File file) throws JSONException, IOException {
|
||||
JSONObject json = createItemsJson();
|
||||
OutputStream os = new BufferedOutputStream(new FileOutputStream(file), SettingsHelper.BUFFER);
|
||||
ZipOutputStream zos = new ZipOutputStream(os);
|
||||
try {
|
||||
ZipEntry entry = new ZipEntry("items.json");
|
||||
zos.putNextEntry(entry);
|
||||
zos.write(json.toString(2).getBytes("UTF-8"));
|
||||
zos.closeEntry();
|
||||
if (exportItemsFiles) {
|
||||
writeItemFiles(zos);
|
||||
}
|
||||
zos.flush();
|
||||
zos.finish();
|
||||
} finally {
|
||||
Algorithms.closeStream(zos);
|
||||
Algorithms.closeStream(os);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeItemFiles(ZipOutputStream zos) throws IOException {
|
||||
for (SettingsItem item : items.values()) {
|
||||
SettingsItemWriter<? extends SettingsItem> writer = item.getWriter();
|
||||
if (writer != null) {
|
||||
String fileName = item.getFileName();
|
||||
if (Algorithms.isEmpty(fileName)) {
|
||||
fileName = item.getDefaultFileName();
|
||||
}
|
||||
ZipEntry entry = new ZipEntry(fileName);
|
||||
zos.putNextEntry(entry);
|
||||
writer.writeToStream(zos);
|
||||
zos.closeEntry();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private JSONObject createItemsJson() throws JSONException {
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("version", SettingsHelper.VERSION);
|
||||
for (Map.Entry<String, String> param : additionalParams.entrySet()) {
|
||||
json.put(param.getKey(), param.getValue());
|
||||
}
|
||||
JSONArray itemsJson = new JSONArray();
|
||||
for (SettingsItem item : items.values()) {
|
||||
itemsJson.put(new JSONObject(item.toJson()));
|
||||
}
|
||||
json.put("items", itemsJson);
|
||||
return json;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,643 @@
|
|||
package net.osmand.plus.settings.backend.backup;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.IndexConstants;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.data.LatLon;
|
||||
import net.osmand.map.ITileSource;
|
||||
import net.osmand.map.TileSourceManager;
|
||||
import net.osmand.map.TileSourceManager.TileSourceTemplate;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.OsmandPlugin;
|
||||
import net.osmand.plus.SQLiteTileSource;
|
||||
import net.osmand.plus.audionotes.AudioVideoNotesPlugin;
|
||||
import net.osmand.plus.audionotes.AudioVideoNotesPlugin.Recording;
|
||||
import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo;
|
||||
import net.osmand.plus.helpers.GpxUiHelper;
|
||||
import net.osmand.plus.helpers.GpxUiHelper.GPXInfo;
|
||||
import net.osmand.plus.poi.PoiUIFilter;
|
||||
import net.osmand.plus.quickaction.QuickAction;
|
||||
import net.osmand.plus.quickaction.QuickActionRegistry;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode.ApplicationModeBean;
|
||||
import net.osmand.plus.settings.backend.ExportSettingsType;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.json.JSONException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static net.osmand.IndexConstants.OSMAND_SETTINGS_FILE_EXT;
|
||||
|
||||
/*
|
||||
Usage:
|
||||
|
||||
SettingsHelper helper = app.getSettingsHelper();
|
||||
File file = new File(app.getAppPath(null), "settings.zip");
|
||||
|
||||
List<SettingsItem> items = new ArrayList<>();
|
||||
items.add(new GlobalSettingsItem(app.getSettings()));
|
||||
items.add(new ProfileSettingsItem(app.getSettings(), ApplicationMode.DEFAULT));
|
||||
items.add(new ProfileSettingsItem(app.getSettings(), ApplicationMode.CAR));
|
||||
items.add(new ProfileSettingsItem(app.getSettings(), ApplicationMode.PEDESTRIAN));
|
||||
items.add(new ProfileSettingsItem(app.getSettings(), ApplicationMode.BICYCLE));
|
||||
items.add(new FileSettingsItem(app, new File(app.getAppPath(GPX_INDEX_DIR), "Day 2.gpx")));
|
||||
items.add(new FileSettingsItem(app, new File(app.getAppPath(GPX_INDEX_DIR), "Day 3.gpx")));
|
||||
items.add(new FileSettingsItem(app, new File(app.getAppPath(RENDERERS_DIR), "default.render.xml")));
|
||||
items.add(new DataSettingsItem(new byte[] {'t', 'e', 's', 't', '1'}, "data1"));
|
||||
items.add(new DataSettingsItem(new byte[] {'t', 'e', 's', 't', '2'}, "data2"));
|
||||
|
||||
helper.exportSettings(file, items);
|
||||
|
||||
helper.importSettings(file);
|
||||
*/
|
||||
|
||||
public class SettingsHelper {
|
||||
|
||||
public static final int VERSION = 1;
|
||||
|
||||
public static final String SETTINGS_TYPE_LIST_KEY = "settings_type_list_key";
|
||||
public static final String REPLACE_KEY = "replace";
|
||||
public static final String SETTINGS_LATEST_CHANGES_KEY = "settings_latest_changes";
|
||||
public static final String SETTINGS_VERSION_KEY = "settings_version";
|
||||
|
||||
public static final int BUFFER = 1024;
|
||||
|
||||
protected static final Log LOG = PlatformUtil.getLog(SettingsHelper.class);
|
||||
|
||||
private OsmandApplication app;
|
||||
|
||||
private ImportAsyncTask importTask;
|
||||
private Map<File, ExportAsyncTask> exportAsyncTasks = new HashMap<>();
|
||||
|
||||
public interface SettingsImportListener {
|
||||
void onSettingsImportFinished(boolean succeed, @NonNull List<SettingsItem> items);
|
||||
}
|
||||
|
||||
public interface SettingsCollectListener {
|
||||
void onSettingsCollectFinished(boolean succeed, boolean empty, @NonNull List<SettingsItem> items);
|
||||
}
|
||||
|
||||
public interface CheckDuplicatesListener {
|
||||
void onDuplicatesChecked(@NonNull List<Object> duplicates, List<SettingsItem> items);
|
||||
}
|
||||
|
||||
public interface SettingsExportListener {
|
||||
void onSettingsExportFinished(@NonNull File file, boolean succeed);
|
||||
}
|
||||
|
||||
public enum ImportType {
|
||||
COLLECT,
|
||||
CHECK_DUPLICATES,
|
||||
IMPORT
|
||||
}
|
||||
|
||||
public SettingsHelper(@NonNull OsmandApplication app) {
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ImportAsyncTask getImportTask() {
|
||||
return importTask;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ImportType getImportTaskType() {
|
||||
ImportAsyncTask importTask = this.importTask;
|
||||
return importTask != null ? importTask.getImportType() : null;
|
||||
}
|
||||
|
||||
public boolean isImportDone() {
|
||||
ImportAsyncTask importTask = this.importTask;
|
||||
return importTask == null || importTask.isImportDone();
|
||||
}
|
||||
|
||||
public boolean isFileExporting(File file) {
|
||||
return exportAsyncTasks.containsKey(file);
|
||||
}
|
||||
|
||||
public void updateExportListener(File file, SettingsExportListener listener) {
|
||||
ExportAsyncTask exportAsyncTask = exportAsyncTasks.get(file);
|
||||
if (exportAsyncTask != null) {
|
||||
exportAsyncTask.listener = listener;
|
||||
}
|
||||
}
|
||||
|
||||
private void finishImport(@Nullable SettingsImportListener listener, boolean success, @NonNull List<SettingsItem> items) {
|
||||
importTask = null;
|
||||
List<String> warnings = new ArrayList<>();
|
||||
for (SettingsItem item : items) {
|
||||
warnings.addAll(item.getWarnings());
|
||||
}
|
||||
if (!warnings.isEmpty()) {
|
||||
app.showToastMessage(AndroidUtils.formatWarnings(warnings).toString());
|
||||
}
|
||||
if (listener != null) {
|
||||
listener.onSettingsImportFinished(success, items);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
private class ImportItemsAsyncTask extends AsyncTask<Void, Void, Boolean> {
|
||||
|
||||
private SettingsImporter importer;
|
||||
private File file;
|
||||
private SettingsImportListener listener;
|
||||
private List<SettingsItem> items;
|
||||
|
||||
ImportItemsAsyncTask(@NonNull File file,
|
||||
@Nullable SettingsImportListener listener,
|
||||
@NonNull List<SettingsItem> items) {
|
||||
importer = new SettingsImporter(app);
|
||||
this.file = file;
|
||||
this.listener = listener;
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... voids) {
|
||||
try {
|
||||
importer.importItems(file, items);
|
||||
return true;
|
||||
} catch (IllegalArgumentException e) {
|
||||
LOG.error("Failed to import items from: " + file.getName(), e);
|
||||
} catch (IOException e) {
|
||||
LOG.error("Failed to import items from: " + file.getName(), e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean success) {
|
||||
finishImport(listener, success, items);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
private class ExportAsyncTask extends AsyncTask<Void, Void, Boolean> {
|
||||
|
||||
private SettingsExporter exporter;
|
||||
private File file;
|
||||
private SettingsExportListener listener;
|
||||
|
||||
ExportAsyncTask(@NonNull File settingsFile,
|
||||
@Nullable SettingsExportListener listener,
|
||||
@NonNull List<SettingsItem> items, boolean exportItemsFiles) {
|
||||
this.file = settingsFile;
|
||||
this.listener = listener;
|
||||
this.exporter = new SettingsExporter(exportItemsFiles);
|
||||
for (SettingsItem item : items) {
|
||||
exporter.addSettingsItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... voids) {
|
||||
try {
|
||||
exporter.exportSettings(file);
|
||||
return true;
|
||||
} catch (JSONException e) {
|
||||
LOG.error("Failed to export items to: " + file.getName(), e);
|
||||
} catch (IOException e) {
|
||||
LOG.error("Failed to export items to: " + file.getName(), e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean success) {
|
||||
exportAsyncTasks.remove(file);
|
||||
if (listener != null) {
|
||||
listener.onSettingsExportFinished(file, success);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
public class ImportAsyncTask extends AsyncTask<Void, Void, List<SettingsItem>> {
|
||||
|
||||
private File file;
|
||||
private String latestChanges;
|
||||
private int version;
|
||||
|
||||
private SettingsImportListener importListener;
|
||||
private SettingsCollectListener collectListener;
|
||||
private CheckDuplicatesListener duplicatesListener;
|
||||
private SettingsImporter importer;
|
||||
|
||||
private List<SettingsItem> items = new ArrayList<>();
|
||||
private List<SettingsItem> selectedItems = new ArrayList<>();
|
||||
private List<Object> duplicates;
|
||||
|
||||
private ImportType importType;
|
||||
private boolean importDone;
|
||||
|
||||
ImportAsyncTask(@NonNull File file, String latestChanges, int version, @Nullable SettingsCollectListener collectListener) {
|
||||
this.file = file;
|
||||
this.collectListener = collectListener;
|
||||
this.latestChanges = latestChanges;
|
||||
this.version = version;
|
||||
importer = new SettingsImporter(app);
|
||||
importType = ImportType.COLLECT;
|
||||
}
|
||||
|
||||
ImportAsyncTask(@NonNull File file, @NonNull List<SettingsItem> items, String latestChanges, int version, @Nullable SettingsImportListener importListener) {
|
||||
this.file = file;
|
||||
this.importListener = importListener;
|
||||
this.items = items;
|
||||
this.latestChanges = latestChanges;
|
||||
this.version = version;
|
||||
importer = new SettingsImporter(app);
|
||||
importType = ImportType.IMPORT;
|
||||
}
|
||||
|
||||
ImportAsyncTask(@NonNull File file, @NonNull List<SettingsItem> items, @NonNull List<SettingsItem> selectedItems, @Nullable CheckDuplicatesListener duplicatesListener) {
|
||||
this.file = file;
|
||||
this.items = items;
|
||||
this.duplicatesListener = duplicatesListener;
|
||||
this.selectedItems = selectedItems;
|
||||
importer = new SettingsImporter(app);
|
||||
importType = ImportType.CHECK_DUPLICATES;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
ImportAsyncTask importTask = SettingsHelper.this.importTask;
|
||||
if (importTask != null && !importTask.importDone) {
|
||||
finishImport(importListener, false, items);
|
||||
}
|
||||
SettingsHelper.this.importTask = this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<SettingsItem> doInBackground(Void... voids) {
|
||||
switch (importType) {
|
||||
case COLLECT:
|
||||
try {
|
||||
return importer.collectItems(file);
|
||||
} catch (IllegalArgumentException e) {
|
||||
LOG.error("Failed to collect items from: " + file.getName(), e);
|
||||
} catch (IOException e) {
|
||||
LOG.error("Failed to collect items from: " + file.getName(), e);
|
||||
}
|
||||
break;
|
||||
case CHECK_DUPLICATES:
|
||||
this.duplicates = getDuplicatesData(selectedItems);
|
||||
return selectedItems;
|
||||
case IMPORT:
|
||||
return items;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(@Nullable List<SettingsItem> items) {
|
||||
if (items != null && importType != ImportType.CHECK_DUPLICATES) {
|
||||
this.items = items;
|
||||
} else {
|
||||
selectedItems = items;
|
||||
}
|
||||
switch (importType) {
|
||||
case COLLECT:
|
||||
importDone = true;
|
||||
collectListener.onSettingsCollectFinished(true, false, this.items);
|
||||
break;
|
||||
case CHECK_DUPLICATES:
|
||||
importDone = true;
|
||||
if (duplicatesListener != null) {
|
||||
duplicatesListener.onDuplicatesChecked(duplicates, selectedItems);
|
||||
}
|
||||
break;
|
||||
case IMPORT:
|
||||
if (items != null && items.size() > 0) {
|
||||
for (SettingsItem item : items) {
|
||||
item.apply();
|
||||
}
|
||||
new ImportItemsAsyncTask(file, importListener, items).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public List<SettingsItem> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
public File getFile() {
|
||||
return file;
|
||||
}
|
||||
|
||||
public void setImportListener(SettingsImportListener importListener) {
|
||||
this.importListener = importListener;
|
||||
}
|
||||
|
||||
public void setDuplicatesListener(CheckDuplicatesListener duplicatesListener) {
|
||||
this.duplicatesListener = duplicatesListener;
|
||||
}
|
||||
|
||||
ImportType getImportType() {
|
||||
return importType;
|
||||
}
|
||||
|
||||
boolean isImportDone() {
|
||||
return importDone;
|
||||
}
|
||||
|
||||
public List<Object> getDuplicates() {
|
||||
return duplicates;
|
||||
}
|
||||
|
||||
public List<SettingsItem> getSelectedItems() {
|
||||
return selectedItems;
|
||||
}
|
||||
|
||||
private List<Object> getDuplicatesData(List<SettingsItem> items) {
|
||||
List<Object> duplicateItems = new ArrayList<>();
|
||||
for (SettingsItem item : items) {
|
||||
if (item instanceof ProfileSettingsItem) {
|
||||
if (item.exists()) {
|
||||
duplicateItems.add(((ProfileSettingsItem) item).getModeBean());
|
||||
}
|
||||
} else if (item instanceof CollectionSettingsItem<?>) {
|
||||
List<?> duplicates = ((CollectionSettingsItem<?>) item).processDuplicateItems();
|
||||
if (!duplicates.isEmpty()) {
|
||||
duplicateItems.addAll(duplicates);
|
||||
}
|
||||
} else if (item instanceof FileSettingsItem) {
|
||||
if (item.exists()) {
|
||||
duplicateItems.add(((FileSettingsItem) item).getFile());
|
||||
}
|
||||
}
|
||||
}
|
||||
return duplicateItems;
|
||||
}
|
||||
}
|
||||
|
||||
public void collectSettings(@NonNull File settingsFile, String latestChanges, int version,
|
||||
@Nullable SettingsCollectListener listener) {
|
||||
new ImportAsyncTask(settingsFile, latestChanges, version, listener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
public void checkDuplicates(@NonNull File file, @NonNull List<SettingsItem> items, @NonNull List<SettingsItem> selectedItems, CheckDuplicatesListener listener) {
|
||||
new ImportAsyncTask(file, items, selectedItems, listener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
public void importSettings(@NonNull File settingsFile, @NonNull List<SettingsItem> items, String latestChanges, int version, @Nullable SettingsImportListener listener) {
|
||||
new ImportAsyncTask(settingsFile, items, latestChanges, version, listener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
public void exportSettings(@NonNull File fileDir, @NonNull String fileName, @Nullable SettingsExportListener listener, @NonNull List<SettingsItem> items, boolean exportItemsFiles) {
|
||||
File file = new File(fileDir, fileName + OSMAND_SETTINGS_FILE_EXT);
|
||||
ExportAsyncTask exportAsyncTask = new ExportAsyncTask(file, listener, items, exportItemsFiles);
|
||||
exportAsyncTasks.put(file, exportAsyncTask);
|
||||
exportAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
public void exportSettings(@NonNull File fileDir, @NonNull String fileName, @Nullable SettingsExportListener listener,
|
||||
boolean exportItemsFiles, @NonNull SettingsItem... items) {
|
||||
exportSettings(fileDir, fileName, listener, new ArrayList<>(Arrays.asList(items)), exportItemsFiles);
|
||||
}
|
||||
|
||||
public List<SettingsItem> getFilteredSettingsItems(Map<ExportSettingsType, List<?>> additionalData,
|
||||
List<ExportSettingsType> settingsTypes) {
|
||||
List<SettingsItem> settingsItems = new ArrayList<>();
|
||||
for (ExportSettingsType settingsType : settingsTypes) {
|
||||
List<?> settingsDataObjects = additionalData.get(settingsType);
|
||||
if (settingsDataObjects != null) {
|
||||
for (Object object : settingsDataObjects) {
|
||||
if (object instanceof ApplicationModeBean) {
|
||||
settingsItems.add(new ProfileSettingsItem(app, null, (ApplicationModeBean) object));
|
||||
}
|
||||
}
|
||||
settingsItems.addAll(prepareAdditionalSettingsItems(new ArrayList<>(settingsDataObjects)));
|
||||
}
|
||||
}
|
||||
return settingsItems;
|
||||
}
|
||||
|
||||
public Map<ExportSettingsType, List<?>> getAdditionalData() {
|
||||
Map<ExportSettingsType, List<?>> dataList = new HashMap<>();
|
||||
|
||||
QuickActionRegistry registry = app.getQuickActionRegistry();
|
||||
List<QuickAction> actionsList = registry.getQuickActions();
|
||||
if (!actionsList.isEmpty()) {
|
||||
dataList.put(ExportSettingsType.QUICK_ACTIONS, actionsList);
|
||||
}
|
||||
|
||||
List<PoiUIFilter> poiList = app.getPoiFilters().getUserDefinedPoiFilters(false);
|
||||
if (!poiList.isEmpty()) {
|
||||
dataList.put(ExportSettingsType.POI_TYPES, poiList);
|
||||
}
|
||||
|
||||
List<ITileSource> iTileSources = new ArrayList<>();
|
||||
Set<String> tileSourceNames = app.getSettings().getTileSourceEntries(true).keySet();
|
||||
for (String name : tileSourceNames) {
|
||||
File f = app.getAppPath(IndexConstants.TILES_INDEX_DIR + name);
|
||||
if (f != null) {
|
||||
ITileSource template;
|
||||
if (f.getName().endsWith(SQLiteTileSource.EXT)) {
|
||||
template = new SQLiteTileSource(app, f, TileSourceManager.getKnownSourceTemplates());
|
||||
} else {
|
||||
template = TileSourceManager.createTileSourceTemplate(f);
|
||||
}
|
||||
if (template.getUrlTemplate() != null) {
|
||||
iTileSources.add(template);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!iTileSources.isEmpty()) {
|
||||
dataList.put(ExportSettingsType.MAP_SOURCES, iTileSources);
|
||||
}
|
||||
|
||||
Map<String, File> externalRenderers = app.getRendererRegistry().getExternalRenderers();
|
||||
if (!externalRenderers.isEmpty()) {
|
||||
dataList.put(ExportSettingsType.CUSTOM_RENDER_STYLE, new ArrayList<>(externalRenderers.values()));
|
||||
}
|
||||
|
||||
File routingProfilesFolder = app.getAppPath(IndexConstants.ROUTING_PROFILES_DIR);
|
||||
if (routingProfilesFolder.exists() && routingProfilesFolder.isDirectory()) {
|
||||
File[] fl = routingProfilesFolder.listFiles();
|
||||
if (fl != null && fl.length > 0) {
|
||||
dataList.put(ExportSettingsType.CUSTOM_ROUTING, Arrays.asList(fl));
|
||||
}
|
||||
}
|
||||
|
||||
Map<LatLon, AvoidRoadInfo> impassableRoads = app.getAvoidSpecificRoads().getImpassableRoads();
|
||||
if (!impassableRoads.isEmpty()) {
|
||||
dataList.put(ExportSettingsType.AVOID_ROADS, new ArrayList<>(impassableRoads.values()));
|
||||
}
|
||||
AudioVideoNotesPlugin plugin = OsmandPlugin.getPlugin(AudioVideoNotesPlugin.class);
|
||||
if (plugin != null) {
|
||||
List<File> files = new ArrayList<>();
|
||||
for (Recording rec : plugin.getAllRecordings()) {
|
||||
File file = rec.getFile();
|
||||
if (file != null && file.exists()) {
|
||||
files.add(file);
|
||||
}
|
||||
}
|
||||
if (!files.isEmpty()) {
|
||||
dataList.put(ExportSettingsType.MULTIMEDIA_NOTES, files);
|
||||
}
|
||||
}
|
||||
File gpxDir = app.getAppPath(IndexConstants.GPX_INDEX_DIR);
|
||||
List<GPXInfo> gpxInfoList = GpxUiHelper.getSortedGPXFilesInfo(gpxDir, null, true);
|
||||
if (!gpxInfoList.isEmpty()) {
|
||||
List<File> files = new ArrayList<>();
|
||||
for (GPXInfo gpxInfo : gpxInfoList) {
|
||||
File file = new File(gpxInfo.getFileName());
|
||||
if (file.exists()) {
|
||||
files.add(file);
|
||||
}
|
||||
}
|
||||
if (!files.isEmpty()) {
|
||||
dataList.put(ExportSettingsType.TRACKS, files);
|
||||
}
|
||||
}
|
||||
return dataList;
|
||||
}
|
||||
|
||||
public List<SettingsItem> prepareAdditionalSettingsItems(List<? super Object> data) {
|
||||
List<SettingsItem> settingsItems = new ArrayList<>();
|
||||
List<QuickAction> quickActions = new ArrayList<>();
|
||||
List<PoiUIFilter> poiUIFilters = new ArrayList<>();
|
||||
List<ITileSource> tileSourceTemplates = new ArrayList<>();
|
||||
List<AvoidRoadInfo> avoidRoads = new ArrayList<>();
|
||||
for (Object object : data) {
|
||||
if (object instanceof QuickAction) {
|
||||
quickActions.add((QuickAction) object);
|
||||
} else if (object instanceof PoiUIFilter) {
|
||||
poiUIFilters.add((PoiUIFilter) object);
|
||||
} else if (object instanceof TileSourceTemplate || object instanceof SQLiteTileSource) {
|
||||
tileSourceTemplates.add((ITileSource) object);
|
||||
} else if (object instanceof File) {
|
||||
try {
|
||||
settingsItems.add(new FileSettingsItem(app, (File) object));
|
||||
} catch (IllegalArgumentException e) {
|
||||
LOG.warn("Trying to export unsuported file type", e);
|
||||
}
|
||||
} else if (object instanceof AvoidRoadInfo) {
|
||||
avoidRoads.add((AvoidRoadInfo) object);
|
||||
}
|
||||
}
|
||||
if (!quickActions.isEmpty()) {
|
||||
settingsItems.add(new QuickActionsSettingsItem(app, quickActions));
|
||||
}
|
||||
if (!poiUIFilters.isEmpty()) {
|
||||
settingsItems.add(new PoiUiFiltersSettingsItem(app, poiUIFilters));
|
||||
}
|
||||
if (!tileSourceTemplates.isEmpty()) {
|
||||
settingsItems.add(new MapSourcesSettingsItem(app, tileSourceTemplates));
|
||||
}
|
||||
if (!avoidRoads.isEmpty()) {
|
||||
settingsItems.add(new AvoidRoadsSettingsItem(app, avoidRoads));
|
||||
}
|
||||
return settingsItems;
|
||||
}
|
||||
|
||||
public static Map<ExportSettingsType, List<?>> getSettingsToOperate(List<SettingsItem> settingsItems, boolean importComplete) {
|
||||
Map<ExportSettingsType, List<?>> settingsToOperate = new HashMap<>();
|
||||
List<ApplicationModeBean> profiles = new ArrayList<>();
|
||||
List<QuickAction> quickActions = new ArrayList<>();
|
||||
List<PoiUIFilter> poiUIFilters = new ArrayList<>();
|
||||
List<ITileSource> tileSourceTemplates = new ArrayList<>();
|
||||
List<File> routingFilesList = new ArrayList<>();
|
||||
List<File> renderFilesList = new ArrayList<>();
|
||||
List<File> multimediaFilesList = new ArrayList<>();
|
||||
List<File> tracksFilesList = new ArrayList<>();
|
||||
List<AvoidRoadInfo> avoidRoads = new ArrayList<>();
|
||||
for (SettingsItem item : settingsItems) {
|
||||
switch (item.getType()) {
|
||||
case PROFILE:
|
||||
profiles.add(((ProfileSettingsItem) item).getModeBean());
|
||||
break;
|
||||
case FILE:
|
||||
FileSettingsItem fileItem = (FileSettingsItem) item;
|
||||
if (fileItem.getSubtype() == FileSettingsItem.FileSubtype.RENDERING_STYLE) {
|
||||
renderFilesList.add(fileItem.getFile());
|
||||
} else if (fileItem.getSubtype() == FileSettingsItem.FileSubtype.ROUTING_CONFIG) {
|
||||
routingFilesList.add(fileItem.getFile());
|
||||
} else if (fileItem.getSubtype() == FileSettingsItem.FileSubtype.MULTIMEDIA_NOTES) {
|
||||
multimediaFilesList.add(fileItem.getFile());
|
||||
} else if (fileItem.getSubtype() == FileSettingsItem.FileSubtype.GPX) {
|
||||
tracksFilesList.add(fileItem.getFile());
|
||||
}
|
||||
break;
|
||||
case QUICK_ACTIONS:
|
||||
QuickActionsSettingsItem quickActionsItem = (QuickActionsSettingsItem) item;
|
||||
if (importComplete) {
|
||||
quickActions.addAll(quickActionsItem.getAppliedItems());
|
||||
} else {
|
||||
quickActions.addAll(quickActionsItem.getItems());
|
||||
}
|
||||
break;
|
||||
case POI_UI_FILTERS:
|
||||
PoiUiFiltersSettingsItem poiUiFilterItem = (PoiUiFiltersSettingsItem) item;
|
||||
if (importComplete) {
|
||||
poiUIFilters.addAll(poiUiFilterItem.getAppliedItems());
|
||||
} else {
|
||||
poiUIFilters.addAll(poiUiFilterItem.getItems());
|
||||
}
|
||||
break;
|
||||
case MAP_SOURCES:
|
||||
MapSourcesSettingsItem mapSourcesItem = (MapSourcesSettingsItem) item;
|
||||
if (importComplete) {
|
||||
tileSourceTemplates.addAll(mapSourcesItem.getAppliedItems());
|
||||
} else {
|
||||
tileSourceTemplates.addAll(mapSourcesItem.getItems());
|
||||
}
|
||||
break;
|
||||
case AVOID_ROADS:
|
||||
AvoidRoadsSettingsItem avoidRoadsItem = (AvoidRoadsSettingsItem) item;
|
||||
if (importComplete) {
|
||||
avoidRoads.addAll(avoidRoadsItem.getAppliedItems());
|
||||
} else {
|
||||
avoidRoads.addAll(avoidRoadsItem.getItems());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!profiles.isEmpty()) {
|
||||
settingsToOperate.put(ExportSettingsType.PROFILE, profiles);
|
||||
}
|
||||
if (!quickActions.isEmpty()) {
|
||||
settingsToOperate.put(ExportSettingsType.QUICK_ACTIONS, quickActions);
|
||||
}
|
||||
if (!poiUIFilters.isEmpty()) {
|
||||
settingsToOperate.put(ExportSettingsType.POI_TYPES, poiUIFilters);
|
||||
}
|
||||
if (!tileSourceTemplates.isEmpty()) {
|
||||
settingsToOperate.put(ExportSettingsType.MAP_SOURCES, tileSourceTemplates);
|
||||
}
|
||||
if (!renderFilesList.isEmpty()) {
|
||||
settingsToOperate.put(ExportSettingsType.CUSTOM_RENDER_STYLE, renderFilesList);
|
||||
}
|
||||
if (!routingFilesList.isEmpty()) {
|
||||
settingsToOperate.put(ExportSettingsType.CUSTOM_ROUTING, routingFilesList);
|
||||
}
|
||||
if (!avoidRoads.isEmpty()) {
|
||||
settingsToOperate.put(ExportSettingsType.AVOID_ROADS, avoidRoads);
|
||||
}
|
||||
if (!multimediaFilesList.isEmpty()) {
|
||||
settingsToOperate.put(ExportSettingsType.MULTIMEDIA_NOTES, multimediaFilesList);
|
||||
}
|
||||
if (!tracksFilesList.isEmpty()) {
|
||||
settingsToOperate.put(ExportSettingsType.TRACKS, tracksFilesList);
|
||||
}
|
||||
return settingsToOperate;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
package net.osmand.plus.settings.backend.backup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import org.json.JSONException;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import static net.osmand.IndexConstants.OSMAND_SETTINGS_FILE_EXT;
|
||||
|
||||
class SettingsImporter {
|
||||
|
||||
private OsmandApplication app;
|
||||
|
||||
SettingsImporter(@NonNull OsmandApplication app) {
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
List<SettingsItem> collectItems(@NonNull File file) throws IllegalArgumentException, IOException {
|
||||
return processItems(file, null);
|
||||
}
|
||||
|
||||
void importItems(@NonNull File file, @NonNull List<SettingsItem> items) throws IllegalArgumentException, IOException {
|
||||
processItems(file, items);
|
||||
}
|
||||
|
||||
private List<SettingsItem> getItemsFromJson(@NonNull File file) throws IOException {
|
||||
List<SettingsItem> items = new ArrayList<>();
|
||||
ZipInputStream zis = new ZipInputStream(new FileInputStream(file));
|
||||
InputStream ois = new BufferedInputStream(zis);
|
||||
try {
|
||||
ZipEntry entry;
|
||||
while ((entry = zis.getNextEntry()) != null) {
|
||||
String fileName = checkEntryName(entry.getName());
|
||||
if (fileName.equals("items.json")) {
|
||||
String itemsJson = null;
|
||||
try {
|
||||
itemsJson = Algorithms.readFromInputStream(ois, false).toString();
|
||||
} catch (IOException e) {
|
||||
SettingsHelper.LOG.error("Error reading items.json: " + itemsJson, e);
|
||||
throw new IllegalArgumentException("No items");
|
||||
} finally {
|
||||
zis.closeEntry();
|
||||
}
|
||||
try {
|
||||
SettingsItemsFactory itemsFactory = new SettingsItemsFactory(app, itemsJson);
|
||||
items.addAll(itemsFactory.getItems());
|
||||
} catch (IllegalArgumentException e) {
|
||||
SettingsHelper.LOG.error("Error parsing items: " + itemsJson, e);
|
||||
throw new IllegalArgumentException("No items");
|
||||
} catch (JSONException e) {
|
||||
SettingsHelper.LOG.error("Error parsing items: " + itemsJson, e);
|
||||
throw new IllegalArgumentException("No items");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
SettingsHelper.LOG.error("Failed to read next entry", ex);
|
||||
} finally {
|
||||
Algorithms.closeStream(ois);
|
||||
Algorithms.closeStream(zis);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
private List<SettingsItem> processItems(@NonNull File file, @Nullable List<SettingsItem> items) throws IllegalArgumentException, IOException {
|
||||
boolean collecting = items == null;
|
||||
if (collecting) {
|
||||
items = getItemsFromJson(file);
|
||||
} else {
|
||||
if (items.size() == 0) {
|
||||
throw new IllegalArgumentException("No items");
|
||||
}
|
||||
}
|
||||
ZipInputStream zis = new ZipInputStream(new FileInputStream(file));
|
||||
InputStream ois = new BufferedInputStream(zis);
|
||||
try {
|
||||
ZipEntry entry;
|
||||
while ((entry = zis.getNextEntry()) != null) {
|
||||
String fileName = checkEntryName(entry.getName());
|
||||
SettingsItem item = null;
|
||||
for (SettingsItem settingsItem : items) {
|
||||
if (settingsItem != null && settingsItem.applyFileName(fileName)) {
|
||||
item = settingsItem;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (item != null && collecting && item.shouldReadOnCollecting()
|
||||
|| item != null && !collecting && !item.shouldReadOnCollecting()) {
|
||||
try {
|
||||
SettingsItemReader<? extends SettingsItem> reader = item.getReader();
|
||||
if (reader != null) {
|
||||
reader.readFromStream(ois);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
item.warnings.add(app.getString(R.string.settings_item_read_error, item.getName()));
|
||||
SettingsHelper.LOG.error("Error reading item data: " + item.getName(), e);
|
||||
} catch (IOException e) {
|
||||
item.warnings.add(app.getString(R.string.settings_item_read_error, item.getName()));
|
||||
SettingsHelper.LOG.error("Error reading item data: " + item.getName(), e);
|
||||
} finally {
|
||||
zis.closeEntry();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
SettingsHelper.LOG.error("Failed to read next entry", ex);
|
||||
} finally {
|
||||
Algorithms.closeStream(ois);
|
||||
Algorithms.closeStream(zis);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
private String checkEntryName(String entryName) {
|
||||
String fileExt = OSMAND_SETTINGS_FILE_EXT + "/";
|
||||
int index = entryName.indexOf(fileExt);
|
||||
if (index != -1) {
|
||||
entryName = entryName.substring(index + fileExt.length());
|
||||
}
|
||||
return entryName;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,236 @@
|
|||
package net.osmand.plus.settings.backend.backup;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class SettingsItem {
|
||||
|
||||
protected OsmandApplication app;
|
||||
|
||||
protected String pluginId;
|
||||
protected String fileName;
|
||||
|
||||
boolean shouldReplace = false;
|
||||
|
||||
protected List<String> warnings;
|
||||
|
||||
SettingsItem(@NonNull OsmandApplication app) {
|
||||
this.app = app;
|
||||
init();
|
||||
}
|
||||
|
||||
SettingsItem(@NonNull OsmandApplication app, @Nullable SettingsItem baseItem) {
|
||||
this.app = app;
|
||||
if (baseItem != null) {
|
||||
this.pluginId = baseItem.pluginId;
|
||||
this.fileName = baseItem.fileName;
|
||||
}
|
||||
init();
|
||||
}
|
||||
|
||||
SettingsItem(OsmandApplication app, @NonNull JSONObject json) throws JSONException {
|
||||
this.app = app;
|
||||
init();
|
||||
readFromJson(json);
|
||||
}
|
||||
|
||||
protected void init() {
|
||||
warnings = new ArrayList<>();
|
||||
}
|
||||
|
||||
public List<String> getWarnings() {
|
||||
return warnings;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public abstract SettingsItemType getType();
|
||||
|
||||
@NonNull
|
||||
public abstract String getName();
|
||||
|
||||
@NonNull
|
||||
public abstract String getPublicName(@NonNull Context ctx);
|
||||
|
||||
@NonNull
|
||||
public String getDefaultFileName() {
|
||||
return getName() + getDefaultFileExtension();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getDefaultFileExtension() {
|
||||
return ".json";
|
||||
}
|
||||
|
||||
public String getPluginId() {
|
||||
return pluginId;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public boolean applyFileName(@NonNull String fileName) {
|
||||
String n = getFileName();
|
||||
return n != null && n.endsWith(fileName);
|
||||
}
|
||||
|
||||
public boolean shouldReadOnCollecting() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setShouldReplace(boolean shouldReplace) {
|
||||
this.shouldReplace = shouldReplace;
|
||||
}
|
||||
|
||||
static SettingsItemType parseItemType(@NonNull JSONObject json) throws IllegalArgumentException, JSONException {
|
||||
String type = json.has("type") ? json.getString("type") : null;
|
||||
if (type == null) {
|
||||
throw new IllegalArgumentException("No type field");
|
||||
}
|
||||
if (type.equals("QUICK_ACTION")) {
|
||||
type = "QUICK_ACTIONS";
|
||||
}
|
||||
return SettingsItemType.valueOf(type);
|
||||
}
|
||||
|
||||
public boolean exists() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void apply() {
|
||||
// non implemented
|
||||
}
|
||||
|
||||
void readFromJson(@NonNull JSONObject json) throws JSONException {
|
||||
pluginId = json.has("pluginId") ? json.getString("pluginId") : null;
|
||||
if (json.has("name")) {
|
||||
fileName = json.getString("name") + getDefaultFileExtension();
|
||||
}
|
||||
if (json.has("file")) {
|
||||
fileName = json.getString("file");
|
||||
}
|
||||
readItemsFromJson(json);
|
||||
}
|
||||
|
||||
void writeToJson(@NonNull JSONObject json) throws JSONException {
|
||||
json.put("type", getType().name());
|
||||
String pluginId = getPluginId();
|
||||
if (!Algorithms.isEmpty(pluginId)) {
|
||||
json.put("pluginId", pluginId);
|
||||
}
|
||||
if (getWriter() != null) {
|
||||
String fileName = getFileName();
|
||||
if (Algorithms.isEmpty(fileName)) {
|
||||
fileName = getDefaultFileName();
|
||||
}
|
||||
json.put("file", fileName);
|
||||
}
|
||||
writeItemsToJson(json);
|
||||
}
|
||||
|
||||
String toJson() throws JSONException {
|
||||
JSONObject json = new JSONObject();
|
||||
writeToJson(json);
|
||||
return json.toString();
|
||||
}
|
||||
|
||||
void readItemsFromJson(@NonNull JSONObject json) throws IllegalArgumentException {
|
||||
// override
|
||||
}
|
||||
|
||||
void writeItemsToJson(@NonNull JSONObject json) {
|
||||
// override
|
||||
}
|
||||
|
||||
@Nullable
|
||||
abstract SettingsItemReader<? extends SettingsItem> getReader();
|
||||
|
||||
@Nullable
|
||||
abstract SettingsItemWriter<? extends SettingsItem> getWriter();
|
||||
|
||||
@NonNull
|
||||
SettingsItemReader<? extends SettingsItem> getJsonReader() {
|
||||
return new SettingsItemReader<SettingsItem>(this) {
|
||||
@Override
|
||||
public void readFromStream(@NonNull InputStream inputStream) throws IOException, IllegalArgumentException {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
try {
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
|
||||
String str;
|
||||
while ((str = in.readLine()) != null) {
|
||||
buf.append(str);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new IOException("Cannot read json body", e);
|
||||
}
|
||||
String json = buf.toString();
|
||||
if (json.length() == 0) {
|
||||
throw new IllegalArgumentException("Json body is empty");
|
||||
}
|
||||
try {
|
||||
readItemsFromJson(new JSONObject(json));
|
||||
} catch (JSONException e) {
|
||||
throw new IllegalArgumentException("Json parsing error", e);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@NonNull
|
||||
SettingsItemWriter<? extends SettingsItem> getJsonWriter() {
|
||||
return new SettingsItemWriter<SettingsItem>(this) {
|
||||
@Override
|
||||
public boolean writeToStream(@NonNull OutputStream outputStream) throws IOException {
|
||||
JSONObject json = new JSONObject();
|
||||
writeItemsToJson(json);
|
||||
if (json.length() > 0) {
|
||||
try {
|
||||
String s = json.toString(2);
|
||||
outputStream.write(s.getBytes("UTF-8"));
|
||||
} catch (JSONException e) {
|
||||
SettingsHelper.LOG.error("Failed to write json to stream", e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (getType().name() + getName()).hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (other == this) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof SettingsItem)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SettingsItem item = (SettingsItem) other;
|
||||
return item.getType() == getType()
|
||||
&& item.getName().equals(getName())
|
||||
&& Algorithms.stringsEqual(item.getFileName(), getFileName());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package net.osmand.plus.settings.backend.backup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public abstract class SettingsItemReader<T extends SettingsItem> {
|
||||
|
||||
private T item;
|
||||
|
||||
public SettingsItemReader(@NonNull T item) {
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
public abstract void readFromStream(@NonNull InputStream inputStream) throws IOException, IllegalArgumentException;
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package net.osmand.plus.settings.backend.backup;
|
||||
|
||||
public enum SettingsItemType {
|
||||
GLOBAL,
|
||||
PROFILE,
|
||||
PLUGIN,
|
||||
DATA,
|
||||
FILE,
|
||||
RESOURCES,
|
||||
QUICK_ACTIONS,
|
||||
POI_UI_FILTERS,
|
||||
MAP_SOURCES,
|
||||
AVOID_ROADS,
|
||||
SUGGESTED_DOWNLOADS,
|
||||
DOWNLOADS
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package net.osmand.plus.settings.backend.backup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public abstract class SettingsItemWriter<T extends SettingsItem> {
|
||||
|
||||
private T item;
|
||||
|
||||
public SettingsItemWriter(T item) {
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
public T getItem() {
|
||||
return item;
|
||||
}
|
||||
|
||||
public abstract boolean writeToStream(@NonNull OutputStream outputStream) throws IOException;
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
package net.osmand.plus.settings.backend.backup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
class SettingsItemsFactory {
|
||||
|
||||
private OsmandApplication app;
|
||||
private List<SettingsItem> items = new ArrayList<>();
|
||||
|
||||
SettingsItemsFactory(@NonNull OsmandApplication app, String jsonStr) throws IllegalArgumentException, JSONException {
|
||||
this.app = app;
|
||||
collectItems(new JSONObject(jsonStr));
|
||||
}
|
||||
|
||||
private void collectItems(JSONObject json) throws IllegalArgumentException, JSONException {
|
||||
JSONArray itemsJson = json.getJSONArray("items");
|
||||
int version = json.has("version") ? json.getInt("version") : 1;
|
||||
if (version > SettingsHelper.VERSION) {
|
||||
throw new IllegalArgumentException("Unsupported osf version: " + version);
|
||||
}
|
||||
Map<String, List<SettingsItem>> pluginItems = new HashMap<>();
|
||||
for (int i = 0; i < itemsJson.length(); i++) {
|
||||
JSONObject itemJson = itemsJson.getJSONObject(i);
|
||||
SettingsItem item;
|
||||
try {
|
||||
item = createItem(itemJson);
|
||||
items.add(item);
|
||||
String pluginId = item.getPluginId();
|
||||
if (pluginId != null && item.getType() != SettingsItemType.PLUGIN) {
|
||||
List<SettingsItem> items = pluginItems.get(pluginId);
|
||||
if (items != null) {
|
||||
items.add(item);
|
||||
} else {
|
||||
items = new ArrayList<>();
|
||||
items.add(item);
|
||||
pluginItems.put(pluginId, items);
|
||||
}
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
SettingsHelper.LOG.error("Error creating item from json: " + itemJson, e);
|
||||
}
|
||||
}
|
||||
if (items.size() == 0) {
|
||||
throw new IllegalArgumentException("No items");
|
||||
}
|
||||
for (SettingsItem item : items) {
|
||||
if (item instanceof PluginSettingsItem) {
|
||||
PluginSettingsItem pluginSettingsItem = ((PluginSettingsItem) item);
|
||||
List<SettingsItem> pluginDependentItems = pluginItems.get(pluginSettingsItem.getName());
|
||||
if (!Algorithms.isEmpty(pluginDependentItems)) {
|
||||
pluginSettingsItem.getPluginDependentItems().addAll(pluginDependentItems);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<SettingsItem> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public SettingsItem getItemByFileName(@NonNull String fileName) {
|
||||
for (SettingsItem item : items) {
|
||||
if (Algorithms.stringsEqual(item.getFileName(), fileName)) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private SettingsItem createItem(@NonNull JSONObject json) throws IllegalArgumentException, JSONException {
|
||||
SettingsItem item = null;
|
||||
SettingsItemType type = SettingsItem.parseItemType(json);
|
||||
OsmandSettings settings = app.getSettings();
|
||||
switch (type) {
|
||||
case GLOBAL:
|
||||
item = new GlobalSettingsItem(settings);
|
||||
break;
|
||||
case PROFILE:
|
||||
item = new ProfileSettingsItem(app, json);
|
||||
break;
|
||||
case PLUGIN:
|
||||
item = new PluginSettingsItem(app, json);
|
||||
break;
|
||||
case DATA:
|
||||
item = new DataSettingsItem(app, json);
|
||||
break;
|
||||
case FILE:
|
||||
item = new FileSettingsItem(app, json);
|
||||
break;
|
||||
case RESOURCES:
|
||||
item = new ResourcesSettingsItem(app, json);
|
||||
break;
|
||||
case QUICK_ACTIONS:
|
||||
item = new QuickActionsSettingsItem(app, json);
|
||||
break;
|
||||
case POI_UI_FILTERS:
|
||||
item = new PoiUiFiltersSettingsItem(app, json);
|
||||
break;
|
||||
case MAP_SOURCES:
|
||||
item = new MapSourcesSettingsItem(app, json);
|
||||
break;
|
||||
case AVOID_ROADS:
|
||||
item = new AvoidRoadsSettingsItem(app, json);
|
||||
break;
|
||||
case SUGGESTED_DOWNLOADS:
|
||||
item = new SuggestedDownloadsItem(app, json);
|
||||
break;
|
||||
case DOWNLOADS:
|
||||
item = new DownloadsItem(app, json);
|
||||
break;
|
||||
}
|
||||
return item;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package net.osmand.plus.settings.backend.backup;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
public abstract class StreamSettingsItem extends SettingsItem {
|
||||
|
||||
@Nullable
|
||||
private InputStream inputStream;
|
||||
protected String name;
|
||||
|
||||
public StreamSettingsItem(@NonNull OsmandApplication app, @NonNull String name) {
|
||||
super(app);
|
||||
this.name = name;
|
||||
this.fileName = name;
|
||||
}
|
||||
|
||||
StreamSettingsItem(@NonNull OsmandApplication app, @NonNull JSONObject json) throws JSONException {
|
||||
super(app, json);
|
||||
}
|
||||
|
||||
public StreamSettingsItem(@NonNull OsmandApplication app, @NonNull InputStream inputStream, @NonNull String name) {
|
||||
super(app);
|
||||
this.inputStream = inputStream;
|
||||
this.name = name;
|
||||
this.fileName = name;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public InputStream getInputStream() {
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
protected void setInputStream(@Nullable InputStream inputStream) {
|
||||
this.inputStream = inputStream;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getPublicName(@NonNull Context ctx) {
|
||||
return getName();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getDefaultFileExtension() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
void readFromJson(@NonNull JSONObject json) throws JSONException {
|
||||
super.readFromJson(json);
|
||||
name = json.has("name") ? json.getString("name") : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public SettingsItemWriter<? extends SettingsItem> getWriter() {
|
||||
return new StreamSettingsItemWriter(this);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package net.osmand.plus.settings.backend.backup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public abstract class StreamSettingsItemReader extends SettingsItemReader<StreamSettingsItem> {
|
||||
|
||||
public StreamSettingsItemReader(@NonNull StreamSettingsItem item) {
|
||||
super(item);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package net.osmand.plus.settings.backend.backup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class StreamSettingsItemWriter extends SettingsItemWriter<StreamSettingsItem> {
|
||||
|
||||
public StreamSettingsItemWriter(StreamSettingsItem item) {
|
||||
super(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean writeToStream(@NonNull OutputStream outputStream) throws IOException {
|
||||
boolean hasData = false;
|
||||
InputStream is = getItem().getInputStream();
|
||||
if (is != null) {
|
||||
byte[] data = new byte[SettingsHelper.BUFFER];
|
||||
int count;
|
||||
while ((count = is.read(data, 0, SettingsHelper.BUFFER)) != -1) {
|
||||
outputStream.write(data, 0, count);
|
||||
if (!hasData) {
|
||||
hasData = true;
|
||||
}
|
||||
}
|
||||
Algorithms.closeStream(is);
|
||||
}
|
||||
return hasData;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
package net.osmand.plus.settings.backend.backup;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import net.osmand.plus.CustomOsmandPlugin;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SuggestedDownloadsItem extends SettingsItem {
|
||||
|
||||
private List<CustomOsmandPlugin.SuggestedDownloadItem> items;
|
||||
|
||||
SuggestedDownloadsItem(@NonNull OsmandApplication app, @NonNull JSONObject json) throws JSONException {
|
||||
super(app, json);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
items = new ArrayList<>();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public SettingsItemType getType() {
|
||||
return SettingsItemType.SUGGESTED_DOWNLOADS;
|
||||
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return "suggested_downloads";
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getPublicName(@NonNull Context ctx) {
|
||||
return "suggested_downloads";
|
||||
}
|
||||
|
||||
public List<CustomOsmandPlugin.SuggestedDownloadItem> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
@Override
|
||||
void readItemsFromJson(@NonNull JSONObject json) throws IllegalArgumentException {
|
||||
try {
|
||||
if (!json.has("items")) {
|
||||
return;
|
||||
}
|
||||
JSONArray jsonArray = json.getJSONArray("items");
|
||||
for (int i = 0; i < jsonArray.length(); i++) {
|
||||
JSONObject object = jsonArray.getJSONObject(i);
|
||||
String scopeId = object.optString("scope-id");
|
||||
String searchType = object.optString("search-type");
|
||||
int limit = object.optInt("limit", -1);
|
||||
|
||||
List<String> names = new ArrayList<>();
|
||||
if (object.has("names")) {
|
||||
JSONArray namesArray = object.getJSONArray("names");
|
||||
for (int j = 0; j < namesArray.length(); j++) {
|
||||
names.add(namesArray.getString(j));
|
||||
}
|
||||
}
|
||||
CustomOsmandPlugin.SuggestedDownloadItem suggestedDownload = new CustomOsmandPlugin.SuggestedDownloadItem(scopeId, searchType, names, limit);
|
||||
items.add(suggestedDownload);
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
warnings.add(app.getString(R.string.settings_item_read_error, String.valueOf(getType())));
|
||||
throw new IllegalArgumentException("Json parse error", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void writeItemsToJson(@NonNull JSONObject json) {
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
if (!items.isEmpty()) {
|
||||
try {
|
||||
for (CustomOsmandPlugin.SuggestedDownloadItem downloadItem : items) {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("scope-id", downloadItem.getScopeId());
|
||||
if (downloadItem.getLimit() != -1) {
|
||||
jsonObject.put("limit", downloadItem.getLimit());
|
||||
}
|
||||
if (!Algorithms.isEmpty(downloadItem.getSearchType())) {
|
||||
jsonObject.put("search-type", downloadItem.getSearchType());
|
||||
}
|
||||
if (!Algorithms.isEmpty(downloadItem.getNames())) {
|
||||
JSONArray namesArray = new JSONArray();
|
||||
for (String downloadName : downloadItem.getNames()) {
|
||||
namesArray.put(downloadName);
|
||||
}
|
||||
jsonObject.put("names", namesArray);
|
||||
}
|
||||
jsonArray.put(jsonObject);
|
||||
}
|
||||
json.put("items", jsonArray);
|
||||
} catch (JSONException e) {
|
||||
warnings.add(app.getString(R.string.settings_item_write_error, String.valueOf(getType())));
|
||||
SettingsHelper.LOG.error("Failed write to json", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
SettingsItemReader<? extends SettingsItem> getReader() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
SettingsItemWriter<? extends SettingsItem> getWriter() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -12,13 +12,13 @@ import androidx.fragment.app.Fragment;
|
|||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import net.osmand.plus.osmedit.ValidateOsmLoginDetailsTask;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem;
|
||||
import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
|
||||
import net.osmand.plus.osmedit.SettingsOsmEditingActivity;
|
||||
import net.osmand.plus.settings.fragments.OnPreferenceChanged;
|
||||
|
||||
public class OsmLoginDataBottomSheet extends BasePreferenceBottomSheet {
|
||||
|
@ -84,7 +84,7 @@ public class OsmLoginDataBottomSheet extends BasePreferenceBottomSheet {
|
|||
|
||||
app.getSettings().USER_NAME.set(userNameEditText.getText().toString());
|
||||
app.getSettings().USER_PASSWORD.set(passwordEditText.getText().toString());
|
||||
new SettingsOsmEditingActivity.ValidateOsmLoginDetailsTask(app).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
new ValidateOsmLoginDetailsTask(app).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
|
||||
Fragment target = getTargetFragment();
|
||||
Preference preference = getPreference();
|
||||
|
|
|
@ -53,11 +53,7 @@ import com.google.android.material.snackbar.Snackbar;
|
|||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.access.AccessibilitySettingsFragment;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.settings.backend.OsmandPreference;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.plus.settings.backend.CommonPreference;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
|
@ -69,6 +65,10 @@ import net.osmand.plus.monitoring.MonitoringSettingsFragment;
|
|||
import net.osmand.plus.osmedit.OsmEditingFragment;
|
||||
import net.osmand.plus.profiles.SelectAppModesBottomSheetDialogFragment;
|
||||
import net.osmand.plus.profiles.SelectAppModesBottomSheetDialogFragment.AppModeChangedListener;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.settings.backend.CommonPreference;
|
||||
import net.osmand.plus.settings.backend.OsmandPreference;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.plus.settings.bottomsheets.BooleanPreferenceBottomSheet;
|
||||
import net.osmand.plus.settings.bottomsheets.ChangeGeneralProfilesPrefBottomSheet;
|
||||
import net.osmand.plus.settings.bottomsheets.EditTextPreferenceBottomSheet;
|
||||
|
@ -112,7 +112,7 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl
|
|||
|
||||
public enum SettingsScreenType {
|
||||
|
||||
MAIN_SETTINGS(MainSettingsFragment.TAG, false, null, R.xml.settings_main_screen, R.layout.global_preference_toolbar),
|
||||
MAIN_SETTINGS(MainSettingsFragment.class.getName(), false, null, R.xml.settings_main_screen, R.layout.global_preference_toolbar),
|
||||
GLOBAL_SETTINGS(GlobalSettingsFragment.class.getName(), false, null, R.xml.global_settings, R.layout.global_preference_toolbar),
|
||||
CONFIGURE_PROFILE(ConfigureProfileFragment.class.getName(), true, null, R.xml.configure_profile, R.layout.profile_preference_toolbar_with_switch),
|
||||
PROXY_SETTINGS(ProxySettingsFragment.class.getName(), false, null, R.xml.proxy_preferences, R.layout.global_preferences_toolbar_with_switch),
|
||||
|
@ -899,9 +899,13 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl
|
|||
}
|
||||
|
||||
public static boolean showInstance(FragmentActivity activity, SettingsScreenType screenType, @Nullable ApplicationMode appMode) {
|
||||
return showInstance(activity, screenType, null, new Bundle());
|
||||
}
|
||||
|
||||
public static boolean showInstance(FragmentActivity activity, SettingsScreenType screenType,
|
||||
@Nullable ApplicationMode appMode, @NonNull Bundle args) {
|
||||
try {
|
||||
Fragment fragment = Fragment.instantiate(activity, screenType.fragmentName);
|
||||
Bundle args = new Bundle();
|
||||
if (appMode != null) {
|
||||
args.putString(APP_MODE_KEY, appMode.getStringKey());
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package net.osmand.plus.settings.fragments;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
|
@ -22,13 +21,13 @@ import androidx.annotation.Nullable;
|
|||
import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.ContextMenuAdapter;
|
||||
import net.osmand.plus.ContextMenuItem;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
|
@ -36,14 +35,14 @@ import net.osmand.plus.R;
|
|||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.activities.MapActivityActions;
|
||||
import net.osmand.plus.activities.PluginsActivity;
|
||||
import net.osmand.plus.activities.PluginsFragment;
|
||||
import net.osmand.plus.base.BaseOsmAndFragment;
|
||||
import net.osmand.plus.dialogs.ConfigureMapMenu;
|
||||
import net.osmand.plus.helpers.FontCache;
|
||||
import net.osmand.plus.mapcontextmenu.MapContextMenu;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.widgets.style.CustomTypefaceSpan;
|
||||
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -229,8 +228,7 @@ public class ConfigureMenuRootFragment extends BaseOsmAndFragment {
|
|||
if (holder instanceof DescriptionHolder) {
|
||||
DescriptionHolder descriptionHolder = (DescriptionHolder) holder;
|
||||
String plugins = getString(R.string.prefs_plugins);
|
||||
setupClickableText(
|
||||
descriptionHolder.description, (String) currentItem, plugins, new Intent(app, PluginsActivity.class));
|
||||
setupClickableText(descriptionHolder.description, (String) currentItem, plugins);
|
||||
descriptionHolder.image.setVisibility(View.GONE);
|
||||
} else {
|
||||
final ScreenType item = (ScreenType) currentItem;
|
||||
|
@ -253,12 +251,15 @@ public class ConfigureMenuRootFragment extends BaseOsmAndFragment {
|
|||
return items.size();
|
||||
}
|
||||
|
||||
private void setupClickableText(TextView textView, String text, String clickableText, final Intent intent) {
|
||||
private void setupClickableText(TextView textView, String text, String clickableText) {
|
||||
SpannableString spannableString = new SpannableString(text);
|
||||
ClickableSpan clickableSpan = new ClickableSpan() {
|
||||
@Override
|
||||
public void onClick(@NonNull View view) {
|
||||
startActivity(intent);
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity != null) {
|
||||
PluginsFragment.showInstance(activity.getSupportFragmentManager());
|
||||
}
|
||||
}
|
||||
};
|
||||
try {
|
||||
|
|
|
@ -35,8 +35,8 @@ import net.osmand.plus.settings.backend.ApplicationMode;
|
|||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.OsmandPlugin;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.SettingsCollectListener;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsHelper;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsHelper.SettingsCollectListener;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||
|
@ -44,6 +44,7 @@ import net.osmand.plus.helpers.FontCache;
|
|||
import net.osmand.plus.openseamapsplugin.NauticalMapsPlugin;
|
||||
import net.osmand.plus.profiles.SelectCopyAppModeBottomSheet;
|
||||
import net.osmand.plus.profiles.SelectCopyAppModeBottomSheet.CopyAppModePrefsListener;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsItem;
|
||||
import net.osmand.plus.settings.bottomsheets.ResetProfilePrefsBottomSheet;
|
||||
import net.osmand.plus.settings.bottomsheets.ResetProfilePrefsBottomSheet.ResetAppModePrefsListener;
|
||||
import net.osmand.plus.skimapsplugin.SkiMapsPlugin;
|
||||
|
@ -186,9 +187,9 @@ public class ConfigureProfileFragment extends BaseSettingsFragment implements Co
|
|||
private void restoreCustomModeFromFile(final File file) {
|
||||
app.getSettingsHelper().collectSettings(file, "", 1, new SettingsCollectListener() {
|
||||
@Override
|
||||
public void onSettingsCollectFinished(boolean succeed, boolean empty, @NonNull List<SettingsHelper.SettingsItem> items) {
|
||||
public void onSettingsCollectFinished(boolean succeed, boolean empty, @NonNull List<SettingsItem> items) {
|
||||
if (succeed) {
|
||||
for (SettingsHelper.SettingsItem item : items) {
|
||||
for (SettingsItem item : items) {
|
||||
item.setShouldReplace(true);
|
||||
}
|
||||
importBackupSettingsItems(file, items);
|
||||
|
@ -197,10 +198,10 @@ public class ConfigureProfileFragment extends BaseSettingsFragment implements Co
|
|||
});
|
||||
}
|
||||
|
||||
private void importBackupSettingsItems(File file, List<SettingsHelper.SettingsItem> items) {
|
||||
private void importBackupSettingsItems(File file, List<SettingsItem> items) {
|
||||
app.getSettingsHelper().importSettings(file, items, "", 1, new SettingsHelper.SettingsImportListener() {
|
||||
@Override
|
||||
public void onSettingsImportFinished(boolean succeed, @NonNull List<SettingsHelper.SettingsItem> items) {
|
||||
public void onSettingsImportFinished(boolean succeed, @NonNull List<SettingsItem> items) {
|
||||
app.showToastMessage(R.string.profile_prefs_reset_successful);
|
||||
updateCopiedOrResetPrefs();
|
||||
}
|
||||
|
@ -368,7 +369,7 @@ public class ConfigureProfileFragment extends BaseSettingsFragment implements Co
|
|||
}
|
||||
List<OsmandPlugin> plugins = OsmandPlugin.getVisiblePlugins();
|
||||
for (OsmandPlugin plugin : plugins) {
|
||||
if (plugin instanceof SkiMapsPlugin || plugin instanceof NauticalMapsPlugin || plugin.getSettingsFragment() == null) {
|
||||
if (plugin instanceof SkiMapsPlugin || plugin instanceof NauticalMapsPlugin || plugin.getSettingsScreenType() == null) {
|
||||
continue;
|
||||
}
|
||||
Preference preference = new Preference(ctx);
|
||||
|
@ -378,7 +379,7 @@ public class ConfigureProfileFragment extends BaseSettingsFragment implements Co
|
|||
preference.setSummary(plugin.getPrefsDescription());
|
||||
preference.setIcon(getContentIcon(plugin.getLogoResourceId()));
|
||||
preference.setLayoutResource(R.layout.preference_with_descr);
|
||||
preference.setFragment(plugin.getSettingsFragment().getName());
|
||||
preference.setFragment(plugin.getSettingsScreenType().fragmentName);
|
||||
|
||||
preferenceCategory.addPreference(preference);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@ import net.osmand.AndroidUtils;
|
|||
import net.osmand.IndexConstants;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.map.ITileSource;
|
||||
import net.osmand.plus.audionotes.AudioVideoNotesPlugin;
|
||||
import net.osmand.plus.helpers.GpxUiHelper;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode.ApplicationModeBean;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
|
@ -131,6 +133,15 @@ public class DuplicatesSettingsAdapter extends RecyclerView.Adapter<RecyclerView
|
|||
itemHolder.icon.setImageDrawable(uiUtilities.getIcon(R.drawable.ic_action_map_style, activeColorRes));
|
||||
} else if (file.getAbsolutePath().contains(IndexConstants.ROUTING_PROFILES_DIR)) {
|
||||
itemHolder.icon.setImageDrawable(uiUtilities.getIcon(R.drawable.ic_action_route_distance, activeColorRes));
|
||||
} else if (file.getAbsolutePath().contains(IndexConstants.GPX_INDEX_DIR)) {
|
||||
itemHolder.title.setText(GpxUiHelper.getGpxTitle(file.getName()));
|
||||
itemHolder.icon.setImageDrawable(uiUtilities.getIcon(R.drawable.ic_action_route_distance, activeColorRes));
|
||||
} else if (file.getAbsolutePath().contains(IndexConstants.AV_INDEX_DIR)) {
|
||||
int iconId = AudioVideoNotesPlugin.getIconIdForRecordingFile(file);
|
||||
if (iconId == -1) {
|
||||
iconId = R.drawable.ic_action_photo_dark;
|
||||
}
|
||||
itemHolder.icon.setImageDrawable(uiUtilities.getIcon(iconId, activeColorRes));
|
||||
}
|
||||
itemHolder.subTitle.setVisibility(View.GONE);
|
||||
} else if (currentItem instanceof AvoidRoadInfo) {
|
||||
|
|
|
@ -16,19 +16,21 @@ import net.osmand.AndroidUtils;
|
|||
import net.osmand.IndexConstants;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.map.ITileSource;
|
||||
import net.osmand.plus.settings.backend.ExportSettingsType;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode.ApplicationModeBean;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.activities.OsmandBaseExpandableListAdapter;
|
||||
import net.osmand.plus.audionotes.AudioVideoNotesPlugin;
|
||||
import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo;
|
||||
import net.osmand.plus.helpers.GpxUiHelper;
|
||||
import net.osmand.plus.poi.PoiUIFilter;
|
||||
import net.osmand.plus.profiles.ProfileIconColors;
|
||||
import net.osmand.plus.profiles.RoutingProfileDataObject.RoutingProfilesResources;
|
||||
import net.osmand.plus.quickaction.QuickAction;
|
||||
import net.osmand.plus.render.RenderingIcons;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode.ApplicationModeBean;
|
||||
import net.osmand.plus.settings.backend.ExportSettingsType;
|
||||
import net.osmand.util.Algorithms;
|
||||
import net.osmand.view.ThreeStateCheckbox;
|
||||
|
||||
|
@ -244,6 +246,22 @@ class ExportImportSettingsAdapter extends OsmandBaseExpandableListAdapter {
|
|||
setupIcon(icon, R.drawable.ic_action_alert, itemSelected);
|
||||
subText.setVisibility(View.GONE);
|
||||
break;
|
||||
case MULTIMEDIA_NOTES:
|
||||
File file = (File) currentItem;
|
||||
title.setText(file.getName());
|
||||
int iconId = AudioVideoNotesPlugin.getIconIdForRecordingFile(file);
|
||||
if (iconId == -1) {
|
||||
iconId = R.drawable.ic_action_photo_dark;
|
||||
}
|
||||
setupIcon(icon, iconId, itemSelected);
|
||||
subText.setVisibility(View.GONE);
|
||||
break;
|
||||
case TRACKS:
|
||||
String fileName = ((File) currentItem).getName();
|
||||
title.setText(GpxUiHelper.getGpxTitle(fileName));
|
||||
setupIcon(icon, R.drawable.ic_action_route_distance, itemSelected);
|
||||
subText.setVisibility(View.GONE);
|
||||
break;
|
||||
default:
|
||||
return child;
|
||||
}
|
||||
|
@ -316,6 +334,10 @@ class ExportImportSettingsAdapter extends OsmandBaseExpandableListAdapter {
|
|||
return R.string.shared_string_routing;
|
||||
case AVOID_ROADS:
|
||||
return R.string.avoid_road;
|
||||
case TRACKS:
|
||||
return R.string.shared_string_tracks;
|
||||
case MULTIMEDIA_NOTES:
|
||||
return R.string.audionotes_plugin_name;
|
||||
default:
|
||||
return R.string.access_empty_list;
|
||||
}
|
||||
|
|
|
@ -33,9 +33,9 @@ import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
|
|||
import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem;
|
||||
import net.osmand.plus.settings.backend.ExportSettingsType;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.ProfileSettingsItem;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.SettingsItem;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsHelper;
|
||||
import net.osmand.plus.settings.backend.backup.ProfileSettingsItem;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsItem;
|
||||
import net.osmand.plus.settings.bottomsheets.BasePreferenceBottomSheet;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
@ -174,7 +174,6 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet {
|
|||
|
||||
@Override
|
||||
protected void onRightBottomButtonClick() {
|
||||
super.onRightBottomButtonClick();
|
||||
prepareFile();
|
||||
}
|
||||
|
||||
|
|
|
@ -31,8 +31,8 @@ import net.osmand.plus.quickaction.QuickActionListFragment;
|
|||
import net.osmand.plus.routepreparationmenu.AvoidRoadsBottomSheetDialogFragment;
|
||||
import net.osmand.plus.search.QuickSearchDialogFragment;
|
||||
import net.osmand.plus.settings.backend.ExportSettingsType;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.SettingsItem;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsHelper;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
|
|
@ -26,24 +26,28 @@ import com.google.android.material.appbar.CollapsingToolbarLayout;
|
|||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.map.ITileSource;
|
||||
import net.osmand.plus.AppInitializer;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.ImportAsyncTask;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.ImportType;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.SettingsItem;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.base.BaseOsmAndFragment;
|
||||
import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo;
|
||||
import net.osmand.plus.poi.PoiUIFilter;
|
||||
import net.osmand.plus.quickaction.QuickAction;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsHelper;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsHelper.ImportAsyncTask;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsHelper.ImportType;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsItem;
|
||||
import net.osmand.view.ComplexButton;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static net.osmand.IndexConstants.AV_INDEX_DIR;
|
||||
import static net.osmand.IndexConstants.GPX_INDEX_DIR;
|
||||
import static net.osmand.IndexConstants.RENDERERS_DIR;
|
||||
import static net.osmand.IndexConstants.ROUTING_PROFILES_DIR;
|
||||
import static net.osmand.plus.settings.fragments.ImportSettingsFragment.IMPORT_SETTINGS_TAG;
|
||||
|
||||
|
||||
|
@ -171,6 +175,8 @@ public class ImportDuplicatesFragment extends BaseOsmAndFragment implements View
|
|||
List<ITileSource> tileSources = new ArrayList<>();
|
||||
List<File> renderFilesList = new ArrayList<>();
|
||||
List<File> routingFilesList = new ArrayList<>();
|
||||
List<File> multimediaFilesList = new ArrayList<>();
|
||||
List<File> trackFilesList = new ArrayList<>();
|
||||
List<AvoidRoadInfo> avoidRoads = new ArrayList<>();
|
||||
|
||||
for (Object object : duplicatesList) {
|
||||
|
@ -184,10 +190,14 @@ public class ImportDuplicatesFragment extends BaseOsmAndFragment implements View
|
|||
tileSources.add((ITileSource) object);
|
||||
} else if (object instanceof File) {
|
||||
File file = (File) object;
|
||||
if (file.getAbsolutePath().contains("files/rendering")) {
|
||||
if (file.getAbsolutePath().contains(RENDERERS_DIR)) {
|
||||
renderFilesList.add(file);
|
||||
} else if (file.getAbsolutePath().contains("files/routing")) {
|
||||
} else if (file.getAbsolutePath().contains(ROUTING_PROFILES_DIR)) {
|
||||
routingFilesList.add(file);
|
||||
} else if (file.getAbsolutePath().contains(AV_INDEX_DIR)) {
|
||||
multimediaFilesList.add(file);
|
||||
} else if (file.getAbsolutePath().contains(GPX_INDEX_DIR)) {
|
||||
trackFilesList.add(file);
|
||||
}
|
||||
} else if (object instanceof AvoidRoadInfo) {
|
||||
avoidRoads.add((AvoidRoadInfo) object);
|
||||
|
@ -217,6 +227,14 @@ public class ImportDuplicatesFragment extends BaseOsmAndFragment implements View
|
|||
duplicates.add(getString(R.string.shared_string_rendering_style));
|
||||
duplicates.addAll(renderFilesList);
|
||||
}
|
||||
if (!multimediaFilesList.isEmpty()) {
|
||||
duplicates.add(getString(R.string.audionotes_plugin_name));
|
||||
duplicates.addAll(multimediaFilesList);
|
||||
}
|
||||
if (!trackFilesList.isEmpty()) {
|
||||
duplicates.add(getString(R.string.shared_string_tracks));
|
||||
duplicates.addAll(trackFilesList);
|
||||
}
|
||||
if (!avoidRoads.isEmpty()) {
|
||||
duplicates.add(getString(R.string.avoid_road));
|
||||
duplicates.addAll(avoidRoads);
|
||||
|
|
|
@ -42,17 +42,17 @@ import net.osmand.plus.poi.PoiUIFilter;
|
|||
import net.osmand.plus.quickaction.QuickAction;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode.ApplicationModeBean;
|
||||
import net.osmand.plus.settings.backend.ExportSettingsType;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.AvoidRoadsSettingsItem;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.FileSettingsItem;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.ImportAsyncTask;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.ImportType;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.MapSourcesSettingsItem;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.PoiUiFiltersSettingsItem;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.ProfileSettingsItem;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.QuickActionsSettingsItem;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.SettingsItem;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.SettingsItemType;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsHelper;
|
||||
import net.osmand.plus.settings.backend.backup.AvoidRoadsSettingsItem;
|
||||
import net.osmand.plus.settings.backend.backup.FileSettingsItem;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsHelper.ImportAsyncTask;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsHelper.ImportType;
|
||||
import net.osmand.plus.settings.backend.backup.MapSourcesSettingsItem;
|
||||
import net.osmand.plus.settings.backend.backup.PoiUiFiltersSettingsItem;
|
||||
import net.osmand.plus.settings.backend.backup.ProfileSettingsItem;
|
||||
import net.osmand.plus.settings.backend.backup.QuickActionsSettingsItem;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsItem;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsItemType;
|
||||
import net.osmand.plus.widgets.TextViewEx;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
|
|
|
@ -106,6 +106,14 @@ public class ImportedSettingsItemsAdapter extends
|
|||
holder.icon.setImageDrawable(uiUtils.getIcon(R.drawable.ic_action_alert, activeColorRes));
|
||||
holder.title.setText(R.string.avoid_road);
|
||||
break;
|
||||
case MULTIMEDIA_NOTES:
|
||||
holder.icon.setImageDrawable(uiUtils.getIcon(R.drawable.ic_action_photo_dark, activeColorRes));
|
||||
holder.title.setText(R.string.audionotes_plugin_name);
|
||||
break;
|
||||
case TRACKS:
|
||||
holder.icon.setImageDrawable(uiUtils.getIcon(R.drawable.ic_action_route_distance, activeColorRes));
|
||||
holder.title.setText(R.string.shared_string_tracks);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,8 +18,8 @@ import net.osmand.CallbackWithObject;
|
|||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.SettingsItem;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper.SettingsItemType;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsItem;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsItemType;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||
|
|
|
@ -42,7 +42,8 @@ import net.osmand.IndexConstants;
|
|||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.settings.backend.SettingsHelper;
|
||||
import net.osmand.plus.settings.backend.backup.ProfileSettingsItem;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsHelper;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.UiUtilities.DialogButtonType;
|
||||
import net.osmand.plus.profiles.LocationIcon;
|
||||
|
@ -828,7 +829,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment {
|
|||
tempDir.mkdirs();
|
||||
}
|
||||
app.getSettingsHelper().exportSettings(tempDir, mode.getStringKey(),
|
||||
getSettingsExportListener(), true, new SettingsHelper.ProfileSettingsItem(app, mode));
|
||||
getSettingsExportListener(), true, new ProfileSettingsItem(app, mode));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue