احکام صداقت

این صفحه نحوه تفسیر و کار با حکم یکپارچگی بازگشتی را شرح می‌دهد. چه درخواست API استاندارد یا کلاسیک ارسال کنید، حکم یکپارچگی با فرمت یکسان و محتوای مشابه بازگردانده می‌شود. حکم یکپارچگی، اطلاعاتی در مورد اعتبار دستگاه‌ها، برنامه‌ها و حساب‌ها ارائه می‌دهد. سرور برنامه شما می‌تواند از بار داده حاصل در یک حکم رمزگشایی شده و تأیید شده استفاده کند تا بهترین روش برای انجام یک اقدام یا درخواست خاص در برنامه شما را تعیین کند.

قالب حکم یکپارچگی بازگردانده شده

این داده‌ی مخرب از نوع JSON با متن ساده است و حاوی سیگنال‌های یکپارچگی در کنار اطلاعات ارائه شده توسط توسعه‌دهنده می‌باشد.

ساختار کلی بار مفید به شرح زیر است:

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

قبل از بررسی هر حکم صحت، ابتدا باید بررسی کنید که مقادیر موجود در فیلد requestDetails با مقادیر درخواست اصلی مطابقت داشته باشند. بخش‌های بعدی هر فیلد را با جزئیات بیشتری شرح می‌دهند.

فیلد جزئیات درخواست

فیلد requestDetails حاوی اطلاعاتی در مورد درخواست است، از جمله اطلاعات ارائه شده توسط توسعه‌دهنده در requestHash برای درخواست‌های استاندارد و nonce برای درخواست‌های کلاسیک.

برای درخواست‌های استاندارد API:

"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 requested.
  "timestampMillis": "1675655009345"
}

این مقادیر باید با مقادیر درخواست اصلی مطابقت داشته باشند. بنابراین، بخش requestDetails از JSON payload را با اطمینان از اینکه requestPackageName و requestHash با آنچه در درخواست اصلی ارسال شده است مطابقت دارند، همانطور که در قطعه کد زیر نشان داده شده است، تأیید کنید:

کاتلین

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

جاوا

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

برای درخواست‌های API کلاسیک :

"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 payload را با اطمینان از اینکه requestPackageName و nonce با آنچه در درخواست اصلی ارسال شده است مطابقت دارند، همانطور که در قطعه کد زیر نشان داده شده است، تأیید کنید:

کاتلین

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

جاوا

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
برنامه و گواهی با نسخه‌های توزیع‌شده توسط گوگل پلی مطابقت دارند.
UNRECOGNIZED_VERSION
نام گواهی یا بسته با سوابق Google Play مطابقت ندارد.
UNEVALUATED
یکپارچگی برنامه ارزیابی نشد. یک الزام ضروری، مانند عدم قابلیت اطمینان کافی دستگاه، نادیده گرفته شد.

برای اطمینان از اینکه توکن توسط برنامه‌ای که توسط شما ایجاد شده است، تولید شده است، تأیید کنید که یکپارچگی برنامه مطابق انتظار است، همانطور که در قطعه کد زیر نشان داده شده است:

کاتلین

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

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

جاوا

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

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

همچنین می‌توانید نام بسته برنامه، نسخه برنامه و گواهی‌های برنامه را به صورت دستی بررسی کنید.

فیلد یکپارچگی دستگاه

فیلد deviceIntegrity می‌تواند شامل یک مقدار واحد به deviceRecognitionVerdict باشد که دارای یک یا چند برچسب است که نشان می‌دهد یک دستگاه چقدر می‌تواند یکپارچگی برنامه را رعایت کند. اگر دستگاهی معیارهای هیچ برچسبی را نداشته باشد، فیلد deviceIntegrity deviceRecognitionVerdict حذف می‌کند.

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

به طور پیش‌فرض، deviceRecognitionVerdict می‌تواند شامل موارد زیر باشد:

