حظر المتجر

تنظيم صفحاتك في مجموعات يمكنك حفظ المحتوى وتصنيفه حسب إعداداتك المفضّلة.

لا يزال العديد من المستخدمين يديرون بيانات اعتمادهم عند إعداد جهاز جديد يعمل بنظام التشغيل Android. يمكن أن تصبح هذه العملية اليدوية صعبة وغالبًا ما تؤدي إلى تجربة سيئة للمستخدم. تتطلع واجهة برمجة تطبيقات متجر Play، وهي مكتبة تدعمها خدمات Google Play، إلى حل هذه المشكلة عن طريق توفير طريقة للتطبيقات لحفظ بيانات اعتماد المستخدم بدون تعقيد أو مخاطر أمان مرتبطة بحفظ كلمات مرور المستخدمين.

تسمح واجهة برمجة تطبيقات حظر التطبيقات لتطبيقك بتخزين البيانات التي يمكنه استردادها لاحقًا لإعادة مصادقة المستخدمين على جهاز جديد. ويساعد هذا في توفير تجربة سلسة للمستخدم، حيث لا يحتاج إلى شاشة تسجيل الدخول عند تشغيل تطبيقك لأول مرة على الجهاز الجديد.

وتشمل مزايا استخدام "متجر Play" ما يلي:

  • حل مشفّر لتخزين بيانات الاعتماد لمطوّري البرامج. يتم تشفير بيانات الاعتماد بين الطرفين عند الإمكان.
  • احفظ الرموز المميزة بدلاً من أسماء المستخدمين وكلمات المرور.
  • تخلص من أي صعوبات قد تواجهها أثناء عملية تسجيل الدخول.
  • وفِّر على المستخدمين عبء إدارة كلمات المرور المعقدة.
  • تتحقق Google من هوية المستخدم.

قبل البدء

لإعداد تطبيقك، أكمِل الخطوات الواردة في الأقسام التالية.

تهيئة تطبيقك

في ملف build.gradle على مستوى مشروعك، عليك تضمين مستودع Google Maven في القسمين buildscript وallprojects:

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

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

يمكنك إضافة تبعيّة خدمات Google Play إلى واجهة برمجة التطبيقات في "متجر Play" إلى ملف إنشاء Gradle في وحدتك، عادةً ما يكون app/build.gradle:

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

آلية العمل

يسمح تطبيق "متجر Play" لمطوّري البرامج بحفظ مصفوفات يصل حجمها إلى 16 بايت واستعادتها. ويتيح لك ذلك حفظ المعلومات المهمة بشأن جلسة المستخدم الحالية كما يمنحك المرونة في حفظ هذه المعلومات كيفما تشاء. ويمكن أن تكون هذه البيانات مشفّرة بشكل تام، وأنّ البنية الأساسية التي تتوافق مع "متجر Play" مصمَّمة بشكل أساسي في البنية الأساسية للنسخ الاحتياطي والاستعادة.

سيغطي هذا الدليل حالة استخدام حفظ الرمز المميز للمستخدم في متجر Play. توضّح الخطوات التالية آلية عمل تطبيق يستخدم "متجر Play":

  1. أثناء تدفق مصادقة تطبيقك، أو في أي وقت بعد ذلك، يمكنك تخزين الرمز المميز لمصادقة المستخدم في حظر المتجر لاسترداده لاحقًا.
  2. سيتم تخزين الرمز المميّز محليًا ويمكن أيضًا الاحتفاظ بنسخة احتياطية منه في السحابة الإلكترونية، وتشفيره بين الأطراف متى أمكن ذلك.
  3. يتم نقل البيانات عندما يبدأ المستخدم تدفق الاستعادة على جهاز جديد.
  4. إذا استعاد المستخدم تطبيقك أثناء عملية الاستعادة، يمكن لهذا التطبيق حينئذٍ استرداد الرمز المميز المحفوظ في "متجر Play" على الجهاز الجديد.

حفظ الرمز المميز

