หน้านี้อธิบายวิธีตีความและทำงานด้วยความสมบูรณ์ที่แสดงผลไว้ คำตัดสิน ไม่ว่าคุณจะส่งคำขอ 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 โดยตรวจสอบว่าส่วน
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
ของเพย์โหลด 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 เล่นแผ่นเสียง
UNEVALUATED
- ระบบไม่ได้ประเมินความสมบูรณ์ของแอปพลิเคชัน ข้อกำหนดที่จำเป็น ขาดหายไป เช่น อุปกรณ์ไม่น่าเชื่อถือพอ
หากต้องการตรวจสอบว่าโทเค็นสร้างขึ้นโดยแอปที่คุณสร้างขึ้น โปรดยืนยัน ความสมบูรณ์ของแอปพลิเคชันเป็นไปตามที่คาดไว้ ดังที่แสดงในโค้ดต่อไปนี้ snippet:
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
ที่มีป้ายกำกับอย่างน้อย 1 ป้ายระบุว่า
สามารถบังคับใช้ความสมบูรณ์ของแอปได้ หากอุปกรณ์ไม่เป็นไปตามเกณฑ์
ป้ายกำกับ ช่อง deviceIntegrity
ว่างเปล่า
deviceIntegrity: { // "MEETS_DEVICE_INTEGRITY" is one of several possible values. deviceRecognitionVerdict: ["MEETS_DEVICE_INTEGRITY"] }
โดยค่าเริ่มต้น deviceRecognitionVerdict
สามารถมีสิ่งต่อไปนี้ได้
MEETS_DEVICE_INTEGRITY
- แอปกำลังทำงานบนอุปกรณ์ที่ใช้ Android ที่มี บริการ Google Play อุปกรณ์ผ่านการตรวจสอบความสมบูรณ์ของระบบและเป็นไปตาม ข้อกำหนดด้านความเข้ากันได้กับ Android
- ว่างเปล่า (ค่าว่าง)
- แอปกำลังทำงานในอุปกรณ์ที่มีสัญญาณ การโจมตี (เช่น การฮุก API) หรือการบุกรุกระบบ (เช่น การรูท) หรือ แอปไม่ได้ทำงานบนอุปกรณ์จริง (เช่น โปรแกรมจำลองที่ ไม่ผ่านการตรวจสอบความสมบูรณ์ของ Google Play)
หากต้องการตรวจสอบว่าโทเค็นมาจากอุปกรณ์ที่เชื่อถือได้ โปรดยืนยัน
deviceRecognitionVerdict
เป็นไปตามที่คาดไว้ดังที่แสดงในโค้ดต่อไปนี้
snippet:
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 จากโรงงานแล้ว (เช่น โดยการรีเซ็ตอุปกรณ์) และ Bootloader ล็อกอยู่ นอกจากนี้ คุณยังสร้างการทดสอบ Play Integrity API ได้ด้วย ใน Play Console
ป้ายกำกับอุปกรณ์แบบมีเงื่อนไข
หากแอปมีการเผยแพร่ใน Google Play Games สำหรับ PC ระบบจะดำเนินการต่อไปนี้
deviceRecognitionVerdict
จะมีป้ายกำกับต่อไปนี้ได้ด้วย:
MEETS_VIRTUAL_INTEGRITY
- แอปกำลังทำงานบนโปรแกรมจำลองที่ขับเคลื่อนโดย Android บริการ Google Play โปรแกรมจำลองผ่านการตรวจสอบความสมบูรณ์ของระบบและเป็นไปตาม ข้อกำหนดหลักด้านความเข้ากันได้ของ Android
ข้อมูลอุปกรณ์ที่ไม่บังคับ
หากคุณเลือกรับข้อมูลเพิ่มเติม
ป้ายกำกับในการตัดสินความสมบูรณ์
deviceRecognitionVerdict
สามารถมีป้ายกำกับเพิ่มเติมต่อไปนี้ได้:
MEETS_BASIC_INTEGRITY
- แอปกำลังทำงานบนอุปกรณ์ที่ผ่านการตรวจสอบขั้นพื้นฐาน การตรวจสอบความสมบูรณ์ของระบบ อุปกรณ์อาจไม่เป็นไปตามความเข้ากันได้ของ Android และอาจไม่ได้รับอนุมัติให้เรียกใช้บริการ Google Play สำหรับ ตัวอย่างเช่น อุปกรณ์อาจใช้ Android เวอร์ชันที่ไม่รู้จัก มี Bootloader ที่ปลดล็อกแล้ว หรืออาจไม่ได้รับการรับรองจาก ผู้ผลิต
MEETS_STRONG_INTEGRITY
- แอปกำลังทำงานบนอุปกรณ์ที่ใช้ Android ที่มี บริการ Google Play และมีการรับประกันความสมบูรณ์ของระบบที่เข้มงวด เช่น หลักฐานยืนยันความสมบูรณ์ในการเปิดเครื่องที่ได้รับการสนับสนุนจากฮาร์ดแวร์ อุปกรณ์ผ่านระบบ การตรวจสอบความสมบูรณ์และเป็นไปตามข้อกําหนดความเข้ากันได้ของ Android
อุปกรณ์เครื่องเดียวจะแสดงป้ายกำกับอุปกรณ์หลายรายการในความสมบูรณ์ของอุปกรณ์ เพื่อดูว่าตรงกับเกณฑ์ของป้ายกำกับแต่ละรายการหรือไม่
กิจกรรมล่าสุดในอุปกรณ์
คุณยังเลือกใช้กิจกรรมล่าสุดในอุปกรณ์ได้ด้วย ซึ่งจะบอกวิธี แอปของคุณขอโทเค็นความสมบูรณ์ในอุปกรณ์หนึ่งๆ หลายครั้ง ในชั่วโมงที่แล้ว คุณสามารถใช้กิจกรรมล่าสุดในอุปกรณ์เพื่อปกป้องแอป อุปกรณ์ที่ไม่คาดคิดและไวต่อความรู้สึกซึ่งอาจบ่งบอกถึงการโจมตีที่กำลังดำเนินอยู่ คุณเลือกได้ว่าจะเชื่อถือระดับกิจกรรมล่าสุดแต่ละระดับในอุปกรณ์เท่าใดโดยอิงตาม บ่อยครั้งที่คุณคาดว่าแอปที่ติดตั้งในอุปกรณ์ทั่วไปจะส่งคำขอ โทเค็นความสมบูรณ์ในแต่ละชั่วโมง
หากคุณเลือกรับrecentDeviceActivity
ช่อง deviceIntegrity
จะมี 2 ค่า ได้แก่
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 |
ระบบไม่ได้ประเมินกิจกรรมล่าสุดในอุปกรณ์ กรณีนี้อาจเกิดขึ้น
เพราะ:
|
ช่องรายละเอียดบัญชี
ฟิลด์ 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 ไม่รู้จักเวอร์ชันของแอปที่ติดตั้งในอุปกรณ์ เล่น
- ผู้ใช้ไม่ได้ลงชื่อเข้าใช้ 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 ในอุปกรณ์แล้วหรือไม่และ พบมัลแวร์ที่รู้จัก
หากคุณเลือกใช้คำตัดสินความเสี่ยงในการเข้าถึงแอปหรือผลการตัดสิน Play Protect
ใน Google Play Console การตอบกลับจาก API จะรวม
environmentDetails
ฟิลด์ environmentDetails
สามารถมีได้ 2 รายการ
ค่า 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
ที่มีการตอบกลับอย่างน้อย 1 รายการ คำตอบเหล่านี้จัดอยู่ใน
2 กลุ่มต่อไปนี้โดยขึ้นอยู่กับแหล่งที่มาของการติดตั้งของแอปที่ตรวจพบ
แอป 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 Store ในอุปกรณ์เป็นเวอร์ชันเก่า
- เกมเท่านั้น: บัญชีผู้ใช้ไม่มีใบอนุญาต Play สำหรับเกม
- มีการใช้คำขอมาตรฐานกับพารามิเตอร์
verdictOptOut
- มีการใช้คำขอมาตรฐานกับเวอร์ชันไลบรารี Play Integrity API แล้ว ที่ยังไม่รองรับความเสี่ยงในการเข้าถึงแอปสำหรับคำขอมาตรฐาน
ความเสี่ยงในการเข้าถึงแอปจะยกเว้นบริการการช่วยเหลือพิเศษที่ยืนยันแล้วโดยอัตโนมัติ ซึ่ง
ได้ผ่านการตรวจสอบการช่วยเหลือพิเศษที่มีประสิทธิภาพมากขึ้นของ Google Play (ซึ่งติดตั้งโดย
App Store ใดก็ได้ในอุปกรณ์) "ยกเว้น" หมายความว่าการเข้าถึง
ที่ได้รับการยืนยัน
บริการที่ทำงานอยู่ในอุปกรณ์จะไม่ส่งกลับการจับภาพ การควบคุม หรือ
การตอบสนองการวางซ้อนในผลการตัดสินความเสี่ยงในการเข้าถึงแอป หากต้องการขอรับบริการขั้นสูงสำหรับ
เปิดรีวิวการช่วยเหลือพิเศษสำหรับแอปการช่วยเหลือพิเศษ และเผยแพร่ใน Google
เล่นเพื่อตรวจสอบว่าแอปได้ตั้งค่า Flag isAccessibilityTool
เป็น "จริง"
ไฟล์ Manifest ของแอป หรือขอรับการตรวจสอบ
ตารางต่อไปนี้แสดงตัวอย่างการตัดสินและความหมายของการตัดสิน (นี่คือ ตารางไม่ได้แสดงรายการผลลัพธ์ที่เป็นไปได้ทั้งหมด):
ตัวอย่างการตอบกลับผลการตัดสินความเสี่ยงในการเข้าถึงแอป | การตีความ |
---|---|
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 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 ได้โดยขึ้นอยู่กับการยอมรับความเสี่ยงของคุณ ปกป้องและดำเนินการกับคำเตือนของ Play Protect หากผู้ใช้ไม่สามารถกรอกข้อมูลได้ ข้อกำหนดเหล่านี้สามารถบล็อก จากการทำงานของเซิร์ฟเวอร์ได้