MEETS_DEVICE_INTEGRITY
این برنامه روی یک دستگاه اندروید اصلی و دارای گواهی اجرا می‌شود. در اندروید ۱۳ و بالاتر، مدرک سخت‌افزاری وجود دارد که نشان می‌دهد بوت لودر دستگاه قفل شده است و سیستم عامل اندروید بارگذاری شده، یک ایمیج تأیید شده از سازنده دستگاه است.
خالی (یک مقدار خالی)
برنامه روی دستگاهی اجرا می‌شود که نشانه‌هایی از حمله (مانند اتصال API) یا اختلال در سیستم (مانند روت بودن) دارد، یا برنامه روی یک دستگاه فیزیکی اجرا نمی‌شود (مانند شبیه‌ساز که از بررسی‌های یکپارچگی Google Play سربلند بیرون نمی‌آید).

برای اطمینان از اینکه توکن از یک دستگاه قابل اعتماد آمده است، بررسی کنید که deviceRecognitionVerdict مطابق انتظار باشد، همانطور که در قطعه کد زیر نشان داده شده است:

کاتلین

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

جاوا

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

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

اگر در تست دستگاه خود برای بررسی یکپارچگی دستگاه با مشکل مواجه هستید، مطمئن شوید که رام کارخانه نصب شده است (برای مثال، با تنظیم مجدد دستگاه) و بوت لودر قفل شده است. همچنین می‌توانید تست‌های API یکپارچگی بازی را در کنسول بازی خود ایجاد کنید .

برچسب‌های مشروط دستگاه

اگر برنامه شما برای Google Play Games for PC منتشر می‌شود، deviceRecognitionVerdict می‌تواند شامل برچسب زیر نیز باشد:

MEETS_VIRTUAL_INTEGRITY
این برنامه روی یک شبیه‌ساز مبتنی بر اندروید با سرویس‌های گوگل پلی اجرا می‌شود. این شبیه‌ساز از بررسی‌های یکپارچگی سیستم سربلند بیرون می‌آید و الزامات اصلی سازگاری با اندروید را برآورده می‌کند.

اطلاعات اختیاری دستگاه و فراخوان دستگاه

شما می‌توانید به عنوان بخشی از یک استراتژی اجرایی چند مرحله‌ای، برچسب‌های اختیاری دستگاه را دریافت کنید. اگر در حکم یکپارچگی، برچسب‌های اضافی را دریافت کنید ، deviceRecognitionVerdict می‌تواند شامل برچسب‌های اضافی زیر باشد:

MEETS_BASIC_INTEGRITY
برنامه روی دستگاهی اجرا می‌شود که بررسی‌های اولیه‌ی یکپارچگی سیستم را با موفقیت پشت سر می‌گذارد. بوت‌لودر دستگاه می‌تواند قفل یا باز شود و وضعیت بوت می‌تواند تأیید یا تأیید نشود. ممکن است دستگاه گواهی نداشته باشد، در این صورت گوگل نمی‌تواند هیچ تضمینی در مورد امنیت، حریم خصوصی یا سازگاری برنامه ارائه دهد. در اندروید ۱۳ و بالاتر، حکم MEETS_BASIC_INTEGRITY فقط مستلزم آن است که ریشه‌ی اعتماد گواهی توسط گوگل ارائه شود.
MEETS_STRONG_INTEGRITY
این برنامه روی یک دستگاه اندروید اصلی و دارای گواهی با به‌روزرسانی امنیتی اخیر اجرا می‌شود.
  • در اندروید ۱۳ و بالاتر، حکم MEETS_STRONG_INTEGRITY مستلزم MEETS_DEVICE_INTEGRITY و به‌روزرسانی‌های امنیتی در سال گذشته برای تمام پارتیشن‌های دستگاه، از جمله وصله پارتیشن سیستم عامل اندروید و وصله پارتیشن فروشنده است.
  • در اندروید ۱۲ و پایین‌تر، حکم MEETS_STRONG_INTEGRITY فقط به اثبات صحت بوت با پشتیبانی سخت‌افزار نیاز دارد و نیازی به به‌روزرسانی امنیتی اخیر دستگاه ندارد . بنابراین، هنگام استفاده از MEETS_STRONG_INTEGRITY ، توصیه می‌شود نسخه SDK اندروید را نیز در فیلد deviceAttributes در نظر بگیرید.

