Restore settings.

This commit is contained in:
Alex Ning 2021-03-06 21:28:37 +08:00
parent 65e654a23c
commit a03cdfe814
4 changed files with 228 additions and 43 deletions

View File

@ -95,17 +95,18 @@ public class BackupSettings {
String fileName) { String fileName) {
boolean result = false; boolean result = false;
ObjectOutputStream output = null;
String backupDir = context.getExternalCacheDir() + "/Backup/" + BuildConfig.VERSION_NAME;
if (!new File(backupDir).exists()) {
new File(backupDir).mkdirs();
} else {
File backupDirFile = new File(backupDir);
backupDirFile.delete();
backupDirFile.mkdirs();
}
ObjectOutputStream output = null;
try { try {
String backupDir = context.getExternalCacheDir() + "/Backup/" + BuildConfig.VERSION_NAME;
if (!new File(backupDir).exists()) {
new File(backupDir).mkdirs();
} else {
File backupDirFile = new File(backupDir);
FileUtils.deleteDirectory(backupDirFile);
backupDirFile.mkdirs();
}
output = new ObjectOutputStream(new FileOutputStream(new File(backupDir + "/" + fileName + ".txt"))); output = new ObjectOutputStream(new FileOutputStream(new File(backupDir + "/" + fileName + ".txt")));
output.writeObject(sharedPreferences.getAll()); output.writeObject(sharedPreferences.getAll());

View File

@ -0,0 +1,171 @@
package ml.docilealligator.infinityforreddit.asynctasks;
import android.content.ContentResolver;
import android.content.Context;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Handler;
import net.lingala.zip4j.ZipFile;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executor;
import ml.docilealligator.infinityforreddit.R;
import ml.docilealligator.infinityforreddit.utils.CustomThemeSharedPreferencesUtils;
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
public class RestoreSettings {
public static void restoreSettings(Context context, Executor executor, Handler handler,
ContentResolver contentResolver, Uri zipFileUri,
SharedPreferences defaultSharedPreferences,
SharedPreferences lightThemeSharedPreferences,
SharedPreferences darkThemeSharedPreferences,
SharedPreferences amoledThemeSharedPreferences,
SharedPreferences sortTypeSharedPreferences,
SharedPreferences postLayoutSharedPreferences,
SharedPreferences postFeedScrolledPositionSharedPreferences,
SharedPreferences mainActivityTabsSharedPreferences,
SharedPreferences nsfwAndSpoilerSharedPreferencs,
SharedPreferences bottomAppBarSharedPreferences,
SharedPreferences postHistorySharedPreferences,
RestoreSettingsListener restoreSettingsListener) {
executor.execute(() -> {
try {
InputStream zipFileInputStream = contentResolver.openInputStream(zipFileUri);
if (zipFileInputStream == null) {
handler.post(() -> restoreSettingsListener.failed(context.getString(R.string.restore_settings_failed_cannot_get_file)));
return;
}
String cachePath = context.getExternalCacheDir() + "/Restore/";
if (new File(cachePath).exists()) {
FileUtils.deleteDirectory(new File(cachePath));
}
new File(cachePath).mkdir();
FileOutputStream zipCacheOutputStream = new FileOutputStream(new File(cachePath + "restore.zip"));
byte[] fileReader = new byte[1024];
while (true) {
int read = zipFileInputStream.read(fileReader);
if (read == -1) {
break;
}
zipCacheOutputStream.write(fileReader, 0, read);
}
new ZipFile(cachePath + "restore.zip", "123321".toCharArray()).extractAll(cachePath);
new File(cachePath + "restore.zip").delete();
File[] files = new File(cachePath).listFiles();
if (files == null || files.length <= 0) {
handler.post(() -> restoreSettingsListener.failed(context.getString(R.string.restore_settings_failed_file_corrupted)));
} else {
File restoreFilesDir = files[0];
File[] restoreFiles = restoreFilesDir.listFiles();
boolean result = true;
if (restoreFiles != null) {
for (File f : restoreFiles) {
if (f.getName().startsWith(SharedPreferencesUtils.DEFAULT_PREFERENCES_FILE)) {
result = result & importSharedPreferencsFromFile(defaultSharedPreferences, f.toString());
} else if (f.getName().startsWith(CustomThemeSharedPreferencesUtils.LIGHT_THEME_SHARED_PREFERENCES_FILE)) {
result = result & importSharedPreferencsFromFile(lightThemeSharedPreferences, f.toString());
} else if (f.getName().startsWith(CustomThemeSharedPreferencesUtils.DARK_THEME_SHARED_PREFERENCES_FILE)) {
result = result & importSharedPreferencsFromFile(darkThemeSharedPreferences, f.toString());
} else if (f.getName().startsWith(CustomThemeSharedPreferencesUtils.AMOLED_THEME_SHARED_PREFERENCES_FILE)) {
result = result & importSharedPreferencsFromFile(amoledThemeSharedPreferences, f.toString());
} else if (f.getName().startsWith(SharedPreferencesUtils.SORT_TYPE_SHARED_PREFERENCES_FILE)) {
result = result & importSharedPreferencsFromFile(sortTypeSharedPreferences, f.toString());
} else if (f.getName().startsWith(SharedPreferencesUtils.POST_LAYOUT_SHARED_PREFERENCES_FILE)) {
result = result & importSharedPreferencsFromFile(postLayoutSharedPreferences, f.toString());
} else if (f.getName().startsWith(SharedPreferencesUtils.FRONT_PAGE_SCROLLED_POSITION_SHARED_PREFERENCES_FILE)) {
result = result & importSharedPreferencsFromFile(postFeedScrolledPositionSharedPreferences, f.toString());
} else if (f.getName().startsWith(SharedPreferencesUtils.MAIN_PAGE_TABS_SHARED_PREFERENCES_FILE)) {
result = result & importSharedPreferencsFromFile(mainActivityTabsSharedPreferences, f.toString());
} else if (f.getName().startsWith(SharedPreferencesUtils.NSFW_AND_SPOILER_SHARED_PREFERENCES_FILE)) {
result = result & importSharedPreferencsFromFile(nsfwAndSpoilerSharedPreferencs, f.toString());
} else if (f.getName().startsWith(SharedPreferencesUtils.BOTTOM_APP_BAR_SHARED_PREFERENCES_FILE)) {
result = result & importSharedPreferencsFromFile(bottomAppBarSharedPreferences, f.toString());
} else if (f.getName().startsWith(SharedPreferencesUtils.POST_HISTORY_SHARED_PREFERENCES_FILE)) {
result = result & importSharedPreferencsFromFile(postHistorySharedPreferences, f.toString());
}
}
} else {
handler.post(() -> restoreSettingsListener.failed(context.getString(R.string.restore_settings_failed_file_corrupted)));
}
FileUtils.deleteDirectory(new File(cachePath));
if (result) {
handler.post(restoreSettingsListener::success);
} else {
handler.post(() -> restoreSettingsListener.failed(context.getString(R.string.restore_settings_partially_failed)));
}
}
} catch (IOException e) {
e.printStackTrace();
handler.post(() -> restoreSettingsListener.failed(context.getString(R.string.restore_settings_partially_failed)));
}
});
}
private static boolean importSharedPreferencsFromFile(SharedPreferences sharedPreferences, String uriString) {
boolean result = false;
ObjectInputStream input = null;
try {
input = new ObjectInputStream(new FileInputStream(new File(uriString)));
Object object = input.readObject();
if (object instanceof Map) {
Map<String, Object> map = (Map<String, Object>) object;
Set<Map.Entry<String, Object>> entrySet = map.entrySet();
SharedPreferences.Editor editor = sharedPreferences.edit();
for (Map.Entry<String, Object> e : entrySet) {
if (e.getValue() instanceof String) {
editor.putString(e.getKey(), (String) e.getValue());
} else if (e.getValue() instanceof Integer) {
editor.putInt(e.getKey(), (Integer) e.getValue());
} else if (e.getValue() instanceof Float) {
editor.putFloat(e.getKey(), (Float) e.getValue());
} else if (e.getValue() instanceof Boolean) {
editor.putBoolean(e.getKey(), (Boolean) e.getValue());
} else if (e.getValue() instanceof Long) {
editor.putLong(e.getKey(), (Long) e.getValue());
}
}
editor.apply();
result = true;
}
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
if (input != null) {
input.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return result;
}
public interface RestoreSettingsListener {
void success();
void failed(String errorMessage);
}
}

View File

@ -35,6 +35,7 @@ import ml.docilealligator.infinityforreddit.asynctasks.DeleteAllSortTypes;
import ml.docilealligator.infinityforreddit.asynctasks.DeleteAllSubreddits; import ml.docilealligator.infinityforreddit.asynctasks.DeleteAllSubreddits;
import ml.docilealligator.infinityforreddit.asynctasks.DeleteAllThemes; import ml.docilealligator.infinityforreddit.asynctasks.DeleteAllThemes;
import ml.docilealligator.infinityforreddit.asynctasks.DeleteAllUsers; import ml.docilealligator.infinityforreddit.asynctasks.DeleteAllUsers;
import ml.docilealligator.infinityforreddit.asynctasks.RestoreSettings;
import ml.docilealligator.infinityforreddit.events.RecreateActivityEvent; import ml.docilealligator.infinityforreddit.events.RecreateActivityEvent;
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils; import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
@ -47,6 +48,7 @@ import static android.content.Intent.ACTION_OPEN_DOCUMENT_TREE;
public class AdvancedPreferenceFragment extends PreferenceFragmentCompat { public class AdvancedPreferenceFragment extends PreferenceFragmentCompat {
private static final int SELECT_BACKUP_SETTINGS_DIRECTORY_REQUEST_CODE = 1; private static final int SELECT_BACKUP_SETTINGS_DIRECTORY_REQUEST_CODE = 1;
private static final int SELECT_RESTORE_SETTINGS_DIRECTORY_REQUEST_CODE = 2;
@Inject @Inject
RedditDataRoomDatabase mRedditDataRoomDatabase; RedditDataRoomDatabase mRedditDataRoomDatabase;
@Inject @Inject
@ -276,23 +278,6 @@ public class AdvancedPreferenceFragment extends PreferenceFragmentCompat {
Intent intent = new Intent(ACTION_OPEN_DOCUMENT_TREE); Intent intent = new Intent(ACTION_OPEN_DOCUMENT_TREE);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
startActivityForResult(intent, SELECT_BACKUP_SETTINGS_DIRECTORY_REQUEST_CODE); startActivityForResult(intent, SELECT_BACKUP_SETTINGS_DIRECTORY_REQUEST_CODE);
/*BackupSettings.backupSettings(activity, executor, new Handler(), activity.getContentResolver(), null,
mSharedPreferences, lightThemeSharedPreferences, darkThemeSharedPreferences,
amoledThemeSharedPreferences, mSortTypeSharedPreferences, mPostLayoutSharedPreferences,
postFeedScrolledPositionSharedPreferences, mainActivityTabsSharedPreferences,
nsfwAndBlurringSharedPreferences, bottomAppBarSharedPreferences, postHistorySharedPreferences,
new BackupSettings.BackupSettingsListener() {
@Override
public void success() {
}
@Override
public void failed() {
}
});*/
return true; return true;
} }
}); });
@ -302,6 +287,10 @@ public class AdvancedPreferenceFragment extends PreferenceFragmentCompat {
restoreSettingsPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { restoreSettingsPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override @Override
public boolean onPreferenceClick(Preference preference) { public boolean onPreferenceClick(Preference preference) {
Intent chooseFile = new Intent(Intent.ACTION_GET_CONTENT);
chooseFile.setType("application/zip");
chooseFile = Intent.createChooser(chooseFile, "Choose a file");
startActivityForResult(chooseFile, SELECT_RESTORE_SETTINGS_DIRECTORY_REQUEST_CODE);
return true; return true;
} }
}); });
@ -310,24 +299,44 @@ public class AdvancedPreferenceFragment extends PreferenceFragmentCompat {
@Override @Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
if (requestCode == SELECT_BACKUP_SETTINGS_DIRECTORY_REQUEST_CODE && resultCode == RESULT_OK) { if (resultCode == RESULT_OK) {
Uri uri = data.getData(); if (requestCode == SELECT_BACKUP_SETTINGS_DIRECTORY_REQUEST_CODE) {
BackupSettings.backupSettings(activity, executor, new Handler(), activity.getContentResolver(), uri, Uri uri = data.getData();
mSharedPreferences, lightThemeSharedPreferences, darkThemeSharedPreferences, BackupSettings.backupSettings(activity, executor, new Handler(), activity.getContentResolver(), uri,
amoledThemeSharedPreferences, mSortTypeSharedPreferences, mPostLayoutSharedPreferences, mSharedPreferences, lightThemeSharedPreferences, darkThemeSharedPreferences,
postFeedScrolledPositionSharedPreferences, mainActivityTabsSharedPreferences, amoledThemeSharedPreferences, mSortTypeSharedPreferences, mPostLayoutSharedPreferences,
nsfwAndBlurringSharedPreferences, bottomAppBarSharedPreferences, postHistorySharedPreferences, postFeedScrolledPositionSharedPreferences, mainActivityTabsSharedPreferences,
new BackupSettings.BackupSettingsListener() { nsfwAndBlurringSharedPreferences, bottomAppBarSharedPreferences, postHistorySharedPreferences,
@Override new BackupSettings.BackupSettingsListener() {
public void success() { @Override
Toast.makeText(activity, R.string.backup_settings_success, Toast.LENGTH_LONG).show(); public void success() {
} Toast.makeText(activity, R.string.backup_settings_success, Toast.LENGTH_LONG).show();
}
@Override @Override
public void failed(String errorMessage) { public void failed(String errorMessage) {
Toast.makeText(activity, errorMessage, Toast.LENGTH_LONG).show(); Toast.makeText(activity, errorMessage, Toast.LENGTH_LONG).show();
} }
}); });
} else if (requestCode == SELECT_RESTORE_SETTINGS_DIRECTORY_REQUEST_CODE) {
Uri uri = data.getData();
RestoreSettings.restoreSettings(activity, executor, new Handler(), activity.getContentResolver(), uri,
mSharedPreferences, lightThemeSharedPreferences, darkThemeSharedPreferences,
amoledThemeSharedPreferences, mSortTypeSharedPreferences, mPostLayoutSharedPreferences,
postFeedScrolledPositionSharedPreferences, mainActivityTabsSharedPreferences,
nsfwAndBlurringSharedPreferences, bottomAppBarSharedPreferences, postHistorySharedPreferences,
new RestoreSettings.RestoreSettingsListener() {
@Override
public void success() {
Toast.makeText(activity, R.string.restore_settings_success, Toast.LENGTH_LONG).show();
}
@Override
public void failed(String errorMessage) {
Toast.makeText(activity, errorMessage, Toast.LENGTH_LONG).show();
}
});
}
} }
} }

View File

@ -1042,5 +1042,9 @@
<string name="backup_settings_success">Successfully exported settings to the destination directory</string> <string name="backup_settings_success">Successfully exported settings to the destination directory</string>
<string name="create_zip_in_destination_directory_failed">Could not create backup zip in the destination directory</string> <string name="create_zip_in_destination_directory_failed">Could not create backup zip in the destination directory</string>
<string name="backup_some_settings_failed">Could not backup some settings but others were successfully exported to the destination directory</string> <string name="backup_some_settings_failed">Could not backup some settings but others were successfully exported to the destination directory</string>
<string name="restore_settings_success">Successfully restored settings. Restart the app to see the changes.</string>
<string name="restore_settings_partially_failed">Some settings may not be restored successfully. Restart the app to see the changes.</string>
<string name="restore_settings_failed_file_corrupted">Cannot restore settings. The file may be corrupted.</string>
<string name="restore_settings_failed_cannot_get_file">Cannot access the file</string>
</resources> </resources>