Geschäft sperren

Viele Nutzer verwalten weiterhin ihre eigenen Anmeldedaten, wenn sie ein neues Android-Gerät einrichten. Dieser manuelle Prozess kann schwierig sein und zu einer schlechten Nutzererfahrung führen. Die Block Store API, eine Bibliothek mit Google Play-Diensten, bietet dieses Problem. Sie ermöglicht es Apps, Nutzeranmeldedaten zu speichern, ohne dabei das Komplexitätsrisiko zu überschreiten und das mit dem Speichern von Nutzerpasswörtern verbundene Sicherheitsrisiken zu minimieren.

Mit der Block Store API können Sie Daten in Ihrer App speichern, um sie später auf einem neuen Gerät noch einmal zu authentifizieren. Dies ist nutzerfreundlicher, da der Anmeldebildschirm beim ersten Start der App auf dem neuen Gerät nicht angezeigt werden muss.

Die Verwendung des Block Stores hat folgende Vorteile:

  • Verschlüsselte Anmeldedaten-Speicherlösung für Entwickler. Anmeldedaten werden nach Möglichkeit mit Ende-zu-Ende-Verschlüsselung geschützt.
  • Tokens anstelle von Nutzernamen und Passwörtern speichern.
  • Sorgen Sie dafür, dass alles reibungslos funktioniert.
  • Nutzer müssen keine komplizierten Passwörter verwalten.
  • 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 das Maven-Repository von Google in die Abschnitte buildscript und allprojects ein:

buildscript {
  repositories {
    google()
    mavenCentral()
  }
}

allprojects {
  repositories {
    google()
    mavenCentral()
  }
}

Fügen Sie die Google Play-Dienste-Abhängigkeit für die Block Store API in die Gradle-Build-Datei des Moduls ein. Diese ist üblicherweise app/build.gradle:

dependencies {
  implementation 'com.google.android.gms:play-services-auth-blockstore:16.2.0'
}

Funktionsweise

Mit Block Store können Entwickler bis zu 16-Byte-Arrays speichern und wiederherstellen. So können Sie wichtige Informationen über die aktuelle Nutzersitzung speichern und diese Informationen so speichern, wie Sie möchten. Diese Daten können mit Ende-zu-Ende-Verschlüsselung geschützt sein. Die Infrastruktur, die Block Store unterstützt, basiert auf der Infrastruktur von Sicherung und Wiederherstellung.

In dieser Anleitung wird der Anwendungsfall des Speicherns eines Nutzertokens im Block Store behandelt. In den folgenden Schritten wird beschrieben, wie eine App, die Block Store verwendet, funktioniert:

  1. Während der Authentifizierung Ihrer App oder jederzeit danach können Sie das Authentifizierungstoken des Nutzers speichern, um es später abzurufen.
  2. Das Token wird lokal gespeichert und kann, wenn möglich, mit Ende-zu-Ende-Verschlüsselung in der Cloud gesichert werden.
  3. Die Daten werden übertragen, wenn der Nutzer auf einem neuen Gerät einen Wiederherstellungsvorgang initiiert.
  4. Wenn der Nutzer Ihre App während des Wiederherstellungsvorgangs wiederherstellt, kann er das gespeicherte Token aus dem Block Store auf dem neuen Gerät abrufen.

Token speichern

Wenn sich ein Nutzer in Ihrer App anmeldet, können Sie das von ihm generierte Authentifizierungstoken im Block Store speichern. Sie können dieses Token mit einem eindeutigen Schlüsselpaarwert mit einem maximalen Wert von 4 KB pro Eintrag speichern. Rufen Sie zum Speichern des Tokens setBytes() und setKey() auf 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.

Im folgenden Beispiel wird gezeigt, wie Sie das Authentifizierungstoken auf dem lokalen Gerät speichern:

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

Mit StoreBytes ohne Schlüssel gespeicherte Daten verwenden den standardmäßigen Schlü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

Später, wenn ein Nutzer den Wiederherstellungsvorgang auf einem neuen Gerät durchläuft, wird er zuerst von den Google Play-Diensten geprüft und dann die Daten des Block Store abgerufen. Der Nutzer hat bereits zugestimmt, die App-Daten im Rahmen der Wiederherstellung wiederherzustellen. Daher sind keine zusätzlichen Einwilligungen erforderlich. Wenn der Nutzer Ihre App öffnet, können Sie das Token im Block Store anfordern, indem Sie retrieveBytes() aufrufen. Das abgerufene Token kann dann verwendet werden, damit der Nutzer auf dem neuen Gerät angemeldet bleibt.

Das folgende Beispiel zeigt, wie mehrere Tokens auf der Grundlage bestimmter Schlüssel 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

List requestedKeys = 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 Sie alle im BlockStore gespeicherten Tokens abrufen.

Java

BlockstoreClient client = Blockstore.getClient(this)

// Retrieve all data.
RetrieveBytesRequest retrieveRequest = new RetrieveBytesRequest.Builder()
    .setRetrieveAll(true)
    .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)

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 werden gelöscht

Das Löschen von Tokens aus BlockStore kann aus folgenden Gründen erforderlich sein:

  • Nutzer durchläuft Abmeldung.
  • Das Token wurde widerrufen oder ist ungültig.

Ähnlich wie beim Abrufen von Tokens können Sie auch hier ein Array mit Schlüsseln festlegen, die gelöscht werden müssen, um festzulegen, welche Tokens gelöscht werden sollen.

