ブロックストア

コレクションでコンテンツを整理 必要に応じて、コンテンツの保存と分類を行います。

多くのユーザーが新しい Android デバイスをセットアップする際に自身の認証情報を管理します。この手動プロセスは難しく、ユーザー エクスペリエンスの低下につながることがよくあります。Google Play 開発者サービスを利用したライブラリである Block Store API は、ユーザー パスワードの保存に伴う複雑さやセキュリティ リスクなしでアプリがユーザー認証情報を保存できるようにすることで、この問題を解決しようとしています。

Block Store API を使用すると、アプリは、後で新しいデバイスでユーザーを再認証するために取得できるユーザー認証情報を保存できます。こうすることで、ユーザーが新しいデバイスで初めてアプリを開いたときに、ログイン画面を表示する必要がなくなるため、よりシームレスなエクスペリエンスが実現します。

Block Store を使用するメリットは次のとおりです。

  • デベロッパー向けの暗号化された認証情報ストレージ ソリューション。可能であれば、認証情報はエンドツーエンドで暗号化されます。
  • ユーザー名とパスワードの代わりにトークンを保存します。
  • ログインフローをスムーズにする。
  • 複雑なパスワードを管理する手間を省くことができます。
  • Google がユーザーの本人確認を行います。

始める前に

アプリを準備するには、以下のセクションに示す手順を完了します。

アプリを構成する

プロジェクト レベルの build.gradle ファイルの buildscript セクションと allprojects セクションの両方に Google の Maven リポジトリを含めます。

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

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

Block Store API の Google Play 開発者サービスの依存関係をモジュールの Gradle ビルドファイル(通常は app/build.gradle)に追加します。

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

仕組み

ブロックストアは、エンドツーエンドの暗号化と、バックアップおよび復元用インフラストラクチャ上に構築されたトークンベースのログイン メカニズムです。Block Store を使用するアプリの仕組みを次に示します。

  1. アプリの認証フロー中またはその後のいずれかの時点で、ユーザーの認証トークンをブロックブロック ストアに保存して、後で取得できます。
  2. トークンはローカルに保存されます。また、可能であればクラウドにバックアップし、エンドツーエンドで暗号化することも可能です。
  3. ユーザーが新しいデバイスで復元フローを開始すると、データが転送されます。
  4. 復元フロー中にユーザーがアプリを復元した場合、アプリは新しいデバイスのブロックストアから保存済みトークンを取得できます。

トークンの保存

ユーザーがアプリにログインしたら、そのユーザー用に生成した認証トークンをブロックストアに保存できます。これを行うには、StoreBytesData.Builder のインスタンスで setBytes() を呼び出し、ユーザーの認証情報をソースデバイスに保存します。Block Store でトークンを保存すると、トークンは暗号化され、デバイスにローカルに保存されます。

次のサンプルは、認証トークンをローカル デバイスに保存する方法を示しています。

val client = Blockstore.getClient(this)
val data = StoreBytesData.Builder()
        .setBytes(/* BYTE_ARRAY */)
        .build()
client.storeBytes(data)
        .addOnSuccessListener{ result ->
            Log.d(TAG, "Stored: ${result} bytes")
        }
        .addOnFailureListener { e ->
            Log.e(TAG, “Failed to store bytes”, e)
        }

トークンの取得

その後、ユーザーが新しいデバイスで復元フローを実行すると、Google Play 開発者サービスはまずユーザーを確認し、次にブロックストア データを取得します。ユーザーは復元フローの一環としてアプリデータを復元することに同意しているため、追加の同意は必要ありません。ユーザーがアプリを開いたときに、retrieveBytes() を呼び出して、Block Store からトークンをリクエストできます。取得したトークンを使用して、新しいデバイスでユーザーのログイン状態を維持できます。

次のサンプルは、以前に Block Store で保存されている暗号化トークンを取得する方法を示しています。

val client = Blockstore.getClient(this)
client.retrieveBytes()
            .addOnSuccessListener { result ->
                Log.d(TAG, "Retrieved: ${String(result)}")
            }
            .addOnFailureListener { e ->
                Log.e(TAG, "Failed to retrieve bytes", e)
            }
}

エンドツーエンドの暗号化

