इंटेग्रिटी के नतीजे

इस पेज पर, जवाब के तौर पर मिले इंटिग्रिटी वर्दिक्ट को समझने और उसका इस्तेमाल करने का तरीका बताया गया है. स्टैंडर्ड या क्लासिक एपीआई अनुरोध करने पर, सुरक्षा की जांच के नतीजे एक ही फ़ॉर्मैट में मिलते हैं. साथ ही, उनमें एक जैसा कॉन्टेंट होता है. इंटिग्रिटी के नतीजे से, डिवाइसों, ऐप्लिकेशन, और खातों की वैधता के बारे में जानकारी मिलती है. आपके ऐप्लिकेशन का सर्वर, डिक्रिप्ट किए गए और पुष्टि किए गए नतीजे वाले पेलोड का इस्तेमाल कर सकता है. इससे यह तय किया जा सकता है कि आपके ऐप्लिकेशन में किसी कार्रवाई या अनुरोध को सबसे सही तरीके से कैसे पूरा किया जाए.

इंटिग्रिटी के नतीजे का फ़ॉर्मैट

पेलोड, सादा टेक्स्ट वाला 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 requested.
  "timestampMillis": "1675655009345"
}

ये वैल्यू, मूल अनुरोध में दी गई वैल्यू से मेल खानी चाहिए. इसलिए, JSON पेलोड के requestDetails हिस्से की पुष्टि करें. इसके लिए, यह पक्का करें कि 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"
}

ये वैल्यू, मूल अनुरोध में दी गई वैल्यू से मेल खानी चाहिए. इसलिए, JSON पेलोड के requestDetails हिस्से की पुष्टि करें. इसके लिए, पक्का करें कि 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 फ़ील्ड में deviceRecognitionVerdict शामिल नहीं होता है.

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

डिफ़ॉल्ट रूप से, deviceRecognitionVerdict में ये शामिल हो सकते हैं:

MEETS_DEVICE_INTEGRITY
यह ऐप्लिकेशन, ओरिजनल और सर्टिफ़ाइड Android डिवाइस पर चल रहा है. Android 13 और उसके बाद के वर्शन में, हार्डवेयर से यह पुष्टि की जाती है कि डिवाइस का बूटलोडर लॉक है और लोड किया गया Android OS, डिवाइस बनाने वाली कंपनी की सर्टिफ़ाइड इमेज है.
खाली (वैल्यू खाली है)
ऐप्लिकेशन किसी ऐसे डिवाइस पर चल रहा है जिस पर हमला होने (जैसे कि एपीआई हुकिंग) या सिस्टम से छेड़छाड़ (जैसे कि रूट किया गया) के संकेत मिले हैं. ऐसा भी हो सकता है कि ऐप्लिकेशन किसी फ़िज़िकल डिवाइस पर न चल रहा हो. उदाहरण के लिए, किसी ऐसे एम्युलेटर पर चल रहा हो जिसमें पूरी सुरक्षा देने वाला Google Play Integrity मौजूद नहीं है.

यह पक्का करने के लिए कि टोकन किसी भरोसेमंद डिवाइस से मिला है, पुष्टि करें कि 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!
}

अगर आपको टेस्टिंग डिवाइस पर डिवाइस इंटिग्रिटी की जांच करने में समस्याएं आ रही हैं, तो पक्का करें कि फ़ैक्ट्री ROM इंस्टॉल किया गया हो. उदाहरण के लिए, डिवाइस को रीसेट करके और बूटलोडर लॉक करके ऐसा किया जा सकता है. आपके पास Play Console में, Play Integrity API के टेस्ट बनाने का विकल्प भी होता है.

शर्तों के हिसाब से डिवाइस के लेबल

अगर आपका ऐप्लिकेशन पीसी के लिए Google Play Games पर रिलीज़ किया जा रहा है, तो deviceRecognitionVerdict में यह लेबल भी शामिल हो सकता है:

MEETS_VIRTUAL_INTEGRITY
यह ऐप्लिकेशन, Android Emulator पर चल रहा है. यह Emulator, Google Play services के साथ काम करता है. एम्युलेटर की जांच से यह पता चला है कि इस पर सिस्टम को पूरी सुरक्षा मिलती है. साथ ही, यह Android के साथ काम करने की ज़रूरी शर्तों के मुताबिक है.