عندما يسجّل مستخدم الدخول إلى تطبيقك، يمكنك حفظ الرمز المميز للمصادقة الذي تنشئه لهذا المستخدم في "متجر Play". يمكنك تخزين هذا الرمز المميز باستخدام قيمة فريدة لزوج من المفاتيح يبلغ الحد الأقصى 4 كيلوبايت لكل إدخال. لتخزين الرمز المميَّز، استدعِ setBytes() و'setKey(/android/reference/com/google/android/gms/auth/blockstore/StoreBytesData.Builder.html#setKey(java.lang.String)' على مثيل من StoreBytesData.Builder لتخزين بيانات اعتماد المستخدم على الجهاز المصدر. بعد حفظ الرمز المميز باستخدام "متجر Play"، يتم تشفير الرمز المميز وتخزينه محليًا على الجهاز.

يعرض النموذج التالي كيفية حفظ الرمز المميز للمصادقة على الجهاز المحلي:

لغة 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 بدون مفتاح المفتاح التلقائي storestoreClient.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" أولاً من المستخدم ثم تسترد بيانات "متجر Play". وافق المستخدم من قبل على استعادة بيانات تطبيقك كجزء من عملية الاستعادة، لذلك لا يلزم الحصول على موافقات إضافية. عندما يفتح المستخدم تطبيقك، يمكنك طلب رمزك المميز من "متجر 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

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

جارٍ استرداد جميع الرموز المميزة.

في ما يلي مثال على كيفية استرداد جميع الرموز المميزة المحفوظة في 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)
  }

في ما يلي مثال على كيفية استرداد المفتاح التلقائي.

لغة 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

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)

حذف جميع الرموز المميزة

يحذف المثال أدناه جميع الرموز المميزة المحفوظة حاليًا في 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")
        }

تفعيل النسخ الاحتياطي عبر السحابة الإلكترونية

لتفعيل الاحتفاظ بنسخة احتياطية في السحابة الإلكترونية، أضِف طريقة setShouldBackupToCloud() إلى كائن StoreBytesData. ستحظر ميزة "متجر Play" من آن لآخر الاحتفاظ بنسخة احتياطية من وحدات البايت المخزنة في السحابة الإلكترونية عندما يتم ضبط السياسة setShouldBackupToCloud() على "صحيح".

يوضح النموذج التالي كيفية تمكين النسخ الاحتياطي عبر السحابة الإلكترونية فقط عندما تكون ميزة النسخ الاحتياطي عبر السحابة الإلكترونية تخضع للتشفير التام بين الأطراف:

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 > الاحتفاظ بنسخة احتياطية)، تظل بيانات "متجر Play" مثبتة عبر التطبيق أو إلغاء تثبيته.

يمكنك اتباع الخطوات التالية لاختبار هذه الميزة:

  1. ادمج واجهة برمجة تطبيقات BlockStore في تطبيقك الاختباري.
  2. استخدِم التطبيق التجريبي لاستدعاء واجهة برمجة تطبيقات BlockStore لتخزين بياناتك.
  3. ألغِ تثبيت التطبيق التجريبي، ثم أعِد تثبيته على الجهاز نفسه.
  4. استخدِم التطبيق التجريبي لاستدعاء واجهة برمجة تطبيقات BlockStore لاسترداد بياناتك.
  5. تحقق من أن وحدات البايت المستردة هي نفسها التي تم تخزينها قبل الإزالة.

من جهاز إلى جهاز

وفي معظم الحالات، سيتطلب هذا إعادة تعيين إعدادات المصنع للجهاز المستهدف. يمكنك بعد ذلك إدخال تدفق الاستعادة اللاسلكية لنظام Android أو استعادة كابل Google (للأجهزة المتوافقة).

