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

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

מאפייני המכשיר

אפשר גם להביע הסכמה לשימוש במאפייני המכשיר, שמציינים את גרסת Android SDK של מערכת ההפעלה Android שפועלת במכשיר. יכול להיות שבעתיד נוסיף עוד מאפייני מכשיר.

הערך של גרסת ה-SDK הוא מספר גרסת Android SDK שמוגדר בקובץ Build.VERSION_CODES. גרסת ה-SDK לא תיבצע הערכה אם לא תהיה עמידה בדרישה חיונית. במקרה כזה, השדה sdkVersion לא מוגדר, ולכן השדה deviceAttributes ריק. הסיבה לכך יכולה להיות:

  • המכשיר לא מהימן מספיק.
  • גרסת האפליקציה שמותקנת במכשיר לא ידועה ל-Google Play.
  • היו בעיות טכניות במכשיר.

אם תבחרו לקבל את 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.
}

השדה 'פרטי החשבון'

השדה 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 שפועלים במכשיר.
ריק (ערך ריק)

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