优化
This commit is contained in:
@@ -40,6 +40,8 @@ object Backup {
|
|||||||
}
|
}
|
||||||
val zipFilePath = "${appCtx.externalFiles.absolutePath}${File.separator}tmp_backup.zip"
|
val zipFilePath = "${appCtx.externalFiles.absolutePath}${File.separator}tmp_backup.zip"
|
||||||
|
|
||||||
|
private const val TAG = "Backup"
|
||||||
|
|
||||||
private val mutex = Mutex()
|
private val mutex = Mutex()
|
||||||
|
|
||||||
private val backupFileNames by lazy {
|
private val backupFileNames by lazy {
|
||||||
@@ -102,7 +104,16 @@ object Backup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun backup(context: Context, path: String?) {
|
suspend fun backupLocked(context: Context, path: String?) {
|
||||||
|
mutex.withLock {
|
||||||
|
withContext(IO) {
|
||||||
|
backup(context, path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun backup(context: Context, path: String?) {
|
||||||
|
LogUtils.d(TAG, "开始备份 path:$path")
|
||||||
LocalConfig.lastBackup = System.currentTimeMillis()
|
LocalConfig.lastBackup = System.currentTimeMillis()
|
||||||
val aes = BackupAES()
|
val aes = BackupAES()
|
||||||
FileUtils.delete(backupPath)
|
FileUtils.delete(backupPath)
|
||||||
@@ -216,14 +227,14 @@ object Backup {
|
|||||||
coroutineContext.ensureActive()
|
coroutineContext.ensureActive()
|
||||||
withContext(IO) {
|
withContext(IO) {
|
||||||
if (list.isNotEmpty()) {
|
if (list.isNotEmpty()) {
|
||||||
AppLog.put("阅读备份 $fileName 列表大小 ${list.size}")
|
LogUtils.d(TAG, "阅读备份 $fileName 列表大小 ${list.size}")
|
||||||
val file = FileUtils.createFileIfNotExist(path + File.separator + fileName)
|
val file = FileUtils.createFileIfNotExist(path + File.separator + fileName)
|
||||||
file.outputStream().buffered().use {
|
file.outputStream().buffered().use {
|
||||||
GSON.writeToOutputStream(it, list)
|
GSON.writeToOutputStream(it, list)
|
||||||
}
|
}
|
||||||
AppLog.put("阅读备份 $fileName 写入大小 ${file.length()}")
|
LogUtils.d(TAG, "阅读备份 $fileName 写入大小 ${file.length()}")
|
||||||
} else {
|
} else {
|
||||||
AppLog.put("阅读备份 $fileName 列表为空")
|
LogUtils.d(TAG, "阅读备份 $fileName 列表为空")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import android.view.View
|
|||||||
import androidx.core.view.MenuProvider
|
import androidx.core.view.MenuProvider
|
||||||
import androidx.documentfile.provider.DocumentFile
|
import androidx.documentfile.provider.DocumentFile
|
||||||
import androidx.fragment.app.activityViewModels
|
import androidx.fragment.app.activityViewModels
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.preference.EditTextPreference
|
import androidx.preference.EditTextPreference
|
||||||
import androidx.preference.ListPreference
|
import androidx.preference.ListPreference
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
@@ -50,6 +51,7 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.Dispatchers.Main
|
import kotlinx.coroutines.Dispatchers.Main
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.ensureActive
|
import kotlinx.coroutines.ensureActive
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import splitties.init.appCtx
|
import splitties.init.appCtx
|
||||||
import kotlin.collections.set
|
import kotlin.collections.set
|
||||||
@@ -77,25 +79,11 @@ class BackupConfigFragment : PreferenceFragment(),
|
|||||||
result.uri?.let { uri ->
|
result.uri?.let { uri ->
|
||||||
if (uri.isContentScheme()) {
|
if (uri.isContentScheme()) {
|
||||||
AppConfig.backupPath = uri.toString()
|
AppConfig.backupPath = uri.toString()
|
||||||
Coroutine.async {
|
backup(uri.toString())
|
||||||
Backup.backup(appCtx, uri.toString())
|
|
||||||
}.onSuccess {
|
|
||||||
appCtx.toastOnUi(R.string.backup_success)
|
|
||||||
}.onError {
|
|
||||||
AppLog.put("备份出错\n${it.localizedMessage}", it)
|
|
||||||
appCtx.toastOnUi(getString(R.string.backup_fail, it.localizedMessage))
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
uri.path?.let { path ->
|
uri.path?.let { path ->
|
||||||
AppConfig.backupPath = path
|
AppConfig.backupPath = path
|
||||||
Coroutine.async {
|
backup(path)
|
||||||
Backup.backup(appCtx, path)
|
|
||||||
}.onSuccess {
|
|
||||||
appCtx.toastOnUi(R.string.backup_success)
|
|
||||||
}.onError {
|
|
||||||
AppLog.put("备份出错\n${it.localizedMessage}", it)
|
|
||||||
appCtx.toastOnUi(getString(R.string.backup_fail, it.localizedMessage))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -278,27 +266,7 @@ class BackupConfigFragment : PreferenceFragment(),
|
|||||||
val uri = Uri.parse(backupPath)
|
val uri = Uri.parse(backupPath)
|
||||||
val doc = DocumentFile.fromTreeUri(requireContext(), uri)
|
val doc = DocumentFile.fromTreeUri(requireContext(), uri)
|
||||||
if (doc?.checkWrite() == true) {
|
if (doc?.checkWrite() == true) {
|
||||||
waitDialog.setText("备份中…")
|
backup(backupPath)
|
||||||
waitDialog.setOnCancelListener {
|
|
||||||
backupJob?.cancel()
|
|
||||||
}
|
|
||||||
waitDialog.show()
|
|
||||||
Coroutine.async {
|
|
||||||
backupJob = coroutineContext[Job]
|
|
||||||
Backup.backup(requireContext(), backupPath)
|
|
||||||
}.onSuccess {
|
|
||||||
appCtx.toastOnUi(R.string.backup_success)
|
|
||||||
}.onError {
|
|
||||||
AppLog.put("备份出错\n${it.localizedMessage}", it)
|
|
||||||
appCtx.toastOnUi(
|
|
||||||
appCtx.getString(
|
|
||||||
R.string.backup_fail,
|
|
||||||
it.localizedMessage
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}.onFinally(Main) {
|
|
||||||
waitDialog.dismiss()
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
backupDir.launch()
|
backupDir.launch()
|
||||||
}
|
}
|
||||||
@@ -308,28 +276,39 @@ class BackupConfigFragment : PreferenceFragment(),
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun backup(backupPath: String) {
|
||||||
|
waitDialog.setText("备份中…")
|
||||||
|
waitDialog.setOnCancelListener {
|
||||||
|
backupJob?.cancel()
|
||||||
|
}
|
||||||
|
waitDialog.show()
|
||||||
|
backupJob?.cancel()
|
||||||
|
backupJob = lifecycleScope.launch {
|
||||||
|
try {
|
||||||
|
Backup.backupLocked(requireContext(), backupPath)
|
||||||
|
appCtx.toastOnUi(R.string.backup_success)
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
ensureActive()
|
||||||
|
AppLog.put("备份出错\n${e.localizedMessage}", e)
|
||||||
|
appCtx.toastOnUi(
|
||||||
|
appCtx.getString(
|
||||||
|
R.string.backup_fail,
|
||||||
|
e.localizedMessage
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} finally {
|
||||||
|
ensureActive()
|
||||||
|
waitDialog.dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun backupUsePermission(path: String) {
|
private fun backupUsePermission(path: String) {
|
||||||
PermissionsCompat.Builder()
|
PermissionsCompat.Builder()
|
||||||
.addPermissions(*Permissions.Group.STORAGE)
|
.addPermissions(*Permissions.Group.STORAGE)
|
||||||
.rationale(R.string.tip_perm_request_storage)
|
.rationale(R.string.tip_perm_request_storage)
|
||||||
.onGranted {
|
.onGranted {
|
||||||
waitDialog.setText("备份中…")
|
backup(path)
|
||||||
waitDialog.setOnCancelListener {
|
|
||||||
backupJob?.cancel()
|
|
||||||
}
|
|
||||||
waitDialog.show()
|
|
||||||
Coroutine.async {
|
|
||||||
backupJob = coroutineContext[Job]
|
|
||||||
AppConfig.backupPath = path
|
|
||||||
Backup.backup(requireContext(), path)
|
|
||||||
}.onSuccess {
|
|
||||||
appCtx.toastOnUi(R.string.backup_success)
|
|
||||||
}.onError {
|
|
||||||
AppLog.put("备份出错\n${it.localizedMessage}", it)
|
|
||||||
appCtx.toastOnUi(appCtx.getString(R.string.backup_fail, it.localizedMessage))
|
|
||||||
}.onFinally {
|
|
||||||
waitDialog.dismiss()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.request()
|
.request()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user