mirror of
https://github.com/yuliskov/SmartTube.git
synced 2026-03-13 15:20:26 +08:00
BackupManager: create backup zip on api < 30
This commit is contained in:
@@ -17,18 +17,20 @@ import com.liskovsoft.smartyoutubetv2.common.app.presenters.settings.BackupSetti
|
||||
import com.liskovsoft.smartyoutubetv2.common.misc.MotherActivity.OnResult;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
public class BackupAndRestoreHelper implements OnResult {
|
||||
private static final int REQ_PICK_FILES = 1001;
|
||||
private final Context mContext;
|
||||
private Runnable mOnSuccess;
|
||||
private final String[] mBackupPatterns = new String[] {
|
||||
"yt_service_prefs.xml",
|
||||
"com.liskovsoft.appupdatechecker2.preferences.xml",
|
||||
"com.liskovsoft.sharedutils.prefs.GlobalPreferences.xml",
|
||||
"_preferences.xml" // before _ should be the app package name
|
||||
};
|
||||
|
||||
public BackupAndRestoreHelper(Context context) {
|
||||
mContext = context;
|
||||
@@ -44,7 +46,7 @@ public class BackupAndRestoreHelper implements OnResult {
|
||||
if (!dataDir.exists()) return;
|
||||
|
||||
File zipFile = new File(mediaDir, "backup_" + mContext.getPackageName() + ".zip");
|
||||
zipDirectory(dataDir, zipFile);
|
||||
ZipHelper2.zipDirectory(dataDir, zipFile);
|
||||
|
||||
Uri uri = FileProvider.getUriForFile(
|
||||
mContext,
|
||||
@@ -99,7 +101,7 @@ public class BackupAndRestoreHelper implements OnResult {
|
||||
deleteRecursive(dataDir);
|
||||
dataDir.mkdirs();
|
||||
|
||||
unzip(zipFile, mediaDir);
|
||||
ZipHelper2.unzip(zipFile, mediaDir);
|
||||
|
||||
zipFile.delete();
|
||||
|
||||
@@ -129,11 +131,11 @@ public class BackupAndRestoreHelper implements OnResult {
|
||||
copyUriToFile(zipUri, tempZip);
|
||||
|
||||
// Unpack ZIP with data folder
|
||||
unzip(tempZip, mediaDir);
|
||||
ZipHelper2.unzip(tempZip, mediaDir);
|
||||
|
||||
if (FileHelpers.isEmpty(dataDir)) {
|
||||
// Seems we've packed the contents of the data dir not data itself
|
||||
unzip(tempZip, dataDir);
|
||||
ZipHelper2.unzip(tempZip, dataDir);
|
||||
}
|
||||
|
||||
// Delete the temporary ZIP
|
||||
@@ -150,6 +152,10 @@ public class BackupAndRestoreHelper implements OnResult {
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getBackupPatterns() {
|
||||
return mBackupPatterns;
|
||||
}
|
||||
|
||||
private void copyUriToDir(Uri uri, File targetDir) {
|
||||
try {
|
||||
String fileName = getFileName(uri);
|
||||
@@ -222,56 +228,6 @@ public class BackupAndRestoreHelper implements OnResult {
|
||||
return result;
|
||||
}
|
||||
|
||||
private void zipDirectory(File sourceDir, File zipFile) {
|
||||
try {
|
||||
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile));
|
||||
zipFileRecursive(zos, sourceDir, "data/");
|
||||
zos.close();
|
||||
} catch (Exception e) { e.printStackTrace(); }
|
||||
}
|
||||
|
||||
private void zipFileRecursive(ZipOutputStream zos, File file, String base) throws Exception {
|
||||
if (file.isDirectory()) {
|
||||
File[] children = file.listFiles();
|
||||
if (children != null) {
|
||||
for (File child : children) {
|
||||
zipFileRecursive(zos, child, base + child.getName() + "/");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
FileInputStream fis = new FileInputStream(file);
|
||||
zos.putNextEntry(new ZipEntry(base.substring(0, base.length() -1))); // strip "/" at the end to mark as file
|
||||
byte[] buf = new byte[8192];
|
||||
int len;
|
||||
while ((len = fis.read(buf)) > 0) zos.write(buf, 0, len);
|
||||
fis.close();
|
||||
zos.closeEntry();
|
||||
}
|
||||
}
|
||||
|
||||
private void unzip(File zipFile, File targetRoot) {
|
||||
try {
|
||||
ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile));
|
||||
ZipEntry entry;
|
||||
byte[] buffer = new byte[8192];
|
||||
|
||||
while ((entry = zis.getNextEntry()) != null) {
|
||||
File out = new File(targetRoot, entry.getName());
|
||||
if (entry.isDirectory()) {
|
||||
out.mkdirs();
|
||||
} else {
|
||||
out.getParentFile().mkdirs();
|
||||
FileOutputStream fos = new FileOutputStream(out);
|
||||
int len;
|
||||
while ((len = zis.read(buffer)) > 0) fos.write(buffer, 0, len);
|
||||
fos.close();
|
||||
}
|
||||
zis.closeEntry();
|
||||
}
|
||||
zis.close();
|
||||
} catch (Exception e) { e.printStackTrace(); }
|
||||
}
|
||||
|
||||
private void deleteRecursive(File f) {
|
||||
if (!f.exists()) return;
|
||||
if (f.isDirectory()) {
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.liskovsoft.sharedutils.helpers.Helpers;
|
||||
import com.liskovsoft.sharedutils.helpers.MessageHelpers;
|
||||
import com.liskovsoft.sharedutils.helpers.PermissionHelpers;
|
||||
import com.liskovsoft.sharedutils.mylogger.Log;
|
||||
import com.liskovsoft.sharedutils.rx.RxHelper;
|
||||
import com.liskovsoft.smartyoutubetv2.common.R;
|
||||
import com.liskovsoft.smartyoutubetv2.common.prefs.HiddenPrefs;
|
||||
|
||||
@@ -20,6 +21,8 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import io.reactivex.disposables.Disposable;
|
||||
|
||||
public class BackupAndRestoreManager implements MotherActivity.OnPermissions {
|
||||
private static final String TAG = BackupAndRestoreManager.class.getSimpleName();
|
||||
private static final String BACKUP_DIR_NAME = "Backup";
|
||||
@@ -29,13 +32,8 @@ public class BackupAndRestoreManager implements MotherActivity.OnPermissions {
|
||||
private final List<File> mBackupDirs;
|
||||
private final BackupAndRestoreHelper mHelper;
|
||||
private final boolean mForceApi30;
|
||||
private final String[] mBackupPatterns = new String[] {
|
||||
"yt_service_prefs.xml",
|
||||
"com.liskovsoft.appupdatechecker2.preferences.xml",
|
||||
"com.liskovsoft.sharedutils.prefs.GlobalPreferences.xml",
|
||||
"_preferences.xml" // before _ should be the app package name
|
||||
};
|
||||
private Runnable mPendingHandler;
|
||||
private Disposable mZipAction;
|
||||
|
||||
public interface OnBackupNames {
|
||||
void onBackupNames(List<String> backupNames);
|
||||
@@ -90,7 +88,6 @@ public class BackupAndRestoreManager implements MotherActivity.OnPermissions {
|
||||
return new File(appDir, BACKUP_DIR_NAME);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private File getExternalStorageDirectory() {
|
||||
File result;
|
||||
|
||||
@@ -158,7 +155,7 @@ public class BackupAndRestoreManager implements MotherActivity.OnPermissions {
|
||||
|
||||
if (mDataDir.isDirectory() && !FileHelpers.isEmpty(mDataDir)) {
|
||||
File destination = new File(currentBackup, mDataDir.getName());
|
||||
FileHelpers.copy(mDataDir, destination, fileName -> Helpers.endsWithAny(fileName.toString(), mBackupPatterns));
|
||||
FileHelpers.copy(mDataDir, destination, fileName -> Helpers.endsWithAny(fileName.toString(), mHelper.getBackupPatterns()));
|
||||
|
||||
// Don't store unique id
|
||||
FileHelpers.delete(new File(destination, HiddenPrefs.SHARED_PREFERENCES_NAME + ".xml"));
|
||||
@@ -166,6 +163,9 @@ public class BackupAndRestoreManager implements MotherActivity.OnPermissions {
|
||||
|
||||
if (hasAccessOnlyToAppFolders()) {
|
||||
mHelper.exportAppMediaFolder();
|
||||
} else {
|
||||
RxHelper.disposeActions(mZipAction);
|
||||
mZipAction = RxHelper.runAsync(this::saveDataToZip);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ public class BackupAndRestoreManager implements MotherActivity.OnPermissions {
|
||||
FileHelpers.delete(mDataDir);
|
||||
}
|
||||
|
||||
FileHelpers.copy(sourceBackupDir, mDataDir, fileName -> Helpers.endsWithAny(fileName.toString(), mBackupPatterns));
|
||||
FileHelpers.copy(sourceBackupDir, mDataDir, fileName -> Helpers.endsWithAny(fileName.toString(), mHelper.getBackupPatterns()));
|
||||
fixFileNames(mDataDir);
|
||||
|
||||
MessageHelpers.showMessage(mContext, R.string.msg_done);
|
||||
@@ -342,4 +342,13 @@ public class BackupAndRestoreManager implements MotherActivity.OnPermissions {
|
||||
private boolean hasAccessOnlyToAppFolders() {
|
||||
return AppInfoHelpers.getTargetSdkVersion(mContext) > 29 || mForceApi30;
|
||||
}
|
||||
|
||||
private void saveDataToZip() {
|
||||
File mediaDir = getExternalStorageDirectory();
|
||||
File dataDir = new File(mediaDir, "data");
|
||||
if (dataDir.exists()) {
|
||||
File zipFile = new File(mediaDir, "SmartTubeBackup.zip");
|
||||
ZipHelper2.zipDirectory(dataDir, zipFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,13 +39,13 @@ public class GDriveBackupManager {
|
||||
private static final String SHARED_PREFS_SUBDIR = "shared_prefs";
|
||||
private static final String BACKUP_NAME = "backup.zip";
|
||||
private final GoogleSignInService mSignInService;
|
||||
private final BackupAndRestoreHelper mHelper;
|
||||
private final String mDataDir;
|
||||
private final String mBackupDir;
|
||||
private final String mRootBackupDir;
|
||||
private final GeneralData mGeneralData;
|
||||
private Disposable mBackupAction;
|
||||
private Disposable mRestoreAction;
|
||||
private final String[] mBackupNames;
|
||||
private boolean mIsBlocking;
|
||||
|
||||
private GDriveBackupManager(Context context) {
|
||||
@@ -55,12 +55,7 @@ public class GDriveBackupManager {
|
||||
mBackupDir = String.format("SmartTubeBackup/%s", context.getPackageName());
|
||||
mRootBackupDir = "SmartTubeBackup";
|
||||
mSignInService = GoogleSignInService.instance();
|
||||
mBackupNames = new String[] {
|
||||
"yt_service_prefs.xml",
|
||||
"com.liskovsoft.appupdatechecker2.preferences.xml",
|
||||
"com.liskovsoft.sharedutils.prefs.GlobalPreferences.xml",
|
||||
"_preferences.xml" // before _ should be the app package name
|
||||
};
|
||||
mHelper = new BackupAndRestoreHelper(context);
|
||||
}
|
||||
|
||||
public static GDriveBackupManager instance(Context context) {
|
||||
@@ -156,7 +151,7 @@ public class GDriveBackupManager {
|
||||
private void startBackup(String backupDir, String dataDir) {
|
||||
File source = new File(dataDir);
|
||||
File zipFile = new File(mContext.getCacheDir(), BACKUP_NAME);
|
||||
ZipHelper.zipFolder(source, zipFile, mBackupNames);
|
||||
ZipHelper.zipFolder(source, zipFile, mHelper.getBackupPatterns());
|
||||
|
||||
Observable<Void> uploadFile = DriveService.uploadFile(zipFile, Uri.parse(String.format("%s/%s", backupDir, BACKUP_NAME)));
|
||||
|
||||
@@ -249,7 +244,7 @@ public class GDriveBackupManager {
|
||||
}
|
||||
|
||||
private boolean checkFileName(String name) {
|
||||
return Helpers.endsWithAny(name, mBackupNames);
|
||||
return Helpers.endsWithAny(name, mHelper.getBackupPatterns());
|
||||
}
|
||||
|
||||
private String fixAltPackageName(String name) {
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.liskovsoft.smartyoutubetv2.common.misc;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
public class ZipHelper2 {
|
||||
public static void zipDirectory(File sourceDir, File zipFile) {
|
||||
try {
|
||||
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile));
|
||||
zipFileRecursive(zos, sourceDir, sourceDir.getName() + "/");
|
||||
zos.close();
|
||||
} catch (Exception e) { e.printStackTrace(); }
|
||||
}
|
||||
|
||||
private static void zipFileRecursive(ZipOutputStream zos, File file, String base) throws Exception {
|
||||
if (file.isDirectory()) {
|
||||
File[] children = file.listFiles();
|
||||
if (children != null) {
|
||||
for (File child : children) {
|
||||
zipFileRecursive(zos, child, base + child.getName() + "/");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
FileInputStream fis = new FileInputStream(file);
|
||||
zos.putNextEntry(new ZipEntry(base.substring(0, base.length() -1))); // strip "/" at the end to mark as file
|
||||
byte[] buf = new byte[8192];
|
||||
int len;
|
||||
while ((len = fis.read(buf)) > 0) zos.write(buf, 0, len);
|
||||
fis.close();
|
||||
zos.closeEntry();
|
||||
}
|
||||
}
|
||||
|
||||
public static void unzip(File zipFile, File targetRoot) {
|
||||
try {
|
||||
ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile));
|
||||
ZipEntry entry;
|
||||
byte[] buffer = new byte[8192];
|
||||
|
||||
while ((entry = zis.getNextEntry()) != null) {
|
||||
File out = new File(targetRoot, entry.getName());
|
||||
if (entry.isDirectory()) {
|
||||
out.mkdirs();
|
||||
} else {
|
||||
out.getParentFile().mkdirs();
|
||||
FileOutputStream fos = new FileOutputStream(out);
|
||||
int len;
|
||||
while ((len = zis.read(buffer)) > 0) fos.write(buffer, 0, len);
|
||||
fos.close();
|
||||
}
|
||||
zis.closeEntry();
|
||||
}
|
||||
zis.close();
|
||||
} catch (Exception e) { e.printStackTrace(); }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user