Многие пользователи по-прежнему управляют своими учетными данными при настройке нового устройства Android. Этот ручной процесс может стать сложным и часто приводит к плохому взаимодействию с пользователем. Block Store API, библиотека на основе сервисов Google Play , пытается решить эту проблему, предоставляя приложениям возможность сохранять учетные данные пользователя без сложности или риска для безопасности, связанного с сохранением паролей пользователей.
API-интерфейс Block Store позволяет вашему приложению хранить данные, которые впоследствии можно извлечь для повторной аутентификации пользователей на новом устройстве. Это помогает обеспечить более удобный интерфейс для пользователя, поскольку ему не нужно видеть экран входа в систему при первом запуске вашего приложения на новом устройстве.
Преимущества использования Block Store включают следующее:
- Зашифрованное решение для хранения учетных данных для разработчиков. Учетные данные по возможности шифруются сквозным шифрованием.
- Сохраняйте токены вместо логинов и паролей.
- Устраните трения в потоках входа.
- Избавьте пользователей от бремени управления сложными паролями.
- Google проверяет личность пользователя.
Прежде чем вы начнете
Чтобы подготовить приложение, выполните действия, описанные в следующих разделах.
Настройте свое приложение
В файле build.gradle
на уровне проекта включите репозиторий Google Maven как в разделы buildscript
, так и в разделы allprojects
:
buildscript {
repositories {
google()
mavenCentral()
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
Добавьте зависимость сервисов Google Play для API Block Store в файл сборки вашего модуля Gradle , обычно это app/build.gradle
:
dependencies {
implementation 'com.google.android.gms:play-services-auth-blockstore:16.2.0'
}
Как это работает
Block Store позволяет разработчикам сохранять и восстанавливать массивы размером до 16 байт. Это позволяет вам сохранять важную информацию о текущем сеансе пользователя и дает возможность сохранять эту информацию по своему усмотрению. Эти данные могут быть зашифрованы сквозным шифрованием, а инфраструктура, поддерживающая Block Store, построена поверх инфраструктуры резервного копирования и восстановления.
В этом руководстве рассматривается пример использования сохранения токена пользователя в Block Store. Следующие шаги описывают, как будет работать приложение, использующее Block Store:
- Во время процесса аутентификации вашего приложения или в любое время после этого вы можете сохранить токен аутентификации пользователя в Block Store для последующего извлечения.
- Токен будет храниться локально, а также может быть скопирован в облако со сквозным шифрованием, если это возможно.
- Данные передаются, когда пользователь инициирует процесс восстановления на новом устройстве.
- Если пользователь восстанавливает ваше приложение во время процесса восстановления, ваше приложение может получить сохраненный токен из Block Store на новом устройстве.
Сохранение токена
Когда пользователь входит в ваше приложение, вы можете сохранить маркер проверки подлинности, созданный для этого пользователя, в Block Store. Вы можете сохранить этот токен, используя уникальное значение пары ключей, которое имеет максимум 4 КБ на запись. Чтобы сохранить токен, вызовите setBytes()
и setKey()
для экземпляра StoreBytesData.Builder
, чтобы сохранить учетные данные пользователя на исходном устройстве. После сохранения токена в Block Store он шифруется и хранится локально на устройстве.
В следующем примере показано, как сохранить токен проверки подлинности на локальном устройстве:
Джава
BlockstoreClient client = Blockstore.getClient(this); byte[] bytes1 = new byte[] { 1, 2, 3, 4 }; // Store one data block. String key1 = "com.example.app.key1"; StoreBytesData storeRequest1 = StoreBytesData.Builder() .setBytes(bytes1) // Call this method to set the key value pair the data should be associated with. .setKeys(Arrays.asList(key1)) .build(); client.storeBytes(storeRequest1) .addOnSuccessListener(result -> Log.d(TAG, "stored " + result + " bytes")) .addOnFailureListener(e -> Log.e(TAG, "Failed to store bytes", e));
Котлин
val client = Blockstore.getClient(this) val bytes1 = byteArrayOf(1, 2, 3, 4) // Store one data block. val key1 = "com.example.app.key1" val storeRequest1 = StoreBytesData.Builder() .setBytes(bytes1) // Call this method to set the key value with which the data should be associated with. .setKeys(Arrays.asList(key1)) .build() client.storeBytes(storeRequest1) .addOnSuccessListener { result: Int -> Log.d(TAG, "Stored $result bytes") } .addOnFailureListener { e -> Log.e(TAG, "Failed to store bytes", e) }
Использовать токен по умолчанию
Данные, сохраненные с помощью StoreBytes без ключа, используют ключ по умолчанию BlockstoreClient.DEFAULT_BYTES_DATA_KEY.
Джава
BlockstoreClient client = Blockstore.getClient(this); // The default key BlockstoreClient.DEFAULT_BYTES_DATA_KEY. byte[] bytes = new byte[] { 9, 10 }; StoreBytesData storeRequest = StoreBytesData.Builder() .setBytes(bytes) .build(); client.storeBytes(storeRequest) .addOnSuccessListener(result -> Log.d(TAG, "stored " + result + " bytes")) .addOnFailureListener(e -> Log.e(TAG, "Failed to store bytes", e));
Котлин
val client = Blockstore.getClient(this); // the default key BlockstoreClient.DEFAULT_BYTES_DATA_KEY. val bytes = byteArrayOf(1, 2, 3, 4) val storeRequest = StoreBytesData.Builder() .setBytes(bytes) .build(); client.storeBytes(storeRequest) .addOnSuccessListener { result: Int -> Log.d(TAG, "stored $result bytes") } .addOnFailureListener { e -> Log.e(TAG, "Failed to store bytes", e) }
Получение токена
Позже, когда пользователь проходит процесс восстановления на новом устройстве, сервисы Google Play сначала проверяют пользователя, а затем извлекают данные вашего Block Store. Пользователь уже дал согласие на восстановление данных вашего приложения в рамках процесса восстановления, поэтому дополнительные согласия не требуются. Когда пользователь открывает ваше приложение, вы можете запросить свой токен из Block Store, вызвав retrieveBytes()
. Затем полученный токен можно использовать для удержания пользователя в системе на новом устройстве.
В следующем примере показано, как получить несколько токенов на основе определенных ключей.
Джава
BlockstoreClient client = Blockstore.getClient(this); // Retrieve data associated with certain keys. String key1 = "com.example.app.key1"; String key2 = "com.example.app.key2"; String key3 = BlockstoreClient.DEFAULT_BYTES_DATA_KEY; // Used to retrieve data stored without a key ListrequestedKeys = Arrays.asList(key1, key2, key3); // Add keys to array RetrieveBytesRequest retrieveRequest = new RetrieveBytesRequest.Builder() .setKeys(requestedKeys) .build(); client.retrieveBytes(retrieveRequest) .addOnSuccessListener( result -> { Map blockstoreDataMap = result.getBlockstoreDataMap(); for (Map.Entry entry : blockstoreDataMap.entrySet()) { Log.d(TAG, String.format( "Retrieved bytes %s associated with key %s.", new String(entry.getValue().getBytes()), entry.getKey())); } }) .addOnFailureListener(e -> Log.e(TAG, "Failed to store bytes", e));
Котлин
val client = Blockstore.getClient(this) // Retrieve data associated with certain keys. val key1 = "com.example.app.key1" val key2 = "com.example.app.key2" val key3 = BlockstoreClient.DEFAULT_BYTES_DATA_KEY // Used to retrieve data stored without a key val requestedKeys = Arrays.asList(key1, key2, key3) // Add keys to array val retrieveRequest = RetrieveBytesRequest.Builder() .setKeys(requestedKeys) .build() client.retrieveBytes(retrieveRequest) .addOnSuccessListener { result: RetrieveBytesResponse -> val blockstoreDataMap = result.blockstoreDataMap for ((key, value) in blockstoreDataMap) { Log.d(ContentValues.TAG, String.format( "Retrieved bytes %s associated with key %s.", String(value.bytes), key)) } } .addOnFailureListener { e: Exception? -> Log.e(ContentValues.TAG, "Failed to store bytes", e) }
Получение всех токенов.
Ниже приведен пример того, как получить все токены, сохраненные в BlockStore.
Джава
BlockstoreClient client = Blockstore.getClient(this) // Retrieve all data. RetrieveBytesRequest retrieveRequest = new RetrieveBytesRequest.Builder() .setRetrieveAll(true) .build(); client.retrieveBytes(retrieveRequest) .addOnSuccessListener( result -> { MapblockstoreDataMap = result.getBlockstoreDataMap(); for (Map.Entry entry : blockstoreDataMap.entrySet()) { Log.d(TAG, String.format( "Retrieved bytes %s associated with key %s.", new String(entry.getValue().getBytes()), entry.getKey())); } }) .addOnFailureListener(e -> Log.e(TAG, "Failed to store bytes", e));
Котлин
val client = Blockstore.getClient(this) val retrieveRequest = RetrieveBytesRequest.Builder() .setRetrieveAll(true) .build() client.retrieveBytes(retrieveRequest) .addOnSuccessListener { result: RetrieveBytesResponse -> val blockstoreDataMap = result.blockstoreDataMap for ((key, value) in blockstoreDataMap) { Log.d(ContentValues.TAG, String.format( "Retrieved bytes %s associated with key %s.", String(value.bytes), key)) } } .addOnFailureListener { e: Exception? -> Log.e(ContentValues.TAG, "Failed to store bytes", e) }
Ниже приведен пример получения ключа по умолчанию.
Джава
BlockStoreClient client = Blockstore.getClient(this); RetrieveBytesRequest retrieveRequest = new RetrieveBytesRequest.Builder() .setKeys(Arrays.asList(BlockstoreClient.DEFAULT_BYTES_DATA_KEY)) .build(); client.retrieveBytes(retrieveRequest);
Котлин
val client = Blockstore.getClient(this) val retrieveRequest = RetrieveBytesRequest.Builder() .setKeys(Arrays.asList(BlockstoreClient.DEFAULT_BYTES_DATA_KEY)) .build() client.retrieveBytes(retrieveRequest)
Удаление токенов
Удаление токенов из BlockStore может потребоваться по следующим причинам:
- Пользователь проходит процесс выхода из системы.
- Токен был отозван или недействителен.
Подобно извлечению токенов, вы можете указать, какие токены нужно удалить, установив массив ключей, которые требуют удаления.
Ниже приведен пример удаления определенных ключей.
Джава
BlockstoreClient client = Blockstore.getClient(this); // Delete data associated with certain keys. String key1 = "com.example.app.key1"; String key2 = "com.example.app.key2"; String key3 = BlockstoreClient.DEFAULT_BYTES_DATA_KEY; // Used to delete data stored without key ListrequestedKeys = Arrays.asList(key1, key2, key3) // Add keys to array DeleteBytesRequest deleteRequest = new DeleteBytesRequest.Builder() .setKeys(requestedKeys) .build(); client.deleteBytes(deleteRequest)
Котлин
val client = Blockstore.getClient(this) // Retrieve data associated with certain keys. val key1 = "com.example.app.key1" val key2 = "com.example.app.key2" val key3 = BlockstoreClient.DEFAULT_BYTES_DATA_KEY // Used to retrieve data stored without a key val requestedKeys = Arrays.asList(key1, key2, key3) // Add keys to array val retrieveRequest = DeleteBytesRequest.Builder() .setKeys(requestedKeys) .build() client.deleteBytes(retrieveRequest)
Удалить все токены
В приведенном ниже примере удаляются все токены, сохраненные в настоящее время в BlockStore:
Джава
// Delete all data. DeleteBytesRequest deleteAllRequest = new DeleteBytesRequest.Builder() .setDeleteAll(true) .build(); client.deleteBytes(deleteAllRequest) .addOnSuccessListener(result -> Log.d(TAG, "Any data found and deleted? " + result));
Котлин
val deleteAllRequest = DeleteBytesRequest.Builder() .setDeleteAll(true) .build() client.deleteBytes(deleteAllRequest) .addOnSuccessListener { result: Boolean -> Log.d(TAG, "Any data found and deleted? $result") }
Сквозное шифрование
Чтобы сквозное шифрование было доступно, устройство должно работать под управлением Android 9 или более поздней версии, а пользователь должен установить блокировку экрана (PIN-код, графический ключ или пароль) для своего устройства. Вы можете проверить, будет ли доступно шифрование на устройстве, вызвав isEndToEndEncryptionAvailable()
.
В следующем примере показано, как проверить, будет ли доступно шифрование во время резервного копирования в облаке:
client.isEndToEndEncryptionAvailable()
.addOnSuccessListener { result ->
Log.d(TAG, "Will Block Store cloud backup be end-to-end encrypted? $result")
}
Включить облачное резервное копирование
Чтобы включить резервное копирование в облаке, добавьте метод setShouldBackupToCloud()
в свой объект StoreBytesData
. Block Store будет периодически создавать резервные копии в облаке байтов, сохраненных, если для setShouldBackupToCloud()
задано значение true.
В следующем примере показано, как включить облачное резервное копирование , только если облачное резервное копирование зашифровано сквозным шифрованием :
val client = Blockstore.getClient(this)
val storeBytesDataBuilder = StoreBytesData.Builder()
.setBytes(/* BYTE_ARRAY */)
client.isEndToEndEncryptionAvailable()
.addOnSuccessListener { isE2EEAvailable ->
if (isE2EEAvailable) {
storeBytesDataBuilder.setShouldBackupToCloud(true)
Log.d(TAG, "E2EE is available, enable backing up bytes to the cloud.")
client.storeBytes(storeBytesDataBuilder.build())
.addOnSuccessListener { result ->
Log.d(TAG, "stored: ${result.getBytesStored()}")
}.addOnFailureListener { e ->
Log.e(TAG, “Failed to store bytes”, e)
}
} else {
Log.d(TAG, "E2EE is not available, only store bytes for D2D restore.")
}
}
Как проверить
Используйте следующие методы во время разработки, чтобы протестировать потоки восстановления.
Удаление/переустановка того же устройства
Если пользователь включает службы резервного копирования (это можно проверить в разделе «Настройки» > «Google» > «Резервное копирование» ), данные Block Store сохраняются при удалении/переустановке приложения.
Вы можете выполнить следующие шаги для тестирования:
- Интегрируйте API BlockStore в тестовое приложение.
- Используйте тестовое приложение, чтобы вызвать BlockStore API для хранения ваших данных.
- Удалите тестовое приложение, а затем переустановите его на том же устройстве.
- Используйте тестовое приложение, чтобы вызвать BlockStore API для извлечения ваших данных.
- Убедитесь, что полученные байты совпадают с теми, которые были сохранены до удаления.
Устройство к устройству
В большинстве случаев для этого потребуется сброс настроек целевого устройства до заводских. Затем вы можете войти в процесс восстановления беспроводной сети Android или восстановления кабеля Google (для поддерживаемых устройств).
Облачное восстановление
- Интегрируйте API Blockstore в тестовое приложение. Тестовое приложение необходимо отправить в Play Store.
- На исходном устройстве используйте тестовое приложение, чтобы вызвать Blockstore API для хранения ваших данных, при этом для параметра shouldBackUpToCloud установлено значение true.
- Для устройств O и выше вы можете вручную запустить облачное резервное копирование Block Store: перейдите в «Настройки»> «Google»> «Резервное копирование» и нажмите кнопку «Создать резервную копию сейчас».
- Чтобы убедиться, что резервное копирование в облачное хранилище Block Store выполнено успешно, вы можете:
- После завершения резервного копирования найдите строки журнала с тегом «CloudSyncBpTkSvc».
- Вы должны увидеть такие строки: «......, CloudSyncBpTkSvc: результат синхронизации: УСПЕШНО, ..., загруженный размер: XXX байт ...»
- После облачного резервного копирования Block Store наступает 5-минутный период «остывания». В течение этих 5 минут нажатие кнопки «Создать резервную копию» не вызовет еще одну резервную копию в облачном хранилище Block Store.
- Чтобы убедиться, что резервное копирование в облачное хранилище Block Store выполнено успешно, вы можете:
- Сбросьте настройки целевого устройства до заводских настроек и выполните процедуру восстановления в облаке. Выберите, чтобы восстановить тестовое приложение во время процесса восстановления. Дополнительные сведения о потоках облачного восстановления см. в разделе Поддерживаемые потоки облачного восстановления .
- На целевом устройстве используйте тестовое приложение, чтобы вызвать Blockstore API для получения ваших данных.
- Убедитесь, что полученные байты совпадают с теми, которые были сохранены на исходном устройстве.
Требования к устройству
Сквозное шифрование
- Сквозное шифрование поддерживается на устройствах под управлением Android 9 (API 29) и выше.
- На устройстве должна быть установлена блокировка экрана с помощью PIN-кода, графического ключа или пароля, чтобы сквозное шифрование было включено и правильно шифровало данные пользователя.
Поток восстановления с устройства на устройство
Для восстановления с устройства на устройство потребуется исходное устройство и целевое устройство. Это будут два устройства, которые передают данные.
Исходные устройства должны работать под управлением Android 6 (API 23) и выше для резервного копирования.
Целевые устройства под управлением Android 9 (API 29) и выше, чтобы иметь возможность восстановления.
Дополнительную информацию о процессе восстановления с устройства на устройство можно найти здесь .
Облачное резервное копирование и восстановление потока
Для резервного копирования и восстановления в облаке потребуются исходное и целевое устройства.
Исходные устройства должны работать под управлением Android 6 (API 23) и выше для резервного копирования.
Целевые устройства поддерживаются в зависимости от их поставщиков. Устройства Pixel могут использовать эту функцию с Android 9 (API 29), а все остальные устройства должны работать под управлением Android 12 (API 31) или более поздней версии.
,Многие пользователи по-прежнему управляют своими учетными данными при настройке нового устройства Android. Этот ручной процесс может стать сложным и часто приводит к плохому взаимодействию с пользователем. Block Store API, библиотека на основе сервисов Google Play , пытается решить эту проблему, предоставляя приложениям возможность сохранять учетные данные пользователя без сложности или риска для безопасности, связанного с сохранением паролей пользователей.
API-интерфейс Block Store позволяет вашему приложению хранить данные, которые впоследствии можно извлечь для повторной аутентификации пользователей на новом устройстве. Это помогает обеспечить более удобный интерфейс для пользователя, поскольку ему не нужно видеть экран входа в систему при первом запуске вашего приложения на новом устройстве.
Преимущества использования Block Store включают следующее:
- Зашифрованное решение для хранения учетных данных для разработчиков. Учетные данные по возможности шифруются сквозным шифрованием.
- Сохраняйте токены вместо логинов и паролей.
- Устраните трения в потоках входа.
- Избавьте пользователей от бремени управления сложными паролями.
- Google проверяет личность пользователя.
Прежде чем вы начнете
Чтобы подготовить приложение, выполните действия, описанные в следующих разделах.
Настройте свое приложение
В файле build.gradle
на уровне проекта включите репозиторий Google Maven как в разделы buildscript
, так и в разделы allprojects
:
buildscript {
repositories {
google()
mavenCentral()
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
Добавьте зависимость сервисов Google Play для API Block Store в файл сборки вашего модуля Gradle , обычно это app/build.gradle
:
dependencies {
implementation 'com.google.android.gms:play-services-auth-blockstore:16.2.0'
}
Как это работает
Block Store позволяет разработчикам сохранять и восстанавливать массивы размером до 16 байт. Это позволяет вам сохранять важную информацию о текущем сеансе пользователя и дает возможность сохранять эту информацию по своему усмотрению. Эти данные могут быть зашифрованы сквозным шифрованием, а инфраструктура, поддерживающая Block Store, построена поверх инфраструктуры резервного копирования и восстановления.
В этом руководстве рассматривается пример использования сохранения токена пользователя в Block Store. Следующие шаги описывают, как будет работать приложение, использующее Block Store:
- Во время процесса аутентификации вашего приложения или в любое время после этого вы можете сохранить токен аутентификации пользователя в Block Store для последующего извлечения.
- Токен будет храниться локально, а также может быть скопирован в облако со сквозным шифрованием, если это возможно.
- Данные передаются, когда пользователь инициирует процесс восстановления на новом устройстве.
- Если пользователь восстанавливает ваше приложение во время процесса восстановления, ваше приложение может получить сохраненный токен из Block Store на новом устройстве.
Сохранение токена
Когда пользователь входит в ваше приложение, вы можете сохранить маркер проверки подлинности, созданный для этого пользователя, в Block Store. Вы можете сохранить этот токен, используя уникальное значение пары ключей, которое имеет максимум 4 КБ на запись. Чтобы сохранить токен, вызовите setBytes()
и setKey()
для экземпляра StoreBytesData.Builder
, чтобы сохранить учетные данные пользователя на исходном устройстве. После сохранения токена в Block Store он шифруется и хранится локально на устройстве.
В следующем примере показано, как сохранить токен проверки подлинности на локальном устройстве:
Джава
BlockstoreClient client = Blockstore.getClient(this); byte[] bytes1 = new byte[] { 1, 2, 3, 4 }; // Store one data block. String key1 = "com.example.app.key1"; StoreBytesData storeRequest1 = StoreBytesData.Builder() .setBytes(bytes1) // Call this method to set the key value pair the data should be associated with. .setKeys(Arrays.asList(key1)) .build(); client.storeBytes(storeRequest1) .addOnSuccessListener(result -> Log.d(TAG, "stored " + result + " bytes")) .addOnFailureListener(e -> Log.e(TAG, "Failed to store bytes", e));
Котлин
val client = Blockstore.getClient(this) val bytes1 = byteArrayOf(1, 2, 3, 4) // Store one data block. val key1 = "com.example.app.key1" val storeRequest1 = StoreBytesData.Builder() .setBytes(bytes1) // Call this method to set the key value with which the data should be associated with. .setKeys(Arrays.asList(key1)) .build() client.storeBytes(storeRequest1) .addOnSuccessListener { result: Int -> Log.d(TAG, "Stored $result bytes") } .addOnFailureListener { e -> Log.e(TAG, "Failed to store bytes", e) }
Использовать токен по умолчанию
Данные, сохраненные с помощью StoreBytes без ключа, используют ключ по умолчанию BlockstoreClient.DEFAULT_BYTES_DATA_KEY.
Джава
BlockstoreClient client = Blockstore.getClient(this); // The default key BlockstoreClient.DEFAULT_BYTES_DATA_KEY. byte[] bytes = new byte[] { 9, 10 }; StoreBytesData storeRequest = StoreBytesData.Builder() .setBytes(bytes) .build(); client.storeBytes(storeRequest) .addOnSuccessListener(result -> Log.d(TAG, "stored " + result + " bytes")) .addOnFailureListener(e -> Log.e(TAG, "Failed to store bytes", e));
Котлин
val client = Blockstore.getClient(this); // the default key BlockstoreClient.DEFAULT_BYTES_DATA_KEY. val bytes = byteArrayOf(1, 2, 3, 4) val storeRequest = StoreBytesData.Builder() .setBytes(bytes) .build(); client.storeBytes(storeRequest) .addOnSuccessListener { result: Int -> Log.d(TAG, "stored $result bytes") } .addOnFailureListener { e -> Log.e(TAG, "Failed to store bytes", e) }
Получение токена
Позже, когда пользователь проходит процесс восстановления на новом устройстве, сервисы Google Play сначала проверяют пользователя, а затем извлекают данные вашего Block Store. Пользователь уже дал согласие на восстановление данных вашего приложения в рамках процесса восстановления, поэтому дополнительные согласия не требуются. Когда пользователь открывает ваше приложение, вы можете запросить свой токен из Block Store, вызвав retrieveBytes()
. Затем полученный токен можно использовать для удержания пользователя в системе на новом устройстве.
В следующем примере показано, как получить несколько токенов на основе определенных ключей.
Джава
BlockstoreClient client = Blockstore.getClient(this); // Retrieve data associated with certain keys. String key1 = "com.example.app.key1"; String key2 = "com.example.app.key2"; String key3 = BlockstoreClient.DEFAULT_BYTES_DATA_KEY; // Used to retrieve data stored without a key ListrequestedKeys = Arrays.asList(key1, key2, key3); // Add keys to array RetrieveBytesRequest retrieveRequest = new RetrieveBytesRequest.Builder() .setKeys(requestedKeys) .build(); client.retrieveBytes(retrieveRequest) .addOnSuccessListener( result -> { Map blockstoreDataMap = result.getBlockstoreDataMap(); for (Map.Entry entry : blockstoreDataMap.entrySet()) { Log.d(TAG, String.format( "Retrieved bytes %s associated with key %s.", new String(entry.getValue().getBytes()), entry.getKey())); } }) .addOnFailureListener(e -> Log.e(TAG, "Failed to store bytes", e));
Котлин
val client = Blockstore.getClient(this) // Retrieve data associated with certain keys. val key1 = "com.example.app.key1" val key2 = "com.example.app.key2" val key3 = BlockstoreClient.DEFAULT_BYTES_DATA_KEY // Used to retrieve data stored without a key val requestedKeys = Arrays.asList(key1, key2, key3) // Add keys to array val retrieveRequest = RetrieveBytesRequest.Builder() .setKeys(requestedKeys) .build() client.retrieveBytes(retrieveRequest) .addOnSuccessListener { result: RetrieveBytesResponse -> val blockstoreDataMap = result.blockstoreDataMap for ((key, value) in blockstoreDataMap) { Log.d(ContentValues.TAG, String.format( "Retrieved bytes %s associated with key %s.", String(value.bytes), key)) } } .addOnFailureListener { e: Exception? -> Log.e(ContentValues.TAG, "Failed to store bytes", e) }
Получение всех токенов.
Ниже приведен пример того, как получить все токены, сохраненные в BlockStore.
Джава
BlockstoreClient client = Blockstore.getClient(this) // Retrieve all data. RetrieveBytesRequest retrieveRequest = new RetrieveBytesRequest.Builder() .setRetrieveAll(true) .build(); client.retrieveBytes(retrieveRequest) .addOnSuccessListener( result -> { MapblockstoreDataMap = result.getBlockstoreDataMap(); for (Map.Entry entry : blockstoreDataMap.entrySet()) { Log.d(TAG, String.format( "Retrieved bytes %s associated with key %s.", new String(entry.getValue().getBytes()), entry.getKey())); } }) .addOnFailureListener(e -> Log.e(TAG, "Failed to store bytes", e));
Котлин
val client = Blockstore.getClient(this) val retrieveRequest = RetrieveBytesRequest.Builder() .setRetrieveAll(true) .build() client.retrieveBytes(retrieveRequest) .addOnSuccessListener { result: RetrieveBytesResponse -> val blockstoreDataMap = result.blockstoreDataMap for ((key, value) in blockstoreDataMap) { Log.d(ContentValues.TAG, String.format( "Retrieved bytes %s associated with key %s.", String(value.bytes), key)) } } .addOnFailureListener { e: Exception? -> Log.e(ContentValues.TAG, "Failed to store bytes", e) }
Ниже приведен пример получения ключа по умолчанию.
Джава
BlockStoreClient client = Blockstore.getClient(this); RetrieveBytesRequest retrieveRequest = new RetrieveBytesRequest.Builder() .setKeys(Arrays.asList(BlockstoreClient.DEFAULT_BYTES_DATA_KEY)) .build(); client.retrieveBytes(retrieveRequest);
Котлин
val client = Blockstore.getClient(this) val retrieveRequest = RetrieveBytesRequest.Builder() .setKeys(Arrays.asList(BlockstoreClient.DEFAULT_BYTES_DATA_KEY)) .build() client.retrieveBytes(retrieveRequest)
Удаление токенов
Удаление токенов из BlockStore может потребоваться по следующим причинам:
- Пользователь проходит процесс выхода из системы.
- Токен был отозван или недействителен.
Подобно извлечению токенов, вы можете указать, какие токены нужно удалить, установив массив ключей, которые требуют удаления.
Ниже приведен пример удаления определенных ключей.
Джава
BlockstoreClient client = Blockstore.getClient(this); // Delete data associated with certain keys. String key1 = "com.example.app.key1"; String key2 = "com.example.app.key2"; String key3 = BlockstoreClient.DEFAULT_BYTES_DATA_KEY; // Used to delete data stored without key ListrequestedKeys = Arrays.asList(key1, key2, key3) // Add keys to array DeleteBytesRequest deleteRequest = new DeleteBytesRequest.Builder() .setKeys(requestedKeys) .build(); client.deleteBytes(deleteRequest)
Котлин
val client = Blockstore.getClient(this) // Retrieve data associated with certain keys. val key1 = "com.example.app.key1" val key2 = "com.example.app.key2" val key3 = BlockstoreClient.DEFAULT_BYTES_DATA_KEY // Used to retrieve data stored without a key val requestedKeys = Arrays.asList(key1, key2, key3) // Add keys to array val retrieveRequest = DeleteBytesRequest.Builder() .setKeys(requestedKeys) .build() client.deleteBytes(retrieveRequest)
Удалить все токены
В приведенном ниже примере удаляются все токены, сохраненные в настоящее время в BlockStore:
Джава
// Delete all data. DeleteBytesRequest deleteAllRequest = new DeleteBytesRequest.Builder() .setDeleteAll(true) .build(); client.deleteBytes(deleteAllRequest) .addOnSuccessListener(result -> Log.d(TAG, "Any data found and deleted? " + result));
Котлин
val deleteAllRequest = DeleteBytesRequest.Builder() .setDeleteAll(true) .build() client.deleteBytes(deleteAllRequest) .addOnSuccessListener { result: Boolean -> Log.d(TAG, "Any data found and deleted? $result") }
Сквозное шифрование
Чтобы сквозное шифрование было доступно, устройство должно работать под управлением Android 9 или более поздней версии, а пользователь должен установить блокировку экрана (PIN-код, графический ключ или пароль) для своего устройства. Вы можете проверить, будет ли доступно шифрование на устройстве, вызвав isEndToEndEncryptionAvailable()
.
В следующем примере показано, как проверить, будет ли доступно шифрование во время резервного копирования в облаке:
client.isEndToEndEncryptionAvailable()
.addOnSuccessListener { result ->
Log.d(TAG, "Will Block Store cloud backup be end-to-end encrypted? $result")
}
Включить облачное резервное копирование
Чтобы включить резервное копирование в облаке, добавьте метод setShouldBackupToCloud()
в свой объект StoreBytesData
. Block Store будет периодически создавать резервные копии в облаке байтов, сохраненных, если для setShouldBackupToCloud()
задано значение true.
В следующем примере показано, как включить облачное резервное копирование , только если облачное резервное копирование зашифровано сквозным шифрованием :
val client = Blockstore.getClient(this)
val storeBytesDataBuilder = StoreBytesData.Builder()
.setBytes(/* BYTE_ARRAY */)
client.isEndToEndEncryptionAvailable()
.addOnSuccessListener { isE2EEAvailable ->
if (isE2EEAvailable) {
storeBytesDataBuilder.setShouldBackupToCloud(true)
Log.d(TAG, "E2EE is available, enable backing up bytes to the cloud.")
client.storeBytes(storeBytesDataBuilder.build())
.addOnSuccessListener { result ->
Log.d(TAG, "stored: ${result.getBytesStored()}")
}.addOnFailureListener { e ->
Log.e(TAG, “Failed to store bytes”, e)
}
} else {
Log.d(TAG, "E2EE is not available, only store bytes for D2D restore.")
}
}
Как проверить
Используйте следующие методы во время разработки, чтобы протестировать потоки восстановления.
Удаление/переустановка того же устройства
Если пользователь включает службы резервного копирования (это можно проверить в разделе «Настройки» > «Google» > «Резервное копирование» ), данные Block Store сохраняются при удалении/переустановке приложения.
Вы можете выполнить следующие шаги для тестирования:
- Интегрируйте API BlockStore в тестовое приложение.
- Используйте тестовое приложение, чтобы вызвать BlockStore API для хранения ваших данных.
- Удалите тестовое приложение, а затем переустановите его на том же устройстве.
- Используйте тестовое приложение, чтобы вызвать BlockStore API для извлечения ваших данных.
- Убедитесь, что полученные байты совпадают с теми, которые были сохранены до удаления.
Устройство к устройству
В большинстве случаев для этого потребуется сброс настроек целевого устройства до заводских. Затем вы можете войти в процесс восстановления беспроводной сети Android или восстановления кабеля Google (для поддерживаемых устройств).
Облачное восстановление
- Интегрируйте API Blockstore в тестовое приложение. Тестовое приложение необходимо отправить в Play Store.
- На исходном устройстве используйте тестовое приложение, чтобы вызвать Blockstore API для хранения ваших данных, при этом для параметра shouldBackUpToCloud установлено значение true.
- Для устройств O и выше вы можете вручную запустить облачное резервное копирование Block Store: перейдите в «Настройки»> «Google»> «Резервное копирование» и нажмите кнопку «Создать резервную копию сейчас».
- Чтобы убедиться, что резервное копирование в облачное хранилище Block Store выполнено успешно, вы можете:
- После завершения резервного копирования найдите строки журнала с тегом «CloudSyncBpTkSvc».
- Вы должны увидеть такие строки: «......, CloudSyncBpTkSvc: результат синхронизации: УСПЕШНО, ..., загруженный размер: XXX байт ...»
- После облачного резервного копирования Block Store наступает 5-минутный период «остывания». В течение этих 5 минут нажатие кнопки «Создать резервную копию» не вызовет еще одну резервную копию в облачном хранилище Block Store.
- Чтобы убедиться, что резервное копирование в облачное хранилище Block Store выполнено успешно, вы можете:
- Сбросьте настройки целевого устройства до заводских настроек и выполните процедуру восстановления в облаке. Выберите, чтобы восстановить тестовое приложение во время процесса восстановления. Дополнительные сведения о потоках облачного восстановления см. в разделе Поддерживаемые потоки облачного восстановления .
- На целевом устройстве используйте тестовое приложение, чтобы вызвать Blockstore API для получения ваших данных.
- Убедитесь, что полученные байты совпадают с теми, которые были сохранены на исходном устройстве.
Требования к устройству
Сквозное шифрование
- Сквозное шифрование поддерживается на устройствах под управлением Android 9 (API 29) и выше.
- На устройстве должна быть установлена блокировка экрана с помощью PIN-кода, графического ключа или пароля, чтобы сквозное шифрование было включено и правильно шифровало данные пользователя.
Поток восстановления с устройства на устройство
Для восстановления с устройства на устройство потребуется исходное устройство и целевое устройство. Это будут два устройства, которые передают данные.
Исходные устройства должны работать под управлением Android 6 (API 23) и выше для резервного копирования.
Целевые устройства под управлением Android 9 (API 29) и выше, чтобы иметь возможность восстановления.
Дополнительную информацию о процессе восстановления с устройства на устройство можно найти здесь .
Облачное резервное копирование и восстановление потока
Для резервного копирования и восстановления в облаке потребуются исходное и целевое устройства.
Исходные устройства должны работать под управлением Android 6 (API 23) и выше для резервного копирования.
Целевые устройства поддерживаются в зависимости от их поставщиков. Устройства Pixel могут использовать эту функцию с Android 9 (API 29), а все остальные устройства должны работать под управлением Android 12 (API 31) или более поздней версии.