קביעות התקינות

בדף הזה מוסבר איך לפרש את תוצאת תקינות הנתונים שחוזרת ואיך להשתמש בה. בין ששולחים בקשה רגילה ל-API ובין ששולחים בקשה קלאסית ל-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 במטען הייעודי (payload) של ה-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.
        ...
}

בבקשות 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 במטען הייעודי (payload) של 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 Services. המכשיר עובר את בדיקות התקינות של המערכת ועומד בדרישות התאימות של Android.
ריק (ערך ריק)
האפליקציה פועלת במכשיר שיש בו סימנים למתקפה (כמו הוק של API) או לפריצה למערכת (כמו גישה ל-root), או שהאפליקציה לא פועלת במכשיר פיזי (כמו אמולטור שלא עובר את בדיקות התקינות של 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!
}

אם נתקלת בבעיות במכשיר הבדיקה בנוגע לתקינות המכשיר, עליך לוודא ש-ROM המקורית מותקנת (לדוגמה, על ידי איפוס המכשיר) ושתוכנת האתחול נעולה. אפשר גם ליצור בדיקות של Play Integrity API ב-Play Console.

תוויות מכשיר מותנות

אם האפליקציה שלכם תיועד ל-Google Play Games למחשב, השדה deviceRecognitionVerdict יכול להכיל גם את התווית הבאה:

MEETS_VIRTUAL_INTEGRITY
האפליקציה פועלת באמולטור שמבוסס על Android עם Google Play Services. האמולטור עובר את בדיקות התקינות של המערכת ועומד בדרישות התאימות הבסיסיות של Android.

מידע אופציונלי לגבי המכשיר

אם תבחרו לקבל תוויות נוספות בתוצאה של בדיקת תקינות הבחירות, הערך של deviceRecognitionVerdict יכול לכלול את התוויות הנוספות הבאות:

MEETS_BASIC_INTEGRITY
האפליקציה פועלת במכשיר שעובר את הבדיקות הבסיסיות של תקינות המערכת. יכול להיות שהמכשיר לא עומד בדרישות התאימות ל-Android, ויכול להיות שהוא לא אושר להריץ את Google Play Services. לדוגמה, יכול להיות שפועלת במכשיר גרסה לא מוכרת של Android, או שיש לו תוכנת אתחול לא נעולה, או שהוא לא אושר על ידי היצרן.
MEETS_STRONG_INTEGRITY
האפליקציה פועלת במכשיר Android עם Google Play Services, ויש לה הוכחה חזקה לתקינות המערכת, כמו הוכחה לחתימה על התקינות של האתחול שמגובת בחומרה. המכשיר עובר את בדיקות התקינות של המערכת ועומד בדרישות התאימות של Android.

מכשיר יחיד יחזיר כמה תוויות של מכשיר בפסיקה לגבי תקינות המכשיר, אם הוא עומד בכל הקריטריונים של התווית.

פעילות במכשיר מהזמן האחרון

אפשר גם להביע הסכמה לקבלת אותות של פעילות במכשיר מהזמן האחרון, שמציינים כמה פעמים האפליקציה שלכם ביקשה טוקן תקינות במכשיר ספציפי בשעה האחרונה. אתם יכולים להשתמש בפעילות מהזמן האחרון במכשיר כדי להגן על האפליקציה מפני מכשירי היפר-פעילות לא צפויים, שיכולים להעיד על מתקפה פעילה. אתם יכולים לקבוע את מידת האמון בכל רמה של פעילות במכשיר מהזמן האחרון על סמך מספר הפעמים שאתם מצפים שהאפליקציה שמותקנת במכשיר טיפוסי תבקש טוקן תקינות בכל שעה.

אם תבחרו לקבל את recentDeviceActivity, בשדה deviceIntegrity יהיו שני ערכים:

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

ההגדרות של deviceActivityLevel משתנות בין המצבים, והן יכולות להיות אחד מהערכים הבאים:

רמת הפעילות במכשיר מהזמן האחרון בקשות רגילות לטוקן תקינות API במכשיר הזה בשעה האחרונה לכל אפליקציה בקשות לטוקן תקינות של API קלאסי במכשיר הזה בשעה האחרונה לכל אפליקציה
LEVEL_1 (הנמוך ביותר) 10 או פחות 5 או פחות
LEVEL_2 בין 11 ל-25 בין 6 ל-10
LEVEL_3 בין 26 ל-50 בין 11 ל-15
LEVEL_4 (הגבוה ביותר) יותר מ-50 יותר מ-15
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!
}

השדה Environment details

אפשר גם להביע הסכמה לשימוש באותות נוספים לגבי הסביבה. האות 'סיכון לגישה לאפליקציה' מאפשר לאפליקציה לבדוק אם יש אפליקציות פועלות אחרות שיכולות לצלם את המסך, להציג שכבות-על או לשלוט במכשיר. לפי קביעת Play Protect אפשר לדעת אם Google Play Protect מופעל במכשיר ואם הוא זיהה תוכנות זדוניות מוכרות.

אם הבעתם הסכמה לקביעה של סיכון הגישה לאפליקציה או לקביעה של Play Protect ב-Google Play Console, תגובת ה-API תכלול את השדה 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 (רמת API ‏23) ואילך.
  • הגרסה של האפליקציה שמותקנת במכשיר לא ידועה ל-Google Play.
  • הגרסה של חנות Google Play במכשיר לא עדכנית.
  • משחקים בלבד: לחשבון המשתמש אין רישיון Play למשחק.
  • נעשה שימוש בבקשה רגילה עם הפרמטר verdictOptOut.
  • השתמשתם בבקשה רגילה עם גרסת ספרייה של Play Integrity API שעדיין לא תומכת בסיכון לגישה לאפליקציה בבקשות רגילות.

הסיכון לגישה לאפליקציה כולל באופן אוטומטי החרגה של שירותי נגישות מאומתים שעברו בדיקה משופרת של נגישות ב-Google Play (שמתקינים מחנות אפליקציות כלשהי במכשיר). המשמעות של 'לא נכלל' היא ששירותי נגישות מאומתים שפועלים במכשיר לא מחזירים תגובה של צילום, בקרה או שכבות-על, בקביעת סיכון הגישה לאפליקציה. כדי לבקש בדיקה משופרת של נגישות באפליקציית הנגישות ב-Google Play, צריך לפרסם אותה ב-Google Play ולוודא שהדגל isAccessibilityTool מוגדר כ-true במניפסט של האפליקציה. לחלופין, אפשר לבקש בדיקה.

בטבלה הבאה מפורטות דוגמאות לכמה מהחלטות המערכת, והמשמעות שלהן (הטבלה הזו לא כוללת את כל התוצאות האפשריות):

דוגמה לתגובה של קביעת סיכון הגישה לאפליקציה פרשנות
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

אחרי ההפעלה, השדה environmentDetails במטען הייעודי של Play Integrity API יכיל את התוצאה של Play Protect:

environmentDetails: {
  playProtectVerdict: "NO_ISSUES"
}

הערך של playProtectVerdict יכול להיות אחד מהערכים הבאים:

NO_ISSUES
Play Protect מופעל ולא נמצאו בעיות באפליקציה במכשיר.
NO_DATA
שירותי Play Protect מופעלים, אבל עדיין לא בוצעה סריקה. יכול להיות שהמכשיר או האפליקציה של חנות Play אופסו לאחרונה.
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. אם המשתמש לא יכול למלא את הדרישות האלה, אתם יכולים לחסום אותו מפעולת השרת.