डिवाइस की जानकारी और डिवाइस रीकॉल करने की वैकल्पिक सुविधा

अगर आपने इंटेग्रिटी की जांच के नतीजे में ज़्यादा लेबल पाने के लिए ऑप्ट-इन किया है, तो deviceRecognitionVerdict में ये अतिरिक्त लेबल शामिल हो सकते हैं:

MEETS_BASIC_INTEGRITY
यह ऐप्लिकेशन एक ऐसे डिवाइस पर चल रहा है जिस पर सिस्टम को बुनियादी स्तर की पूरी सुरक्षा मिलती है. डिवाइस के बूटलोडर को लॉक या अनलॉक किया जा सकता है. साथ ही, बूट की स्थिति की पुष्टि की जा सकती है या नहीं की जा सकती. ऐसा हो सकता है कि डिवाइस को सर्टिफ़िकेट न मिला हो. ऐसे में, Google सुरक्षा, निजता या ऐप्लिकेशन के साथ काम करने से जुड़ी कोई भी गारंटी नहीं दे सकता. Android 13 और इसके बाद के वर्शन पर, MEETS_BASIC_INTEGRITY का नतीजा पाने के लिए, यह ज़रूरी है कि पुष्टि करने वाला रूट ऑफ़ ट्रस्ट, Google ने दिया हो.
MEETS_STRONG_INTEGRITY
यह ऐप्लिकेशन, ओरिजनल और सर्टिफ़ाइड Android डिवाइस पर चल रहा है. साथ ही, इस पर हाल ही का सुरक्षा अपडेट इंस्टॉल है.
  • Android 13 और इसके बाद के वर्शन पर, MEETS_STRONG_INTEGRITY का नतीजा पाने के लिए, MEETS_DEVICE_INTEGRITY और डिवाइस के सभी सेगमेंट के लिए, पिछले एक साल में किए गए सुरक्षा अपडेट ज़रूरी हैं. इनमें Android OS के सेगमेंट के लिए पैच और वेंडर के सेगमेंट के लिए पैच शामिल हैं.
  • Android 12 और उससे पहले के वर्शन पर, MEETS_STRONG_INTEGRITY का नतीजा पाने के लिए, सिर्फ़ हार्डवेयर के ज़रिए बूट इंटेग्रिटी की पुष्टि की ज़रूरत होती है. साथ ही, डिवाइस पर हाल ही का सुरक्षा अपडेट होना ज़रूरी नहीं है. इसलिए, MEETS_STRONG_INTEGRITY का इस्तेमाल करते समय, यह सुझाव दिया जाता है कि deviceAttributes फ़ील्ड में Android SDK टूल के वर्शन को भी ध्यान में रखा जाए.

अगर डिवाइस हर लेबल की शर्त पूरी करता है, तो डिवाइस इंटेग्रिटी के नतीजे में एक ही डिवाइस के लिए कई लेबल दिखेंगे.

डिवाइस की विशेषताएं

डिवाइस एट्रिब्यूट के लिए भी ऑप्ट इन किया जा सकता है. इससे आपको डिवाइस पर चल रहे Android OS का Android SDK वर्शन पता चलता है. आने वाले समय में, इसे डिवाइस के अन्य एट्रिब्यूट के साथ जोड़ा जा सकता है.

एसडीके वर्शन की वैल्यू, Android SDK का वह वर्शन नंबर होता है जो Build.VERSION_CODES में तय किया गया है. अगर कोई ज़रूरी शर्त पूरी नहीं की गई है, तो एसडीके टूल के वर्शन की जांच नहीं की जाती. इस मामले में, sdkVersion फ़ील्ड को सेट नहीं किया गया है. इसलिए, deviceAttributes फ़ील्ड खाली है. ऐसा इन वजहों से हो सकता है:

  • डिवाइस भरोसेमंद नहीं है.
  • डिवाइस में तकनीकी समस्याएं थीं.

deviceAttributes पाने के लिए ऑप्ट इन करने पर, deviceIntegrity फ़ील्ड में यह अतिरिक्त फ़ील्ड दिखेगा:

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

