Sklep blokowy

Wielu użytkowników nadal samodzielnie zarządza danymi logowania podczas konfigurowania nowego urządzenia z Androidem urządzenia. Ten ręczny proces może być trudny i często kończy się użytkowników. Block Store API, biblioteka wykorzystująca Google Play , rozwiązuje ten problem, udostępniając aplikacjom sposób zapisywania dane logowania użytkownika bez złożoności i bezpieczeństwa związanych z zapisywaniem haseł użytkowników.

Interfejs Block Store API umożliwia aplikacji przechowywanie danych, które może później wykorzystać pobrać w celu ponownego uwierzytelnienia użytkowników na nowym urządzeniu. Dzięki temu możemy uzyskać bezproblemową obsługę, ponieważ użytkownik nie musi widzieć ekranu logowania. przy pierwszym uruchomieniu aplikacji na nowym urządzeniu.

Zalety korzystania z funkcji Block Store:

  • Rozwiązanie dla deweloperów do przechowywania zaszyfrowanych danych logowania. Dane logowania: pełne szyfrowanie, gdy tylko jest to możliwe.
  • Zapisywanie tokenów zamiast nazw użytkowników i haseł.
  • Wyeliminuj problemy związane z procesami logowania.
  • Ułatw użytkownikom zarządzanie złożonymi hasłami.
  • Google weryfikuje tożsamość użytkownika.

Zanim zaczniesz

Aby przygotować aplikację, wykonaj czynności opisane w poniższych sekcjach.

Konfiguracja aplikacji

W pliku build.gradle na poziomie projektu uwzględnij narzędzie Maven Google w buildscript i allprojects sekcje:

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

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

Dodaj Usługi Google Play. zależność od interfejsu Block Store API pliku build.gradle modułu, czyli zwykle app/build.gradle:

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

Jak to działa

Magazyn blokowy umożliwia programistom zapisywanie i przywracanie tablic o wielkości do 16 bajtów. Dzięki temu możesz zapisać ważne informacje o bieżącej sesji użytkownika i możesz je zapisać w dowolny sposób. Dane te mogą być w pełni szyfrowane, a infrastruktura obsługująca magazyn blokowy jest zbudowana na infrastrukturze do tworzenia i przywracania kopii zapasowych.

Z tego przewodnika dowiesz się, jak zapisać token użytkownika w Block Store. Aby zobaczyć, jak działa aplikacja korzystająca z funkcji Block Store:

  1. W trakcie procesu uwierzytelniania w aplikacji lub w dowolnym momencie po jej zakończeniu możesz przechowywać token uwierzytelniania użytkownika do Block Store w celu późniejszego pobrania.
  2. Token będzie przechowywany lokalnie. Można też utworzyć jego kopię zapasową w chmurze. pełne szyfrowanie, gdy tylko jest to możliwe.
  3. Dane są przenoszone, gdy użytkownik rozpocznie proces przywracania na nowym urządzeniu.
  4. Jeśli użytkownik przywróci aplikację w trakcie procesu przywracania, będzie ona mogła wtedy pobierz zapisany token z Block Store na nowym urządzeniu.

Zapisuję token

Gdy użytkownik loguje się w Twojej aplikacji, możesz zapisać wygenerowany dla niego token uwierzytelniania w programie Block Store. Możesz przechowywać ten token przy użyciu unikalnej wartości pary kluczy o maksymalnym rozmiarze 4 KB na wpis. Aby zapisać token, wywołaj setBytes() i setKey() w instancji StoreBytesData.Builder pozwalającego zapisać dane logowania użytkownika na urządzeniu źródłowym. Po zapisaniu tokena za pomocą Block Store token jest szyfrowany i przechowywany lokalnie na urządzeniu.

Z przykładu poniżej dowiesz się, jak zapisać token uwierzytelniania w urządzenie lokalne:

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

Użyj tokena domyślnego

