【发布时间】:2021-07-29 21:13:00
【问题描述】:
我正在为我的 Android 应用实施备份系统。我正在使用自定义 BackupAgentHelper 来备份共享首选项和数据库文件:
class CustomAgent : BackupAgentHelper() {
val DB_NAME = "notesDB"
val DB_BACKUP_KEY = "dbBackup"
val SHARED_PREFS_KEY = "prefsBackup"
override fun onCreate() {
super.onCreate()
//Backup note's database file
val dbHelper = FileBackupHelper(this, DB_NAME)
addHelper(DB_BACKUP_KEY, dbHelper)
//Backup SharedPreferences
val prefHelper = SharedPreferencesBackupHelper(this)
addHelper(SHARED_PREFS_KEY, prefHelper)
}
override fun onBackup(
oldState: ParcelFileDescriptor?,
data: BackupDataOutput?,
newState: ParcelFileDescriptor?
) {
super.onBackup(oldState, data, newState)
Toast.makeText(this, "Performing backup...", Toast.LENGTH_SHORT).show()
}
override fun onRestore(
data: BackupDataInput?,
appVersionCode: Int,
newState: ParcelFileDescriptor?
) {
Toast.makeText(this, "Restoring...", Toast.LENGTH_SHORT).show()
super.onRestore(data, appVersionCode, newState)
}
override fun onQuotaExceeded(backupDataBytes: Long, quotaBytes: Long) {
Toast.makeText(this, "Failed backup: The size is too big.", Toast.LENGTH_SHORT).show()
super.onQuotaExceeded(backupDataBytes, quotaBytes)
}
override fun getFilesDir(): File {
val path = getDatabasePath(DB_NAME)
return path.parentFile
}
}
我想显示一条 Toast 消息,让用户知道备份正在运行,并在有任何问题时通知他们。但是,如果我使用 Toast 消息运行应用程序,并执行以下 adb 命令来请求备份...
adb -s emulator-5554 shell bmgr backupnow com.byteseb.grafobook
我得到这个输出:
为 1 个请求的包运行增量备份。
打包@pm@,结果:成功
使用结果打包 com.byteseb.grafobook:代理错误
备份完成,结果:成功
并且没有显示 Toast 消息。
但是如果我删除 Toast 消息行或用 println() 函数替换它们并执行相同的命令,我会得到以下输出:
为 1 个请求的包运行增量备份。
打包@pm@,结果:成功
使用结果打包 com.byteseb.grafobook:成功
备份完成,结果:成功
为什么会发生这个错误?如果不允许我显示 Toast,我还能做些什么来通知用户有关备份的信息?
【问题讨论】:
-
"为什么会出现这个错误?" – 您不能从非 UI 线程中显示
Toasts,因此这可能会引发异常。 “...我还能做些什么来通知用户有关备份的信息?” – 您可能不想直接从您的BackupAgentHelper触发任何 UI 通知,因为您永远不知道系统何时会自行运行它。就个人而言,我只会在SharedPreferences中跟踪上次备份时间,例如,将当前时间保存在onBackup()的末尾。如果您想实时更新备份请求,可以设置OnSharedPreferenceChangeListener。 -
@MikeM 你认为使用 BroadcastReceiver 是个好主意吗?
-
实时更新的东西?这可以工作,但很少需要在同一个应用程序中进行广播,通常也不再推荐它。曾经有一个专门的支持库类——
LocalBroadcastManager——但这早已被弃用,取而代之的是ViewModels 和观察者等。如果你想做一个ViewModel-type 设置,你基本上可以告诉 UI 任何你想要从你的备份代理那里得到的东西,但是这需要更多的设置。 -
如果您打算直接从帮助程序中显示一些 UI 通知,您可以考虑使用
Notifications。只是一个建议。 -
@MikeM。是的,谢谢。我确实最终使用了通知,但我在答案中使用了 Toasts,因为问题使用了它们:)