بيانات السلامة

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

تنسيق بيان السلامة المعروض

حمولة البيانات بتنسيق JSON بتنسيق نص عادي وتحتوي على إشارات سلامة بالإضافة إلى المعلومات التي يقدّمها المطوّر.

في ما يلي البنية العامة للحمولة:

{
  requestDetails: { ... }
  appIntegrity: { ... }
  deviceIntegrity: { ... }
  accountDetails: { ... }
  environmentDetails: { ... }
}

يجب أولاً التحقّق من أنّ القيم في الحقل requestDetails تتطابق مع قيم الطلب الأصلي قبل التحقّق من كل بيان سلامة. تصف الأقسام التالية كل حقل بمزيد من التفصيل.

حقل تفاصيل الطلب

ويحتوي الحقل requestDetails على معلومات حول الطلب، بما في ذلك المعلومات التي يقدّمها المطوّر في requestHash للطلبات العادية والحقل nonce للطلبات الكلاسيكية.

بالنسبة إلى طلبات البيانات من واجهة برمجة التطبيقات العادية:

requestDetails: {
  // Application package name this attestation was requested for.
  // Note that this field might be spoofed in the middle of the request.
  requestPackageName: "com.package.name"
  // Request hash provided by the developer.
  requestHash: "aGVsbG8gd29scmQgdGhlcmU"
  // The timestamp in milliseconds when the integrity token
  // was prepared (computed on the server).
  timestampMillis: "1675655009345"
}

يجب أن تتطابق هذه القيم مع قيم الطلب الأصلي. لذلك، تحقق من جزء requestDetails من حمولة JSON عن طريق التأكد من تطابق الrequestPackageName وrequestHash مع ما تم إرساله في الطلب الأصلي، كما هو موضّح في مقتطف الرمز التالي:

Kotlin

val requestDetails = JSONObject(payload).getJSONObject("requestDetails")
val requestPackageName = requestDetails.getString("requestPackageName")
val requestHash = requestDetails.getString("requestHash")
val timestampMillis = requestDetails.getLong("timestampMillis")
val currentTimestampMillis = ...

// Ensure the token is from your app.
if (!requestPackageName.equals(expectedPackageName)
        // Ensure the token is for this specific request
    || !requestHash.equals(expectedRequestHash)
        // Ensure the freshness of the token.
    || currentTimestampMillis - timestampMillis > ALLOWED_WINDOW_MILLIS) {
        // The token is invalid! See below for further checks.
        ...
}

Java

RequestDetails requestDetails =
    decodeIntegrityTokenResponse
    .getTokenPayloadExternal()
    .getRequestDetails();
String requestPackageName = requestDetails.getRequestPackageName();
String requestHash = requestDetails.getRequestHash();
long timestampMillis = requestDetails.getTimestampMillis();
long currentTimestampMillis = ...;

// Ensure the token is from your app.
if (!requestPackageName.equals(expectedPackageName)
        // Ensure the token is for this specific request.
    || !requestHash.equals(expectedRequestHash)
        // Ensure the freshness of the token.
    || currentTimestampMillis - timestampMillis > ALLOWED_WINDOW_MILLIS) {
        // The token is invalid! See below for further checks.
        ...
}

لطلبات البيانات من واجهة برمجة التطبيقات الكلاسيكية:

requestDetails: {
  // Application package name this attestation was requested for.
  // Note that this field might be spoofed in the middle of the
  // request.
  requestPackageName: "com.package.name"
  // base64-encoded URL-safe no-wrap nonce provided by the developer.
  nonce: "aGVsbG8gd29scmQgdGhlcmU"
  // The timestamp in milliseconds when the request was made
  // (computed on the server).
  timestampMillis: "1617893780"
}

يجب أن تتطابق هذه القيم مع قيم الطلب الأصلي. لذلك، تحقق من جزء requestDetails من حمولة JSON عن طريق التأكد من تطابق requestPackageName وnonce مع ما تم إرساله في الطلب الأصلي، كما هو موضح في مقتطف الرمز التالي:

Kotlin

val requestDetails = JSONObject(payload).getJSONObject("requestDetails")
val requestPackageName = requestDetails.getString("requestPackageName")
val nonce = requestDetails.getString("nonce")
val timestampMillis = requestDetails.getLong("timestampMillis")
val currentTimestampMillis = ...

// Ensure the token is from your app.
if (!requestPackageName.equals(expectedPackageName)
        // Ensure the token is for this specific request. See 'Generate a nonce'
        // section of the doc on how to store/compute the expected nonce.
    || !nonce.equals(expectedNonce)
        // Ensure the freshness of the token.
    || currentTimestampMillis - timestampMillis > ALLOWED_WINDOW_MILLIS) {
        // The token is invalid! See below for further checks.
        ...
}

Java

JSONObject requestDetails =
    new JSONObject(payload).getJSONObject("requestDetails");
String requestPackageName = requestDetails.getString("requestPackageName");
String nonce = requestDetails.getString("nonce");
long timestampMillis = requestDetails.getLong("timestampMillis");
long currentTimestampMillis = ...;

// Ensure the token is from your app.
if (!requestPackageName.equals(expectedPackageName)
        // Ensure the token is for this specific request. See 'Generate a nonce'
        // section of the doc on how to store/compute the expected nonce.
    || !nonce.equals(expectedNonce)
        // Ensure the freshness of the token.
    || currentTimestampMillis - timestampMillis > ALLOWED_WINDOW_MILLIS) {
        // The token is invalid! See below for further checks.
        ...
}

حقل سلامة التطبيق

يحتوي الحقل appIntegrity على معلومات متعلقة بالحزمة.

appIntegrity: {
  // PLAY_RECOGNIZED, UNRECOGNIZED_VERSION, or UNEVALUATED.
  appRecognitionVerdict: "PLAY_RECOGNIZED"
  // The package name of the app.
  // This field is populated iff appRecognitionVerdict != UNEVALUATED.
  packageName: "com.package.name"
  // The sha256 digest of app certificates (base64-encoded URL-safe).
  // This field is populated iff appRecognitionVerdict != UNEVALUATED.
  certificateSha256Digest: ["6a6a1474b5cbbb2b1aa57e0bc3"]
  // The version of the app.
  // This field is populated iff appRecognitionVerdict != UNEVALUATED.
  versionCode: "42"
}

يمكن أن يحتوي appRecognitionVerdict على القيم التالية:

PLAY_RECOGNIZED
يتطابق التطبيق والشهادة مع الإصدارات التي تم توزيعها من خلال Google Play.
UNRECOGNIZED_VERSION
لا يتطابق اسم الشهادة أو اسم الحزمة مع سجلّات Google Play.
UNEVALUATED
لم يتم تقييم سلامة التطبيق. تم إغفال أحد المتطلبات الضرورية، مثل أن الجهاز لم يكن جديرًا بالثقة بما يكفي.

للتأكُّد من إنشاء الرمز المميّز بواسطة تطبيق أنشأته بنفسك، تأكَّد من أنّ سلامة التطبيق كما هو متوقَّع، كما هو موضَّح في مقتطف الرمز التالي:

Kotlin

val appIntegrity = JSONObject(payload).getJSONObject("appIntegrity")
val appRecognitionVerdict = appIntegrity.getString("appRecognitionVerdict")

if (appRecognitionVerdict == "PLAY_RECOGNIZED") {
    // Looks good!
}

Java

JSONObject appIntegrity =
    new JSONObject(payload).getJSONObject("appIntegrity");
String appRecognitionVerdict =
    appIntegrity.getString("appRecognitionVerdict");

if (appRecognitionVerdict.equals("PLAY_RECOGNIZED")) {
    // Looks good!
}

يمكنك أيضًا التحقّق من اسم حزمة التطبيقات وإصدار التطبيق وشهادات التطبيق يدويًا.

حقل سلامة الجهاز

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

deviceIntegrity: {
  // "MEETS_DEVICE_INTEGRITY" is one of several possible values.
  deviceRecognitionVerdict: ["MEETS_DEVICE_INTEGRITY"]
}

تلقائيًا، يمكن أن يحتوي deviceRecognitionVerdict على ما يلي:

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

للتأكُّد من أنّ الرمز المميّز تم الحصول عليه من جهاز موثوق، تأكَّد من أنّ الرمز deviceRecognitionVerdict هو كما هو متوقع، كما هو موضّح في مقتطف الرمز التالي:

Kotlin

val deviceIntegrity =
    JSONObject(payload).getJSONObject("deviceIntegrity")
val deviceRecognitionVerdict =
    if (deviceIntegrity.has("deviceRecognitionVerdict")) {
        deviceIntegrity.getJSONArray("deviceRecognitionVerdict").toString()
    } else {
        ""
    }

if (deviceRecognitionVerdict.contains("MEETS_DEVICE_INTEGRITY")) {
    // Looks good!
}

Java

JSONObject deviceIntegrity =
    new JSONObject(payload).getJSONObject("deviceIntegrity");
String deviceRecognitionVerdict =
    deviceIntegrity.has("deviceRecognitionVerdict")
    ? deviceIntegrity.getJSONArray("deviceRecognitionVerdict").toString()
    : "";

if (deviceRecognitionVerdict.contains("MEETS_DEVICE_INTEGRITY")) {
    // Looks good!
}

إذا كنت تواجه مشاكل في اختبار سلامة جهاز الاجتماع، يُرجى التأكّد من تثبيت برنامج القراءة فقط على الإعدادات الأصلية (على سبيل المثال، من خلال إعادة ضبط الجهاز) وأن يكون برنامج الإقلاع مقفل. يمكنك أيضًا إنشاء اختبارات واجهة برمجة التطبيقات Play Integrity API في Play Console.

التصنيفات الشرطية للأجهزة

إذا تم طرح تطبيقك في برنامج "ألعاب Google Play على الكمبيوتر"، يمكن أن يتضمّن deviceRecognitionVerdict أيضًا التصنيف التالي:

MEETS_VIRTUAL_INTEGRITY
يعمل التطبيق على محاكي يعمل بنظام التشغيل Android ويتضمّن "خدمات Google Play". يجتاز المحاكي عمليات فحص سلامة النظام ويلبي متطلبات التوافق الأساسية مع Android.

معلومات الجهاز الاختيارية

في حال الموافقة على تلقّي تصنيفات إضافية في بيان السلامة، يمكن أن يتضمّن تصنيف deviceRecognitionVerdict التصنيفات الإضافية التالية:

MEETS_BASIC_INTEGRITY
التطبيق يعمل على جهاز يجتاز عمليات التحقق الأساسية من سلامة النظام. قد لا يستوفي الجهاز متطلبات التوافق مع Android وقد لا تتم الموافقة عليه لتشغيل "خدمات Google Play". على سبيل المثال، قد يكون الجهاز يعمل بإصدار غير معروف من نظام التشغيل Android، أو قد يحتوي على برنامج إقلاع تم فتح قفله، أو ربما لم يتم اعتماده من قِبل الشركة المصنّعة.
MEETS_STRONG_INTEGRITY
يعمل التطبيق على جهاز يعمل بنظام التشغيل Android ويتضمّن خدمات Google Play، وله ضمان قوي لسلامة النظام، مثل دليل مستند إلى الأجهزة يثبت سلامة التشغيل. يجتاز الجهاز عمليات فحص سلامة النظام ويلبي متطلبات التوافق مع Android.