Im Folgenden finden Sie ein Beispiel für das 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

List requestedKeys = 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 die 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. Mit dem Aufruf von isEndToEndEncryptionAvailable() können Sie prüfen, ob die Verschlüsselung auf dem Gerät verfügbar ist.

Im folgenden Beispiel sehen Sie, wie Sie überprüfen können, ob die Verschlüsselung während der 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 Objekt StoreBytesData die Methode setShouldBackupToCloud() hinzu, um die Cloud-Sicherung zu aktivieren. Block Store sichert regelmäßig Sicherungen in den Clouds, wenn setShouldBackupToCloud() als „true“ festgelegt ist.

Im folgenden Beispiel wird gezeigt, wie Sie die Cloud-Sicherung aktivieren, wenn die Cloud-Sicherung mit Ende-zu-Ende-Verschlüsselung läuft:

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 die folgenden Methoden während der Entwicklung, um die Wiederherstellungsabläufe zu testen.

Deinstallation/Neuinstallation desselben Geräts

Wenn der Nutzer Sicherungsdienste aktiviert (kann unter Einstellungen > Google > Sicherung geprüft werden), werden die Block Store-Daten für die Deinstallation/Neuinstallation der App beibehalten.

Gehen Sie dazu so vor:

  1. Binden Sie die BlockStore API in Ihre Test-App ein.
  2. Verwenden Sie die Test-App, um die BlockStore API zum Speichern Ihrer Daten aufzurufen.
  3. Deinstallieren Sie die Test-App und installieren Sie sie anschließend auf demselben Gerät neu.
  4. Verwenden Sie die Test-App, um die BlockStore API aufzurufen, um Ihre Daten abzurufen.
  5. Prüfen Sie, ob die abgerufenen Byte mit den vor der Deinstallation gespeicherten Daten übereinstimmen.

Gerät zu Gerät

In den meisten Fällen muss das Zielgerät auf die Werkseinstellungen zurückgesetzt werden. Anschließend können Sie den Ablauf der kabellosen Wiederherstellung über Android oder die Google-Kabelwiederherstellung (für unterstützte Geräte) eingeben.

Cloud-Wiederherstellung

  1. Binden Sie die Blockstore API in Ihre Test-App ein. Die Test-App muss an den Play Store gesendet werden.
  2. Verwenden Sie auf dem Quellgerät die Test-App, um die Blockstore API aufzurufen, um Ihre Daten zu speichern. Daher sollte „ShouldBackUpToCloud“ auf „true“ gesetzt sein.
  3. Für O- und höhere Geräte können Sie eine Block Store-Cloud-Sicherung manuell auslösen: Rufen Sie Einstellungen > Google > Sicherung auf und klicken Sie auf die Schaltfläche „Jetzt sichern“.
    1. So prüfen Sie, ob die Cloud-Sicherung von Block Store erfolgreich war:
      1. Suchen Sie nach Abschluss der Sicherung nach Logzeilen mit dem Tag „CloudSyncBpTkSvc“.
      2. Sie sollten folgende Zeilen sehen: „......, CloudSyncBpTkSvc: sync result: SUCCESS, ..., uploaded size: XXXbytes ...“
    2. Nach einer Blockspeicher-Cloud-Sicherung gilt für die Wartezeit 5 Minuten. Innerhalb von 5 Minuten wird beim Klicken auf die Schaltfläche „Jetzt sichern“ keine weitere Block Store-Cloud-Sicherung ausgelöst.
  4. Setzen Sie das Zielgerät auf die Werkseinstellungen zurück und führen Sie einen Cloud-Wiederherstellungsvorgang durch. Wählen Sie aus, dass die Test-App während der Wiederherstellung wiederhergestellt werden soll. Weitere Informationen zu Abläufen zur Cloud-Wiederherstellung finden Sie unter Unterstützte Abläufe zur Cloud-Wiederherstellung.
  5. Verwenden Sie auf dem Zielgerät die Test-App, um die Blockstore API aufzurufen, um Ihre Daten abzurufen.
  6. 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 PIN, Muster oder Passwort eingerichtet sein, damit die Ende-zu-Ende-Verschlüsselung aktiviert und die Daten der Nutzer korrekt verschlüsselt werden.

Ablauf für die Wiederherstellung von Gerät zu Gerät

Für die Wiederherstellung von Gerät zu Gerät benötigen Sie ein Quellgerät und ein Zielgerät. Das sind die beiden Geräte, die Daten übertragen.

Auf Quellgeräten muss Android 6 (API 23) oder höher installiert sein.

Richten Sie ein Targeting auf Geräte ein, die Android 9 (API 29 oder höher) haben, damit sie wiederhergestellt werden können.

Weitere Informationen zum Ablauf der Wiederherstellung von Gerät zu Gerät finden Sie hier.

Ablauf der Sicherung und Wiederherstellung in der Cloud

Für das Sichern und Wiederherstellen der Cloud sind ein Quellgerät und ein Zielgerät erforderlich.

Auf Quellgeräten muss Android 6 (API 23) oder höher installiert sein.

Zielgeräte werden je nach Anbieter unterstützt. Pixel kann diese Funktion ab Android 9 (API 29) verwenden. Auf allen anderen Geräten muss Android 12 (API 31) oder höher installiert sein.