अगर एसडीके टूल के वर्शन की जांच नहीं की जाती है, तो 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 की परिभाषाएं, मोड के हिसाब से अलग-अलग होती हैं. इनमें से कोई एक वैल्यू हो सकती है:

डिवाइस पर हाल ही में की गई गतिविधि का लेवल हर ऐप्लिकेशन के लिए, इस डिवाइस पर पिछले एक घंटे में किए गए स्टैंडर्ड एपीआई इंटेग्रिटी टोकन के अनुरोध हर ऐप्लिकेशन के लिए, इस डिवाइस पर पिछले एक घंटे में किए गए क्लासिक एपीआई इंटेग्रिटी टोकन के अनुरोध
LEVEL_1 (सबसे कम) 10 या इससे कम 5 या इससे कम
LEVEL_2 11 से 25 के बीच 6 से 10 के बीच
LEVEL_3 26 से 50 के बीच 11 से 15 के बीच
LEVEL_4 (सबसे ज़्यादा) 50 से ज़्यादा 15 से ज़्यादा
UNEVALUATED डिवाइस पर हाल ही में की गई गतिविधि की जांच नहीं की गई. ऐसा इन वजहों से हो सकता है:
  • डिवाइस भरोसेमंद नहीं है.
  • डिवाइस पर इंस्टॉल किए गए आपके ऐप्लिकेशन के वर्शन की जानकारी Google Play को नहीं है.
  • डिवाइस में तकनीकी समस्याएं.

डिवाइस को बाज़ार से हटाएं (बीटा वर्शन)

डिवाइस रीकॉल की सुविधा के लिए भी ऑप्ट-इन किया जा सकता है. इसकी मदद से, किसी डिवाइस के लिए कुछ कस्टम डेटा सेव किया जा सकता है. इस डेटा को उसी डिवाइस पर ऐप्लिकेशन को फिर से इंस्टॉल करने पर, आसानी से वापस लाया जा सकता है. इंटीग्रिटी टोकन का अनुरोध करने के बाद, आपको किसी डिवाइस के लिए डिवाइस रीकॉल वैल्यू में बदलाव करने के लिए, सर्वर-टू-सर्वर कॉल करना होगा.

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: यूटीसी में बिट राइट की तारीखों को साल और महीने के हिसाब से सटीक तरीके से याद रखें. किसी रिकॉल बिट की तारीख, हर बार बिट को true पर सेट करने पर अपडेट की जाएगी. साथ ही, बिट को false पर सेट करने पर इसे हटा दिया जाएगा.

अगर डिवाइस रीकॉल करने की जानकारी उपलब्ध नहीं है, तो डिवाइस रीकॉल करने की वैल्यू खाली होगी:

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

खाते की जानकारी वाला फ़ील्ड

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 Protect के नतीजे से आपको यह पता चलता है कि डिवाइस पर Google Play Protect की सुविधा चालू है या नहीं. साथ ही, यह भी पता चलता है कि उसे डिवाइस पर पहले से मौजूद मैलवेयर मिला है या नहीं.

अगर आपने Google Play Console में, ऐप्लिकेशन के ऐक्सेस से जुड़े जोखिम के बारे में जानकारी देने वाले नतीजे या Play Protect के नतीजे पाने के लिए ऑप्ट-इन किया है, तो एपीआई से मिलने वाले रिस्पॉन्स में environmentDetails फ़ील्ड शामिल होगा. environmentDetails फ़ील्ड में दो वैल्यू, appAccessRiskVerdict और playProtectVerdict शामिल हो सकती हैं.

ऐप्लिकेशन को ऐक्सेस करने से जुड़े जोखिम की जानकारी

इस सुविधा को चालू करने के बाद, Play Integrity API पेलोड में मौजूद environmentDetails फ़ील्ड में, ऐप्लिकेशन ऐक्सेस करने से जुड़े जोखिम की नई जानकारी शामिल होगी.

