访问共享数据集

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

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

系统维护共享数据 blob 并控制哪些应用可以访问它们。当您的应用贡献数据 blob 时,您可以通过调用以下方法之一来指明应允许哪些其他应用访问:

  • 如需授予对设备上特定应用集的访问权限,请将这些应用的软件包名称传递给 allowPackageAccess()
  • 如果您只想允许使用与您的应用所用密钥相同的密钥进行签名的应用(例如您管理的某个应用套件)进行访问,请调用 allowSameSignatureAccess()
  • 如需授予对设备上所有应用的访问权限,请调用 allowPublicAccess()

访问共享数据 blob

系统使用一个 BlobHandle 对象来表示每个共享数据 blob。BlobHandle 的每个实例都包含一个加密安全的哈希和数据集的一些标识信息。

如需访问共享数据 blob,请从服务器下载标识信息。使用这些信息,检查数据集是否已在系统上可用。

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

数据集可用

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

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);
    }
}