访问共享数据集

从 Android 11(API 级别 30)开始,系统会缓存多个应用可能访问的大型数据集,用于机器学习和媒体播放等用例。此功能有助于减少网络和磁盘上的数据冗余。

当您的应用需要访问共享的大型数据集时,它可以首先查找这些缓存的数据集(称为共享数据块),然后再确定是否下载新副本。应用可以使用BlobStoreManager中的 API 访问这些共享数据集功能。

系统维护共享数据块并控制哪些应用可以访问它们。当您的应用贡献数据块时,您可以通过调用以下方法之一来指示哪些其他应用应该具有访问权限

  • 要授予设备上特定应用集的访问权限,请将这些应用的包名称传递到allowPackageAccess()
  • 要仅允许使用与用于您的应用的密钥相同的密钥签名的证书的应用(例如您管理的应用套件),请调用allowSameSignatureAccess()
  • 要授予设备上所有应用的访问权限,请调用allowPublicAccess()

访问共享数据块

系统使用BlobHandle对象表示每个共享数据块。每个BlobHandle实例都包含一个加密安全的哈希值以及数据集的一些识别详细信息。

要访问共享数据块,请从服务器下载识别详细信息。使用这些详细信息,检查数据集是否已在系统上可用。

下一步取决于数据是否可用。

数据集可用

如果数据集已在设备上可用,则从系统访问它,如下面的代码片段所示

Kotlin

val blobStoreManager =
        getSystemService(Context.BLOB_STORE_SERVICE) as BlobStoreManager
// The label "Sample photos" is visible to the user.
val blobHandle = BlobHandle.createWithSha256(sha256DigestBytes,
        "Sample photos",
        System.currentTimeMillis() + TimeUnit.DAYS.toMillis(1),
        "photoTrainingDataset")
try {
    val input = ParcelFileDescriptor.AutoCloseInputStream(
            blobStoreManager.openBlob(blobHandle))
    useDataset(input)
}

Java

BlobStoreManager blobStoreManager =
        ((BlobStoreManager) getSystemService(Context.BLOB_STORE_SERVICE));
if (blobStoreManager != null) {
    // The label "Sample photos" is visible to the user.
    BlobHandle blobHandle = BlobHandle.createWithSha256(
            sha256DigestBytes,
            "Sample photos",
            System.currentTimeMillis() + TimeUnit.DAYS.toMillis(1),
            "photoTrainingDataset");
    try (InputStream input = new ParcelFileDescriptor.AutoCloseInputStream(
            blobStoreManager.openBlob(blobHandle))) {
        useDataset(input);
    }
}

数据集不可用

如果数据集不可用,则从服务器下载它并将其贡献给系统,如下面的代码片段所示

Kotlin

val sessionId = blobStoreManager.createSession(blobHandle)
try {
    val session = blobStoreManager.openSession(sessionId)
    try {
        // For this example, write 200 MiB at the beginning of the file.
        val output = ParcelFileDescriptor.AutoCloseOutputStream(
                session.openWrite(0, 1024 * 1024 * 200))
        writeDataset(output)

        session.apply {
            allowSameSignatureAccess()
            allowPackageAccess(your-app-package,
                    app-certificate)
            allowPackageAccess(some-other-app-package,
                    app-certificate)
            commit(mainExecutor, callback)
        }
    }
}

Java

long sessionId = blobStoreManager.createSession(blobHandle);
try (BlobStoreManager.Session session =
        blobStoreManager.openSession(sessionId)) {
    // For this example, write 200 MiB at the beginning of the file.
    try (OutputStream output = new ParcelFileDescriptor.AutoCloseOutputStream(
            session.openWrite(0, 1024 * 1024 * 200)))
        writeDataset(output);
        session.allowSameSignatureAccess();
        session.allowPackageAccess(your-app-package,
                    app-certificate);
        session.allowPackageAccess(some-other-app-package,
                    app-certificate);
        session.commit(getMainExecutor(), callback);
    }
}