refactor: 优化备份逻辑
使用 GPT-4o
This commit is contained in:
parent
b06bea2cbe
commit
23143e4265
2 changed files with 37 additions and 47 deletions
|
|
@ -34,7 +34,7 @@ android {
|
||||||
applicationId = "cn.super12138.todo"
|
applicationId = "cn.super12138.todo"
|
||||||
minSdk = 24
|
minSdk = 24
|
||||||
targetSdk = 36
|
targetSdk = 36
|
||||||
versionCode = 611
|
versionCode = 617
|
||||||
versionName = "2.1.2"
|
versionName = "2.1.2"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|
|
||||||
|
|
@ -179,68 +179,58 @@ class MainViewModel : ViewModel() {
|
||||||
|
|
||||||
fun backupAppData(uri: Uri, context: Context, onResult: (completed: Boolean) -> Unit) {
|
fun backupAppData(uri: Uri, context: Context, onResult: (completed: Boolean) -> Unit) {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
try {
|
val result = runCatching {
|
||||||
// 获取数据库文件路径
|
|
||||||
val dbPath = TodoApp.db.openHelper.writableDatabase.path
|
|
||||||
val prefPath = "${context.filesDir.parent}/shared_prefs"
|
|
||||||
// 开启输出文件流,输出位置为用户选取的文件夹URI
|
|
||||||
context.contentResolver.openOutputStream(uri)?.use { outputStream ->
|
context.contentResolver.openOutputStream(uri)?.use { outputStream ->
|
||||||
ZipOutputStream(BufferedOutputStream(outputStream)).use { zipOutStream ->
|
ZipOutputStream(BufferedOutputStream(outputStream)).use { zipOutStream ->
|
||||||
listOf(
|
getBackupFiles(context).forEach { file ->
|
||||||
context.getDatabasePath(Constants.DB_NAME), // 数据库
|
|
||||||
File("$dbPath-wal"), // 数据库-wal
|
|
||||||
File("$dbPath-shm"), // 数据库-shm
|
|
||||||
File("$prefPath/${Constants.SP_NAME}.xml") // SharedPreferences
|
|
||||||
).filter { it.exists() }.forEach { file ->
|
|
||||||
FileUtils.addFileToZip(file, file.name, zipOutStream)
|
FileUtils.addFileToZip(file, file.name, zipOutStream)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 执行成功的回调
|
}.isSuccess
|
||||||
withContext(Dispatchers.Main) { onResult(true) }
|
withContext(Dispatchers.Main) { onResult(result) }
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
// 执行失败的回调
|
|
||||||
withContext(Dispatchers.Main) { onResult(false) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun restoreAppData(uri: Uri, context: Context, onResult: (completed: Boolean) -> Unit) {
|
fun restoreAppData(uri: Uri, context: Context, onResult: (completed: Boolean) -> Unit) {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
try {
|
val result = runCatching {
|
||||||
// 获取数据库文件夹
|
|
||||||
val dbPath = context.getDatabasePath(Constants.DB_NAME).parent
|
|
||||||
val prefPath = "${context.filesDir.parent}/shared_prefs/"
|
|
||||||
// 开启输入文件流,输入位置为用户选取的文件URI
|
|
||||||
context.contentResolver.openInputStream(uri)?.use { inputStream ->
|
context.contentResolver.openInputStream(uri)?.use { inputStream ->
|
||||||
ZipInputStream(BufferedInputStream(inputStream)).use { zipInputStream ->
|
ZipInputStream(BufferedInputStream(inputStream)).use { zipInputStream ->
|
||||||
generateSequence { zipInputStream.nextEntry }.forEach { zipEntry ->
|
extractZipEntries(zipInputStream, context)
|
||||||
// 判断是否为 SharedPreferences 设置文件
|
|
||||||
val outputFile = if (zipEntry.name.endsWith(".xml")) {
|
|
||||||
File(prefPath, zipEntry.name)
|
|
||||||
} else {
|
|
||||||
File(dbPath, zipEntry.name)
|
|
||||||
}
|
|
||||||
// 输出文件
|
|
||||||
if (zipEntry.isDirectory) {
|
|
||||||
// 如果是文件夹则创建文件夹
|
|
||||||
outputFile.mkdirs()
|
|
||||||
} else {
|
|
||||||
// 父文件夹为空就创建父文件夹
|
|
||||||
outputFile.parentFile?.mkdirs()
|
|
||||||
// 输出文件
|
|
||||||
FileOutputStream(outputFile).use { zipInputStream.copyTo(it) }
|
|
||||||
}
|
|
||||||
zipInputStream.closeEntry()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
withContext(Dispatchers.Main) { onResult(true) }
|
}.isSuccess
|
||||||
} catch (e: Exception) {
|
withContext(Dispatchers.Main) { onResult(result) }
|
||||||
e.printStackTrace()
|
}
|
||||||
withContext(Dispatchers.Main) { onResult(false) }
|
}
|
||||||
|
|
||||||
|
private fun getBackupFiles(context: Context): List<File> {
|
||||||
|
val dbPath = TodoApp.db.openHelper.writableDatabase.path
|
||||||
|
val prefPath = "${context.filesDir.parent}/shared_prefs"
|
||||||
|
return listOf(
|
||||||
|
context.getDatabasePath(Constants.DB_NAME), // 数据库
|
||||||
|
File("$dbPath-wal"), // 数据库-wal
|
||||||
|
File("$dbPath-shm"), // 数据库-shm
|
||||||
|
File("$prefPath/${Constants.SP_NAME}.xml") // SharedPreferences
|
||||||
|
).filter { it.exists() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun extractZipEntries(zipInputStream: ZipInputStream, context: Context) {
|
||||||
|
val dbPath = context.getDatabasePath(Constants.DB_NAME).parent
|
||||||
|
val prefPath = "${context.filesDir.parent}/shared_prefs/"
|
||||||
|
generateSequence { zipInputStream.nextEntry }.forEach { zipEntry ->
|
||||||
|
val outputFile = File(
|
||||||
|
if (zipEntry.name.endsWith(".xml")) prefPath else dbPath,
|
||||||
|
zipEntry.name
|
||||||
|
)
|
||||||
|
if (zipEntry.isDirectory) {
|
||||||
|
outputFile.mkdirs()
|
||||||
|
} else {
|
||||||
|
outputFile.parentFile?.mkdirs()
|
||||||
|
FileOutputStream(outputFile).use { zipInputStream.copyTo(it) }
|
||||||
}
|
}
|
||||||
|
zipInputStream.closeEntry()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue