Доступ к общим наборам данных

Начиная с Android 11 (уровень API 30), система кэширует большие наборы данных, к которым могут получить доступ несколько приложений для таких сценариев использования, как машинное обучение и воспроизведение мультимедиа. Эта функция помогает уменьшить избыточность данных как по сети, так и на диске.

Когда вашему приложению требуется доступ к общему большому набору данных, оно может сначала найти эти кэшированные наборы данных, называемые общими двоичными объектами данных , прежде чем принимать решение о загрузке новой копии. Приложения могут получить доступ к этим функциям общих наборов данных с помощью API в BlobStoreManager .

Система поддерживает общие объекты данных и контролирует, какие приложения могут получить к ним доступ. Когда ваше приложение предоставляет большие объемы данных, вы можете указать, какие другие приложения должны иметь доступ, вызвав один из следующих методов:

  • Чтобы предоставить доступ к определенному набору приложений на устройстве, передайте имена пакетов этих приложений в allowPackageAccess() .
  • Чтобы разрешить только приложения, сертификаты которых подписаны с использованием того же ключа, который используется для вашего приложения (например, набора приложений, которым вы управляете), вызовите allowSameSignatureAccess() .
  • Чтобы предоставить доступ ко всем приложениям на устройстве, вызовите allowPublicAccess() .

Доступ к общим объектам данных

Система представляет каждый общий блок данных с помощью объекта BlobHandle . Каждый экземпляр BlobHandle содержит криптографически безопасный хеш и некоторые идентифицирующие данные набора данных.

Чтобы получить доступ к общим объектам данных, загрузите идентификационные данные с сервера. Используя эти данные, проверьте, доступен ли набор данных в системе.

Следующий шаг зависит от того, доступны ли данные.

Доступен набор данных

Если набор данных уже доступен на устройстве, получите к нему доступ из системы, как показано в следующем фрагменте кода:

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

Набор данных недоступен

Если набор данных недоступен, загрузите его с сервера и добавьте в систему, как показано в следующем фрагменте кода:

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