سيعرض جهاز واحد تصنيفات جهاز متعددة في بيان سلامة الجهاز إذا تم استيفاء كل معيار من معايير التصنيف.

أحدث أنشطة الجهاز (ميزة تجريبية)

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

إذا فعّلت خيار تلقّي recentDeviceActivity، سيحتوي الحقل deviceIntegrity على قيمتَين:

deviceIntegrity: {
  deviceRecognitionVerdict: ["MEETS_DEVICE_INTEGRITY"]
  recentDeviceActivity: {
    // "LEVEL_2" is one of several possible values.
    deviceActivityLevel: "LEVEL_2"
  }
}

تختلف تعريفات deviceActivityLevel بين الأوضاع ويمكن أن تحتوي على إحدى القيم التالية:

مستوى النشاط الأخير للجهاز الطلبات العادية خلال الساعة الأخيرة الطلبات الكلاسيكية خلال الساعة الأخيرة
LEVEL_1 (الأدنى) طلب التطبيق 10 رموز مميّزة للسلامة على هذا الجهاز أو أقل. طلب التطبيق 5 رموز مميزة أو أقل للسلامة على هذا الجهاز.
LEVEL_2 طلب التطبيق ما بين 11 و25 رمزًا مميّزًا للسلامة على هذا الجهاز. طلب التطبيق توفّر ما بين 6 و15 رمزًا مميّزًا للسلامة على هذا الجهاز.
LEVEL_3 طلب التطبيق ما بين 26 و50 رمزًا مميّزًا للسلامة على هذا الجهاز. طلب التطبيق ما بين 16 و30 رمزًا مميّزًا للسلامة على هذا الجهاز.
LEVEL_4 (الأعلى) طلب التطبيق أكثر من 50 رمزًا مميّزًا للسلامة على هذا الجهاز. طلب التطبيق أكثر من 30 رمزًا مميّزًا للسلامة على هذا الجهاز.
UNEVALUATED لم يتم تقييم نشاط الجهاز الأخير. قد يحدث ذلك للأسباب التالية:
  • الجهاز غير موثوق بالقدر الكافي
  • لا يعرف Google Play إصدار تطبيقك المثبَّت على الجهاز.
  • حدثت مشاكل فنية في الجهاز.

حقل تفاصيل الحساب

يحتوي الحقل accountDetails على قيمة واحدة، وهي appLicensingVerdict، تمثّل حالة ترخيص التطبيق في Google Play لحساب المستخدم الذي تم تسجيل الدخول إليه على الجهاز. إذا حصل حساب المستخدم على ترخيص Play للتطبيق، فهذا يعني أنه نزّل التطبيق أو اشتراه من Google Play.

accountDetails: {
  // This field can be LICENSED, UNLICENSED, or UNEVALUATED.
  appLicensingVerdict: "LICENSED"
}

يمكن أن تحتوي السمة appLicensingVerdict على إحدى القيم التالية:

LICENSED
لدى المستخدم استحقاق تطبيق. بعبارة أخرى، ثبّت المستخدم تطبيقك أو اشتراه من Google Play.
UNLICENSED
لا يملك المستخدم إذنًا بالوصول إلى التطبيقات. ويحدث ذلك مثلاً عندما يثبّت المستخدِم تطبيقك من مصدر غير معروف أو لا يكتسبه من Google Play. يمكنك عرض مربّع الحوار GET_LICENSED للمستخدمين لحلّ هذه المشكلة.
UNEVALUATED

لم يتم تقييم تفاصيل الترخيص بسبب عدم استيفاء أحد المتطلبات الضرورية.

وقد يحدث ذلك لعدة أسباب، بما فيها ما يلي:

  • الجهاز غير موثوق بالقدر الكافي
  • لا يعرف Google Play إصدار تطبيقك المثبَّت على الجهاز.
  • لم يسجّل المستخدم الدخول إلى Google Play.