اگر هر یک از معیارهای برچسب رعایت شود، یک دستگاه واحد چندین برچسب دستگاه را در حکم یکپارچگی دستگاه برمی‌گرداند.

ویژگی‌های دستگاه

همچنین می‌توانید ویژگی‌های دستگاه را انتخاب کنید که نسخه SDK اندروید سیستم عامل اندروید در حال اجرا روی دستگاه را نشان می‌دهد. نسخه SDK اندروید برای تمایز بین دستگاه‌هایی که اندروید ۱۳ و بالاتر را اجرا می‌کنند و دستگاه‌هایی که نسخه‌های SDK اندروید پایین‌تر را اجرا می‌کنند، به عنوان بخشی از یک استراتژی اجرای چند مرحله‌ای، مفید است. در آینده، ممکن است با سایر ویژگی‌های دستگاه گسترش یابد.

مقدار نسخه SDK، شماره نسخه Android SDK است که در Build.VERSION_CODES تعریف شده است. اگر یک الزام ضروری از قلم افتاده باشد، نسخه SDK ارزیابی نمی‌شود. در این حالت، فیلد sdkVersion تنظیم نشده است؛ بنابراین، فیلد deviceAttributes خالی است. این اتفاق می‌تواند به دلایل زیر رخ دهد:

  • دستگاه به اندازه کافی قابل اعتماد نیست.
  • مشکلات فنی در دستگاه وجود داشت.

اگر دریافت deviceAttributes را انتخاب کنید، فیلد deviceIntegrity فیلد اضافی زیر را خواهد داشت:

"deviceIntegrity": {
  "deviceRecognitionVerdict": ["MEETS_DEVICE_INTEGRITY"],
  "deviceAttributes": {
    // 33 is one possible value, which represents Android 13 (Tiramisu).
    "sdkVersion": 33
  }
}

در صورتی که نسخه SDK ارزیابی نشود، فیلد deviceAttributes به صورت زیر تنظیم خواهد شد:

"deviceIntegrity": {
  "deviceRecognitionVerdict": ["MEETS_DEVICE_INTEGRITY"],
  "deviceAttributes": {}  // sdkVersion field is not set.
}

فعالیت اخیر دستگاه

همچنین می‌توانید فعالیت اخیر دستگاه را انتخاب کنید، که به شما می‌گوید برنامه شما در یک ساعت گذشته چند بار درخواست توکن یکپارچگی را روی یک دستگاه خاص انجام داده است. می‌توانید از فعالیت اخیر دستگاه برای محافظت از برنامه خود در برابر دستگاه‌های غیرمنتظره و بیش‌فعال که می‌توانند نشانه‌ای از یک حمله فعال باشند، استفاده کنید. می‌توانید بر اساس تعداد دفعاتی که انتظار دارید برنامه شما که روی یک دستگاه معمولی نصب شده است، در هر ساعت درخواست توکن یکپارچگی کند، تصمیم بگیرید که چقدر به هر سطح فعالیت اخیر دستگاه اعتماد کنید.

اگر گزینه دریافت recentDeviceActivity را انتخاب کنید، فیلد deviceIntegrity دو مقدار خواهد داشت:

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

تعاریف deviceActivityLevel بین حالت‌ها متفاوت است و می‌تواند یکی از مقادیر زیر را داشته باشد:

سطح فعالیت اخیر دستگاه درخواست‌های استاندارد توکن یکپارچگی API در این دستگاه در ساعت گذشته به ازای هر برنامه درخواست‌های توکن یکپارچگی API کلاسیک در این دستگاه در ساعت گذشته به ازای هر برنامه
LEVEL_1 (پایین‌ترین) ۱۰ یا کمتر ۵ یا کمتر
LEVEL_2 بین ۱۱ تا ۲۵ بین ۶ تا ۱۰
LEVEL_3 بین ۲۶ تا ۵۰ بین ۱۱ تا ۱۵
LEVEL_4 (بالاترین) بیش از ۵۰ بیش از ۱۵
UNEVALUATED فعالیت اخیر دستگاه ارزیابی نشد. این می‌تواند به دلایل زیر اتفاق بیفتد:
  • دستگاه به اندازه کافی قابل اعتماد نیست.
  • نسخه برنامه نصب شده روی دستگاه شما برای گوگل پلی ناشناخته است.
  • مشکلات فنی در دستگاه

