diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java index 62cd9df7d5..fd28e05adc 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/FileSettingsItem.java @@ -208,7 +208,7 @@ public class FileSettingsItem extends StreamSettingsItem { } public long getSize() { - return size; + return file != null && !file.isDirectory() ? file.length() : size; } public void setSize(long size) { @@ -273,6 +273,7 @@ public class FileSettingsItem extends StreamSettingsItem { dest = renameFile(dest); } if (dest.getParentFile() != null && !dest.getParentFile().exists()) { + //noinspection ResultOfMethodCallIgnored dest.getParentFile().mkdirs(); } output = new FileOutputStream(dest); diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java index 5b27f2afb4..e97a109561 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsExporter.java @@ -21,6 +21,7 @@ class SettingsExporter { private Map items; private Map additionalParams; private boolean exportItemsFiles; + private boolean exportCancel; SettingsExporter(boolean exportItemsFiles) { this.exportItemsFiles = exportItemsFiles; @@ -35,11 +36,15 @@ class SettingsExporter { items.put(item.getName(), item); } + public void setExportCancel(boolean exportCancel) { + this.exportCancel = exportCancel; + } + void addAdditionalParam(String key, String value) { additionalParams.put(key, value); } - void exportSettings(File file) throws JSONException, IOException { + void exportSettings(File file, SettingsHelper.ExportProgress exportProgress) throws JSONException, IOException { JSONObject json = createItemsJson(); OutputStream os = new BufferedOutputStream(new FileOutputStream(file), SettingsHelper.BUFFER); ZipOutputStream zos = new ZipOutputStream(os); @@ -49,7 +54,7 @@ class SettingsExporter { zos.write(json.toString(2).getBytes("UTF-8")); zos.closeEntry(); if (exportItemsFiles) { - writeItemFiles(zos); + writeItemFiles(zos, exportProgress); } zos.flush(); zos.finish(); @@ -59,7 +64,8 @@ class SettingsExporter { } } - private void writeItemFiles(ZipOutputStream zos) throws IOException { + private void writeItemFiles(ZipOutputStream zos, SettingsHelper.ExportProgress exportProgress) throws IOException { + int progress = 0; for (SettingsItem item : items.values()) { SettingsItemWriter writer = item.getWriter(); if (writer != null) { @@ -69,6 +75,17 @@ class SettingsExporter { } writer.writeEntry(fileName, zos); } + if (exportCancel) { + exportCancel = false; + return; + } + if (item instanceof FileSettingsItem) { + int size = (int) ((FileSettingsItem) item).getSize() / 1000000; + progress += size; + if (exportProgress != null) { + exportProgress.setProgress(progress); + } + } } } diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsHelper.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsHelper.java index 469e9ebde0..09389bcefa 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsHelper.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsHelper.java @@ -111,6 +111,8 @@ public class SettingsHelper { public interface SettingsExportListener { void onSettingsExportFinished(@NonNull File file, boolean succeed); + + void onSettingsExportProgressUpdate(int value); } public enum ImportType { @@ -139,6 +141,10 @@ public class SettingsHelper { return importTask == null || importTask.isImportDone(); } + public ExportAsyncTask getExportAsyncTask(File file) { + return exportAsyncTasks.get(file); + } + public boolean isFileExporting(File file) { return exportAsyncTasks.containsKey(file); } @@ -200,28 +206,41 @@ public class SettingsHelper { } } - @SuppressLint("StaticFieldLeak") - private class ExportAsyncTask extends AsyncTask { + public interface ExportProgress { + void setProgress(int value); + } - private SettingsExporter exporter; - private File file; + @SuppressLint("StaticFieldLeak") + public class ExportAsyncTask extends AsyncTask { + + private final SettingsExporter exporter; + private final File file; private SettingsExportListener listener; + private final ExportProgress exportProgress; + ExportAsyncTask(@NonNull File settingsFile, - @Nullable SettingsExportListener listener, - @NonNull List items, boolean exportItemsFiles) { + @Nullable SettingsExportListener listener, + @NonNull List items, boolean exportItemsFiles) { this.file = settingsFile; this.listener = listener; this.exporter = new SettingsExporter(exportItemsFiles); for (SettingsItem item : items) { exporter.addSettingsItem(item); } + exportProgress = new ExportProgress() { + @Override + public void setProgress(int value) { + exporter.setExportCancel(isCancelled()); + publishProgress(value); + } + }; } @Override protected Boolean doInBackground(Void... voids) { try { - exporter.exportSettings(file); + exporter.exportSettings(file, exportProgress); return true; } catch (JSONException e) { LOG.error("Failed to export items to: " + file.getName(), e); @@ -231,6 +250,14 @@ public class SettingsHelper { return false; } + @Override + protected void onProgressUpdate(Integer... values) { + super.onProgressUpdate(values); + if (listener != null) { + listener.onSettingsExportProgressUpdate(values[0]); + } + } + @Override protected void onPostExecute(Boolean success) { exportAsyncTasks.remove(file); @@ -238,6 +265,13 @@ public class SettingsHelper { listener.onSettingsExportFinished(file, success); } } + + @Override + protected void onCancelled() { + super.onCancelled(); + //noinspection ResultOfMethodCallIgnored + file.delete(); + } } @SuppressLint("StaticFieldLeak") @@ -416,6 +450,8 @@ public class SettingsHelper { public void exportSettings(@NonNull File fileDir, @NonNull String fileName, @Nullable SettingsExportListener listener, @NonNull List items, boolean exportItemsFiles) { File file = new File(fileDir, fileName + OSMAND_SETTINGS_FILE_EXT); ExportAsyncTask exportAsyncTask = new ExportAsyncTask(file, listener, items, exportItemsFiles); + + exportAsyncTasks.put(file, exportAsyncTask); exportAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportProfileBottomSheet.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportProfileBottomSheet.java index 0d621b6b50..2657e58d2a 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportProfileBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportProfileBottomSheet.java @@ -2,6 +2,7 @@ package net.osmand.plus.settings.fragments; import android.app.ProgressDialog; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.content.res.ColorStateList; import android.graphics.drawable.ColorDrawable; @@ -33,6 +34,7 @@ import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem; import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.ExportSettingsType; +import net.osmand.plus.settings.backend.backup.FileSettingsItem; import net.osmand.plus.settings.backend.backup.GlobalSettingsItem; import net.osmand.plus.settings.backend.backup.ProfileSettingsItem; import net.osmand.plus.settings.backend.backup.SettingsHelper.SettingsExportListener; @@ -47,6 +49,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; public class ExportProfileBottomSheet extends BasePreferenceBottomSheet { @@ -60,8 +63,10 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet { private static final String EXPORTING_PROFILE_KEY = "exporting_profile_key"; private static final String INCLUDE_ADDITIONAL_DATA_KEY = "include_additional_data_key"; private static final String INCLUDE_GLOBAL_SETTINGS_KEY = "include_global_settings_key"; + private static final String PROGRESS_MAX_KEY = "progress_max_key"; + private static final String PROGRESS_VALUE_KEY = "progress_value_key"; - private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd-MM-yy"); + private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd-MM-yy", Locale.US); private OsmandApplication app; private Map> dataList = new HashMap<>(); @@ -69,6 +74,8 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet { private SettingsExportListener exportListener; private ProgressDialog progress; + int progressMax; + int progressValue; private long exportStartTime; @@ -87,6 +94,8 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet { includeAdditionalData = savedInstanceState.getBoolean(INCLUDE_ADDITIONAL_DATA_KEY); includeGlobalSettings = savedInstanceState.getBoolean(INCLUDE_GLOBAL_SETTINGS_KEY); exportStartTime = savedInstanceState.getLong(EXPORT_START_TIME_KEY); + progressMax = savedInstanceState.getInt(PROGRESS_MAX_KEY); + progressValue = savedInstanceState.getInt(PROGRESS_VALUE_KEY); } dataList = app.getSettingsHelper().getAdditionalData(globalExport); } @@ -99,6 +108,8 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet { outState.putBoolean(INCLUDE_ADDITIONAL_DATA_KEY, includeAdditionalData); outState.putBoolean(INCLUDE_GLOBAL_SETTINGS_KEY, includeGlobalSettings); outState.putLong(EXPORT_START_TIME_KEY, exportStartTime); + outState.putInt(PROGRESS_MAX_KEY, progress.getMax()); + outState.putInt(PROGRESS_VALUE_KEY, progress.getProgress()); } @Override @@ -271,10 +282,22 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet { showExportProgressDialog(); File tempDir = FileUtils.getTempDir(app); String fileName = getFileName(); - app.getSettingsHelper().exportSettings(tempDir, fileName, getSettingsExportListener(), prepareSettingsItemsForExport(), true); + List items = prepareSettingsItemsForExport(); + progress.setMax(getMaxProgress(items)); + app.getSettingsHelper().exportSettings(tempDir, fileName, getSettingsExportListener(), items, true); } } + private int getMaxProgress(List items) { + long maxProgress = 0; + for (SettingsItem item : items) { + if (item instanceof FileSettingsItem) { + maxProgress += ((FileSettingsItem) item).getSize(); + } + } + return (int) maxProgress / 1000000; + } + private String getFileName() { if (globalExport) { if (exportStartTime == 0) { @@ -295,12 +318,33 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet { progress.dismiss(); } progress = new ProgressDialog(context); + progress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); + progress.setCancelable(true); progress.setTitle(app.getString(R.string.shared_string_export)); progress.setMessage(app.getString(R.string.shared_string_preparing)); - progress.setCancelable(false); + progress.setButton(DialogInterface.BUTTON_NEGATIVE, app.getString(R.string.shared_string_cancel), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + cancelExport(); + } + }); + progress.setOnCancelListener(new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + cancelExport(); + } + }); progress.show(); } + private void cancelExport() { + app.getSettingsHelper().getExportAsyncTask(getExportFile()).cancel(true); + //noinspection ResultOfMethodCallIgnored + getExportFile().delete(); + progress.dismiss(); + dismiss(); + } + private SettingsExportListener getSettingsExportListener() { if (exportListener == null) { exportListener = new SettingsExportListener() { @@ -315,6 +359,11 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet { app.showToastMessage(R.string.export_profile_failed); } } + + @Override + public void onSettingsExportProgressUpdate(int value) { + progress.setProgress(value); + } }; } return exportListener; @@ -326,6 +375,8 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet { boolean fileExporting = app.getSettingsHelper().isFileExporting(file); if (fileExporting) { showExportProgressDialog(); + progress.setMax(progressMax); + progress.setProgress(progressValue); app.getSettingsHelper().updateExportListener(file, getSettingsExportListener()); } else if (file.exists()) { dismissExportProgressDialog(); diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ProfileAppearanceFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ProfileAppearanceFragment.java index 1bdbc38b19..bc3092d963 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ProfileAppearanceFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ProfileAppearanceFragment.java @@ -735,6 +735,11 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment { app.showToastMessage(R.string.profile_backup_failed); } } + + @Override + public void onSettingsExportProgressUpdate(int value) { + + } }; } return exportListener;