Viele Nutzer verwalten ihre eigenen Anmeldedaten, wenn sie ein neues Android-Gerät einrichten. Dieser manuelle Prozess kann eine Herausforderung darstellen und führt oft zu einer schlechten Nutzererfahrung. Die Block Store API, eine auf Google Play-Diensten basierende Bibliothek, möchte dieses Problem lösen, indem sie Apps die Möglichkeit bietet, Nutzeranmeldedaten ohne die Komplexität oder das Sicherheitsrisiko zu speichern, die mit dem Speichern von Nutzerpasswörtern verbunden sind.
Mit der Block Store API kann Ihre App Daten speichern, die sie später abrufen kann, um Nutzer auf einem neuen Gerät noch einmal zu authentifizieren. Dies ermöglicht den Nutzern eine nahtlose Nutzung, da sie keinen Anmeldebildschirm sehen müssen, wenn sie Ihre App zum ersten Mal auf dem neuen Gerät starten.
Die Nutzung von Block Store bietet unter anderem folgende Vorteile:
- Verschlüsselte Lösung zum Speichern von Anmeldedaten für Entwickler Anmeldedaten werden nach Möglichkeit mit Ende-zu-Ende-Verschlüsselung geschützt.
- Speichern Sie Tokens anstelle von Nutzernamen und Passwörtern.
- Sorgen Sie für eine reibungslose Anmeldung.
- Nutzer müssen sich nicht um komplizierte Passwörter kümmern müssen.
- Google überprüft die Identität des Nutzers.
Hinweis
Führen Sie die Schritte in den folgenden Abschnitten aus, um Ihre App vorzubereiten.
Eigene Anwendung konfigurieren
Fügen Sie in der Datei build.gradle
auf Projektebene sowohl im Abschnitt buildscript
als auch im Abschnitt allprojects
das Maven-Repository von Google ein:
buildscript {
repositories {
google()
mavenCentral()
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
Fügen Sie die Abhängigkeit der Google Play-Dienste für die Block Store API der Gradle-Build-Datei Ihres Moduls hinzu. Diese ist in der Regel app/build.gradle
:
dependencies {
implementation 'com.google.android.gms:play-services-auth-blockstore:16.2.0'
}
Funktionsweise
Block Store ermöglicht es Entwicklern, Arrays mit bis zu 16 Byte zu speichern und wiederherzustellen. So können Sie wichtige Informationen zur aktuellen Nutzersitzung speichern und diese Informationen beliebig speichern. Diese Daten können mit Ende-zu-Ende-Verschlüsselung geschützt werden. Die Infrastruktur, die Block Store unterstützt, basiert auf der Sicherungs- und Wiederherstellungsinfrastruktur.
In diesem Leitfaden wird der Anwendungsfall zum Speichern eines Nutzertokens im Block Store beschrieben. Die folgenden Schritte beschreiben, wie eine App funktioniert, die Block Store verwendet:
- Während des Authentifizierungsvorgangs Ihrer App oder zu einem beliebigen späteren Zeitpunkt können Sie das Authentifizierungstoken des Nutzers im Block Store speichern, um es später abzurufen.
- Das Token wird lokal gespeichert und kann nach Möglichkeit mit Ende-zu-Ende-Verschlüsselung in der Cloud gesichert werden.
- Die Daten werden übertragen, wenn der Nutzer auf einem neuen Gerät einen Wiederherstellungsvorgang startet.
- Wenn der Nutzer deine App während des Wiederherstellungsvorgangs wiederherstellt, kann sie das gespeicherte Token aus dem Block Store auf dem neuen Gerät abrufen.
Token speichern
Wenn sich ein Nutzer bei Ihrer App anmeldet, können Sie das für diesen Nutzer generierte Authentifizierungstoken im Block Store speichern. Sie können dieses Token mit einem eindeutigen Schlüsselpaarwert von maximal 4 KB pro Eintrag speichern.
Rufen Sie zum Speichern des Tokens setBytes()
und setKey()
in einer Instanz von StoreBytesData.Builder
auf, um die Anmeldedaten des Nutzers auf dem Quellgerät zu speichern. Nachdem Sie das Token mit Block Store gespeichert haben, wird es verschlüsselt und lokal auf dem Gerät gespeichert.
Das folgende Beispiel zeigt, wie das Authentifizierungstoken auf dem lokalen Gerät gespeichert wird:
Java
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));
Kotlin
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) }
Standardtoken verwenden
Daten, die mit StoreBytes ohne Schlüssel gespeichert werden, verwenden den Standardschlüssel BlockstoreClient.DEFAULT_BYTES_DATA_KEY.
Java
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));
Kotlin
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) }
Token abrufen
Wenn ein Nutzer später den Wiederherstellungsprozess auf einem neuen Gerät durchläuft, überprüfen die Google Play-Dienste den Nutzer und rufen dann Ihre Block Store-Daten ab. Der Nutzer hat der Wiederherstellung Ihrer App-Daten im Rahmen des Wiederherstellungsvorgangs bereits zugestimmt. Daher sind keine zusätzlichen Einwilligungen erforderlich. Wenn der Nutzer deine App öffnet, kannst du dein Token vom Block Store anfordern, indem du retrieveBytes()
aufrufst.
Das abgerufene Token kann dann verwendet werden, damit der Nutzer auf dem neuen Gerät angemeldet bleibt.
Das folgende Beispiel zeigt, wie mehrere Tokens basierend auf bestimmten Schlüsseln abgerufen werden.
Java
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));
Kotlin
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) }
Alle Tokens werden abgerufen.
Das folgende Beispiel zeigt, wie alle im BlockStore gespeicherten Tokens abgerufen werden können.
Java
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));
Kotlin
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) }
Das folgende Beispiel zeigt, wie der Standardschlüssel abgerufen wird.
Java
BlockStoreClient client = Blockstore.getClient(this); RetrieveBytesRequest retrieveRequest = new RetrieveBytesRequest.Builder() .setKeys(Arrays.asList(BlockstoreClient.DEFAULT_BYTES_DATA_KEY)) .build(); client.retrieveBytes(retrieveRequest);
Kotlin
val client = Blockstore.getClient(this) val retrieveRequest = RetrieveBytesRequest.Builder() .setKeys(Arrays.asList(BlockstoreClient.DEFAULT_BYTES_DATA_KEY)) .build() client.retrieveBytes(retrieveRequest)
Tokens löschen
Das Löschen von Tokens aus BlockStore kann aus folgenden Gründen erforderlich sein:
- Die Nutzenden durchlaufen den User Flow für die Abmeldung.
- Token wurde widerrufen oder ist ungültig.
Ähnlich wie beim Abrufen von Tokens können Sie angeben, welche Tokens gelöscht werden müssen, indem Sie ein Array von Schlüsseln festlegen, die gelöscht werden müssen.
Unten sehen Sie ein Beispiel zum Löschen bestimmter Schlüssel.
Java
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)
Kotlin
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)
Alle Tokens löschen
Im folgenden Beispiel werden alle derzeit im BlockStore gespeicherten Tokens gelöscht:
Java
// 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));
Kotlin
val deleteAllRequest = DeleteBytesRequest.Builder() .setDeleteAll(true) .build() client.deleteBytes(deleteAllRequest) .addOnSuccessListener { result: Boolean -> Log.d(TAG, "Any data found and deleted? $result") }
Ende-zu-Ende-Verschlüsselung
Damit eine Ende-zu-Ende-Verschlüsselung verfügbar ist, muss auf dem Gerät Android 9 oder höher installiert sein und der Nutzer muss eine Displaysperre (PIN, Muster oder Passwort) für sein Gerät eingerichtet haben. Sie können prüfen, ob die Verschlüsselung auf dem Gerät verfügbar ist, indem Sie isEndToEndEncryptionAvailable()
aufrufen.
Das folgende Beispiel zeigt, wie Sie prüfen können, ob die Verschlüsselung während einer Cloud-Sicherung verfügbar ist:
client.isEndToEndEncryptionAvailable()
.addOnSuccessListener { result ->
Log.d(TAG, "Will Block Store cloud backup be end-to-end encrypted? $result")
}
Cloud-Sicherung aktivieren
Fügen Sie dem StoreBytesData
-Objekt die Methode setShouldBackupToCloud()
hinzu, um die Cloud-Sicherung zu aktivieren. Block Store erstellt regelmäßig eine Sicherung der gespeicherten Byte in der Cloud, wenn setShouldBackupToCloud()
auf „true“ gesetzt ist.
Das folgende Beispiel zeigt, wie die Cloud-Sicherung nur dann aktiviert wird, wenn die Cloud-Sicherung mit Ende-zu-Ende-Verschlüsselung geschützt ist:
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.")
}
}
Testen
Verwenden Sie während der Entwicklung die folgenden Methoden, um die Wiederherstellungsabläufe zu testen.
Gleiches Gerät deinstallieren/neu installieren
Wenn der Nutzer die Sicherungsdienste aktiviert (die Option kann unter Einstellungen > Google > Sicherung aktiviert werden), werden Block Store-Daten für die gesamte Deinstallation/Neuinstallation der App beibehalten.
Gehen Sie dazu so vor:
- Binden Sie die BlockStore API in Ihre Test-App ein.
- Verwenden Sie die Test-App, um die BlockStore API zum Speichern Ihrer Daten aufzurufen.
- Deinstallieren Sie die Test-App und installieren Sie sie dann auf demselben Gerät neu.
- Verwenden Sie die Test-App, um die BlockStore API zum Abrufen Ihrer Daten aufzurufen.
- Die abgerufenen Byte müssen mit denen übereinstimmen, die vor der Deinstallation gespeichert wurden.
Gerät zu Gerät
In den meisten Fällen ist es dazu erforderlich, das Zielgerät auf die Werkseinstellungen zurückzusetzen. Anschließend können Sie den Vorgang für die kabellose Wiederherstellung von Android-Geräten oder die Google-Kabelwiederherstellung (bei unterstützten Geräten) aufrufen.
Cloud-Wiederherstellung
- Binden Sie die Blockstore API in Ihre Test-App ein. Die Test-App muss an den Play Store gesendet werden.
- Verwenden Sie auf dem Quellgerät die Test-App, um die Blockstore API zum Speichern Ihrer Daten aufzurufen. Der Wert sollte auf „true“ festgelegt sein.
- Bei Geräten mit O und höher können Sie manuell eine Block Store-Cloudsicherung auslösen: Gehen Sie zu Einstellungen > Google > Sicherung und klicken Sie auf die Schaltfläche „Jetzt sichern“.
- So prüfen Sie, ob die Block Store-Cloudsicherung erfolgreich war:
- Suchen Sie nach Abschluss der Sicherung nach Logzeilen mit dem Tag „CloudSyncBpTkSvc“.
- Sie sollten folgende Zeilen sehen: „......, CloudSyncBpTkSvc: sync result: SUCCESS, ..., uploaded size: XXX bytes ...”
- Nach einem Block Store-Cloud-Back-up folgt eine 5-minütige Wartezeit. Innerhalb dieser 5 Minuten wird durch Klicken auf die Schaltfläche „Jetzt sichern“ keine weitere Block Store-Cloudsicherung ausgelöst.
- So prüfen Sie, ob die Block Store-Cloudsicherung erfolgreich war:
- Setzen Sie das Zielgerät auf die Werkseinstellungen zurück und führen Sie die Wiederherstellung über die Cloud durch. Wählen Sie diese Option aus, um die Test-App während des Wiederherstellungsvorgangs wiederherzustellen. Weitere Informationen zu Cloud-Wiederherstellungsprozessen finden Sie unter Unterstützte Cloud-Wiederherstellungsabläufe.
- Verwenden Sie auf dem Zielgerät die Test-App, um die Blockstore API zum Abrufen Ihrer Daten aufzurufen.
- Prüfen Sie, ob die abgerufenen Byte mit den auf dem Quellgerät gespeicherten Byte übereinstimmen.
Geräteanforderungen
Ende-zu-Ende-Verschlüsselung
- Die Ende-zu-Ende-Verschlüsselung wird auf Geräten mit Android 9 (API 29) und höher unterstützt.
- Auf dem Gerät muss eine Displaysperre mit einer PIN, einem Muster oder einem Passwort eingerichtet sein, damit die Ende-zu-Ende-Verschlüsselung aktiviert und die Nutzerdaten korrekt verschlüsselt werden können.
Ablauf der Geräte-zu-Gerät-Wiederherstellung
Für die Wiederherstellung von Gerät zu Gerät benötigen Sie ein Quell- und ein Zielgerät. Das sind die beiden Geräte, die Daten übertragen.
Auf den Quellgeräten muss Android 6 (API 23) oder höher ausgeführt werden, damit die Sicherung durchgeführt werden kann.
Targeting auf Geräte mit Android 9 (API 29) und höher, um Wiederherstellung möglich zu machen
Weitere Informationen zur Wiederherstellung von einem Gerät zu einem anderen Gerät finden Sie hier.
Cloud-Sicherungs- und -Wiederherstellungsablauf
Zum Sichern und Wiederherstellen in der Cloud sind ein Quell- und ein Zielgerät erforderlich.
Auf den Quellgeräten muss Android 6 (API 23) oder höher ausgeführt werden, damit die Sicherung durchgeführt werden kann.
Zielgeräte werden je nach Anbieter unterstützt. Pixel-Geräte können diese Funktion ab Android 9 (API 29) nutzen. Auf allen anderen Geräten muss Android 12 (API 31) oder höher installiert sein.