فراخوان دستگاه (بتا)

همچنین می‌توانید فراخوانی دستگاه را انتخاب کنید، که به شما امکان می‌دهد برخی داده‌های سفارشی را برای هر دستگاه با دستگاه‌های خاص ذخیره کنید که می‌توانید هنگام نصب مجدد برنامه خود در همان دستگاه، آنها را به طور قابل اعتمادی بازیابی کنید. پس از درخواست یک توکن یکپارچگی، یک فراخوانی سرور به سرور جداگانه برای تغییر مقادیر فراخوانی دستگاه برای یک دستگاه خاص انجام می‌دهید.

اگر گزینه deviceRecall را انتخاب کنید، فیلد deviceIntegrity شامل اطلاعات فراخوانی دستگاهی خواهد بود که برای دستگاه خاص تنظیم کرده‌اید:

"deviceIntegrity": {
  "deviceRecognitionVerdict": ["MEETS_DEVICE_INTEGRITY"],
  "deviceRecall": {
    "values": {
      "bitFirst": true,
      "bitSecond": false,
      "bitThird": true
    },
    "writeDates": {
      // Write time in YYYYMM format in UTC.
      "yyyymmFirst": 202401,
      // Note that yyyymmSecond is not set because bitSecond is false.
      "yyyymmThird": 202310
    }
  }
}

deviceRecall به دو فیلد تقسیم می‌شود:

  • values : مقادیر بیتی که قبلاً برای این دستگاه تنظیم کرده‌اید را بازیابی می‌کند.
  • writeDates : تاریخ‌های نوشتن بیت را بر اساس UTC و دقیقاً مطابق با سال و ماه فراخوانی می‌کند. تاریخ نوشتن یک بیت فراخوانی هر بار که بیت روی true تنظیم شود، به‌روزرسانی می‌شود و وقتی بیت روی false تنظیم شود، حذف می‌شود.

در صورتی که اطلاعات فراخوان دستگاه در دسترس نباشد، مقدار فراخوان دستگاه خالی خواهد بود:

"deviceIntegrity": {
  "deviceRecognitionVerdict": ["MEETS_DEVICE_INTEGRITY"],
  "deviceRecall": {
    "values": {},
    "writeDates": {}
  }
}

فیلد جزئیات حساب

فیلد accountDetails شامل یک مقدار واحد به appLicensingVerdict است که وضعیت مجوز گوگل پلی برنامه را برای حساب کاربری که در دستگاه وارد شده است، نشان می‌دهد. اگر حساب کاربری مجوز گوگل پلی برنامه را داشته باشد، به این معنی است که آن را از گوگل پلی دانلود یا خریداری کرده است.

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

appLicensingVerdict می‌تواند یکی از مقادیر زیر را داشته باشد:

LICENSED
کاربر دارای حق استفاده از برنامه است. به عبارت دیگر، کاربر برنامه شما را از گوگل پلی روی دستگاه خود نصب یا به‌روزرسانی کرده است.
UNLICENSED
کاربر مجوز برنامه را ندارد. این اتفاق زمانی می‌افتد که، برای مثال، کاربر برنامه شما را از طریق دانلود جانبی دانلود می‌کند یا آن را از گوگل پلی دریافت نمی‌کند. می‌توانید برای رفع این مشکل، کادر محاوره‌ای GET_LICENSED را به کاربران نشان دهید.
UNEVALUATED

جزئیات صدور مجوز ارزیابی نشد زیرا یک الزام ضروری از قلم افتاده بود.

