1
0
Fork 1

Allow import settings.dat from anywhere

This commit is contained in:
Arne 2025-01-11 09:32:15 +01:00
parent ba0581f42f
commit d1218c7713
2 changed files with 71 additions and 49 deletions

View file

@ -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() {

View file

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