Dane zapisywane za pomocą StoreBytes bez klucza używają domyślnego klucza 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)
    }

Pobieram token

Później, gdy użytkownik wykona proces przywracania na nowym urządzeniu urządzenia, Usługi Google Play najpierw weryfikuje użytkownika, a następnie pobiera blokadę. Przechowuj dane. Użytkownik zgodził się już przywrócić dane aplikacji w ramach w procesie przywracania danych, więc nie są wymagane dodatkowe zgody. Gdy użytkownik otworzy możesz poprosić o token do sklepu Block Store, wywołując retrieveBytes() Pobrany token może następnie posłużyć do utrzymywania zalogowania użytkownika na nowym urządzenia.

Z przykładu poniżej dowiesz się, jak pobrać wiele tokenów na podstawie konkretnych kluczy.

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

Pobieram wszystkie tokeny.

Poniżej znajdziesz przykład pobierania wszystkich tokenów zapisanych w BlockStore.

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

Poniżej znajdziesz przykład pobierania klucza domyślnego.

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)

Usuwam tokeny

Usunięcie tokenów z BlockStore może być wymagane z tych powodów:

  • Użytkownik przechodzi proces wylogowania.
  • Token został unieważniony lub jest nieprawidłowy.

Podobnie jak w przypadku pobierania tokenów, możesz określić, które tokeny należy usunąć, ustawiając tablicę kluczy, które wymagają usunięcia.

Poniżej znajdziesz przykład usuwania niektórych kluczy.

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)

Usuń wszystkie tokeny

Ten przykład spowoduje usunięcie wszystkich tokenów zapisanych obecnie w BlockStore:

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

Pełne szyfrowanie

Aby można było udostępnić pełne szyfrowanie, urządzenie musi być z Androidem 9 lub nowszym, a użytkownik musi ustawić blokadę ekranu. (kod PIN, wzór lub hasło). Możesz sprawdzić, czy szyfrowanie będą dostępne na urządzeniu, dzwoniąc pod numer isEndToEndEncryptionAvailable().

Z przykładu poniżej dowiesz się, jak sprawdzić, czy szyfrowanie będzie dostępne podczas tworzenie kopii zapasowych w chmurze:

client.isEndToEndEncryptionAvailable()
        .addOnSuccessListener { result ->
          Log.d(TAG, "Will Block Store cloud backup be end-to-end encrypted? $result")
        }

Włącz kopię zapasową w chmurze

Aby włączyć tworzenie kopii zapasowych w chmurze, dodaj: setShouldBackupToCloud() do StoreBytesData obiektu. Magazyn bloków będzie okresowo tworzyć w chmurze kopie zapasowe bajtów zapisanych podczas setShouldBackupToCloud() ma wartość true (prawda).

Poniższy przykład pokazuje, jak włączyć kopię zapasową w chmurze tylko wtedy, gdy kopia zapasowa w chmurze jest włączona są w pełni szyfrowane:

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.")
          }
        }

Jak to sprawdzić

Podczas programowania korzystaj z tych metod, aby przetestować przywracanie procesu.

Odinstalowanie/ponowna instalacja na tym samym urządzeniu

Jeśli użytkownik włączy usługi kopii zapasowej (możesz to sprawdzić, klikając Ustawienia > Google > Kopia zapasowa). Zablokuj dane Sklepu, po odinstalowaniu/instalacji aplikacji.

Aby to sprawdzić, wykonaj te czynności:

  1. Zintegruj interfejs BlockStore API z aplikacją testową.
  2. Użyj aplikacji testowej, aby wywołać interfejs BlockStore API w celu przechowywania danych.
  3. Odinstaluj aplikację testową, a potem zainstaluj ją ponownie na tym samym urządzeniu.
  4. Użyj aplikacji testowej, aby wywołać interfejs BlockStore API w celu pobrania danych.
  5. Sprawdź, czy pobrane bajty są takie same jak zapisane wcześniej odinstalowywanie.

