diff --git a/OsmAnd/src/net/osmand/plus/CustomOsmandPlugin.java b/OsmAnd/src/net/osmand/plus/CustomOsmandPlugin.java index 27ee8e4242..7c4f8fc23e 100644 --- a/OsmAnd/src/net/osmand/plus/CustomOsmandPlugin.java +++ b/OsmAnd/src/net/osmand/plus/CustomOsmandPlugin.java @@ -1,8 +1,10 @@ package net.osmand.plus; +import android.app.Activity; import android.content.res.Configuration; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import net.osmand.PlatformUtil; import net.osmand.util.Algorithms; @@ -31,23 +33,7 @@ public class CustomOsmandPlugin extends OsmandPlugin { public CustomOsmandPlugin(@NonNull OsmandApplication app, @NonNull JSONObject json) throws JSONException { super(app); pluginId = json.getString("pluginId"); - - JSONObject nameJson = json.getJSONObject("name"); - if (nameJson != null) { - for (Iterator it = nameJson.keys(); it.hasNext(); ) { - String localeKey = it.next(); - String name = nameJson.getString(localeKey); - names.put(localeKey, name); - } - } - JSONObject descriptionJson = json.getJSONObject("description"); - if (descriptionJson != null) { - for (Iterator it = descriptionJson.keys(); it.hasNext(); ) { - String localeKey = it.next(); - String name = descriptionJson.getString(localeKey); - descriptions.put(localeKey, name); - } - } + readAdditionalDataFromJson(json); } // Prepare ".opr" desert-package manually + add all resources inside (extend json to describe package). @@ -64,6 +50,16 @@ public class CustomOsmandPlugin extends OsmandPlugin { // so we could remove all code for Nautical / Ski Maps from OsmAnd // and put to separate "skimaps.opr", "nautical.opr" in future + @Override + public boolean init(@NonNull OsmandApplication app, @Nullable Activity activity) { + return super.init(app, activity); + } + + @Override + public void disable(OsmandApplication app) { + super.disable(app); + } + @Override public String getId() { return pluginId; @@ -104,12 +100,26 @@ public class CustomOsmandPlugin extends OsmandPlugin { return R.drawable.ic_action_skiing; } - public String toJson() throws JSONException { - JSONObject json = new JSONObject(); - - json.put("type", SettingsHelper.SettingsItemType.PLUGIN.name()); - json.put("pluginId", getId()); + public void readAdditionalDataFromJson(JSONObject json) throws JSONException { + JSONObject nameJson = json.has("name") ? json.getJSONObject("name") : null; + if (nameJson != null) { + for (Iterator it = nameJson.keys(); it.hasNext(); ) { + String localeKey = it.next(); + String name = nameJson.getString(localeKey); + names.put(localeKey, name); + } + } + JSONObject descriptionJson = json.has("description") ? json.getJSONObject("description") : null; + if (descriptionJson != null) { + for (Iterator it = descriptionJson.keys(); it.hasNext(); ) { + String localeKey = it.next(); + String name = descriptionJson.getString(localeKey); + descriptions.put(localeKey, name); + } + } + } + public void writeAdditionalDataToJson(JSONObject json) throws JSONException { JSONObject nameJson = new JSONObject(); for (Map.Entry entry : names.entrySet()) { nameJson.put(entry.getKey(), entry.getValue()); @@ -121,8 +131,6 @@ public class CustomOsmandPlugin extends OsmandPlugin { descriptionJson.put(entry.getKey(), entry.getValue()); } json.put("description", descriptionJson); - - return json.toString(); } @Override diff --git a/OsmAnd/src/net/osmand/plus/OsmandPlugin.java b/OsmAnd/src/net/osmand/plus/OsmandPlugin.java index 2dccb2762c..d8477172b4 100644 --- a/OsmAnd/src/net/osmand/plus/OsmandPlugin.java +++ b/OsmAnd/src/net/osmand/plus/OsmandPlugin.java @@ -268,15 +268,12 @@ public abstract class OsmandPlugin { activatePlugins(app, enabledPlugins); } - public static void addCustomPlugin(@NonNull OsmandApplication app, @Nullable Activity activity, @NonNull CustomOsmandPlugin plugin) { + public static void addCustomPlugin(@NonNull OsmandApplication app, @NonNull CustomOsmandPlugin plugin) { OsmandPlugin oldPlugin = OsmandPlugin.getPlugin(plugin.getId()); if (oldPlugin != null) { allPlugins.remove(oldPlugin); } allPlugins.add(plugin); - if (activity != null) { - plugin.onInstall(app, activity); - } initPlugin(app, plugin); saveCustomPlugins(app); } @@ -307,7 +304,10 @@ public abstract class OsmandPlugin { JSONArray itemsJson = new JSONArray(); for (CustomOsmandPlugin plugin : customOsmandPlugins) { try { - itemsJson.put(new JSONObject(plugin.toJson())); + JSONObject json = new JSONObject(); + json.put("pluginId", plugin.getId()); + plugin.writeAdditionalDataToJson(json); + itemsJson.put(json); } catch (JSONException e) { e.printStackTrace(); } diff --git a/OsmAnd/src/net/osmand/plus/SettingsHelper.java b/OsmAnd/src/net/osmand/plus/SettingsHelper.java index 1ff827a4b8..7beb20c5d8 100644 --- a/OsmAnd/src/net/osmand/plus/SettingsHelper.java +++ b/OsmAnd/src/net/osmand/plus/SettingsHelper.java @@ -317,12 +317,17 @@ public class SettingsHelper { public static class PluginSettingsItem extends SettingsItem { private CustomOsmandPlugin plugin; - private List pluginItems; + private List pluginDependentItems; PluginSettingsItem(@NonNull OsmandApplication app, @NonNull JSONObject json) throws JSONException { super(app, json); } + @Override + protected void init() { + pluginDependentItems = new ArrayList<>(); + } + @NonNull @Override public SettingsItemType getType() { @@ -344,15 +349,30 @@ public class SettingsHelper { @NonNull @Override public String getDefaultFileName() { - return getName() + ".zip"; + return getName(); } public CustomOsmandPlugin getPlugin() { return plugin; } - public List getPluginItems() { - return pluginItems; + public List getPluginDependentItems() { + return pluginDependentItems; + } + + @Override + public void apply() { + for (SettingsHelper.SettingsItem item : pluginDependentItems) { + if (item instanceof SettingsHelper.FileSettingsItem) { + FileSettingsItem fileItem = (FileSettingsItem) item; + if (fileItem.getSubtype() == FileSettingsItem.FileSubtype.RENDERING_STYLE) { + plugin.rendererNames.add(fileItem.getFileName()); + } else if (fileItem.getSubtype() == FileSettingsItem.FileSubtype.ROUTING_CONFIG) { + plugin.routerNames.add(fileItem.getFileName()); + } + } + } + OsmandPlugin.addCustomPlugin(app, plugin); } @Override @@ -361,6 +381,12 @@ public class SettingsHelper { plugin = new CustomOsmandPlugin(app, json); } + @Override + void writeToJson(@NonNull JSONObject json) throws JSONException { + super.writeToJson(json); + plugin.writeAdditionalDataToJson(json); + } + @Nullable @Override SettingsItemReader getReader() { @@ -1154,8 +1180,7 @@ public class SettingsHelper { } String itemFileName = getFileName(); if (itemFileName.endsWith(File.separator)) { - if (fileName.startsWith(itemFileName)) - { + if (fileName.startsWith(itemFileName)) { this.file = new File(getPluginPath(), fileName); return true; } else { @@ -1866,7 +1891,10 @@ public class SettingsHelper { for (SettingsItem item : items) { if (item instanceof PluginSettingsItem) { PluginSettingsItem pluginSettingsItem = ((PluginSettingsItem) item); - pluginSettingsItem.pluginItems = pluginItems.get(pluginSettingsItem.getName()); + List pluginDependentItems = pluginItems.get(pluginSettingsItem.getName()); + if (!Algorithms.isEmpty(pluginDependentItems)) { + pluginSettingsItem.getPluginDependentItems().addAll(pluginDependentItems); + } } } } @@ -1931,8 +1959,10 @@ public class SettingsHelper { private Map items; private Map additionalParams; + private boolean onlyJson; - SettingsExporter() { + SettingsExporter(boolean onlyJson) { + this.onlyJson = onlyJson; items = new LinkedHashMap<>(); additionalParams = new LinkedHashMap<>(); } @@ -1949,16 +1979,26 @@ public class SettingsHelper { } void exportSettings(File file) throws JSONException, IOException { - JSONObject json = new JSONObject(); - json.put("version", VERSION); - for (Map.Entry param : additionalParams.entrySet()) { - json.put(param.getKey(), param.getValue()); + JSONObject json = createItemsJson(); + if (onlyJson) { + saveJsonItems(file, json); + } else { + saveZipItems(file, json); } - JSONArray itemsJson = new JSONArray(); - for (SettingsItem item : items.values()) { - itemsJson.put(new JSONObject(item.toJson())); + } + + private void saveJsonItems(File file, JSONObject json) throws JSONException, IOException { + InputStream inputStream = new ByteArrayInputStream(json.toString(2).getBytes("UTF-8")); + OutputStream os = new BufferedOutputStream(new FileOutputStream(file), BUFFER); + try { + Algorithms.streamCopy(inputStream, os); + } finally { + Algorithms.closeStream(inputStream); + Algorithms.closeStream(os); } - json.put("items", itemsJson); + } + + private void saveZipItems(File file, JSONObject json) throws JSONException, IOException { OutputStream os = new BufferedOutputStream(new FileOutputStream(file), BUFFER); ZipOutputStream zos = new ZipOutputStream(os); try { @@ -1982,6 +2022,20 @@ public class SettingsHelper { Algorithms.closeStream(os); } } + + private JSONObject createItemsJson() throws JSONException { + JSONObject json = new JSONObject(); + json.put("version", VERSION); + for (Map.Entry 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; + } } private static class SettingsImporter { @@ -2326,10 +2380,10 @@ public class SettingsHelper { ExportAsyncTask(@NonNull File settingsFile, @Nullable SettingsExportListener listener, - @NonNull List items) { + @NonNull List items, boolean onlyJson) { this.file = settingsFile; this.listener = listener; - this.exporter = new SettingsExporter(); + this.exporter = new SettingsExporter(onlyJson); for (SettingsItem item : items) { exporter.addSettingsItem(item); } @@ -2372,7 +2426,14 @@ public class SettingsHelper { public void exportSettings(@NonNull File fileDir, @NonNull String fileName, @Nullable SettingsExportListener listener, @NonNull List items) { File file = new File(fileDir, fileName + OSMAND_SETTINGS_FILE_EXT); - ExportAsyncTask exportAsyncTask = new ExportAsyncTask(file, listener, items); + ExportAsyncTask exportAsyncTask = new ExportAsyncTask(file, listener, items, false); + exportAsyncTasks.put(file, exportAsyncTask); + exportAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + + public void exportPluginItems(@NonNull File pluginDir, @Nullable SettingsExportListener listener, @NonNull List items) { + File file = new File(pluginDir, "items.json"); + ExportAsyncTask exportAsyncTask = new ExportAsyncTask(file, listener, items, true); exportAsyncTasks.put(file, exportAsyncTask); exportAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } diff --git a/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java b/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java index 9d59d99d6f..82d108cec3 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java @@ -41,14 +41,16 @@ import net.osmand.data.FavouritePoint; import net.osmand.plus.AppInitializer; import net.osmand.plus.AppInitializer.AppInitializeListener; import net.osmand.plus.AppInitializer.InitEvents; -import net.osmand.plus.CustomOsmandPlugin; import net.osmand.plus.FavouritesDbHelper; import net.osmand.plus.GPXDatabase; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandPlugin; import net.osmand.plus.R; import net.osmand.plus.SettingsHelper; +import net.osmand.plus.SettingsHelper.PluginSettingsItem; import net.osmand.plus.SettingsHelper.SettingsCollectListener; +import net.osmand.plus.SettingsHelper.SettingsImportListener; +import net.osmand.plus.SettingsHelper.SettingsItem; import net.osmand.plus.UiUtilities; import net.osmand.plus.activities.ActivityResultListener; import net.osmand.plus.activities.MapActivity; @@ -746,7 +748,7 @@ public class ImportHelper { } } - private void handleOsmAndSettingsImport(Uri intentUri, String fileName, Bundle extras, CallbackWithObject> callback) { + private void handleOsmAndSettingsImport(Uri intentUri, String fileName, Bundle extras, CallbackWithObject> callback) { if (extras != null && extras.containsKey(SettingsHelper.SETTINGS_VERSION_KEY) && extras.containsKey(SettingsHelper.SETTINGS_LATEST_CHANGES_KEY)) { int version = extras.getInt(SettingsHelper.SETTINGS_VERSION_KEY, -1); String latestChanges = extras.getString(SettingsHelper.SETTINGS_LATEST_CHANGES_KEY); @@ -758,7 +760,7 @@ public class ImportHelper { @SuppressLint("StaticFieldLeak") private void handleOsmAndSettingsImport(final Uri uri, final String name, final String latestChanges, final int version, - final CallbackWithObject> callback) { + final CallbackWithObject> callback) { final AsyncTask settingsImportTask = new AsyncTask() { ProgressDialog progress; @@ -787,45 +789,22 @@ public class ImportHelper { if (error == null && file.exists()) { app.getSettingsHelper().collectSettings(file, latestChanges, version, new SettingsCollectListener() { @Override - public void onSettingsCollectFinished(boolean succeed, boolean empty, @NonNull List items) { + public void onSettingsCollectFinished(boolean succeed, boolean empty, @NonNull List items) { if (progress != null && AndroidUtils.isActivityNotDestroyed(activity)) { progress.dismiss(); } if (succeed) { - List pluginIndependentItems = new ArrayList<>(); - List pluginSettingsItems = new ArrayList<>(); - for (SettingsHelper.SettingsItem item : items) { - if (item instanceof SettingsHelper.PluginSettingsItem) { - pluginSettingsItems.add((SettingsHelper.PluginSettingsItem) item); + List pluginIndependentItems = new ArrayList<>(); + List pluginSettingsItems = new ArrayList<>(); + for (SettingsItem item : items) { + if (item instanceof PluginSettingsItem) { + pluginSettingsItems.add((PluginSettingsItem) item); } else if (Algorithms.isEmpty(item.getPluginId())) { pluginIndependentItems.add(item); } } - for (SettingsHelper.PluginSettingsItem pluginItem : pluginSettingsItems) { - CustomOsmandPlugin plugin = pluginItem.getPlugin(); - List pluginItems = pluginItem.getPluginItems(); - if (!Algorithms.isEmpty(pluginItems)) { - for (SettingsHelper.SettingsItem item : pluginItems) { - item.setShouldReplace(true); - if (item instanceof SettingsHelper.FileSettingsItem) { - SettingsHelper.FileSettingsItem fileItem = (SettingsHelper.FileSettingsItem) item; - if (fileItem.getSubtype() == SettingsHelper.FileSettingsItem.FileSubtype.RENDERING_STYLE) { - plugin.rendererNames.add(fileItem.getFileName()); - } - if (fileItem.getSubtype() == SettingsHelper.FileSettingsItem.FileSubtype.ROUTING_CONFIG) { - plugin.routerNames.add(fileItem.getFileName()); - } - } - } - - OsmandPlugin.addCustomPlugin(app, activity, plugin); - app.getSettingsHelper().importSettings(file, pluginItems, "", 1, new SettingsHelper.SettingsImportListener() { - @Override - public void onSettingsImportFinished(boolean succeed, @NonNull List items) { - app.showShortToastMessage(app.getString(R.string.file_imported_successfully, "")); - } - }); - } + for (PluginSettingsItem pluginItem : pluginSettingsItems) { + handlePluginImport(pluginItem, file); } if (!pluginIndependentItems.isEmpty()) { FragmentManager fragmentManager = activity.getSupportFragmentManager(); @@ -860,6 +839,24 @@ public class ImportHelper { } } + private void handlePluginImport(final PluginSettingsItem pluginItem, File file) { + List pluginItems = new ArrayList<>(pluginItem.getPluginDependentItems()); + pluginItems.add(0, pluginItem); + for (SettingsItem item : pluginItems) { + item.setShouldReplace(true); + } + app.getSettingsHelper().importSettings(file, pluginItems, "", 1, new SettingsImportListener() { + @Override + public void onSettingsImportFinished(boolean succeed, @NonNull List items) { + if (activity != null) { + pluginItem.getPlugin().onInstall(app, activity); + } + File pluginDir = new File(app.getAppPath(null), IndexConstants.PLUGINS_DIR + pluginItem.getPluginId()); + app.getSettingsHelper().exportPluginItems(pluginDir, null, items); + } + }); + } + private void handleXmlFileImport(final Uri intentUri, final String fileName) { AlertDialog.Builder builder = new AlertDialog.Builder(activity);