این اتفاق می‌تواند به دلایل مختلفی از جمله موارد زیر رخ دهد:

  • دستگاه به اندازه کافی قابل اعتماد نیست.
  • نسخه برنامه نصب شده روی دستگاه شما برای گوگل پلی ناشناخته است.
  • کاربر وارد گوگل پلی نشده است.

برای بررسی اینکه کاربر مجوز برنامه شما را دارد یا خیر، تأیید کنید که appLicensingVerdict مطابق انتظار است، همانطور که در قطعه کد زیر نشان داده شده است:

کاتلین

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

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

جاوا

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

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

فیلد جزئیات محیط

همچنین می‌توانید سیگنال‌های اضافی در مورد محیط را انتخاب کنید. ریسک دسترسی به برنامه به برنامه شما می‌گوید که آیا برنامه‌های دیگری در حال اجرا هستند که می‌توانند برای ضبط صفحه نمایش، نمایش همپوشانی‌ها یا کنترل دستگاه استفاده شوند یا خیر. حکم Play Protect به شما می‌گوید که آیا Google Play Protect روی دستگاه فعال است یا خیر و آیا بدافزار شناخته شده‌ای پیدا کرده است یا خیر.

اگر در کنسول گوگل پلی خود، گزینه App Access Risk یا Play Protect را انتخاب کرده باشید، پاسخ API شما شامل فیلد environmentDetails خواهد بود. فیلد environmentDetails می‌تواند شامل دو مقدار باشد: appAccessRiskVerdict و playProtectVerdict .

حکم ریسک دسترسی به برنامه

پس از فعال شدن، فیلد environmentDetails در Payload API مربوط به Play Integrity حاوی حکم ریسک دسترسی به برنامه جدید خواهد بود.