للتأكُّد من أنّ المستخدم لديه أذونات الوصول إلى تطبيقك، تأكَّد من أنّ appLicensingVerdict على النحو المتوقّع، كما هو موضَّح في مقتطف الرمز التالي:

Kotlin

val accountDetails = JSONObject(payload).getJSONObject("accountDetails")
val appLicensingVerdict = accountDetails.getString("appLicensingVerdict")

if (appLicensingVerdict == "LICENSED") {
    // Looks good!
}

Java

JSONObject accountDetails =
    new JSONObject(payload).getJSONObject("accountDetails");
String appLicensingVerdict = accountDetails.getString("appLicensingVerdict");

if (appLicensingVerdict.equals("LICENSED")) {
    // Looks good!
}

حقل تفاصيل البيئة

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

في حال الموافقة على بيان "خطر الوصول إلى التطبيقات" أو بيان "Play للحماية" في أداة Google Play Console، ستتضمّن استجابة واجهة برمجة التطبيقات الحقل environmentDetails. ويمكن أن يحتوي الحقل environmentDetails على قيمتَين، وهما appAccessRiskVerdict وplayProtectVerdict.

بيان خطورة الوصول إلى التطبيق (إصدار تجريبي)

بعد تفعيل هذه الميزة، سيتضمّن الحقل environmentDetails في حمولة البيانات في واجهة برمجة التطبيقات Play Integrity API البيان الجديد بشأن مخاطر الوصول إلى التطبيق.

{
  requestDetails: { ... }
  appIntegrity: { ... }
  deviceIntegrity: { ... }
  accountDetails: { ... }
  environmentDetails: {
      appAccessRiskVerdict: {
          // This field contains one or more responses, for example the following.
          appsDetected: ["KNOWN_INSTALLED", "UNKNOWN_INSTALLED", "UNKNOWN_CAPTURING"]
      }
 }
}

إذا تم تقييم خطر الوصول إلى التطبيق، سيحتوي appAccessRiskVerdict على الحقل appsDetected مع ردّ واحد أو أكثر. وتندرج هذه الردود في إحدى المجموعتين التاليتين بناءً على مصدر تثبيت التطبيقات التي تم رصدها:

  • تطبيقات Play أو تطبيقات النظام: التطبيقات التي يتم تثبيتها من خلال Google Play أو التي تم تحميلها مسبقًا من خلال الشركة المصنّعة للجهاز في قسم نظام الجهاز (الذي يتم تحديده باستخدام FLAG_SYSTEM). تكون الردود على هذه التطبيقات مسبوقة بـ KNOWN_.

  • التطبيقات الأخرى: التطبيقات التي لم يُثبِّتها Google Play. ولا يشمل ذلك التطبيقات التي تم تحميلها مسبقًا على قسم النظام من قِبل الشركة المصنّعة للجهاز. تكون الردود لهذه التطبيقات مسبوقة بـ UNKNOWN_.

يمكن عرض الردود التالية:

