حظر متجر

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

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

تشمل مزايا استخدام حظر المتجر ما يلي:

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

قبل البدء

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

إعداد تطبيقك

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

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

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

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

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

آلية العمل

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

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

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

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

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

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 الخاص بك. سيؤدي حظر المتجر إلى الاحتفاظ بنسخة احتياطية من بيانات وحدات البايت المخزنة بشكل دوري على السحابة الإلكترونية تم ضبط 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. ادمج واجهة برمجة التطبيقات BlockStore API في تطبيقك التجريبي.
  2. استخدِم التطبيق التجريبي لاستدعاء BlockStore API لتخزين بياناتك.
  3. إلغاء تثبيت التطبيق التجريبي ثم إعادة تثبيته على الجهاز نفسه
  4. استخدِم التطبيق التجريبي لاستدعاء BlockStore API لاسترداد بياناتك.
  5. التأكد من أنّ وحدات البايت التي تم استردادها هي نفسها تلك التي تم تخزينها من قبل إلغاء التثبيت.

من جهاز إلى آخر

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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