Połączenia między urządzeniami

W większości przypadków będzie to wymagało przywrócenia urządzenia docelowego do ustawień fabrycznych. Dostępne opcje a następnie rozpocznij proces przywracania bezprzewodowego na Androidzie. lub przywracanie kabla Google (na obsługiwanych urządzeniach).

Przywracanie w chmurze

  1. Zintegruj interfejs Blockstore API z aplikacją testową. Aplikacja testowa musi być przesłane do Sklepu Play.
  2. Na urządzeniu źródłowym użyj aplikacji testowej, aby wywołać interfejs Blockstore API w celu przechowywania z powinienBackUpToCloud o wartości „true” (prawda).
  3. W przypadku urządzeń w wersji O lub nowszej możesz ręcznie aktywować kopię zapasową w chmurze Block Store: wybierz Ustawienia > Google > Kopia zapasowa kliknij przycisk „Utwórz kopię zapasową teraz”.
    1. Aby sprawdzić, czy kopia zapasowa w chmurze Block Store została utworzona, możesz:
      1. Po zakończeniu tworzenia kopii zapasowej wyszukaj wiersze dziennika z tagiem „CloudSyncBpTkSvc”.
      2. Powinny się wyświetlić następujące wiersze: „......, CloudSyncBpTkSvc: sync” wynik: SUKCES, ..., rozmiar przesłanego: XXX B ...”
    2. Po utworzeniu kopii zapasowej w chmurze Block Store obowiązuje 5-minutowy okres oczekiwania. W ciągu tych 5 minut kliknięcie przycisku „Utwórz kopię zapasową teraz” przestanie działać. kolejną kopię zapasową w chmurze Block Store.
  4. Przywróć urządzenie docelowe do ustawień fabrycznych i przeprowadź proces przywracania do chmury. Wybierz aby przywrócić aplikację testową podczas procesu przywracania. Więcej informacji na temat: przepływów przywracania w chmurze znajdziesz w artykule Obsługiwane przepływy przywracania w chmurze.
  5. Na urządzeniu docelowym użyj aplikacji testowej, aby wywołać interfejs Blockstore API w celu pobrać dane.
  6. Sprawdź, czy pobrane bajty są takie same jak te zapisane w pliku urządzenia źródłowego.

Wymagania dotyczące urządzenia

Pełne szyfrowanie

  • Pełne szyfrowanie jest obsługiwane na urządzeniach z Androidem 9 (API 29) lub nowszym.
  • Aby można było włączyć pełne szyfrowanie i prawidłowo zaszyfrować dane użytkownika, urządzenie musi mieć ustawioną blokadę ekranu z kodem PIN, wzorem lub hasłem.

Proces przywracania danych między urządzeniami

Aby przywrócić dane z urządzenia, musisz mieć urządzenie źródłowe i docelowe. Będą to urządzenia służące do przenoszenia danych.

Na urządzeniach źródłowych musi być zainstalowany Android 6 (API 23) lub nowszy, aby można było utworzyć kopię zapasową.

Określ kierowanie urządzeń z Androidem 9 (API 29) lub nowszym, aby mieć możliwość przywracania.

Więcej informacji o procesie przywracania danych z urządzenia na urządzenie znajdziesz tutaj.

Proces tworzenia i przywracania kopii zapasowych w Cloud

Tworzenie i przywracanie kopii zapasowych w chmurze wymaga urządzenia źródłowego i urządzenia docelowego.

Na urządzeniach źródłowych musi być zainstalowany Android 6 (API 23) lub nowszy, aby można było utworzyć kopię zapasową.

Urządzenia docelowe są obsługiwane w zależności od dostawców. Urządzenia Pixel mogą korzystać z tej funkcji w wersji od Androida 9 (API 29), a pozostałe urządzenia muszą mieć zainstalowany Android 12 (API 31) lub nowszy.