KNOWN_INSTALLED، UNKNOWN_INSTALLED
هناك تطبيقات مثبَّتة تتطابق مع مصدر التثبيت المقابل.
KNOWN_CAPTURING، UNKNOWN_CAPTURING
هناك تطبيقات قيد التشغيل بها أذونات مفعّلة ويمكن استخدامها لعرض الشاشة أثناء تشغيل تطبيقك. ولا يشمل ذلك أي خدمات تم التحقّق منها لتسهيل الاستخدام وتُعرف بـ Google Play والتي يتم تشغيلها على الجهاز.
KNOWN_CONTROLLING، UNKNOWN_CONTROLLING
هناك تطبيقات قيد التشغيل بها أذونات يمكن استخدامها للتحكّم في الجهاز والتحكم مباشرةً في إدخالات التطبيق ويمكن استخدامها لتسجيل مدخلات تطبيقك ومخرجاته. ولا يشمل ذلك أي خدمات تم التحقّق منها لتسهيل الاستخدام ومتاحة على Google Play والتي يتم تشغيلها على الجهاز.
KNOWN_OVERLAYS، UNKNOWN_OVERLAYS
هناك تطبيقات قيد التشغيل تم تفعيل أذوناتها ويمكن استخدامها لعرض العناصر المركّبة على تطبيقك. ويُستثنى من ذلك أي خدمات تم التحقّق منها لتسهيل الاستخدام وتُعرف باسم Google Play والتي يتم تشغيلها على الجهاز.
EMPTY (قيمة فارغة)

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

  • الجهاز غير موثوق بالقدر الكافي
  • شكل الجهاز ليس هاتفًا أو جهازًا لوحيًا أو قابلاً للطي.
  • الجهاز لا يعمل بنظام التشغيل Android 6 (المستوى 23 من واجهة برمجة التطبيقات) أو الإصدارات الأحدث.
  • لا يتعرّف Google Play على إصدار التطبيق المثبّت على الجهاز
  • إصدار "متجر Google Play" على الجهاز قديم.
  • الألعاب فقط: لا يملك حساب المستخدم ترخيص Play لهذه اللعبة.

تستبعد مخاطر الوصول إلى التطبيق تلقائيًا خدمات تسهيل الاستخدام التي تم التحقق منها وخضعت لمراجعة محسّنة لإمكانية الوصول في Google Play (تم تثبيتها من خلال أي متجر تطبيقات على الجهاز). تعني الحالة "مستبعدة" أنّ خدمات تسهيل الاستخدام التي تم التحقّق منها والتي تعمل على الجهاز لن تعرض استجابة للالتقاط أو التحكّم أو التراكب في بيان مخاطر الوصول إلى التطبيق. لطلب إجراء مراجعة مُحسَّنة لتطبيق تسهيل الاستخدام على Google Play، يمكنك نشر التطبيق على Google Play مع التأكّد من ضبط علامة isAccessibilityTool على "صحيح" في بيان التطبيق أو طلب إجراء مراجعة.

يقدم الجدول التالي بعض الأمثلة على الأحكام وما تعنيه (ولا يسرد هذا الجدول كل النتائج المحتملة):

مثال على الردّ على بيان خطورة الوصول إلى التطبيق التفسير
appsDetected:
["KNOWN_INSTALLED"]
ما مِن تطبيقات تم تثبيتها إلا للتعرّف عليها Google Play أو التي تم تحميلها مُسبقًا في قسم النظام من قِبل الشركة المصنّعة للجهاز.
ليس هناك تطبيقات قيد التشغيل يمكن أن تؤدي إلى الحصول على بيانات الاعتماد أو التحكّم فيها أو تراكباتها.
appsDetected:
["KNOWN_INSTALLED",
"UNKNOWN_INSTALLED",
"UNKNOWN_CAPTURING"]
هناك تطبيقات مثبَّتة من خلال Google Play أو تم تحميلها مسبقًا على قسم النظام من قِبل الشركة المصنّعة للجهاز.
هناك تطبيقات أخرى قيد التشغيل وتم تفعيل أذونات يمكن استخدامها لعرض الشاشة أو تسجيل مدخلات ومخرجات أخرى.
appsDetected:
["KNOWN_INSTALLED",
"KNOWN_CAPTURING",
"UNKNOWN_INSTALLED",
"UNKNOWN_CONTROLLING"]
هناك Play أو نظام قيد التشغيل به أذونات مفعّلة يمكن استخدامها لعرض الشاشة أو تسجيل مدخلات ومخرجات أخرى.
هناك أيضًا تطبيقات أخرى قيد التشغيل تم تفعيل الأذونات فيها ويمكن استخدامها للتحكّم في الجهاز والتحكّم مباشرةً بالمدخلات التي يتم إدخالها إلى تطبيقك.
appAccessRiskVerdict: {} لا يتم تقييم خطر الوصول إلى التطبيق بسبب عدم استيفاء أحد المتطلبات اللازمة. على سبيل المثال، لم يكن الجهاز موثوقًا به بدرجة كافية.

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

