משתמשים רבים עדיין מנהלים את פרטי הכניסה שלהם בעצמם כשהם מגדירים מכשיר Android חדש. התהליך הידני הזה יכול להיות מאתגר ומוביל לחוויית משתמש גרועה. כדי לפתור את הבעיה, באמצעות Block Store API, ספרייה שמופעלת על ידי שירותי Google Play, האפליקציות יכולות לשמור את פרטי הכניסה של המשתמשים בלי המורכבות או סיכון האבטחה הכרוכים בשמירת סיסמאות של משתמשים.
ה-Block Store API מאפשר לאפליקציה לאחסן נתונים שהיא יכולה לאחזר מאוחר יותר כדי לאמת מחדש משתמשים במכשיר חדש. כך אפשר לספק למשתמשים חוויה חלקה יותר, כי הם לא צריכים לראות מסך כניסה כשמפעילים את האפליקציה בפעם הראשונה במכשיר החדש.
הנה כמה מהיתרונות של השימוש ב-Block Store:
- פתרון למפתחים מוצפנים לאחסון פרטי כניסה מוצפנים. פרטי הכניסה מוצפנים מקצה לקצה כשאפשר.
- שומרים אסימונים במקום שמות משתמש וסיסמאות.
- הפחיתו את הקשיים בתהליך הכניסה.
- לחסוך למשתמשים את נטל הניהול של סיסמאות מורכבות.
- Google מאמתת את זהות המשתמש.
לפני שמתחילים
כדי להכין את האפליקציה שלך, בצע את השלבים המפורטים בקטעים הבאים.
הגדרת האפליקציה
בקובץ build.gradle
ברמת הפרויקט, צריך לכלול את מאגר Maven של Google בקטע buildscript
וגם בקטע allprojects
:
buildscript {
repositories {
google()
mavenCentral()
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
מוסיפים את התלות של Google Play Services של ה-Block Store API לקובץ Gradle של המודול, שלרוב הוא app/build.gradle
:
dependencies {
implementation 'com.google.android.gms:play-services-auth-blockstore:16.2.0'
}
איך זה עובד
בעזרת החסימה Store מפתחים יכולים לשמור ולשחזר מערכים בגודל של עד 16 בייטים. כך תוכלו לשמור מידע חשוב לגבי הסשן הנוכחי של המשתמש, וגם את הגמישות לשמור את המידע בכל דרך שתרצו. הנתונים האלה יכולים להיות מוצפנים מקצה לקצה, והתשתית שתומכת ב-Block Store מבוססת על תשתית הגיבוי והשחזור.
המדריך הזה יעסוק בתרחישים לדוגמה של שמירת אסימון של משתמש ב-block Store. השלבים הבאים מתארים כיצד תפעל אפליקציה שמשתמשת ב-Block Store:
- במהלך תהליך האימות של האפליקציה או בכל שלב לאחר מכן, תוכלו לשמור את אסימון האימות של המשתמש ב-block Store כדי לאחזר אותו מאוחר יותר.
- האסימון יאוחסן באופן מקומי ואפשר גם לגבות אותו בענן בצורה מוצפנת מקצה לקצה, כשזה אפשרי.
- הנתונים מועברים כשהמשתמש מתחיל תהליך שחזור במכשיר חדש.
- אם המשתמש משחזר את האפליקציה במהלך השחזור, האפליקציה יכולה לאחזר את האסימון שנשמר מ-Block Store במכשיר החדש.
שמירת האסימון
כשמשתמש נכנס לאפליקציה, אתם יכולים לשמור ב-Block Store את אסימון האימות שיצרתם עבור המשתמש. אפשר לאחסן את האסימון הזה באמצעות ערך ייחודי של זוג מפתחות, שיש לו לכל היותר 4Kb לכל רשומה.
כדי לאחסן את האסימון, צריך להפעיל את 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 ללא מפתח נעשה שימוש בברירת המחדל של keyblockstoreClient.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 Services מאמתת את המשתמש ואז מאחזרת את נתוני ה-Block Store. המשתמש כבר הסכים לשחזר את נתוני האפליקציה כחלק מתהליך השחזור, לכן לא נדרשת הסכמה נוספת. כשהמשתמש פותח את האפליקציה, אפשר לבקש את האסימון מ-Block Store על ידי ביצוע קריאה ל-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 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) }
המערכת מאחזרת את כל האסימונים.
הדוגמה הבאה ממחישה איך לאחזר את כל האסימונים שנשמרו ב-BlockStore.
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) }
לפניכם דוגמה לאופן שבו מאחזרים את מפתח ברירת המחדל.
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 ואילך, והמשתמש צריך להגדיר נעילת מסך (קוד אימות, קו ביטול נעילה או סיסמה) למכשיר. כדי לבדוק אם ההצפנה תהיה זמינה במכשיר, תוכלו להתקשר למספר isEndToEndEncryptionAvailable()
.
הדוגמה הבאה מראה איך לבדוק אם ההצפנה תהיה זמינה במהלך הגיבוי בענן:
client.isEndToEndEncryptionAvailable()
.addOnSuccessListener { result ->
Log.d(TAG, "Will Block Store cloud backup be end-to-end encrypted? $result")
}
הפעלת הגיבוי בענן
כדי להפעיל גיבוי בענן, צריך להוסיף את ה-method setShouldBackupToCloud()
לאובייקט StoreBytesData
. אם המדיניות 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 > גיבוי), הנתונים של חסימת האפליקציה נשמרים גם בהסרה או בהתקנה מחדש של האפליקציה.
אפשר לבצע את השלבים הבאים כדי לבדוק את הביצועים:
- משלבים אתBlockStore API באפליקציית הבדיקה.
- משתמשים באפליקציית הבדיקה כדי להפעיל את ממשק ה-API של blockStore לאחסון הנתונים.
- מסירים את אפליקציית הבדיקה ומתקינים אותה מחדש באותו המכשיר.
- משתמשים באפליקציית הבדיקה כדי להפעיל את ממשק ה-API שלBlockStore לאחזור הנתונים.
- יש לוודא שהבייטים שאוחזרו זהים לבייטים שאוחסנו לפני ההסרה.
ממכשיר למכשיר
ברוב המקרים, תצטרכו לאפס את מכשיר היעד להגדרות המקוריות. לאחר מכן אפשר להיכנס לתהליך של שחזור אלחוטי ל-Android או לשחזור באמצעות כבל Google (במכשירים נתמכים).
שחזור בענן
- משלבים את ה-Blockstore API באפליקציית הבדיקה. צריך לשלוח את אפליקציית הבדיקה לחנות Play.
- במכשיר המקור, משתמשים באפליקציית הבדיקה כדי להפעיל את ה-Blockstore API לשמירת הנתונים, כשהערך של shouldBackUpToCloud הוא True.
- במכשירים O ואילך, ניתן להפעיל ידנית גיבוי בענן מ-block Store: עוברים להגדרות > Google > גיבוי ולוחצים על הלחצן 'גיבוי עכשיו'.
- כדי לוודא שהגיבוי בענן ל-block Store הסתיים, אתם יכולים:
- אחרי שהגיבוי מסתיים, חפשו שורות ביומן עם התג CloudSyncBpTkSvc.
- אמורות להופיע שורות כמו: “......, CloudSyncBpTkSvc: sync result: SUCCESS, ..., Upload size: XXX bytes ...”
- אחרי הגיבוי בענן של חנות בלוקים, יש 5 דקות 'קירור'. במהלך 5 הדקות האלה, לחיצה על הלחצן 'גיבוי עכשיו' לא תפעיל גיבוי נוסף בענן מ-Block Store.
- כדי לוודא שהגיבוי בענן ל-block Store הסתיים, אתם יכולים:
- מאפסים את מכשיר היעד להגדרות המקוריות ומבצעים תהליך שחזור בענן. בוחרים אם לשחזר את אפליקציית הבדיקה במהלך תהליך השחזור. מידע נוסף על תהליכי השחזור בענן זמין במאמר תהליכי שחזור בענן.
- במכשיר היעד, משתמשים באפליקציית הבדיקה כדי להפעיל את ה-Blockstore API על מנת לאחזר את הנתונים.
- ודאו שהבייטים שאוחזרו זהים למה שאוחסנו במכשיר המקור.
דרישות לגבי המכשיר
הצפנה מקצה לקצה
- הצפנה מקצה לקצה נתמכת במכשירים עם Android מגרסה 9 (API 29) ואילך.
- כדי שההצפנה מקצה לקצה תהיה מופעלת במכשיר, וכדי להצפין את נתוני המשתמש בצורה נכונה, צריך להגדיר במכשיר נעילת מסך עם קוד אימות, קו ביטול נעילה או סיסמה.
תהליך שחזור ממכשיר למכשיר
כדי לבצע שחזור ממכשיר למכשיר, נדרשים מכשיר מקור ומכשיר יעד. אלה יהיו שני המכשירים שמעבירים נתונים.
כדי לבצע גיבוי, מכשירי מקור חייבים לפעול עם Android 6 (API 23) ואילך.
טירגוט למכשירים עם Android 9 (API 29) ואילך כדי שתהיה להם אפשרות לבצע שחזור.
כאן ניתן למצוא מידע נוסף על תהליך שחזור המכשיר.
תהליך הגיבוי והשחזור בענן
כדי לבצע גיבוי ושחזור בענן, נדרשים מכשיר מקור ומכשיר יעד.
כדי לבצע גיבוי, מכשירי מקור חייבים לפעול עם Android 6 (API 23) ואילך.
מכשירי טירגוט נתמכים על סמך הספקים שלהם. מכשירי Pixel יכולים להשתמש בתכונה הזו מ-Android 9 (API 29). כל שאר המכשירים חייבים להיות עם Android 12 (API 31) ואילך.