Allow import settings.dat from anywhere
This commit is contained in:
parent
ba0581f42f
commit
d1218c7713
2 changed files with 71 additions and 49 deletions
|
@ -1,11 +1,15 @@
|
||||||
package eu.siacs.conversations.ui.fragment.settings;
|
package eu.siacs.conversations.ui.fragment.settings;
|
||||||
|
|
||||||
|
import static android.app.Activity.RESULT_OK;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import androidx.preference.PreferenceManager;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
@ -17,6 +21,7 @@ import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.preference.ListPreference;
|
import androidx.preference.ListPreference;
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
import androidx.work.Constraints;
|
import androidx.work.Constraints;
|
||||||
import androidx.work.Data;
|
import androidx.work.Data;
|
||||||
import androidx.work.ExistingPeriodicWorkPolicy;
|
import androidx.work.ExistingPeriodicWorkPolicy;
|
||||||
|
@ -35,7 +40,6 @@ import eu.siacs.conversations.R;
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
import eu.siacs.conversations.persistance.FileBackend;
|
import eu.siacs.conversations.persistance.FileBackend;
|
||||||
import eu.siacs.conversations.ui.activity.SettingsActivity;
|
import eu.siacs.conversations.ui.activity.SettingsActivity;
|
||||||
import eu.siacs.conversations.utils.ChatBackgroundHelper;
|
|
||||||
import eu.siacs.conversations.worker.ExportBackupWorker;
|
import eu.siacs.conversations.worker.ExportBackupWorker;
|
||||||
import me.drakeet.support.toast.ToastCompat;
|
import me.drakeet.support.toast.ToastCompat;
|
||||||
|
|
||||||
|
@ -46,11 +50,17 @@ import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.ObjectInputStream;
|
import java.io.ObjectInputStream;
|
||||||
import java.io.ObjectOutputStream;
|
import java.io.ObjectOutputStream;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public class BackupSettingsFragment extends XmppPreferenceFragment {
|
public class BackupSettingsFragment extends XmppPreferenceFragment {
|
||||||
|
|
||||||
|
private static final SimpleDateFormat DATE_FORMAT =
|
||||||
|
new SimpleDateFormat("yyyy-MM-dd-HH-mm", Locale.US);
|
||||||
public static final String CREATE_ONE_OFF_BACKUP = "create_one_off_backup";
|
public static final String CREATE_ONE_OFF_BACKUP = "create_one_off_backup";
|
||||||
private static final String RECURRING_BACKUP = "recurring_backup";
|
private static final String RECURRING_BACKUP = "recurring_backup";
|
||||||
public static final int REQUEST_EXPORT_SETTINGS = 0xbf8701;
|
public static final int REQUEST_EXPORT_SETTINGS = 0xbf8701;
|
||||||
|
@ -99,7 +109,7 @@ public class BackupSettingsFragment extends XmppPreferenceFragment {
|
||||||
if (importSettingsPreference != null) {
|
if (importSettingsPreference != null) {
|
||||||
importSettingsPreference.setOnPreferenceClickListener(preference -> {
|
importSettingsPreference.setOnPreferenceClickListener(preference -> {
|
||||||
if (requireSettingsActivity().hasStoragePermission(REQUEST_IMPORT_SETTINGS)) {
|
if (requireSettingsActivity().hasStoragePermission(REQUEST_IMPORT_SETTINGS)) {
|
||||||
importSettings();
|
openSettingsPicker();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
@ -116,6 +126,14 @@ public class BackupSettingsFragment extends XmppPreferenceFragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void openSettingsPicker() {
|
||||||
|
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||||
|
intent.setType("*/*");
|
||||||
|
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, false);
|
||||||
|
startActivityForResult(Intent.createChooser(intent, getString(R.string.select_settings_dat)), REQUEST_IMPORT_SETTINGS);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onSharedPreferenceChanged(@NonNull String key) {
|
protected void onSharedPreferenceChanged(@NonNull String key) {
|
||||||
super.onSharedPreferenceChanged(key);
|
super.onSharedPreferenceChanged(key);
|
||||||
|
@ -167,6 +185,16 @@ public class BackupSettingsFragment extends XmppPreferenceFragment {
|
||||||
requireActivity().setTitle(R.string.backup);
|
requireActivity().setTitle(R.string.backup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
|
if (requestCode == REQUEST_IMPORT_SETTINGS) {
|
||||||
|
if (resultCode == RESULT_OK) {
|
||||||
|
Uri uri = data.getData();
|
||||||
|
importSettings(uri, requireSettingsActivity());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||||
|
@ -176,7 +204,8 @@ public class BackupSettingsFragment extends XmppPreferenceFragment {
|
||||||
exportSettings();
|
exportSettings();
|
||||||
}
|
}
|
||||||
if (requestCode == REQUEST_IMPORT_SETTINGS) {
|
if (requestCode == REQUEST_IMPORT_SETTINGS) {
|
||||||
importSettings();
|
ToastCompat.makeText(requireActivity(), "permissions for open setting spicker granted", ToastCompat.LENGTH_SHORT).show();
|
||||||
|
openSettingsPicker();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ToastCompat.makeText(
|
ToastCompat.makeText(
|
||||||
|
@ -234,65 +263,58 @@ public class BackupSettingsFragment extends XmppPreferenceFragment {
|
||||||
builder.create().show();
|
builder.create().show();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked" })
|
private void importSettings(Uri uri, SettingsActivity settingsActivity) {
|
||||||
private boolean importSettings() {
|
boolean success = false;
|
||||||
boolean success;
|
|
||||||
ObjectInputStream input = null;
|
|
||||||
try {
|
try {
|
||||||
final File file = new File(FileBackend.getBackupDirectory(requireContext()).getAbsolutePath(),"settings.dat");
|
String path = uri.getPath();
|
||||||
input = new ObjectInputStream(new FileInputStream(file));
|
if (path == null) {
|
||||||
SharedPreferences.Editor prefEdit = PreferenceManager.getDefaultSharedPreferences(requireSettingsActivity()).edit();
|
success = false;
|
||||||
prefEdit.clear();
|
throw new IllegalArgumentException("Uri path cannot be null.");
|
||||||
Map<String, ?> entries = (Map<String, ?>) input.readObject();
|
}
|
||||||
for (Map.Entry<String, ?> entry : entries.entrySet()) {
|
File file = new File(path);
|
||||||
Object value = entry.getValue();
|
try (ObjectInputStream input = new ObjectInputStream(new FileInputStream(file))) {
|
||||||
String key = entry.getKey();
|
SharedPreferences.Editor prefEdit = PreferenceManager.getDefaultSharedPreferences(settingsActivity).edit();
|
||||||
|
prefEdit.clear();
|
||||||
if (value instanceof Boolean)
|
Map<String, ?> entries = (Map<String, ?>) input.readObject();
|
||||||
prefEdit.putBoolean(key, ((Boolean) value).booleanValue());
|
for (Map.Entry<String, ?> entry : entries.entrySet()) {
|
||||||
else if (value instanceof Float)
|
Object value = entry.getValue();
|
||||||
prefEdit.putFloat(key, ((Float) value).floatValue());
|
String key = entry.getKey();
|
||||||
else if (value instanceof Integer)
|
|
||||||
prefEdit.putInt(key, ((Integer) value).intValue());
|
if (value instanceof Boolean) {
|
||||||
else if (value instanceof Long)
|
prefEdit.putBoolean(key, (Boolean) value);
|
||||||
prefEdit.putLong(key, ((Long) value).longValue());
|
} else if (value instanceof Float) {
|
||||||
else if (value instanceof String)
|
prefEdit.putFloat(key, (Float) value);
|
||||||
prefEdit.putString(key, ((String) value));
|
} else if (value instanceof Integer) {
|
||||||
|
prefEdit.putInt(key, (Integer) value);
|
||||||
|
} else if (value instanceof Long) {
|
||||||
|
prefEdit.putLong(key, (Long) value);
|
||||||
|
} else if (value instanceof String) {
|
||||||
|
prefEdit.putString(key, (String) value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prefEdit.commit();
|
||||||
|
success = true;
|
||||||
}
|
}
|
||||||
prefEdit.commit();
|
|
||||||
success = true;
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
success = false;
|
success = false;
|
||||||
e.printStackTrace();
|
Log.e("SettingsImport", "Error importing settings", e);
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
if (input != null) {
|
|
||||||
input.close();
|
|
||||||
}
|
|
||||||
} catch (IOException ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (success) {
|
|
||||||
new Thread(() -> runOnUiThread(() -> requireActivity().recreate())).start();
|
int messageResId = success ? R.string.success_import_settings : R.string.error_import_settings;
|
||||||
ToastCompat.makeText(requireActivity(), R.string.success_import_settings, ToastCompat.LENGTH_SHORT).show();
|
ToastCompat.makeText(settingsActivity, messageResId, ToastCompat.LENGTH_SHORT).show();
|
||||||
} else {
|
|
||||||
ToastCompat.makeText(requireActivity(), R.string.error_import_settings, ToastCompat.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean exportSettings() {
|
private void exportSettings() {
|
||||||
boolean success = false;
|
boolean success = false;
|
||||||
ObjectOutputStream output = null;
|
ObjectOutputStream output = null;
|
||||||
try {
|
try {
|
||||||
final File file = new File(FileBackend.getBackupDirectory(requireContext()).getAbsolutePath(), "settings.dat");
|
final File file = new File(FileBackend.getBackupDirectory(requireContext()).getAbsolutePath(), DATE_FORMAT.format(new Date()) + "_settings.dat");
|
||||||
final File directory = file.getParentFile();
|
final File directory = file.getParentFile();
|
||||||
if (directory != null && directory.mkdirs()) {
|
if (directory != null && directory.mkdirs()) {
|
||||||
Log.d(Config.LOGTAG, "created backup directory " + directory.getAbsolutePath());
|
Log.d(Config.LOGTAG, "created backup directory " + directory.getAbsolutePath());
|
||||||
}
|
}
|
||||||
output = new ObjectOutputStream(new FileOutputStream(file));
|
output = new ObjectOutputStream(new FileOutputStream(file));
|
||||||
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(requireSettingsActivity());
|
SharedPreferences pref = androidx.preference.PreferenceManager.getDefaultSharedPreferences(requireSettingsActivity());
|
||||||
output.writeObject(pref.getAll());
|
output.writeObject(pref.getAll());
|
||||||
success = true;
|
success = true;
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
|
@ -315,7 +337,6 @@ public class BackupSettingsFragment extends XmppPreferenceFragment {
|
||||||
} else {
|
} else {
|
||||||
ToastCompat.makeText(requireActivity(), R.string.error_export_settings, ToastCompat.LENGTH_SHORT).show();
|
ToastCompat.makeText(requireActivity(), R.string.error_export_settings, ToastCompat.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SettingsActivity requireSettingsActivity() {
|
public SettingsActivity requireSettingsActivity() {
|
||||||
|
|
|
@ -1414,4 +1414,5 @@
|
||||||
<string name="error_export_settings">Error while exporting settings</string>
|
<string name="error_export_settings">Error while exporting settings</string>
|
||||||
<string name="pref_export_plain_text_logs">Export plain text</string>
|
<string name="pref_export_plain_text_logs">Export plain text</string>
|
||||||
<string name="pref_export_plain_text_logs_summary">Export messages unencrypted in human readable plain text</string>
|
<string name="pref_export_plain_text_logs_summary">Export messages unencrypted in human readable plain text</string>
|
||||||
|
<string name="select_settings_dat">Select a settings.dat</string>
|
||||||
</resources>
|
</resources>
|
Loading…
Add table
Reference in a new issue