エンドツーエンドの暗号化を利用できるようにするには、デバイスに Android 9 以降が搭載され、ユーザーがデバイスに画面ロック(PIN、パターン、パスワード)を設定している必要があります。isEndToEndEncryptionAvailable() を呼び出すことで、デバイスで暗号化が利用可能かどうかを確認できます。

次のサンプルは、クラウドのバックアップ中に暗号化が利用可能かどうかを確認する方法を示しています。

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

クラウド バックアップを有効にする

クラウド バックアップを有効にするには、StoreBytesData オブジェクトに setShouldBackupToCloud() メソッドを追加します。setShouldBackupToCloud() が true に設定されている場合、Block Store は保存されたバイトを定期的にクラウドにバックアップします。

次のサンプルは、クラウド バックアップがエンドツーエンドで暗号化されている場合にのみ、クラウド バックアップを有効にする方法を示しています。

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] > [バックアップ] で確認できます)、アンインストールと再インストール後もブロックストア データは保持されます。

次の手順に沿ってテストしてください。

  1. BlockStore API をテストアプリに統合します。
  2. テストアプリを使用して BlockStore API を呼び出し、データを保存します。
  3. テストアプリをアンインストールしてから、同じデバイスにアプリを再インストールします。
  4. テストアプリを使用して BlockStore API を呼び出し、データを取得します。
  5. 取得されたバイト数が、アンインストール前に保存されたバイト数と同じであることを確認します。

デバイス間

ほとんどの場合、この段階で対象デバイスを出荷時設定にリセットする必要があります。その後、Android ワイヤレス復元フローまたは Google ケーブル復元(サポートされているデバイスの場合)を入力できます。

クラウドの復元

  1. Blockstore API をテストアプリに統合します。テストアプリは Play ストアに送信する必要があります。
  2. ソースデバイスで、テストアプリを使用して Blockstore API を呼び出し、shouldBackUpToCloud を true に設定してデータを保存します。
  3. O 以降のデバイスでは、Block Store クラウド バックアップを手動でトリガーできます。[設定] > [Google] > [バックアップ] に移動し、[今すぐバックアップ] ボタンをクリックしてください。
    1. Block Store のクラウド バックアップが成功したことを確認するには、次の操作を行います。
      1. バックアップが終了したら、「CloudSyncBpTkSvc」タグが付いたログ行を検索します。
      2. 「......, CloudSyncBpTkSvc: sync result: SUCCESS, ..., uploaded size: XXX bytes ...」といった行が表示されます。
    2. Block Store のクラウド バックアップの後、5 分間のクールダウン期間があります。その 5 分以内に [今すぐバックアップ] ボタンをクリックしても、別の Block Store クラウド バックアップがトリガーされることはありません。
  4. 対象のデバイスを出荷時の設定にリセットし、クラウド復元フローを進めます。復元フロー中にテストアプリを復元する場合に選択します。クラウド復元フローの詳細については、サポートされているクラウド復元フローをご覧ください。
  5. 対象デバイスで、テストアプリを使用して Blockstore API を呼び出し、データを取得します。
  6. 取得したバイトがソースデバイスに保存されているバイトと同じであることを確認します。

デバイスの要件

エンドツーエンドの暗号化

  • エンドツーエンドの暗号化は、Android 9(API 29)以降を搭載しているデバイスでサポートされています。
  • エンドツーエンドの暗号化を有効にして、ユーザーのデータを正しく暗号化するには、デバイスで PIN、パターン、またはパスワードによる画面ロックを設定する必要があります。

デバイス間の復元フロー

デバイスを復元するには、ソースデバイスとターゲット デバイスが必要です。データの転送を行うデバイスが 2 台あります。

ソースデバイスをバックアップするには、Android 6(API 23)以降を実行している必要があります。

Android 9(API 29)以降を搭載しているデバイスをターゲットにし、復元できるようにします。

デバイス間の復元フローについて詳しくは、こちらを参照してください。

クラウドのバックアップと復元のフロー

クラウドのバックアップと復元には、ソースデバイスとターゲット デバイスが必要です。

ソースデバイスをバックアップするには、Android 6(API 23)以降を実行している必要があります。

Target デバイスは、それぞれのベンダーに基づいてサポートされています。Google Pixel は Android 9(API 29)からこの機能を使用できます。その他のすべてのデバイスは Android 12(API 31)以降を搭載している必要があります。