{
  "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_ مشخص می‌شوند.

  • برنامه‌های دیگر : برنامه‌هایی که توسط گوگل پلی نصب نشده‌اند. این شامل برنامه‌هایی که توسط سازنده دستگاه از قبل روی پارتیشن سیستم بارگذاری شده‌اند، نمی‌شود. پاسخ‌های مربوط به چنین برنامه‌هایی با پیشوند UNKNOWN_ شروع می‌شوند.

پاسخ‌های زیر را می‌توان برگرداند:

KNOWN_INSTALLED ، نصب‌شده‌ها UNKNOWN_INSTALLED
برنامه‌هایی نصب شده‌اند که با منبع نصب مربوطه مطابقت دارند.
KNOWN_CAPTURING ، UNKNOWN_CAPTURING
برنامه‌هایی در حال اجرا هستند که مجوزهای فعالی دارند که می‌توانند برای مشاهده صفحه نمایش در حین اجرای برنامه شما استفاده شوند. این شامل هرگونه سرویس دسترسی تأیید شده که برای Google Play در حال اجرا روی دستگاه شناخته شده است، نمی‌شود.
KNOWN_CONTROLLING ، UNKNOWN_CONTROLLING
برنامه‌هایی در حال اجرا هستند که مجوزهایی برای آنها فعال شده است که می‌توانند برای کنترل دستگاه و کنترل مستقیم ورودی‌های برنامه شما و همچنین برای ثبت ورودی‌ها و خروجی‌های برنامه شما استفاده شوند. این شامل هرگونه سرویس دسترسی تأیید شده که برای Google Play در حال اجرا روی دستگاه شناخته شده است، نمی‌شود.
KNOWN_OVERLAYS ، UNKNOWN_OVERLAYS
برنامه‌هایی در حال اجرا هستند که مجوزهای فعالی دارند که می‌توانند برای نمایش لایه‌ها روی برنامه شما استفاده شوند. این شامل هرگونه سرویس دسترسی تأیید شده که برای گوگل پلی شناخته شده و روی دستگاه اجرا می‌شود، نمی‌شود.
خالی (یک مقدار خالی)

اگر یک الزام ضروری از قلم افتاده باشد، ریسک دسترسی به برنامه ارزیابی نمی‌شود. در این مورد، فیلد appAccessRiskVerdict خالی است. این می‌تواند به دلایل مختلفی از جمله موارد زیر اتفاق بیفتد:

  • دستگاه به اندازه کافی قابل اعتماد نیست.
  • فرم فاکتور دستگاه، گوشی، تبلت یا دستگاه تاشو نیست.
  • این دستگاه اندروید ۶ (سطح API 23) یا بالاتر را اجرا نمی‌کند.
  • نسخه برنامه نصب شده روی دستگاه شما برای گوگل پلی ناشناخته است.
  • نسخه فروشگاه گوگل پلی روی دستگاه قدیمی است.
  • حساب کاربری مجوز Play ندارد.
  • یک درخواست استاندارد با پارامتر verdictOptOut استفاده شد.
  • یک درخواست استاندارد با نسخه‌ای از کتابخانه Play Integrity API استفاده شده است که هنوز از ریسک دسترسی به برنامه برای درخواست‌های استاندارد پشتیبانی نمی‌کند.

ریسک دسترسی به برنامه، سرویس‌های دسترسی تأیید شده‌ای را که از طریق بررسی بهبود یافته دسترسی به Google Play (نصب شده توسط هر فروشگاه برنامه‌ای روی دستگاه) بررسی شده‌اند، به طور خودکار مستثنی می‌کند. «حذف شده» به این معنی است که سرویس‌های دسترسی تأیید شده‌ای که روی دستگاه اجرا می‌شوند، پاسخی در مورد ضبط، کنترل یا همپوشانی در حکم ریسک دسترسی به برنامه برنمی‌گردانند. برای درخواست بررسی بهبود یافته دسترسی به Google Play برای برنامه دسترسی خود، آن را در Google Play منتشر کنید و مطمئن شوید که پرچم isAccessibilityTool برنامه شما در مانیفست برنامه روی true تنظیم شده است، یا درخواست بررسی دهید .

احکام مربوط به ریسک دسترسی به برنامه نمونه

جدول زیر چند نمونه از احکام مربوط به ریسک دسترسی به برنامه و معنای آنها را نشان می‌دهد (این جدول تمام نتایج ممکن را فهرست نمی‌کند):

پاسخ به حکم ریسک دسترسی به برنامه نمونه تفسیر
appsDetected:
["KNOWN_INSTALLED"]
فقط برنامه‌هایی نصب می‌شوند که توسط گوگل پلی شناسایی شده باشند یا توسط سازنده دستگاه از قبل روی پارتیشن سیستم بارگذاری شده باشند.
هیچ برنامه‌ای در حال اجرا نیست که منجر به صدور احکام ضبط، کنترل یا همپوشانی شود.
appsDetected:
["KNOWN_INSTALLED",
"UNKNOWN_INSTALLED",
"UNKNOWN_CAPTURING"]
برنامه‌هایی وجود دارند که توسط گوگل پلی نصب شده‌اند یا توسط سازنده دستگاه از قبل روی پارتیشن سیستم بارگذاری شده‌اند.
برنامه‌های دیگری در حال اجرا هستند و مجوزهایی دارند که می‌توانند برای مشاهده صفحه یا ضبط سایر ورودی‌ها و خروجی‌ها استفاده شوند.
appsDetected:
["KNOWN_INSTALLED",
"KNOWN_CAPTURING",
"UNKNOWN_INSTALLED",
"UNKNOWN_CONTROLLING"]
برنامه‌های Play یا سیستمی در حال اجرا هستند که مجوزهایی را فعال کرده‌اند که می‌توانند برای مشاهده صفحه یا ضبط سایر ورودی‌ها و خروجی‌ها استفاده شوند.
همچنین برنامه‌های دیگری نیز در حال اجرا هستند که مجوزهایی را فعال کرده‌اند که می‌توانند برای کنترل دستگاه و کنترل مستقیم ورودی‌ها به برنامه شما استفاده شوند.
appAccessRiskVerdict: {} ریسک دسترسی به برنامه ارزیابی نمی‌شود زیرا یک الزام ضروری از قلم افتاده است. برای مثال، دستگاه به اندازه کافی قابل اعتماد نبوده است.

بسته به سطح ریسک خود، می‌توانید تصمیم بگیرید که چه ترکیبی از احکام برای ادامه قابل قبول است و روی کدام احکام می‌خواهید اقدام کنید. قطعه کد زیر مثالی از تأیید عدم وجود برنامه‌های در حال اجرا که می‌توانند صفحه نمایش را ضبط کنند یا برنامه شما را کنترل کنند، نشان می‌دهد:

کاتلین

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

جاوا

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!
    }
}
رفع خطرات دسترسی به برنامه

