حظر المتجر

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

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

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

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

قبل البدء

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

إعداد تطبيقك

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

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

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

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

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

آلية العمل

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

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

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

جارٍ حفظ الرمز المميّز

عندما يسجّل مستخدم الدخول إلى تطبيقك، يمكنك حفظ الرمز المميز للمصادقة الذي تنشئه لهذا المستخدم في "حظر المتجر". يمكنك تخزين هذا الرمز المميّز باستخدام قيمة مفتاحَي تشفير فريدَين بحد أقصى 4 كيلوبايت لكل إدخال. لتخزين الرمز المميَّز، يمكنك طلب setBytes() وsetKey() في حالات StoreBytesData.Builder لتخزين بيانات اعتماد المستخدم على الجهاز المصدر. بعد حفظ الرمز المميّز برمز حظر المتجر، يتم تشفير الرمز المميّز وتخزينه على الجهاز.

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

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

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

في ما يلي مثال على كيفية استرداد جميع الرموز المميَّزة المحفوظة في سياسة StoreStore.

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

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

قد يكون حذف الرموز المميّزة من حظر المتجر للأسباب التالية:

  • ينتقل المستخدم خلال عملية تسجيل خروج المستخدم.
  • تم إبطال الرمز المميز أو غير صالح.

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

في ما يلي مثال على حذف مفاتيح معيّنة:

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

حذف كل الرموز المميزة

في المثال التالي، يتم حذف جميع الرموز المميَّزة المحفوظة حاليًا في سياسة StoreStore:

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

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

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

على جهاز آخر

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

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

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

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

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

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

عملية استعادة البيانات من جهاز إلى آخر

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

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

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

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

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

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

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

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