在設定新的 Android 時,許多使用者仍然會自行管理憑證 裝置。手動程序相當困難,而且通常會導致 使用者體驗Block Store API 是採用 Google Play 技術的程式庫 服務,不妨透過提供應用程式儲存功能, 使用者憑證,卻沒有與儲存相關的複雜性或安全性風險 使用者密碼。
Block Store API 可讓應用程式儲存資料,以供日後使用 擷取程序,然後在新裝置上重新驗證使用者。這麼做可讓網站 使用者不需要看到登入畫面 以備不時之需
使用 Block Store 的好處如下:
- 適用於開發人員的加密憑證儲存空間解決方案。憑證為 盡可能使用端對端加密
- 儲存權杖,而不是使用者名稱和密碼。
- 避免登入流程中的阻礙。
- 省去管理複雜密碼的負擔。
- Google 會驗證使用者的身分。
事前準備
如要讓應用程式做好準備,請完成下列各節的步驟。
設定應用程式
在專案層級的 build.gradle
檔案中,加入 Google 的 Maven
在您的 buildscript
中和 中
和 allprojects
個區段:
buildscript {
repositories {
google()
mavenCentral()
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
新增 Google Play 服務
Block Store API 依附元件
模組的 Gradle 建構檔案
通常為 app/build.gradle
:
dependencies {
implementation 'com.google.android.gms:play-services-auth-blockstore:16.4.0'
}
運作方式
Block Store 可讓開發人員儲存及還原最多 16 個位元組的陣列。 這樣一來,您就能儲存目前使用者工作階段的重要資訊,也可以視需要儲存這類資訊。這些資料可進行端對端加密處理,支援 Block Store 的基礎架構則以「備份與還原」基礎架構為基礎。
本指南將說明將使用者的權杖儲存至 Block Store 的應用實例。 下列步驟概述採用 Block Store 的應用程式如何運作:
- 在應用程式的驗證流程中或之後,您可以隨時儲存 將使用者驗證權杖新增至 Block Store,以供日後擷取。
- 權杖會儲存在本機,也可備份到雲端 盡可能使用端對端加密
- 使用者在新裝置啟動還原流程時,系統會轉移資料。
- 如果使用者在還原流程中還原應用程式,應用程式可以 在新裝置上從 Block Store 擷取已儲存的權杖。
儲存權杖
使用者登入應用程式時,您可以將先前為使用者產生的驗證權杖儲存至封鎖商店。您可以使用不重複的金鑰組值儲存這個權杖,該值每個項目的上限為 4 KB。
如要儲存權杖,請呼叫 setBytes()
和 setKey()
執行個體
StoreBytesData.Builder
將使用者憑證儲存至來源裝置。儲存符記後
而透過 Block Store,憑證會加密並儲存在裝置本機上。
以下範例顯示如何將驗證權杖儲存至 本機裝置:
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) }
使用預設權杖
在沒有金鑰的情況下,使用 StoreBytes 儲存的資料會使用預設鍵 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) }
擷取權杖
稍後,當使用者在新的
Google Play 服務會先驗證使用者,再擷取您的封鎖
儲存資料。使用者已同意還原您的應用程式資料,
還原流程,因此您不需要另外徵求同意。使用者開啟時
,您可以呼叫
retrieveBytes()
。
擷取到的權杖就能用來讓使用者在新的
裝置。
以下範例說明如何根據特定金鑰擷取多個符記。
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<String, BlockstoreData> blockstoreDataMap = result.getBlockstoreDataMap(); for (Map.Entry<String, BlockstoreData> 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) }
擷取所有權杖。
以下範例說明如何擷取所有儲存至 BlockStore 的權杖。
Java
BlockstoreClient client = Blockstore.getClient(this) // Retrieve all data. RetrieveBytesRequest retrieveRequest = new RetrieveBytesRequest.Builder() .setRetrieveAll(true) .build(); client.retrieveBytes(retrieveRequest) .addOnSuccessListener( result -> { Map<String, BlockstoreData> blockstoreDataMap = result.getBlockstoreDataMap(); for (Map.Entry<String, BlockstoreData> 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) }
以下舉例說明如何擷取預設鍵。
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)
刪除權杖
可能需要從 BlockStore 刪除權杖,原因如下:
- 使用者執行登出使用者流程。
- 權杖已撤銷或無效。
與擷取權杖類似,您可以設定需要刪除的金鑰陣列,藉此指定需要刪除哪些權杖。
以下說明如何刪除特定鍵。
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)
刪除所有權杖
以下範例會刪除目前儲存在 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") }
端對端加密
裝置必須符合下列條件,才能使用端對端加密功能
(搭載 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」>「備份」查看,封鎖商店資料 解除安裝/重新安裝應用程式後仍會保留下來。
測試步驟如下:
- 將 BlockStore API 整合至測試應用程式。
- 請使用測試應用程式叫用 BlockStore API,以便儲存資料。
- 解除安裝測試應用程式,然後在相同裝置上重新安裝應用程式。
- 使用測試應用程式叫用 BlockStore API,以擷取資料。
- 確認擷取的位元組與之前儲存的位元組相同 解除安裝。
裝置間
在大多數情況下,必須將目標裝置恢復原廠設定。你可以 然後進入 Android 無線還原流程 或 Google 傳輸線還原 (適用於支援的裝置)。
雲端還原
- 將 Blockstore API 整合至測試應用程式。測試應用程式必須 產品提交到 Play 商店
- 在來源裝置上,使用測試應用程式叫用 Blockstore API 儲存 您必須將 shouldBackUpToCloud 設為 true。
- 如果是 O 以上裝置,你可以手動觸發 Block Store 雲端備份作業:
前往 [設定] >Google >備份,按一下「立即備份」按鈕。
- 如要確認 Block Store 雲端備份作業是否成功,您可以執行下列操作:
- 備份完成後,搜尋含有標記的記錄行 「CloudSyncBpTkSvc」。
- 您應該會看到類似這樣的行:「......, CloudSyncBpTkSvc: sync」 結果:SUCCESS, ...,上傳大小: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) 以上版本。