首页 > 解决方案 > 为什么我在尝试执行备份时收到“代理错误”?

问题描述

我正在为我的 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,我还能做些什么来通知用户有关备份的信息?

标签: androidkotlin

解决方案


正如@MikeM 所说,发生这种情况是因为我正在从非 UI 线程执行代码。

我通过使用处理程序解决了这个问题,这个处理程序负责从 UI 线程运行代码:

override fun onBackup(
    oldState: ParcelFileDescriptor?,
    data: BackupDataOutput?,
    newState: ParcelFileDescriptor?
) {
    super.onBackup(oldState, data, newState)
    val handler = Handler(Looper.getMainLooper())
    val runnable = Runnable {
        Toast.makeText(this, "Performing backup...", Toast.LENGTH_SHORT).show()
    }
    handler.post(runnable)
}

推荐阅读