You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android 13下Block Store卸载重装后无法读取数据求助

Android 13 卸载重装后 Block Store 数据无法读取的解决方案

问题概述

已实现Block Store的数据存储与读取功能,存储后直接读取在所有设备上均正常。但卸载重装应用后,Android 9-12设备可正常读取数据,Android 13设备(Pixel 7、Samsung S21测试)返回空结果列表,已在AndroidManifest.xml中设置allowBackup="true"。

解决步骤

1. 添加跨版本恢复配置

Android 13默认仅允许恢复与当前应用版本相同或更高版本的备份数据,卸载重装后若应用版本未变更,会触发该限制导致数据无法恢复。需在AndroidManifest.xml的<application>标签中添加:

android:restoreAnyVersion="true"

该配置允许系统恢复任意版本的备份数据,适配卸载重装后的场景。

2. 等待备份完成再操作

存储数据后不要立即卸载应用,需等待系统完成备份同步(可通过系统设置-系统-备份查看进度),避免因备份未完成导致数据丢失。

3. 手动验证备份逻辑

可通过adb命令手动触发备份和恢复,确认数据是否正确备份:

  • 备份命令:adb backup -f backup.ab -noapk com.your.package.name
  • 恢复命令:adb restore backup.ab

完整代码参考

Activity代码

class TestBlocksActivity : AppCompatActivity() {

    lateinit var binding: ActivityTestBlockBinding

    private val blockstoreClient by lazy { Blockstore.getClient(applicationContext) }

    private val tokenKey = "key.token.stage"
    private val tokenValue = "token.test"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityTestBlockBinding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.deleteTokenButton.setOnClickListener {
            deleteBlockstoreData()
        }

        binding.storeTokenButton.setOnClickListener {
            storeBlockstoreData()
        }

        binding.loadTokenButton.setOnClickListener {
            getBlockstoreData()
        }
    }

    private fun storeBlockstoreData() {
        val tokenRequest = StoreBytesData.Builder()
            .setShouldBackupToCloud(true)
            .setBytes(tokenValue.toByteArray())
            .setKey(tokenKey)
            .build()
        blockstoreClient.storeBytes(tokenRequest)
            .addOnSuccessListener {
                binding.lastActionText.text = """Token stored: $tokenValue """
                binding.storedDataText.text = "Unkown - Load to check"
                Timber.tag("BLOCKSTORE_TEST").d("""Stored token: {"$tokenKey", "$tokenValue"}""")
            }
            .addOnFailureListener { e ->
                binding.lastActionText.text = "Exception while storing key"
                Timber.tag("BLOCKSTORE_TEST").e(e)
            }
    }

    private fun getBlockstoreData() {
        val retrieveRequest = RetrieveBytesRequest.Builder()
            .setRetrieveAll(true)
            .build()

        blockstoreClient.retrieveBytes(retrieveRequest)
            .addOnSuccessListener { result ->
                if (result.blockstoreDataMap.isEmpty()) {
                    binding.lastActionText.text = "retrieving token: no token found"
                    Timber.tag("BLOCKSTORE_TEST").d("Retreiving token: no token found")
                }
                result.blockstoreDataMap.forEach { (key, value) ->
                    val valueString = String(value.bytes)
                    if (key == tokenKey) {
                        binding.lastActionText.text = "Retrieved token: $valueString"
                        binding.storedDataText.text = valueString
                    }
                    Timber.tag("BLOCKSTORE_TEST").d("""Retrieved token: {"$key", "$valueString"}""")
                }
            }
            .addOnFailureListener {
                binding.lastActionText.text = "Exception while retreiving key"
                Timber.tag("BLOCKSTORE_TEST").e(it)
            }
    }

    private fun deleteBlockstoreData() {
        val deleteBytesRequest = DeleteBytesRequest.Builder()
            .setDeleteAll(true)
            .build()
        blockstoreClient.deleteBytes(deleteBytesRequest)
            .addOnSuccessListener { success ->
                binding.lastActionText.text = if (success) "Deleted key: $tokenKey"
                else "Could not delete key"
                if (success) binding.storedDataText.text = "no value"
                Timber.tag("BLOCKSTORE_TEST").d("${binding.lastActionText.text}")
            }
            .addOnFailureListener {
                binding.lastActionText.text = "Exception while deleting key"
                Timber.tag("BLOCKSTORE_TEST").e(it)
            }
    }
}

Layout代码

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="24dp">

        <TextView
            android:id="@+id/stored_data_label"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            android:textSize="20sp"
            android:textStyle="bold"
            android:text="Loaded token:"/>

        <TextView
            android:id="@+id/stored_data_text"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:gravity="start"
            android:textSize="20sp"
            android:text="no token value loaded yet"
            app:layout_constraintTop_toBottomOf="@+id/stored_data_label"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            />

        <TextView
            android:layout_marginTop="20dp"
            android:id="@+id/last_action_label"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintTop_toBottomOf="@+id/stored_data_text"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            android:textSize="20sp"
            android:textStyle="bold"
            android:text="Last action:"/>

        <TextView
            android:id="@+id/last_action_text"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:gravity="start"
            android:textSize="20sp"
            android:text="no token value loaded yet"
            app:layout_constraintTop_toBottomOf="@+id/last_action_label"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            />

        <com.google.android.material.button.MaterialButton
            android:id="@+id/load_token_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/last_action_text"
            android:layout_marginTop="40dp"
            android:textAllCaps="false"
            android:textSize="20sp"
            android:text="Load token"/>

        <com.google.android.material.button.MaterialButton
            android:id="@+id/store_token_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/load_token_button"
            android:layout_marginTop="20dp"
            android:textAllCaps="false"
            android:textSize="20sp"
            android:text="Store token"/>

        <com.google.android.material.button.MaterialButton
            android:id="@+id/delete_token_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/store_token_button"
            android:textAllCaps="false"
            android:layout_marginTop="20dp"
            android:textSize="20sp"
            android:text="Delete token"/>

    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>

内容的提问来源于stack exchange,提问作者Djuro Gluvajic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 12:44:59