diff --git a/OsmAnd/src/net/osmand/plus/AppInitializer.java b/OsmAnd/src/net/osmand/plus/AppInitializer.java index 053b787b33..cfb6a127bb 100644 --- a/OsmAnd/src/net/osmand/plus/AppInitializer.java +++ b/OsmAnd/src/net/osmand/plus/AppInitializer.java @@ -499,6 +499,7 @@ public class AppInitializer implements IProgress { } app.travelDbHelper = startupInit(app.travelDbHelper, TravelDbHelper.class); app.lockHelper = startupInit(new LockHelper(app), LockHelper.class); + app.settingsHelper = startupInit(new SettingsHelper(app), SettingsHelper.class); initOpeningHoursParser(); diff --git a/OsmAnd/src/net/osmand/plus/ApplicationMode.java b/OsmAnd/src/net/osmand/plus/ApplicationMode.java index 94a4ec5de3..625990e6e6 100644 --- a/OsmAnd/src/net/osmand/plus/ApplicationMode.java +++ b/OsmAnd/src/net/osmand/plus/ApplicationMode.java @@ -183,6 +183,10 @@ public class ApplicationMode { public static class ApplicationModeBuilder { private ApplicationMode applicationMode; + public ApplicationMode getApplicationMode() { + return applicationMode; + } + private ApplicationMode reg() { values.add(applicationMode); defaultValues.add(applicationMode); @@ -347,7 +351,7 @@ public class ApplicationMode { } public static ApplicationModeBuilder createCustomMode(ApplicationMode parent, String userProfileTitle, String stringKey) { - return create(parent,-1, stringKey).userProfileTitle(userProfileTitle); + return create(parent, -1, stringKey).userProfileTitle(userProfileTitle); } @@ -622,6 +626,31 @@ public class ApplicationMode { } } + public static ApplicationModeBuilder fromJson(OsmandApplication app, String json) { + Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create(); + ApplicationModeBean mb = gson.fromJson(json, ApplicationModeBean.class); + + ApplicationModeBuilder b = createCustomMode(valueOfStringKey(mb.parent, CAR), + mb.userProfileName, mb.stringKey); + b.setRouteService(mb.routeService).setRoutingProfile(mb.routingProfile); + b.icon(app, mb.iconName); + b.setColor(mb.iconColor); + return b; + } + + public String toJson() { + ApplicationModeBean mb = new ApplicationModeBean(); + mb.userProfileName = userProfileName; + mb.iconColor = iconColor; + mb.iconName = iconResName; + mb.parent = parentAppMode != null ? parentAppMode.getStringKey() : null; + mb.stringKey = stringKey; + mb.routeService = routeService; + mb.routingProfile = routingProfile; + Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create(); + return gson.toJson(mb); + } + private static void initCustomModes(OsmandApplication app){ Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create(); Type t = new TypeToken>() {}.getType(); @@ -640,7 +669,6 @@ public class ApplicationMode { } - private static void saveCustomModeToSettings(OsmandSettings settings){ List customModes = new ArrayList<>(); for (ApplicationMode mode : values) { diff --git a/OsmAnd/src/net/osmand/plus/OsmandApplication.java b/OsmAnd/src/net/osmand/plus/OsmandApplication.java index 6d7abb46fe..236f2583a3 100644 --- a/OsmAnd/src/net/osmand/plus/OsmandApplication.java +++ b/OsmAnd/src/net/osmand/plus/OsmandApplication.java @@ -136,6 +136,7 @@ public class OsmandApplication extends MultiDexApplication { InAppPurchaseHelper inAppPurchaseHelper; MapViewTrackingUtilities mapViewTrackingUtilities; LockHelper lockHelper; + SettingsHelper settingsHelper; private RoutingConfiguration.Builder routingConfig; private Locale preferredLocale = null; @@ -335,6 +336,10 @@ public class OsmandApplication extends MultiDexApplication { return lockHelper; } + public SettingsHelper getSettingsHelper() { + return settingsHelper; + } + public synchronized DownloadIndexesThread getDownloadThread() { if(downloadIndexesThread == null) { downloadIndexesThread = new DownloadIndexesThread(this); diff --git a/OsmAnd/src/net/osmand/plus/OsmandSettings.java b/OsmAnd/src/net/osmand/plus/OsmandSettings.java index 8d67e643e7..8dfe395a84 100644 --- a/OsmAnd/src/net/osmand/plus/OsmandSettings.java +++ b/OsmAnd/src/net/osmand/plus/OsmandSettings.java @@ -686,15 +686,9 @@ public class OsmandSettings { set(parseString(globalValue)); } } else { - Object jsonModeValuesObj = json.get(getId()); - if (jsonModeValuesObj instanceof JSONObject) { - JSONObject jsonModeValues = (JSONObject) jsonModeValuesObj; - for (ApplicationMode m : ApplicationMode.allPossibleValues()) { - String modeValue = jsonModeValues.getString(m.getStringKey()); - if (modeValue != null) { - setModeValue(m, parseString(modeValue)); - } - } + String modeValue = json.getString(getId()); + if (modeValue != null) { + setModeValue(appMode, parseString(modeValue)); } } } diff --git a/OsmAnd/src/net/osmand/plus/SettingsHelper.java b/OsmAnd/src/net/osmand/plus/SettingsHelper.java index b3e0dceadf..359a2ba19a 100644 --- a/OsmAnd/src/net/osmand/plus/SettingsHelper.java +++ b/OsmAnd/src/net/osmand/plus/SettingsHelper.java @@ -1,13 +1,20 @@ package net.osmand.plus; +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.DialogInterface; +import android.os.AsyncTask; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.v7.app.AlertDialog; import net.osmand.PlatformUtil; +import net.osmand.plus.ApplicationMode.ApplicationModeBuilder; import net.osmand.plus.OsmandSettings.OsmandPreference; import net.osmand.util.Algorithms; import org.apache.commons.logging.Log; +import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -25,7 +32,6 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.util.ArrayList; -import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; @@ -39,6 +45,37 @@ public class SettingsHelper { private static final Log LOG = PlatformUtil.getLog(SettingsHelper.class); private static final int BUFFER = 1024; + private OsmandApplication app; + private Activity activity; + + private boolean importing; + private ImportAsyncTask importTask; + + public SettingsHelper(OsmandApplication app) { + this.app = app; + } + + public Activity getActivity() { + return activity; + } + + public void setActivity(Activity activity) { + this.activity = activity; + if (importing) { + importTask.processNextItem(); + } + } + + public void resetActivity(Activity activity) { + if (this.activity == activity) { + this.activity = null; + } + } + + public boolean isImporting() { + return importing; + } + public enum SettingsItemType { GLOBAL, PROFILE, @@ -55,15 +92,71 @@ public class SettingsHelper { this.type = type; } + SettingsItem(@NonNull SettingsItemType type, @NonNull JSONObject json) throws JSONException { + this.type = type; + readFromJson(json); + } + + @NonNull public SettingsItemType getType() { return type; } + @NonNull public abstract String getName(); - public abstract SettingsItemReader getReader(); + @NonNull + public abstract String getFileName(); - public abstract SettingsItemWriter getWriter(); + static SettingsItemType parseItemType(@NonNull JSONObject json) throws IllegalArgumentException, JSONException { + return SettingsItemType.valueOf(json.getString("type")); + } + + public boolean exists() { + return false; + } + + public void apply() { + // non implemented + } + + void readFromJson(@NonNull JSONObject json) throws JSONException { + } + + void writeToJson(@NonNull JSONObject json) throws JSONException { + json.put("type", type.name()); + json.put("name", getName()); + } + + String toJson() throws JSONException { + JSONObject json = new JSONObject(); + writeToJson(json); + return json.toString(); + } + + @NonNull + abstract SettingsItemReader getReader(); + + @NonNull + abstract SettingsItemWriter getWriter(); + + @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()); + } } public abstract static class SettingsItemReader { @@ -101,6 +194,11 @@ public class SettingsHelper { this.settings = settings; } + protected OsmandSettingsItem(@NonNull SettingsItemType type, @NonNull OsmandSettings settings, @NonNull JSONObject json) throws JSONException { + super(type, json); + this.settings = settings; + } + public OsmandSettings getSettings() { return settings; } @@ -128,7 +226,7 @@ public class SettingsHelper { buf.append(str); } } catch (IOException e) { - throw new IllegalArgumentException("Cannot read json body", e); + throw new IOException("Cannot read json body", e); } String jsonStr = buf.toString(); if (Algorithms.isEmpty(jsonStr)) { @@ -148,7 +246,7 @@ public class SettingsHelper { try { readPreferenceFromJson(p, json); } catch (JSONException e) { - LOG.error(null, e); + LOG.error("Failed to read preference: " + p.getId(), e); } } } @@ -174,7 +272,7 @@ public class SettingsHelper { try { writePreferenceToJson(pref, json); } catch (JSONException e) { - LOG.error(null, e); + LOG.error("Failed to write preference: " + pref.getId(), e); } } if (json.length() > 0) { @@ -182,7 +280,7 @@ public class SettingsHelper { String s = json.toString(2); outputStream.write(s.getBytes("UTF-8")); } catch (JSONException e) { - LOG.error(null, e); + LOG.error("Failed to write json to stream", e); } return true; } @@ -196,13 +294,26 @@ public class SettingsHelper { super(SettingsItemType.GLOBAL, settings); } + @NonNull @Override public String getName() { - return "global"; + return "general_settings"; + } + + @NonNull + @Override + public String getFileName() { + return getName() + ".json"; } @Override - public SettingsItemReader getReader() { + public boolean exists() { + return true; + } + + @NonNull + @Override + SettingsItemReader getReader() { return new OsmandSettingsItemReader(this, getSettings()) { @Override protected void readPreferenceFromJson(@NonNull OsmandPreference preference, @NonNull JSONObject json) throws JSONException { @@ -211,8 +322,9 @@ public class SettingsHelper { }; } + @NonNull @Override - public SettingsItemWriter getWriter() { + SettingsItemWriter getWriter() { return new OsmandSettingsItemWriter(this, getSettings()) { @Override protected void writePreferenceToJson(@NonNull OsmandPreference preference, @NonNull JSONObject json) throws JSONException { @@ -225,19 +337,56 @@ public class SettingsHelper { public static class ProfileSettingsItem extends OsmandSettingsItem { private ApplicationMode appMode; + private ApplicationModeBuilder builder; public ProfileSettingsItem(@NonNull OsmandSettings settings, @NonNull ApplicationMode appMode) { super(SettingsItemType.PROFILE, settings); this.appMode = appMode; } + public ProfileSettingsItem(@NonNull OsmandSettings settings, @NonNull JSONObject json) throws JSONException { + super(SettingsItemType.PROFILE, settings, json); + readFromJson(settings.getContext(), json); + } + + @NonNull @Override public String getName() { return appMode.getStringKey(); } + @NonNull @Override - public SettingsItemReader getReader() { + public String getFileName() { + return "profile_" + getName() + ".json"; + } + + void readFromJson(@NonNull OsmandApplication app, @NonNull JSONObject json) throws JSONException { + String appModeJson = json.getString("appMode"); + builder = ApplicationMode.fromJson(app, appModeJson); + this.appMode = builder.getApplicationMode(); + } + + @Override + public boolean exists() { + return builder != null && ApplicationMode.valueOfStringKey(getName(), null) != null; + } + + @Override + public void apply() { + appMode = ApplicationMode.saveCustomProfile(builder, getSettings().getContext()); + } + + @Override + void writeToJson(@NonNull JSONObject json) throws JSONException { + super.writeToJson(json); + json.put("appMode", new JSONObject(appMode.toJson())); + } + + + @NonNull + @Override + SettingsItemReader getReader() { return new OsmandSettingsItemReader(this, getSettings()) { @Override protected void readPreferenceFromJson(@NonNull OsmandPreference preference, @NonNull JSONObject json) throws JSONException { @@ -246,8 +395,9 @@ public class SettingsHelper { }; } + @NonNull @Override - public SettingsItemWriter getWriter() { + SettingsItemWriter getWriter() { return new OsmandSettingsItemWriter(this, getSettings()) { @Override protected void writePreferenceToJson(@NonNull OsmandPreference preference, @NonNull JSONObject json) throws JSONException { @@ -294,13 +444,17 @@ public class SettingsHelper { @Nullable private InputStream inputStream; - private String name; + protected String name; public StreamSettingsItem(@NonNull SettingsItemType type, @NonNull String name) { super(type); this.name = name; } + StreamSettingsItem(@NonNull SettingsItemType type, @NonNull JSONObject json) throws JSONException { + super(type, json); + } + public StreamSettingsItem(@NonNull SettingsItemType type, @NonNull InputStream inputStream, @NonNull String name) { super(type); this.inputStream = inputStream; @@ -316,11 +470,19 @@ public class SettingsHelper { this.inputStream = inputStream; } + @NonNull @Override public String getName() { return name; } + @Override + void readFromJson(@NonNull JSONObject json) throws JSONException { + super.readFromJson(json); + name = json.getString("name"); + } + + @NonNull @Override public SettingsItemWriter getWriter() { return new StreamSettingsItemWriter(this); @@ -336,18 +498,29 @@ public class SettingsHelper { super(SettingsItemType.DATA, name); } + DataSettingsItem(@NonNull JSONObject json) throws JSONException { + super(SettingsItemType.DATA, json); + } + public DataSettingsItem(@NonNull byte[] data, @NonNull String name) { super(SettingsItemType.DATA, name); this.data = data; } + @NonNull + @Override + public String getFileName() { + return getName() + ".dat"; + } + @Nullable public byte[] getData() { return data; } + @NonNull @Override - public SettingsItemReader getReader() { + SettingsItemReader getReader() { return new StreamSettingsItemReader(this) { @Override public void readFromStream(@NonNull InputStream inputStream) throws IOException, IllegalArgumentException { @@ -364,6 +537,7 @@ public class SettingsHelper { }; } + @NonNull @Override public SettingsItemWriter getWriter() { setInputStream(new ByteArrayInputStream(data)); @@ -380,12 +554,29 @@ public class SettingsHelper { this.file = file; } + FileSettingsItem(@NonNull OsmandApplication app, @NonNull JSONObject json) throws JSONException { + super(SettingsItemType.FILE, json); + this.file = new File(app.getAppPath(null), name); + } + + @NonNull + @Override + public String getFileName() { + return getName(); + } + public File getFile() { return file; } @Override - public SettingsItemReader getReader() { + public boolean exists() { + return file.exists(); + } + + @NonNull + @Override + SettingsItemReader getReader() { return new StreamSettingsItemReader(this) { @Override public void readFromStream(@NonNull InputStream inputStream) throws IOException, IllegalArgumentException { @@ -400,12 +591,13 @@ public class SettingsHelper { }; } + @NonNull @Override public SettingsItemWriter getWriter() { try { setInputStream(new FileInputStream(file)); } catch (FileNotFoundException e) { - LOG.error(null, e); + LOG.error("Failed to set input stream from file: " + file.getName(), e); } return super.getWriter(); } @@ -414,64 +606,105 @@ public class SettingsHelper { private static class SettingsItemsFactory { private OsmandApplication app; + private List items = new ArrayList<>(); - SettingsItemsFactory(OsmandApplication app) { + SettingsItemsFactory(OsmandApplication app, String jsonStr) throws IllegalArgumentException, JSONException { this.app = app; + JSONObject json = new JSONObject(jsonStr); + JSONArray itemsJson = json.getJSONArray("items"); + for (int i = 0; i < itemsJson.length(); i++) { + JSONObject itemJson = itemsJson.getJSONObject(i); + SettingsItem item = createItem(itemJson); + if (item != null) { + items.add(item); + } + } + if (items.size() == 0) { + throw new IllegalArgumentException("No items"); + } + } + + @NonNull + public List getItems() { + return items; } @Nullable - public SettingsItem createItem(@NonNull SettingsItemType type, @NonNull String name) { - OsmandSettings settings = app.getSettings(); - switch (type) { - case GLOBAL: - return new GlobalSettingsItem(settings); - case PROFILE: - ApplicationMode appMode = ApplicationMode.valueOfStringKey(name, null); - return appMode != null ? new ProfileSettingsItem(settings, appMode) : null; - case PLUGIN: - return null; - case DATA: - return new DataSettingsItem(name); - case FILE: - return new FileSettingsItem(app, new File(app.getAppPath(null), name)); + public SettingsItem getItemByFileName(@NonNull String fileName) { + for (SettingsItem item : items) { + if (item.getFileName().equals(fileName)) { + return item; + } } return null; } + + @Nullable + 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(settings, json); + break; + case PLUGIN: + break; + case DATA: + item = new DataSettingsItem(json); + break; + case FILE: + item = new FileSettingsItem(app, json); + break; + } + return item; + } } - public static class SettingsExporter { + private static class SettingsExporter { private Map items; private Map additionalParams; - public SettingsExporter() { + SettingsExporter() { items = new LinkedHashMap<>(); additionalParams = new LinkedHashMap<>(); } - public void addSettingsItem(SettingsItem item) throws IllegalArgumentException { + 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); } - public void addAdditionalParam(String key, String value) { + void addAdditionalParam(String key, String value) { additionalParams.put(key, value); } - public void exportSettings(File zipFile) throws JSONException, IOException { + void exportSettings(File zipFile) throws JSONException, IOException { JSONObject json = new JSONObject(); json.put("osmand_settings_version", OsmandSettings.VERSION); for (Map.Entry param : additionalParams.entrySet()) { json.put(param.getKey(), param.getValue()); } - BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(zipFile), BUFFER); - ZipOutputStream zos = new ZipOutputStream(bos); + JSONArray itemsJson = new JSONArray(); + for (SettingsItem item : items.values()) { + itemsJson.put(new JSONObject(item.toJson())); + } + json.put("items", itemsJson); + OutputStream os = new BufferedOutputStream(new FileOutputStream(zipFile), 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(); for (SettingsItem item : items.values()) { - ZipEntry entry = new ZipEntry(item.getName()); - entry.setExtra(item.getType().name().getBytes()); + entry = new ZipEntry(item.getFileName()); zos.putNextEntry(entry); item.getWriter().writeToStream(zos); zos.closeEntry(); @@ -480,54 +713,268 @@ public class SettingsHelper { zos.finish(); } finally { Algorithms.closeStream(zos); - Algorithms.closeStream(bos); + Algorithms.closeStream(os); } } } - public static class SettingsImporter { + private static class SettingsImporter { private OsmandApplication app; - private List items; - public SettingsImporter(@NonNull OsmandApplication app) { + SettingsImporter(@NonNull OsmandApplication app) { this.app = app; } - public List getItems() { - return Collections.unmodifiableList(items); + List collectItems(@NonNull File zipFile) throws IllegalArgumentException, IOException { + return processItems(zipFile, null); } - public void importSettings(File zipFile) throws IllegalArgumentException, IOException { - items = new ArrayList<>(); + void importItems(@NonNull File zipFile, @NonNull List items) throws IllegalArgumentException, IOException { + processItems(zipFile, items); + } + + private List processItems(@NonNull File zipFile, @Nullable List items) throws IllegalArgumentException, IOException { + boolean collecting = items == null; + if (collecting) { + items = new ArrayList<>(); + } else { + if (items.size() == 0) { + throw new IllegalArgumentException("No items"); + } + } ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile)); InputStream ois = new BufferedInputStream(zis); - SettingsItemsFactory itemsFactory = new SettingsItemsFactory(app); try { - ZipEntry entry; - while ((entry = zis.getNextEntry()) != null) { - String itemTypeStr = new String(entry.getExtra()); - if (!Algorithms.isEmpty(itemTypeStr)) { - try { - SettingsItemType type = SettingsItemType.valueOf(itemTypeStr); - SettingsItem item = itemsFactory.createItem(type, entry.getName()); - if (item != null) { + ZipEntry entry = zis.getNextEntry(); + if (entry != null && entry.getName().equals("items.json")) { + String itemsJson = null; + try { + itemsJson = Algorithms.readFromInputStream(ois).toString(); + } catch (IOException e) { + LOG.error("Error reading items.json: " + itemsJson, e); + throw new IllegalArgumentException("No items"); + } finally { + zis.closeEntry(); + } + SettingsItemsFactory itemsFactory; + try { + itemsFactory = new SettingsItemsFactory(app, itemsJson); + if (collecting) { + items.addAll(itemsFactory.getItems()); + } + } catch (IllegalArgumentException e) { + LOG.error("Error parsing items: " + itemsJson, e); + throw new IllegalArgumentException("No items"); + } catch (JSONException e) { + LOG.error("Error parsing items: " + itemsJson, e); + throw new IllegalArgumentException("No items"); + } + while ((entry = zis.getNextEntry()) != null && !collecting) { + String fileName = entry.getName(); + SettingsItem item = itemsFactory.getItemByFileName(fileName); + if (item != null) { + try { item.getReader().readFromStream(ois); - items.add(item); + } catch (IllegalArgumentException e) { + LOG.error("Error reading item data: " + item.getName(), e); + } catch (IOException e) { + LOG.error("Error reading item data: " + item.getName(), e); + } finally { + zis.closeEntry(); } - } catch (IllegalArgumentException e) { - LOG.error("Wrong SettingsItemType: " + itemTypeStr, e); - } finally { - zis.closeEntry(); } } + } else { + throw new IllegalArgumentException("No items found"); } } catch (IOException ex) { - LOG.error(ex); + LOG.error("Failed to read next entry", ex); } finally { Algorithms.closeStream(ois); Algorithms.closeStream(zis); } + return items; } } + + @SuppressLint("StaticFieldLeak") + private class ImportAsyncTask extends AsyncTask> { + + private File zipFile; + private SettingsImporter importer; + private List items; + private List processedItems = new ArrayList<>(); + + ImportAsyncTask(@NonNull File zipFile) { + this.zipFile = zipFile; + importer = new SettingsImporter(app); + } + + @Override + protected void onPreExecute() { + if (importing) { + finishImport(false); + } + importing = true; + importTask = this; + } + + @Override + protected List doInBackground(Void... voids) { + try { + return importer.collectItems(zipFile); + } catch (IllegalArgumentException e) { + LOG.error("Failed to collect items from: " + zipFile.getName(), e); + } catch (IOException e) { + LOG.error("Failed to collect items from: " + zipFile.getName(), e); + } + return null; + } + + @Override + protected void onPostExecute(List items) { + this.items = items; + if (items != null && items.size() > 0) { + processNextItem(); + } + } + + private void processNextItem() { + if (activity == null) { + return; + } + if (items.size() == 0) { + if (processedItems.size() > 0) { + new ImportItemsAsyncTask(zipFile, processedItems).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } else { + finishImport(false); + } + } + final SettingsItem item = items.remove(0); + if (item.exists()) { + switch (item.getType()) { + case PROFILE: { + AlertDialog.Builder b = new AlertDialog.Builder(activity); + b.setMessage("Profile \"" + item.getName() + "\" is already exists. Overwrite?"); + b.setPositiveButton(R.string.shared_string_yes, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + acceptItem(item); + } + }); + b.setNegativeButton(R.string.shared_string_no, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + processNextItem(); + } + }); + b.setCancelable(false); + b.show(); + break; + } + case FILE: + break; + default: + acceptItem(item); + break; + } + } else { + acceptItem(item); + } + } + + private void acceptItem(SettingsItem item) { + item.apply(); + processedItems.add(item); + processNextItem(); + } + } + + @SuppressLint("StaticFieldLeak") + private class ImportItemsAsyncTask extends AsyncTask { + + private SettingsImporter importer; + private File zipFile; + private List items; + + ImportItemsAsyncTask(@NonNull File zipFile, @NonNull List items) { + importer = new SettingsImporter(app); + this.zipFile = zipFile; + this.items = items; + } + + @Override + protected Boolean doInBackground(Void... voids) { + try { + importer.importItems(zipFile, items); + return true; + } catch (IllegalArgumentException e) { + LOG.error("Failed to import items from: " + zipFile.getName(), e); + } catch (IOException e) { + LOG.error("Failed to import items from: " + zipFile.getName(), e); + } + return false; + } + + @Override + protected void onPostExecute(Boolean success) { + finishImport(success); + } + } + + private void finishImport(boolean success) { + importing = false; + importTask = null; + if (success) { + app.showShortToastMessage("Import succeed"); + } else { + app.showShortToastMessage("Import failed"); + } + } + + @SuppressLint("StaticFieldLeak") + private class ExportAsyncTask extends AsyncTask { + + private SettingsExporter exporter; + private File zipFile; + + ExportAsyncTask(@NonNull File zipFile, @NonNull List items) { + this.zipFile = zipFile; + this.exporter = new SettingsExporter(); + for (SettingsItem item : items) { + exporter.addSettingsItem(item); + } + } + + @Override + protected Boolean doInBackground(Void... voids) { + try { + exporter.exportSettings(zipFile); + return true; + } catch (JSONException e) { + LOG.error("Failed to export items to: " + zipFile.getName(), e); + } catch (IOException e) { + LOG.error("Failed to export items to: " + zipFile.getName(), e); + } + return false; + } + + @Override + protected void onPostExecute(Boolean success) { + if (success) { + app.showShortToastMessage("Export succeed"); + } else { + app.showShortToastMessage("Export failed"); + } + } + } + + public void importSettings(@NonNull File zipFile) { + new ImportAsyncTask(zipFile).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + + public void exportSettings(@NonNull File zipFile, @NonNull List items) { + new ExportAsyncTask(zipFile, items).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } } diff --git a/OsmAnd/src/net/osmand/plus/activities/MapActivity.java b/OsmAnd/src/net/osmand/plus/activities/MapActivity.java index a260a8310b..31ace5c6b5 100644 --- a/OsmAnd/src/net/osmand/plus/activities/MapActivity.java +++ b/OsmAnd/src/net/osmand/plus/activities/MapActivity.java @@ -840,6 +840,7 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven } app.getDownloadThread().setUiActivity(this); + app.getSettingsHelper().setActivity(this); boolean routeWasFinished = routingHelper.isRouteWasFinished(); if (routeWasFinished && !DestinationReachedMenu.wasShown()) { @@ -1428,6 +1429,7 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven app.getMapMarkersHelper().removeListener(this); app.getRoutingHelper().removeListener(this); app.getDownloadThread().resetUiActivity(this); + app.getSettingsHelper().resetActivity(this); if (atlasMapRendererView != null) { atlasMapRendererView.handleOnPause(); }