diff --git a/k9mail/src/main/java/com/fsck/k9/activity/Accounts.java b/k9mail/src/main/java/com/fsck/k9/activity/Accounts.java
index 74765fd86..86022cfb0 100644
--- a/k9mail/src/main/java/com/fsck/k9/activity/Accounts.java
+++ b/k9mail/src/main/java/com/fsck/k9/activity/Accounts.java
@@ -29,6 +29,7 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.text.Editable;
@@ -137,6 +138,9 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {
private TextView mActionBarSubTitle;
private TextView mActionBarUnread;
+ private boolean exportGlobalSettings;
+ private ArrayList exportAccountUuids;
+
/**
* Contains information about objects that need to be retained on configuration changes.
*
@@ -146,6 +150,7 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {
private static final int ACTIVITY_REQUEST_PICK_SETTINGS_FILE = 1;
+ private static final int ACTIVITY_REQUEST_SAVE_SETTINGS_FILE = 2;
class AccountsHandler extends Handler {
private void setViewTitle() {
@@ -328,6 +333,9 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {
private static String ACCOUNT_STATS = "accountStats";
private static String STATE_UNREAD_COUNT = "unreadCount";
private static String SELECTED_CONTEXT_ACCOUNT = "selectedContextAccount";
+ private static final String STATE_EXPORT_GLOBAL_SETTINGS = "exportGlobalSettings";
+ private static final String STATE_EXPORT_ACCOUNTS = "exportAccountUuids";
+
public static final String EXTRA_STARTUP = "startup";
@@ -476,6 +484,17 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {
}
outState.putSerializable(STATE_UNREAD_COUNT, mUnreadMessageCount);
outState.putSerializable(ACCOUNT_STATS, accountStats);
+
+ outState.putBoolean(STATE_EXPORT_GLOBAL_SETTINGS, exportGlobalSettings);
+ outState.putStringArrayList(STATE_EXPORT_ACCOUNTS, exportAccountUuids);
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Bundle state) {
+ super.onRestoreInstanceState(state);
+
+ exportGlobalSettings = state.getBoolean(STATE_EXPORT_GLOBAL_SETTINGS, false);
+ exportAccountUuids = state.getStringArrayList(STATE_EXPORT_ACCOUNTS);
}
private StorageManager.StorageListener storageListener = new StorageManager.StorageListener() {
@@ -1290,7 +1309,7 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {
getString(R.string.app_revision_url) +
""))
.append("
")
- .append(String.format(getString(R.string.app_copyright_fmt), year, year))
+ .append(String.format(getString(R.string.app_copyright_fmt), Integer.toString(year), Integer.toString(year)))
.append("
")
.append(getString(R.string.app_license))
.append("
");
@@ -1418,9 +1437,12 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {
return;
}
switch (requestCode) {
- case ACTIVITY_REQUEST_PICK_SETTINGS_FILE:
- onImport(data.getData());
- break;
+ case ACTIVITY_REQUEST_PICK_SETTINGS_FILE:
+ onImport(data.getData());
+ break;
+ case ACTIVITY_REQUEST_SAVE_SETTINGS_FILE:
+ onExport(data);
+ break;
}
}
@@ -1884,15 +1906,35 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {
}
public void onExport(final boolean includeGlobals, final Account account) {
-
// TODO, prompt to allow a user to choose which accounts to export
- Set accountUuids = null;
+ ArrayList accountUuids = null;
if (account != null) {
- accountUuids = new HashSet();
+ accountUuids = new ArrayList<>();
accountUuids.add(account.getUuid());
}
- ExportAsyncTask asyncTask = new ExportAsyncTask(this, includeGlobals, accountUuids);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ exportGlobalSettings = includeGlobals;
+ exportAccountUuids = accountUuids;
+
+ Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
+ intent.setType("application/octet-stream");
+ intent.putExtra(Intent.EXTRA_TITLE, SettingsExporter.EXPORT_FILENAME);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+
+ startActivityForResult(intent, ACTIVITY_REQUEST_SAVE_SETTINGS_FILE);
+ } else {
+ startExport(includeGlobals, accountUuids, null);
+ }
+ }
+
+ public void onExport(Intent intent) {
+ Uri documentsUri = intent.getData();
+ startExport(exportGlobalSettings, exportAccountUuids, documentsUri);
+ }
+
+ private void startExport(boolean exportGlobalSettings, ArrayList exportAccountUuids, Uri documentsUri) {
+ ExportAsyncTask asyncTask = new ExportAsyncTask(this, exportGlobalSettings, exportAccountUuids, documentsUri);
setNonConfigurationInstance(asyncTask);
asyncTask.execute();
}
@@ -1904,13 +1946,17 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {
private boolean mIncludeGlobals;
private Set mAccountUuids;
private String mFileName;
+ private Uri mUri;
private ExportAsyncTask(Accounts activity, boolean includeGlobals,
- Set accountUuids) {
+ List accountUuids, Uri uri) {
super(activity);
mIncludeGlobals = includeGlobals;
- mAccountUuids = accountUuids;
+ mUri = uri;
+ if (accountUuids != null) {
+ mAccountUuids = new HashSet<>(accountUuids);
+ }
}
@Override
@@ -1923,8 +1969,13 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {
@Override
protected Boolean doInBackground(Void... params) {
try {
- mFileName = SettingsExporter.exportToFile(mContext, mIncludeGlobals,
+ if (mUri == null) {
+ mFileName = SettingsExporter.exportToFile(mContext, mIncludeGlobals,
mAccountUuids);
+ } else {
+ SettingsExporter.exportToUri(mContext, mIncludeGlobals, mAccountUuids, mUri);
+ }
+
} catch (SettingsImportExportException e) {
Timber.w(e, "Exception during export");
return false;
@@ -1942,8 +1993,13 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {
removeProgressDialog();
if (success) {
- activity.showSimpleDialog(R.string.settings_export_success_header,
- R.string.settings_export_success, mFileName);
+ if (mFileName != null) {
+ activity.showSimpleDialog(R.string.settings_export_success_header,
+ R.string.settings_export_success, mFileName);
+ } else {
+ activity.showSimpleDialog(R.string.settings_export_success_header,
+ R.string.settings_export_success_generic);
+ }
} else {
//TODO: better error messages
activity.showSimpleDialog(R.string.settings_export_failed_header,
diff --git a/k9mail/src/main/java/com/fsck/k9/preferences/SettingsExporter.java b/k9mail/src/main/java/com/fsck/k9/preferences/SettingsExporter.java
index 913173cde..37130cfa7 100644
--- a/k9mail/src/main/java/com/fsck/k9/preferences/SettingsExporter.java
+++ b/k9mail/src/main/java/com/fsck/k9/preferences/SettingsExporter.java
@@ -15,12 +15,13 @@ import java.util.Set;
import java.util.TreeMap;
import android.content.Context;
+import android.net.Uri;
import android.os.Environment;
+
import timber.log.Timber;
import android.util.Xml;
import com.fsck.k9.Account;
-import com.fsck.k9.K9;
import com.fsck.k9.Preferences;
import com.fsck.k9.helper.FileHelper;
import com.fsck.k9.mail.ServerSettings;
@@ -32,7 +33,7 @@ import org.xmlpull.v1.XmlSerializer;
public class SettingsExporter {
- private static final String EXPORT_FILENAME = "settings.k9s";
+ public static final String EXPORT_FILENAME = "settings.k9s";
/**
* File format version number.
@@ -80,7 +81,6 @@ public class SettingsExporter {
throws SettingsImportExportException {
OutputStream os = null;
- String filename = null;
try {
File dir = new File(Environment.getExternalStorageDirectory() + File.separator + context.getPackageName());
if (!dir.mkdirs()) {
@@ -88,7 +88,7 @@ public class SettingsExporter {
}
File file = FileHelper.createUniqueFile(dir, EXPORT_FILENAME);
- filename = file.getAbsolutePath();
+ String filename = file.getAbsolutePath();
os = new FileOutputStream(filename);
exportPreferences(context, os, includeGlobals, accountUuids);
@@ -98,13 +98,33 @@ public class SettingsExporter {
} catch (Exception e) {
throw new SettingsImportExportException(e);
} finally {
- if (os != null) {
- try {
- os.close();
- } catch (IOException ioe) {
- Timber.w("Couldn't close exported settings file: %s", filename);
- }
- }
+ closeOrThrow(os);
+ }
+ }
+
+ public static void exportToUri(Context context, boolean includeGlobals, Set accountUuids, Uri uri)
+ throws SettingsImportExportException {
+
+ OutputStream os = null;
+ try {
+ os = context.getContentResolver().openOutputStream(uri);
+ exportPreferences(context, os, includeGlobals, accountUuids);
+ } catch (Exception e) {
+ throw new SettingsImportExportException(e);
+ } finally {
+ closeOrThrow(os);
+ }
+ }
+
+ private static void closeOrThrow(OutputStream outputStream) throws SettingsImportExportException {
+ if (outputStream == null) {
+ return;
+ }
+
+ try {
+ outputStream.close();
+ } catch (IOException e) {
+ throw new SettingsImportExportException(e);
}
}
diff --git a/k9mail/src/main/res/values/strings.xml b/k9mail/src/main/res/values/strings.xml
index 052485cd6..6fac436c3 100644
--- a/k9mail/src/main/res/values/strings.xml
+++ b/k9mail/src/main/res/values/strings.xml
@@ -975,6 +975,7 @@ Please submit bug reports, contribute new features and ask questions at
Importing settings…
Scanning file…
Saved exported settings to %s
+ Settings successfully exported
Imported global settings from %s
Imported %s from %s