Kotlin

val environmentDetails =
    JSONObject(payload).getJSONObject("environmentDetails")
val appAccessRiskVerdict =
    environmentDetails.getJSONObject("appAccessRiskVerdict")

if (appAccessRiskVerdict.has("appsDetected")) {
    val appsDetected = appAccessRiskVerdict.getJSONArray("appsDetected").toString()
    if (!appsDetected.contains("CAPTURING") && !appsDetected.contains("CONTROLLING")) {
        // Looks good!
    }
}

Java

JSONObject environmentDetails =
    new JSONObject(payload).getJSONObject("environmentDetails");
JSONObject appAccessRiskVerdict =
    environmentDetails.getJSONObject("appAccessRiskVerdict");

if (appAccessRiskVerdict.has("appsDetected")) {
    String appsDetected = appAccessRiskVerdict.getJSONArray("appsDetected").toString()
    if (!appsDetected.contains("CAPTURING") && !appsDetected.contains("CONTROLLING")) {
        // Looks good!
    }
}

بيان "Play للحماية"

بعد تفعيل هذه الميزة، سيتضمّن الحقل environmentDetails في البيانات الأساسية في واجهة برمجة التطبيقات Play Integrity API بيان "Play للحماية":

environmentDetails: {
  playProtectVerdict: "NO_ISSUES"
}

يمكن أن تحتوي السمة playProtectVerdict على إحدى القيم التالية:

NO_ISSUES
تم تفعيل "Play للحماية" ولم ترصد أي مشاكل في التطبيق على الجهاز.
NO_DATA
تم تفعيل "Play للحماية" ولكن لم يتم إجراء أي فحص حتى الآن. من المحتمل أنّه تمّت إعادة ضبط الجهاز أو تطبيق "متجر Play" مؤخرًا.
POSSIBLE_RISK
تم إيقاف "Play للحماية".
MEDIUM_RISK
تم تفعيل خدمة "Play للحماية" ورصدت التطبيقات التي تم تثبيتها على الجهاز والتي قد تتسبّب بضرر.
HIGH_RISK
تم تفعيل خدمة "Play للحماية" ورصدت تطبيقات خطيرة تم تثبيتها على الجهاز.
UNEVALUATED

لم يتم تقييم بيان "Play للحماية".

وقد يحدث ذلك لعدة أسباب، بما فيها ما يلي:

  • الجهاز غير موثوق بالقدر الكافي
  • الألعاب فقط: لا يملك حساب المستخدم ترخيص Play لهذه اللعبة.

إرشادات حول استخدام بيان "Play للحماية"

يمكن لخادم الخلفية لتطبيقك أن يقرّر ما إذا كان يجب التصرّف بناءً على بيان السلامة بناءً على مدى تحملك للمخاطر. في ما يلي بعض الاقتراحات والإجراءات المحتملة للمستخدم:

NO_ISSUES
تم تفعيل "Play للحماية" ولم ترصد أي مشاكل، لذلك ليس مطلوبًا من المستخدم اتّخاذ أي إجراء.
POSSIBLE_RISK وNO_DATA
عند تلقّي هذه الشهادات، اطلب من المستخدم التأكّد من أنّ خدمة "Play للحماية" مفعّلة وأنها قد أجرت فحصًا. يجب أن يظهر NO_DATA في حالات نادرة فقط.
MEDIUM_RISK وHIGH_RISK
بناءً على مدى تحملك للمخاطر، يمكنك أن تطلب من المستخدم تشغيل "Play للحماية" واتخاذ إجراء بشأن تحذيرات "Play للحماية". إذا لم يتمكن المستخدم من تلبية هذه المتطلبات، فيمكنك حظره من إجراء الخادم.