بسته به سطح ریسک خود، می‌توانید قبل از اینکه به کاربر اجازه دهید درخواست یا اقدامی را انجام دهد، تصمیم بگیرید که می‌خواهید در مورد کدام احکام ریسک دسترسی به برنامه اقدام کنید. پس از بررسی حکم ریسک دسترسی به برنامه، می‌توانید پیام‌های اختیاری Google Play را به کاربر نشان دهید. می‌توانید CLOSE_UNKNOWN_ACCESS_RISK را برای درخواست از کاربر برای بستن برنامه‌های ناشناخته‌ای که باعث حکم ریسک دسترسی به برنامه می‌شوند، نشان دهید یا می‌توانید CLOSE_ALL_ACCESS_RISK را برای درخواست از کاربر برای بستن همه برنامه‌های (شناخته شده و ناشناخته) که باعث حکم ریسک دسترسی به برنامه می‌شوند، نشان دهید.

حکم Play Protect

پس از فعال شدن، فیلد environmentDetails در payload API مربوط به Play Integrity حاوی حکم Play Protect خواهد بود:

"environmentDetails": {
  "playProtectVerdict": "NO_ISSUES"
}

playProtectVerdict می‌تواند یکی از مقادیر زیر را داشته باشد:

NO_ISSUES
Play Protect فعال است و هیچ مشکلی در برنامه روی دستگاه پیدا نکرده است.
NO_DATA
Play Protect روشن است اما هنوز هیچ اسکنی انجام نشده است. ممکن است دستگاه یا برنامه Play Store اخیراً تنظیم مجدد شده باشد.
POSSIBLE_RISK
«محافظت از بازی» خاموش است.
MEDIUM_RISK
Play Protect روشن است و برنامه‌های بالقوه مضر نصب‌شده روی دستگاه را پیدا کرده است.
HIGH_RISK
Play Protect روشن است و برنامه‌های خطرناکی را که روی دستگاه نصب شده‌اند، پیدا کرده است.
UNEVALUATED

حکم Play Protect ارزیابی نشد.

این اتفاق می‌تواند به دلایل مختلفی از جمله موارد زیر رخ دهد:

  • دستگاه به اندازه کافی قابل اعتماد نیست.
  • حساب کاربری مجوز Play ندارد.

راهنمایی در مورد استفاده از حکم Play Protect

سرور بک‌اند برنامه شما می‌تواند بر اساس میزان ریسک‌پذیری شما، تصمیم بگیرد که چگونه عمل کند. در اینجا چند پیشنهاد و اقدام بالقوه برای کاربران ارائه شده است:

NO_ISSUES
Play Protect فعال است و هیچ مشکلی پیدا نکرده است، بنابراین نیازی به اقدام کاربر نیست.
POSSIBLE_RISK و NO_DATA
هنگام دریافت این احکام، از کاربر بخواهید که بررسی کند آیا Play Protect فعال است و اسکن را انجام داده است یا خیر. NO_DATA فقط در موارد نادر باید ظاهر شود.
MEDIUM_RISK ​​و HIGH_RISK
بسته به میزان ریسک‌پذیری‌تان، می‌توانید از کاربر بخواهید که Play Protect را اجرا کند و در مورد هشدارهای Play Protect اقدامی انجام دهد. اگر کاربر نمی‌تواند این الزامات را برآورده کند، می‌توانید دسترسی او را به سرور مسدود کنید.