Compartilhamento seguro de grandes conjuntos de dados usando blobs de dados

Em alguns casos, como em aprendizado de máquina ou reprodução de mídia, seu app pode usar o mesmo grande conjunto de dados que outro app.

Para ajudar a reduzir a redundância de dados, tanto na rede quanto no disco, o Android 11 (API de nível 30) armazena em cache conjuntos de dados compartilhados compatíveis com casos de uso, como aprendizado de máquina e reprodução de mídia. Quando seu app precisar acessar um grande conjunto de dados compartilhado, ele poderá procurar esses conjuntos de dados em cache, chamados blobs de dados compartilhados antes de determinar se fará o download de uma nova cópia. Os apps podem usar essa funcionalidade de conjuntos de dados compartilhados usando as APIs em BlobStoreManager, que é um novo gerenciador de serviços do sistema no Android 11.

O sistema mantém os blobs de dados compartilhados e controla os apps que podem acessá-los. Quando seu app contribui com blobs de dados, é possível indicar que outros apps terão acesso chamando um dos seguintes métodos:

  • Para conceder acesso a um conjunto específico de apps em um dispositivo, transmita os nomes dos pacotes desses apps para allowPackageAccess().
  • Para permitir que apenas os apps com certificados assinados com a mesma chave usada para seu app, por exemplo, um pacote de apps gerenciado por você, chame allowSameSignatureAccess().
  • Para conceder acesso a todos os apps em um dispositivo, chame allowPublicAccess().

Acessar blobs de dados compartilhados

O sistema representa cada blob de dados compartilhados usando um objeto BlobHandle. Cada instância de BlobHandle contém um hash criptograficamente seguro e alguns detalhes de identificação para o conjunto de dados.

Para acessar blobs de dados compartilhados, faça o download dos detalhes de identificação do servidor. Com esses detalhes, verifique se o conjunto de dados já está disponível no sistema.

A próxima etapa depende da disponibilidade dos dados.

Conjunto de dados disponível

Se o conjunto de dados já estiver disponível no dispositivo, acesse-o no sistema, como mostrado no snippet de código a seguir:

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

Conjunto de dados indisponível

Se o conjunto de dados não estiver disponível, faça o download dele no servidor e contribua com o sistema, como mostrado no snippet de código a seguir:

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