{
  "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 की उन सभी पुष्टि की गई सुलभता सेवाओं को शामिल नहीं किया गया है जिनके बारे में Google Play को पता है.
खाली (वैल्यू खाली है)

अगर कोई ज़रूरी शर्त पूरी नहीं की गई है, तो ऐप्लिकेशन को ऐक्सेस करने से जुड़े जोखिम की जांच नहीं की जाती. इस मामले में, appAccessRiskVerdict फ़ील्ड खाली है. ऐसा कई वजहों से हो सकता है. इनमें ये वजहें शामिल हैं:

  • डिवाइस भरोसेमंद नहीं है.
  • डिवाइस का साइज़, डाइमेंशन या कॉन्फ़िगरेशन, किसी फ़ोन, टैबलेट या फ़ोल्ड होने वाले डिवाइस जैसा नहीं है.
  • डिवाइस पर Android 6 (एपीआई लेवल 23) या उसके बाद का वर्शन नहीं चल रहा है.
  • Google Play को ऐप्लिकेशन के इंस्टॉल किए गए वर्शन की जानकारी नहीं है.
  • डिवाइस पर Google Play Store का पुराना वर्शन है.
  • उपयोगकर्ता खाते के पास Play का लाइसेंस नहीं है.
  • verdictOptOut पैरामीटर के साथ स्टैंडर्ड अनुरोध का इस्तेमाल किया गया था.
  • Play Integrity API की लाइब्रेरी के ऐसे वर्शन के साथ स्टैंडर्ड अनुरोध का इस्तेमाल किया गया है जो अब तक स्टैंडर्ड अनुरोधों के लिए, ऐप्लिकेशन को ऐक्सेस करने से जुड़े जोखिम की सूचना पाने की सुविधा के साथ काम नहीं करता.

ऐप्लिकेशन ऐक्सेस करने के जोखिम से जुड़ी नीति के तहत, पुष्टि की गई सुलभता सेवाओं को अपने-आप छूट मिल जाती है. इन सेवाओं की, 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!
    }
}
ऐप्लिकेशन को ऐक्सेस करने से जुड़े जोखिम की जानकारी को ठीक करना

जोखिम के लेवल के हिसाब से, यह तय किया जा सकता है कि उपयोगकर्ता को अनुरोध पूरा करने या कार्रवाई करने की अनुमति देने से पहले, आपको ऐप्लिकेशन को ऐक्सेस करने से जुड़े जोखिम की जानकारी के किन नतीजों पर कार्रवाई करनी है. ऐप्लिकेशन को ऐक्सेस करने से जुड़े जोखिम की जांच के नतीजे देखने के बाद, उपयोगकर्ता को Google Play के कुछ प्रॉम्प्ट दिखाए जा सकते हैं. हालांकि, ऐसा करना ज़रूरी नहीं है. उपयोगकर्ता को CLOSE_UNKNOWN_ACCESS_RISK दिखाकर, ऐप्लिकेशन को ऐक्सेस करने से जुड़े जोखिम की जांच के नतीजे में जोखिम वाले पाए गए ऐसे ऐप्लिकेशन बंद करने के लिए कहा जा सकता है जिनके बारे में जानकारी नहीं है. इसके अलावा, CLOSE_ALL_ACCESS_RISK दिखाकर, ऐप्लिकेशन को ऐक्सेस करने से जुड़े जोखिम की जांच के नतीजे में जोखिम वाले पाए गए सभी ऐप्लिकेशन (जिनके बारे में जानकारी है और जिनके बारे में जानकारी नहीं है) बंद करने के लिए कहा जा सकता है.

Play Protect का नतीजा

इस सुविधा को चालू करने के बाद, Play Integrity API पेलोड में मौजूद environmentDetails फ़ील्ड में, Play Protect की जांच का नतीजा दिखेगा:

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

playProtectVerdict में इनमें से कोई एक वैल्यू हो सकती है:

NO_ISSUES
Play Protect चालू है और उसे डिवाइस पर ऐप्लिकेशन से जुड़ी कोई समस्या नहीं मिली है.
NO_DATA
Play Protect चालू है, लेकिन अब तक कोई स्कैन नहीं किया गया है. ऐसा हो सकता है कि डिवाइस या Play Store ऐप्लिकेशन को हाल ही में रीसेट किया गया हो.
POSSIBLE_RISK
Play Protect की सुविधा बंद है.
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 की चेतावनियों पर कार्रवाई करने के लिए कहा जा सकता है. अगर उपयोगकर्ता इन ज़रूरी शर्तों को पूरा नहीं कर पाता है, तो उसे सर्वर पर कार्रवाई करने से रोका जा सकता है.