استعادة السحابة الإلكترونية

  1. يمكنك دمج واجهة برمجة تطبيقات Blockstore في التطبيق التجريبي. ويجب إرسال التطبيق التجريبي إلى "متجر Play".
  2. على الجهاز المصدر، استخدِم التطبيق الاختباري لاستدعاء واجهة برمجة تطبيقات Blockstore لتخزين بياناتك، مع ضبط السياسة BackBackToCloud على "صحيح".
  3. بالنسبة إلى الأجهزة التي تعمل بالإصدار O والإصدارات الأحدث، يمكنك تشغيل النسخ الاحتياطي عبر السحابة الإلكترونية في متجر Play يدويًا: انتقل إلى الإعدادات > Google > الاحتفاظ بنسخة احتياطية، وانقر على الزر "النسخ الاحتياطي الآن".
    1. للتحقّق من نجاح عملية الاحتفاظ بنسخة احتياطية من السحابة الإلكترونية في "متجر Play"، يمكنك تنفيذ ما يلي:
      1. بعد انتهاء عملية الاحتفاظ بنسخة احتياطية، ابحث عن أسطر السجلّ التي تتضمّن العلامة "CloudSyncBpTkSvc".
      2. سترى أسطر على النحو التالي: "......, CloudSyncBpTkSvc: sync result: SUCCESS, ..., size size: XXX بايت ..."
    2. بعد الاحتفاظ بنسخة احتياطية في السحابة الإلكترونية في "متجر Play"، يتم ضبط "فترة تبريد هادئة" لمدة 5 دقائق. خلال 5 دقائق، لن يؤدي النقر على زر "النسخ الاحتياطي الآن" إلى تشغيل نسخ احتياطي آخر في Cloud Store.
  4. يمكنك إعادة ضبط الجهاز المستهدف على الإعدادات الأصلية والانتقال إلى عملية استعادة السحابة الإلكترونية. حدد استعادة التطبيق الاختباري أثناء عملية الاستعادة. لمزيد من المعلومات حول تدفقات استعادة السحابة الإلكترونية، يُرجى الاطِّلاع على التدفقات المتوافقة لاستعادة السحابة الإلكترونية.
  5. على الجهاز المستهدف، استخدِم التطبيق الاختباري لاستدعاء واجهة برمجة تطبيقات Blockstore لاسترداد بياناتك.
  6. تحقق من أن وحدات البايت المستردة هي نفسها التي تم تخزينها في الجهاز المصدر.

متطلبات الجهاز

التشفير التام بين الأطراف

  • يتوفّر التشفير التام بين الأطراف على الأجهزة التي تعمل بنظام التشغيل Android 9 (واجهة برمجة التطبيقات 29) والإصدارات الأحدث.
  • يجب ضبط قفل شاشة للجهاز باستخدام رقم تعريف شخصي أو نقش أو كلمة مرور لتفعيل التشفير التام بين الأطراف وتشفير بيانات المستخدم بشكل صحيح.

عملية استعادة الجهاز إلى الجهاز

ستتطلب استعادة البيانات من جهاز إلى جهاز أن يكون لديك جهاز مصدر وجهاز مستهدف. وسيكون هذان الجهازان اللتان تنقلان البيانات.

يجب أن تعمل أجهزة المصدر بنظام التشغيل Android 6 (واجهة برمجة التطبيقات 23) والإصدارات الأحدث للاحتفاظ بنسخة احتياطية.

استهداف الأجهزة التي تعمل بنظام التشغيل Android 9 (واجهة برمجة التطبيقات 29) والإصدارات الأحدث للحصول على إمكانية الاستعادة.

يمكنك العثور على مزيد من المعلومات حول عملية استعادة الجهاز إلى الجهاز هنا.

النسخ الاحتياطي عبر السحابة الإلكترونية واستعادة التدفق

سيتطلب النسخ الاحتياطي والاستعادة على السحابة الإلكترونية جهازًا مصدرًا وجهازًا مستهدفًا.

يجب أن تعمل أجهزة المصدر بنظام التشغيل Android 6 (واجهة برمجة التطبيقات 23) والإصدارات الأحدث للاحتفاظ بنسخة احتياطية.

الأجهزة المستهدفة متاحة استنادًا إلى المورّدين. ويمكن لأجهزة Pixel استخدام هذه الميزة من نظام التشغيل Android 9 (واجهة برمجة التطبيقات 29)، كما يجب أن تعمل جميع الأجهزة الأخرى بنظام التشغيل Android 12 (واجهة برمجة التطبيقات 31) أو الإصدارات الأحدث.