Save plugin items to json

This commit is contained in:
Vitaliy 2020-03-24 16:45:34 +02:00
parent 235028d317
commit d01b5106ef
4 changed files with 148 additions and 82 deletions

View file

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

View file

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

View file

@ -317,12 +317,17 @@ public class SettingsHelper {
public static class PluginSettingsItem extends SettingsItem {
private CustomOsmandPlugin plugin;
private List<SettingsItem> pluginItems;
private List<SettingsItem> 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<SettingsItem> getPluginItems() {
return pluginItems;
public List<SettingsItem> 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<SettingsItem> pluginDependentItems = pluginItems.get(pluginSettingsItem.getName());
if (!Algorithms.isEmpty(pluginDependentItems)) {
pluginSettingsItem.getPluginDependentItems().addAll(pluginDependentItems);
}
}
}
}
@ -1931,8 +1959,10 @@ public class SettingsHelper {
private Map<String, SettingsItem> items;
private Map<String, String> 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<String, String> 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<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;
}
}
private static class SettingsImporter {
@ -2326,10 +2380,10 @@ public class SettingsHelper {
ExportAsyncTask(@NonNull File settingsFile,
@Nullable SettingsExportListener listener,
@NonNull List<SettingsItem> items) {
@NonNull List<SettingsItem> 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<SettingsItem> 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<SettingsItem> 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);
}

View file

@ -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<List<SettingsHelper.SettingsItem>> callback) {
private void handleOsmAndSettingsImport(Uri intentUri, String fileName, Bundle extras, CallbackWithObject<List<SettingsItem>> 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<List<SettingsHelper.SettingsItem>> callback) {
final CallbackWithObject<List<SettingsItem>> callback) {
final AsyncTask<Void, Void, String> settingsImportTask = new AsyncTask<Void, Void, String>() {
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<SettingsHelper.SettingsItem> items) {
public void onSettingsCollectFinished(boolean succeed, boolean empty, @NonNull List<SettingsItem> items) {
if (progress != null && AndroidUtils.isActivityNotDestroyed(activity)) {
progress.dismiss();
}
if (succeed) {
List<SettingsHelper.SettingsItem> pluginIndependentItems = new ArrayList<>();
List<SettingsHelper.PluginSettingsItem> pluginSettingsItems = new ArrayList<>();
for (SettingsHelper.SettingsItem item : items) {
if (item instanceof SettingsHelper.PluginSettingsItem) {
pluginSettingsItems.add((SettingsHelper.PluginSettingsItem) item);
List<SettingsItem> pluginIndependentItems = new ArrayList<>();
List<PluginSettingsItem> 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<SettingsHelper.SettingsItem> 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<SettingsHelper.SettingsItem> 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<SettingsItem> 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<SettingsItem> 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);