mirror of
https://codeberg.org/Bazsalanszky/Infinity-For-Lemmy.git
synced 2024-12-28 11:58:23 +01:00
Backup settings.
This commit is contained in:
parent
2ef72bc798
commit
65e654a23c
@ -170,6 +170,9 @@ dependencies {
|
||||
// Crash screen
|
||||
implementation 'com.melegy.redscreenofdeath:red-screen-of-death:0.1.2'
|
||||
|
||||
implementation 'net.lingala.zip4j:zip4j:2.7.0'
|
||||
implementation 'org.apache.commons:commons-io:1.3.2'
|
||||
|
||||
|
||||
/**** Builds and flavors ****/
|
||||
// debugImplementation because LeakCanary should only run in debug builds.
|
||||
|
@ -0,0 +1,191 @@
|
||||
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 androidx.documentfile.provider.DocumentFile;
|
||||
|
||||
import net.lingala.zip4j.ZipFile;
|
||||
import net.lingala.zip4j.model.ZipParameters;
|
||||
import net.lingala.zip4j.model.enums.EncryptionMethod;
|
||||
|
||||
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.ObjectOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import ml.docilealligator.infinityforreddit.BuildConfig;
|
||||
import ml.docilealligator.infinityforreddit.R;
|
||||
import ml.docilealligator.infinityforreddit.utils.CustomThemeSharedPreferencesUtils;
|
||||
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
|
||||
|
||||
public class BackupSettings {
|
||||
public static void backupSettings(Context context, Executor executor, Handler handler,
|
||||
ContentResolver contentResolver, Uri destinationDirUri,
|
||||
SharedPreferences defaultSharedPreferences,
|
||||
SharedPreferences lightThemeSharedPreferences,
|
||||
SharedPreferences darkThemeSharedPreferences,
|
||||
SharedPreferences amoledThemeSharedPreferences,
|
||||
SharedPreferences sortTypeSharedPreferences,
|
||||
SharedPreferences postLayoutSharedPreferences,
|
||||
SharedPreferences postFeedScrolledPositionSharedPreferences,
|
||||
SharedPreferences mainActivityTabsSharedPreferences,
|
||||
SharedPreferences nsfwAndSpoilerSharedPreferencs,
|
||||
SharedPreferences bottomAppBarSharedPreferences,
|
||||
SharedPreferences postHistorySharedPreferences,
|
||||
BackupSettingsListener backupSettingsListener) {
|
||||
executor.execute(() -> {
|
||||
boolean res = saveSharedPreferencesToFile(context, defaultSharedPreferences,
|
||||
SharedPreferencesUtils.DEFAULT_PREFERENCES_FILE);
|
||||
boolean res1 = saveSharedPreferencesToFile(context, lightThemeSharedPreferences,
|
||||
CustomThemeSharedPreferencesUtils.LIGHT_THEME_SHARED_PREFERENCES_FILE);
|
||||
boolean res2 = saveSharedPreferencesToFile(context, darkThemeSharedPreferences,
|
||||
CustomThemeSharedPreferencesUtils.DARK_THEME_SHARED_PREFERENCES_FILE);
|
||||
boolean res3 = saveSharedPreferencesToFile(context, amoledThemeSharedPreferences,
|
||||
CustomThemeSharedPreferencesUtils.AMOLED_THEME_SHARED_PREFERENCES_FILE);
|
||||
boolean res4 = saveSharedPreferencesToFile(context, sortTypeSharedPreferences,
|
||||
SharedPreferencesUtils.SORT_TYPE_SHARED_PREFERENCES_FILE);
|
||||
boolean res5 = saveSharedPreferencesToFile(context, postLayoutSharedPreferences,
|
||||
SharedPreferencesUtils.POST_LAYOUT_SHARED_PREFERENCES_FILE);
|
||||
boolean res6 = saveSharedPreferencesToFile(context, postFeedScrolledPositionSharedPreferences,
|
||||
SharedPreferencesUtils.FRONT_PAGE_SCROLLED_POSITION_SHARED_PREFERENCES_FILE);
|
||||
boolean res7 = saveSharedPreferencesToFile(context, mainActivityTabsSharedPreferences,
|
||||
SharedPreferencesUtils.MAIN_PAGE_TABS_SHARED_PREFERENCES_FILE);
|
||||
boolean res8 = saveSharedPreferencesToFile(context, nsfwAndSpoilerSharedPreferencs,
|
||||
SharedPreferencesUtils.NSFW_AND_SPOILER_SHARED_PREFERENCES_FILE);
|
||||
boolean res9 = saveSharedPreferencesToFile(context, bottomAppBarSharedPreferences,
|
||||
SharedPreferencesUtils.BOTTOM_APP_BAR_SHARED_PREFERENCES_FILE);
|
||||
boolean res10 = saveSharedPreferencesToFile(context, postHistorySharedPreferences,
|
||||
SharedPreferencesUtils.POST_HISTORY_SHARED_PREFERENCES_FILE);
|
||||
|
||||
boolean zipRes = zipAndMoveToDestinationDir(context, contentResolver, destinationDirUri);
|
||||
|
||||
try {
|
||||
FileUtils.deleteDirectory(new File(context.getExternalCacheDir() + "/Backup/"));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
handler.post(() -> {
|
||||
boolean finalResult = res && res1 && res2 && res3 && res4 && res5 && res6 && res7 && res8 && res9 && res10 && zipRes;
|
||||
if (finalResult) {
|
||||
backupSettingsListener.success();
|
||||
} else {
|
||||
if (!zipRes) {
|
||||
backupSettingsListener.failed(context.getText(R.string.create_zip_in_destination_directory_failed).toString());
|
||||
} else {
|
||||
backupSettingsListener.failed(context.getText(R.string.backup_some_settings_failed).toString());
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private static boolean saveSharedPreferencesToFile(Context context, SharedPreferences sharedPreferences,
|
||||
String fileName) {
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
try {
|
||||
output = new ObjectOutputStream(new FileOutputStream(new File(backupDir + "/" + fileName + ".txt")));
|
||||
output.writeObject(sharedPreferences.getAll());
|
||||
|
||||
result = true;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
if (output != null) {
|
||||
output.flush();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean zipAndMoveToDestinationDir(Context context, ContentResolver contentResolver, Uri destinationDirUri) {
|
||||
OutputStream outputStream = null;
|
||||
boolean result = false;
|
||||
try {
|
||||
String time = new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date(System.currentTimeMillis()));
|
||||
String fileName = "Infinity_For_Reddit_Settings_Backup_v" + BuildConfig.VERSION_NAME + "-" + time + ".zip";
|
||||
String filePath = context.getExternalCacheDir() + "/Backup/" + fileName;
|
||||
ZipFile zip = new ZipFile(filePath, "123321".toCharArray());
|
||||
ZipParameters zipParameters = new ZipParameters();
|
||||
zipParameters.setEncryptFiles(true);
|
||||
zipParameters.setEncryptionMethod(EncryptionMethod.AES);
|
||||
zip.addFolder(new File(context.getExternalCacheDir() + "/Backup/" + BuildConfig.VERSION_NAME + "/"), zipParameters);
|
||||
|
||||
DocumentFile dir = DocumentFile.fromTreeUri(context, destinationDirUri);
|
||||
if (dir == null) {
|
||||
return false;
|
||||
}
|
||||
DocumentFile checkForDuplicate = dir.findFile(fileName);
|
||||
if (checkForDuplicate != null) {
|
||||
checkForDuplicate.delete();
|
||||
}
|
||||
DocumentFile destinationFile = dir.createFile("application/zip", fileName);
|
||||
if (destinationFile == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
outputStream = contentResolver.openOutputStream(destinationFile.getUri());
|
||||
if (outputStream == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
byte[] fileReader = new byte[1024];
|
||||
|
||||
FileInputStream inputStream = new FileInputStream(filePath);
|
||||
while (true) {
|
||||
int read = inputStream.read(fileReader);
|
||||
|
||||
if (read == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
outputStream.write(fileReader, 0, read);
|
||||
}
|
||||
result = true;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
} finally {
|
||||
if (outputStream != null) {
|
||||
try {
|
||||
outputStream.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public interface BackupSettingsListener {
|
||||
void success();
|
||||
void failed(String errorMessage);
|
||||
}
|
||||
}
|
@ -2,12 +2,15 @@ package ml.docilealligator.infinityforreddit.settings;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.preference.Preference;
|
||||
@ -25,6 +28,7 @@ import javax.inject.Named;
|
||||
import ml.docilealligator.infinityforreddit.Infinity;
|
||||
import ml.docilealligator.infinityforreddit.R;
|
||||
import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase;
|
||||
import ml.docilealligator.infinityforreddit.asynctasks.BackupSettings;
|
||||
import ml.docilealligator.infinityforreddit.asynctasks.DeleteAllPostLayouts;
|
||||
import ml.docilealligator.infinityforreddit.asynctasks.DeleteAllReadPosts;
|
||||
import ml.docilealligator.infinityforreddit.asynctasks.DeleteAllSortTypes;
|
||||
@ -34,11 +38,15 @@ import ml.docilealligator.infinityforreddit.asynctasks.DeleteAllUsers;
|
||||
import ml.docilealligator.infinityforreddit.events.RecreateActivityEvent;
|
||||
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
|
||||
|
||||
import static android.app.Activity.RESULT_OK;
|
||||
import static android.content.Intent.ACTION_OPEN_DOCUMENT_TREE;
|
||||
|
||||
/**
|
||||
* A simple {@link Fragment} subclass.
|
||||
*/
|
||||
public class AdvancedPreferenceFragment extends PreferenceFragmentCompat {
|
||||
|
||||
private static final int SELECT_BACKUP_SETTINGS_DIRECTORY_REQUEST_CODE = 1;
|
||||
@Inject
|
||||
RedditDataRoomDatabase mRedditDataRoomDatabase;
|
||||
@Inject
|
||||
@ -69,6 +77,12 @@ public class AdvancedPreferenceFragment extends PreferenceFragmentCompat {
|
||||
@Named("nsfw_and_spoiler")
|
||||
SharedPreferences nsfwAndBlurringSharedPreferences;
|
||||
@Inject
|
||||
@Named("bottom_app_bar")
|
||||
SharedPreferences bottomAppBarSharedPreferences;
|
||||
@Inject
|
||||
@Named("post_history")
|
||||
SharedPreferences postHistorySharedPreferences;
|
||||
@Inject
|
||||
Executor executor;
|
||||
private Activity activity;
|
||||
|
||||
@ -87,6 +101,8 @@ public class AdvancedPreferenceFragment extends PreferenceFragmentCompat {
|
||||
Preference deleteReadPostsPreference = findPreference(SharedPreferencesUtils.DELETE_READ_POSTS_IN_DATABASE);
|
||||
Preference deleteAllLegacySettingsPreference = findPreference(SharedPreferencesUtils.DELETE_ALL_LEGACY_SETTINGS);
|
||||
Preference resetAllSettingsPreference = findPreference(SharedPreferencesUtils.RESET_ALL_SETTINGS);
|
||||
Preference backupSettingsPreference = findPreference(SharedPreferencesUtils.BACKUP_SETTINGS);
|
||||
Preference restoreSettingsPreference = findPreference(SharedPreferencesUtils.RESTORE_SETTINGS);
|
||||
|
||||
if (deleteSubredditsPreference != null) {
|
||||
deleteSubredditsPreference.setOnPreferenceClickListener(preference -> {
|
||||
@ -252,6 +268,67 @@ public class AdvancedPreferenceFragment extends PreferenceFragmentCompat {
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
if (backupSettingsPreference != null) {
|
||||
backupSettingsPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
Intent intent = new Intent(ACTION_OPEN_DOCUMENT_TREE);
|
||||
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||
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;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (restoreSettingsPreference != null) {
|
||||
restoreSettingsPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
||||
if (requestCode == SELECT_BACKUP_SETTINGS_DIRECTORY_REQUEST_CODE && resultCode == RESULT_OK) {
|
||||
Uri uri = data.getData();
|
||||
BackupSettings.backupSettings(activity, executor, new Handler(), activity.getContentResolver(), uri,
|
||||
mSharedPreferences, lightThemeSharedPreferences, darkThemeSharedPreferences,
|
||||
amoledThemeSharedPreferences, mSortTypeSharedPreferences, mPostLayoutSharedPreferences,
|
||||
postFeedScrolledPositionSharedPreferences, mainActivityTabsSharedPreferences,
|
||||
nsfwAndBlurringSharedPreferences, bottomAppBarSharedPreferences, postHistorySharedPreferences,
|
||||
new BackupSettings.BackupSettingsListener() {
|
||||
@Override
|
||||
public void success() {
|
||||
Toast.makeText(activity, R.string.backup_settings_success, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(String errorMessage) {
|
||||
Toast.makeText(activity, errorMessage, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -169,7 +169,10 @@ public class SharedPreferencesUtils {
|
||||
public static final String HIDE_SUBREDDIT_AND_USER_PREFIX = "hide_subreddit_and_user_prefix";
|
||||
public static final String HIDE_THE_NUMBER_OF_VOTES = "hide_the_number_of_votes";
|
||||
public static final String HIDE_THE_NUMBER_OF_COMMENTS = "hide_the_number_of_comments";
|
||||
public static final String BACKUP_SETTINGS = "backup_settings";
|
||||
public static final String RESTORE_SETTINGS = "restore_settings";
|
||||
|
||||
public static final String DEFAULT_PREFERENCES_FILE = "ml.docilealligator.infinityforreddit_preferences";
|
||||
public static final String MAIN_PAGE_TABS_SHARED_PREFERENCES_FILE = "ml.docilealligator.infinityforreddit.main_page_tabs";
|
||||
public static final String MAIN_PAGE_TAB_COUNT = "_main_page_tab_count";
|
||||
public static final String MAIN_PAGE_SHOW_TAB_NAMES = "_main_page_show_tab_names";
|
||||
|
@ -541,6 +541,8 @@
|
||||
<string name="settings_hide_the_number_of_votes">Hide the Number of Votes</string>
|
||||
<string name="settings_hide_the_number_of_comments">Hide the Number of Comments</string>
|
||||
<string name="settings_show_avatar_on_the_right_in_the_navigation_drawer">Show Avatar on the Left in the Navigation Drawer</string>
|
||||
<string name="settings_backup_settings_title">Backup Settings</string>
|
||||
<string name="settings_restore_settings_title">Restore Settings</string>
|
||||
|
||||
<string name="no_link_available">Cannot get the link</string>
|
||||
|
||||
@ -1037,4 +1039,8 @@
|
||||
|
||||
<string name="anonymous_front_page_no_subscriptions">Start by joining a subreddit!</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="backup_some_settings_failed">Could not backup some settings but others were successfully exported to the destination directory</string>
|
||||
|
||||
</resources>
|
||||
|
@ -38,6 +38,14 @@
|
||||
app:key="reset_all_settings"
|
||||
app:title="@string/settings_reset_all_settings_title" />
|
||||
|
||||
<Preference
|
||||
app:key="backup_settings"
|
||||
app:title="@string/settings_backup_settings_title" />
|
||||
|
||||
<Preference
|
||||
app:key="restore_settings"
|
||||
app:title="@string/settings_restore_settings_title" />
|
||||
|
||||
<Preference
|
||||
android:icon="@drawable/ic_info_preference_24dp"
|
||||
app:summary="@string/settings_advanced_settings_summary"
|
||||
|
Loading…
Reference in New Issue
Block a user