Working on settings import/export
This commit is contained in:
parent
6b221be979
commit
6ca269359e
6 changed files with 551 additions and 74 deletions
|
@ -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();
|
||||
|
|
|
@ -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<ArrayList<ApplicationModeBean>>() {}.getType();
|
||||
|
@ -640,7 +669,6 @@ public class ApplicationMode {
|
|||
|
||||
}
|
||||
|
||||
|
||||
private static void saveCustomModeToSettings(OsmandSettings settings){
|
||||
List<ApplicationModeBean> customModes = new ArrayList<>();
|
||||
for (ApplicationMode mode : values) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<T extends SettingsItem> {
|
||||
|
@ -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<SettingsItem> 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<SettingsItem> 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<String, SettingsItem> items;
|
||||
private Map<String, String> 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<String, String> 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<SettingsItem> items;
|
||||
|
||||
public SettingsImporter(@NonNull OsmandApplication app) {
|
||||
SettingsImporter(@NonNull OsmandApplication app) {
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
public List<SettingsItem> getItems() {
|
||||
return Collections.unmodifiableList(items);
|
||||
List<SettingsItem> 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<SettingsItem> items) throws IllegalArgumentException, IOException {
|
||||
processItems(zipFile, items);
|
||||
}
|
||||
|
||||
private List<SettingsItem> processItems(@NonNull File zipFile, @Nullable List<SettingsItem> 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<Void, Void, List<SettingsItem>> {
|
||||
|
||||
private File zipFile;
|
||||
private SettingsImporter importer;
|
||||
private List<SettingsItem> items;
|
||||
private List<SettingsItem> 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<SettingsItem> 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<SettingsItem> 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<Void, Void, Boolean> {
|
||||
|
||||
private SettingsImporter importer;
|
||||
private File zipFile;
|
||||
private List<SettingsItem> items;
|
||||
|
||||
ImportItemsAsyncTask(@NonNull File zipFile, @NonNull List<SettingsItem> 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<Void, Void, Boolean> {
|
||||
|
||||
private SettingsExporter exporter;
|
||||
private File zipFile;
|
||||
|
||||
ExportAsyncTask(@NonNull File zipFile, @NonNull List<SettingsItem> 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<SettingsItem> items) {
|
||||
new ExportAsyncTask(zipFile, items).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue