Bütünlük kararları

Bu sayfada, döndürülen bütünlük kararının nasıl yorumlanacağı ve bu kararla nasıl çalışılacağı açıklanmaktadır. Standart veya klasik API isteği göndermiş olmanıza bakılmaksızın bütünlük değerlendirmesi benzer içerikle aynı biçimde döndürülür. Bütünlük değerlendirmesi; cihazların, uygulamaların ve hesapların geçerliliği hakkında bilgi sunar. Uygulamanızın sunucusu, şifresi çözülmüş ve doğrulanmış bir karardaki yükü kullanarak uygulamanızda belirli bir işlem veya istekle ilgili izlenecek en iyi yolu belirleyebilir.

Döndürülen bütünlük değerlendirmesi biçimi

Yük, düz metin JSON'dur ve geliştirici tarafından sağlanan bilgilerin yanı sıra bütünlük sinyalleri içerir.

Genel yükü yapısı aşağıdaki gibidir:

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

Her bir bütünlük değerlendirmesini kontrol etmeden önce requestDetails alanındaki değerlerin orijinal istekteki değerlerle eşleştiğinden emin olmanız gerekir. Aşağıdaki bölümlerde her alan ayrıntılı olarak açıklanmıştır.

İstek ayrıntıları alanı

requestDetails alanında istekle ilgili bilgiler yer alır. Standart istekler için requestHash alanında, klasik istekler için de nonce alanında geliştirici tarafından sağlanan bilgiler buna dahildir.

Standart API istekleri için:

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

Bu değerler, orijinal istekteki değerlerle eşleşmelidir. Bu nedenle, JSON yükünün requestDetails bölümünü doğrulamak için requestPackageName ve requestHash değerlerinin aşağıdaki kod snippet'inde gösterildiği gibi orijinal istekte gönderilenlerle eşleştiğinden emin olun:

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

Klasik API istekleri için:

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

Bu değerler, orijinal istekteki değerlerle eşleşmelidir. Bu nedenle, JSON yükünün requestDetails bölümünü doğrulamak için requestPackageName ve nonce değerlerinin aşağıdaki kod snippet'inde gösterildiği gibi orijinal istekte gönderilenlerle eşleştiğinden emin olun:

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

Uygulama bütünlüğü alanı

appIntegrity alanı, paketle ilgili bilgileri içerir.

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 aşağıdaki değerleri alabilir:

PLAY_RECOGNIZED
Uygulama ve sertifika, Google Play tarafından dağıtılan sürümlerle eşleşiyor.
UNRECOGNIZED_VERSION
Sertifika veya paket adı Google Play kayıtlarıyla eşleşmiyor.
UNEVALUATED
Uygulama bütünlüğü değerlendirilmemiştir. Koşullardan biri karşılanmamıştır (örneğin, cihaz yeterince güvenilir olmayabilir).

Jetonun, sizin tarafınızdan oluşturulan bir uygulama tarafından oluşturulduğundan emin olmak için aşağıdaki kod snippet'inde gösterildiği gibi uygulama bütünlüğünün beklendiği gibi olduğunu doğrulayın:

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

Uygulama paket adını, uygulama sürümünü ve uygulama sertifikalarını manuel olarak da kontrol edebilirsiniz.

Cihaz bütünlüğü alanı

deviceIntegrity alanında, bir cihazın uygulama bütünlüğünü ne kadar iyi uygulayabildiğini gösteren bir veya daha fazla etiket içeren tek bir değer ("deviceRecognitionVerdict") bulunabilir. Cihaz hiçbir etiketin ölçütlerini karşılamıyorsa deviceIntegrity alanı boş bırakılır.

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

Varsayılan olarak deviceRecognitionVerdict aşağıdakileri içerebilir:

MEETS_DEVICE_INTEGRITY
Uygulama, Play Protect sertifikalı orijinal bir Android cihazda çalışıyor. Android 13 ve sonraki sürümlerde, cihaz bootloader'ının kilitli olduğunun ve yüklü Android OS'in sertifikalı bir cihaz üreticisi görüntüsünün olduğunun donanım destekli kanıtı vardır.
Boş (boş değer)
Uygulamanın çalıştığı cihazda saldırı (API kancalama gibi) veya sistem bozulması (rootlanma gibi) belirtileri var ya da uygulama fiziksel bir cihazda çalışmıyor (örneğin, Google Play bütünlük kontrollerini geçmeyen bir emülatörde çalışıyor).

Jetonun güvenilir bir cihazdan geldiğinden emin olmak için aşağıdaki kod snippet'inde gösterildiği gibi deviceRecognitionVerdict değerinin beklendiği gibi olduğunu doğrulayın:

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

Test cihazınızın cihaz bütünlüğünü karşılamasıyla ilgili sorun yaşıyorsanız fabrika ROM'unun yüklü olduğundan (ör. cihazı sıfırlayarak) ve önyükleyicinin kilitli olduğundan emin olun. Ayrıca Play Console'da Play Integrity API testleri oluşturabilirsiniz.

Koşullu cihaz etiketleri

Uygulamanız PC Üzerinde Google Play Games için yayınlanıyorsa deviceRecognitionVerdict aşağıdaki etiketi de içerebilir:

MEETS_VIRTUAL_INTEGRITY
Uygulama, Google Play Hizmetleri'nin kullanıldığı Android destekli bir cihazda çalışıyor. Emülatör, sistem bütünlüğü kontrollerini geçer ve temel Android uyumluluk şartlarını karşılar.

İsteğe bağlı cihaz bilgileri ve cihaz geri çağırma

Bütünlük değerlendirmesinde ek etiketler almayı etkinleştirirseniz deviceRecognitionVerdict aşağıdaki ek etiketleri içerebilir:

MEETS_BASIC_INTEGRITY
Uygulama temel sistem bütünlük kontrollerini geçen bir cihazda çalışıyor. Cihazın bootloader'ı kilitli veya kilidi açık olabilir ve önyükleme durumu doğrulanmış veya doğrulanmamış olabilir. Cihaz Play Protect sertifikalı olmayabilir. Bu durumda Google, güvenlik, gizlilik veya uygulama uyumluluğu konusunda herhangi bir güvence veremez. Android 13 ve sonraki sürümlerde MEETS_BASIC_INTEGRITY karar için yalnızca Google'ın doğrulama güvenlik kökü sağlaması gerekir.
MEETS_STRONG_INTEGRITY
Uygulama, son güvenlik güncellemesini almış orijinal bir Play Protect sertifikalı Android cihazda çalışıyor.
  • Android 13 ve sonraki sürümlerde MEETS_STRONG_INTEGRITY kararı için, Android OS bölüm yaması ve tedarikçi bölüm yaması da dahil olmak üzere cihazın tüm bölümlerinde son bir yıl içinde MEETS_DEVICE_INTEGRITY ve güvenlik güncellemeleri yapılmış olması gerekir.
  • Android 12 ve önceki sürümlerde MEETS_STRONG_INTEGRITY kararı için yalnızca donanım destekli bir önyükleme bütünlüğü kanıtı gerekir ve cihazın en son güvenlik güncellemesini almış olması gerekmez. Bu nedenle, MEETS_STRONG_INTEGRITY kullanırken deviceAttributes alanındaki Android SDK sürümünü de dikkate almanız önerilir.

Bir cihaz, etiketin ölçütlerinin her biri karşılandığı takdirde cihaz bütünlüğü kararında birden fazla cihaz etiketi döndürür.

Cihaz özellikleri

Cihaz özelliklerini de etkinleştirebilirsiniz. Bu özellik, cihazda çalışan Android OS'in Android SDK sürümünü belirtir. Gelecekte diğer cihaz özellikleriyle genişletilebilir.

SDK sürümü değeri, Build.VERSION_CODES içinde tanımlanan Android SDK sürüm numarasıdır. Gerekli koşullardan biri karşılanmadıysa SDK sürümü değerlendirilmez. Bu durumda sdkVersion alanının değeri belirlenmemiştir. Bu nedenle deviceAttributes alanı boştur. Bunun nedeni aşağıdakilerden biri olabilir:

  • Cihaz yeterince güvenilir değildir.
  • Cihazda teknik sorunlar vardı.

deviceAttributes almayı etkinleştirirseniz deviceIntegrity alanında aşağıdaki ek alan bulunur:

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

SDK sürümü değerlendirilmezse deviceAttributes alanı aşağıdaki gibi ayarlanır:

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

Son cihaz etkinliği

Ayrıca, uygulamanızın son bir saat içinde belirli bir cihazda kaç kez bütünlük jetonu istediğini belirten son cihaz etkinliğini de etkinleştirebilirsiniz. Uygulamanızı etkin bir saldırının göstergesi olabilecek beklenmedik hiperaktif cihazlara karşı korumak için son cihaz etkinliğini kullanabilirsiniz. Her bir son cihaz etkinliği seviyesine ne kadar güveneceğinize, tipik bir cihaza yüklenen uygulamanızın her saatte kaç kez bütünlük jetonu isteyeceğini tahmin ederek karar verebilirsiniz.

recentDeviceActivity'ü etkinleştirirseniz deviceIntegrity alanının iki değeri olur:

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

deviceActivityLevel tanımları modlar arasında farklılık gösterir ve aşağıdaki değerlerden birine sahip olabilir:

Son cihaz etkinliği seviyesi Bu cihazda son bir saat içinde uygulama başına standart API bütünlük jetonu istekleri Bu cihazda son bir saat içinde uygulama başına klasik API bütünlük jetonu istekleri
LEVEL_1 (en düşük) 10 veya daha az 5 veya daha az
LEVEL_2 11 ile 25 arasında 6 ile 10 arasında
LEVEL_3 26 ile 50 arasında 11 ila 15
LEVEL_4 (en yüksek) 50'den fazla 15'ten fazla
UNEVALUATED Son cihaz etkinliği değerlendirilmemiştir. Bunun nedeni şunlar olabilir:
  • Cihaz yeterince güvenilir değildir.
  • Cihazda uygulamanızın Google Play tarafından tanınmayan bir sürümü yüklüdür.
  • Cihazdaki teknik sorunlar.

Cihaz geri çağırma (beta)

Ayrıca, belirli cihazlarda cihaza özel bazı verileri saklayarak uygulamanız daha sonra aynı cihaza tekrar yüklendiğinde bu verileri güvenle alabileceğiniz cihaz geri çağırma özelliğini de etkinleştirebilirsiniz. Bir bütünlük jetonu isteğinde bulunduktan sonra, belirli bir cihazın cihaz geri çağırma değerlerini değiştirmek için sunucudan sunucuya ayrı bir çağrı yaparsınız.

deviceRecall'ü etkinleştirirseniz deviceIntegrity alanında, belirli bir cihaz için ayarladığınız cihaz geri çağırma bilgileri yer alır:

"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 iki alana ayrılır:

  • values: Bu cihaz için daha önce ayarladığınız bit değerlerini geri çağırın.
  • writeDates: Bit yazma tarihlerini yıl ve aya göre doğru olarak UTC'de geri çağırın. Bir geri çağırma biti, true olarak ayarlandığında her defasında güncellenir ve false olarak ayarlandığında kaldırılır.

Cihaz geri çağırma bilgileri mevcut değilse cihaz geri çağırma değeri boş olur:

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

Hesap ayrıntıları alanı

accountDetails alanında, cihazda oturum açmış kullanıcı hesabı için uygulamanın Google Play lisanslama durumunu gösteren tek bir değer (appLicensingVerdict) bulunur. Kullanıcı hesabının uygulamanın Play lisansına sahip olması, uygulamanın Google Play'den indirildiği veya satın alındığı anlamına gelir.

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

appLicensingVerdict aşağıdaki değerlerden biri olabilir:

LICENSED
Kullanıcının uygulamadan yararlanma hakkı bulunmaktadır. Yani kullanıcı, uygulamanızı cihazında Google Play'den yüklemiş veya güncellemiştir.
UNLICENSED
Kullanıcının uygulamadan yararlanma hakkı yoktur. Kullanıcının uygulamanızı başka cihazdan yüklediği veya Google Play dışında bir kanaldan edindiği durumlarda bu etiket görülür. Bu sorunu düzeltmek için kullanıcılara GET_LICENSED iletişimini gösterebilirsiniz.
UNEVALUATED

Koşullardan biri karşılanmadığı için lisanslama ayrıntıları değerlendirilmemiştir.

Bu durum aşağıdakiler dahil olmak üzere çeşitli nedenlerden kaynaklanabilir:

  • Cihaz yeterince güvenilir değildir.
  • Cihazda uygulamanızın Google Play tarafından tanınmayan bir sürümü yüklüdür.
  • Kullanıcı, Google Play'de oturum açmamıştır.

Kullanıcının uygulamanız için uygulama hakkına sahip olup olmadığını kontrol etmek amacıyla, aşağıdaki kod snippet'inde gösterildiği gibi appLicensingVerdict değerinin beklendiği gibi olduğunu doğrulayın:

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

Ortam ayrıntıları alanı

Ayrıca ortamla ilgili ek sinyalleri de etkinleştirebilirsiniz. Uygulama erişim riski; ekranı kaydetmek, yer paylaşımı görüntülemek veya cihazı kontrol etmek amacıyla başka uygulamaların çalıştırılıp çalıştırılmadığını uygulamanıza bildirir. Play Protect kararı, Google Play Protect'in cihazda etkinleştirilip etkinleştirilmediğini ve bilinen kötü amaçlı yazılım tespit edip etmediğini size bildirir.

Google Play Console'da uygulama erişim riski kararını veya Play Protect kararını etkinleştirdiyseniz API yanıtınızda environmentDetails alanı bulunur. environmentDetails alanı appAccessRiskVerdict ve playProtectVerdict olmak üzere iki değer içerebilir.

Uygulamaya erişim riski kararı

Etkinleştirildikten sonra Play Integrity API yükündeki environmentDetails alanında yeni uygulama erişim riski kararı görüntülenir.

{
  requestDetails: { ... }
  appIntegrity: { ... }
  deviceIntegrity: { ... }
  accountDetails: { ... }
  environmentDetails: {
      appAccessRiskVerdict: {
          // This field contains one or more responses, for example the following.
          appsDetected: ["KNOWN_INSTALLED", "UNKNOWN_INSTALLED", "UNKNOWN_CAPTURING"]
      }
 }
}

Uygulama erişim riski değerlendirildiyse appAccessRiskVerdict, bir veya daha fazla yanıt içeren appsDetected alanını içerir. Bu yanıtlar, algılanan uygulamaların yükleme kaynağına bağlı olarak aşağıdaki iki gruptan birine girer:

  • Play veya sistem uygulamaları: Google Play tarafından yüklenen veya cihaz üreticisi tarafından cihazın sistem bölümüne önceden yüklenen uygulamalar (FLAG_SYSTEM ile tanımlanır). Bu tür uygulamalara verilen yanıtların önüne KNOWN_ ön eki eklenir.

  • Diğer uygulamalar: Google Play tarafından yüklenmeyen uygulamalar. Cihaz üreticisi tarafından sistem bölümüne önceden yüklenmiş uygulamalar bu kapsamda değildir. Bu tür uygulamalara yönelik yanıtların önüne UNKNOWN_ ön eki eklenir.

Aşağıdaki yanıtlar döndürülebilir:

KNOWN_INSTALLED, UNKNOWN_INSTALLED
İlgili yükleme kaynağıyla eşleşen uygulamalar yüklü.
KNOWN_CAPTURING, UNKNOWN_CAPTURING
Uygulamanız çalışırken ekranı görüntülemek için kullanılabilecek izinleri etkinleştirilmiş çalışan uygulamalar var. Google Play'in cihazda çalıştığı bilinen doğrulanmış erişilebilirlik hizmetleri bu kapsamda değildir.
KNOWN_CONTROLLING, UNKNOWN_CONTROLLING
Cihazınızı kontrol etmek ve doğrudan uygulamanıza gelen girişleri kontrol etmek için kullanılabilecek izinlerin etkin olduğu çalışan uygulamalar var. Bu uygulamalar, uygulamanızın girişlerini ve çıkışlarını yakalamak için de kullanılabilir. Google Play'in cihazda çalıştığını bildiği doğrulanmış erişilebilirlik hizmetleri bu kapsamda değildir.
KNOWN_OVERLAYS, UNKNOWN_OVERLAYS
Uygulamanızda yer paylaşımları görüntülemek için kullanılabilecek izinlerin etkin olduğu çalışan uygulamalar var. Bu, cihazda Google Play tarafından bilinen doğrulanmış erişilebilirlik hizmetlerini kapsamaz.
Boş (boş değer)

Koşullardan biri karşılanmamışsa uygulama erişimi riski değerlendirilmez. Bu durumda appAccessRiskVerdict alanı boştur. Bu durum aşağıdakiler dahil olmak üzere çeşitli nedenlerden kaynaklanabilir:

  • Cihaz yeterince güvenilir değildir.
  • Cihaz form faktörü telefon, tablet veya katlanabilir cihaz değil.
  • Cihazınızda Android 6 (API düzeyi 23) veya daha yeni bir sürüm yüklü değil.
  • Cihazda uygulamanızın Google Play tarafından tanınmayan bir sürümü yüklüdür.
  • Cihazdaki Google Play Store sürümü güncel değildir.
  • Yalnızca oyunlar: Kullanıcı hesabının oyun için Play lisansı yoktur.
  • verdictOptOut parametresi ile standart bir istek kullanıldı.
  • Standart istek, standart istekler için henüz uygulama erişim riskini desteklemeyen bir Play Integrity API kitaplığı sürümüyle kullanıldı.

Uygulama erişimi riski, gelişmiş Google Play erişilebilirlik incelemesinden geçmiş olan doğrulanmış erişilebilirlik hizmetlerini (cihazdaki herhangi bir uygulama mağazası tarafından yüklenir) otomatik olarak hariç tutar. "Hariç tutuldu", cihazda çalışan doğrulanmış erişilebilirlik hizmetlerinin, uygulama erişimi riski kararında yakalama, kontrol etme veya yer paylaşımı yanıtı döndürmeyeceği anlamına gelir. Erişilebilirlik uygulamanız için gelişmiş Google Play erişilebilirlik incelemesi isteğinde bulunmak istiyorsanız uygulamanızı Google Play'de yayınlayın ve uygulamanızın manifest dosyasında isAccessibilityTool işaretinin true olarak ayarlandığından emin olun veya inceleme isteğinde bulunun.

Uygulamaya erişim riski kararları örneği

Aşağıdaki tabloda, uygulama erişim riski kararlarının bazı örnekleri ve bu kararların ne anlama geldiği verilmiştir (bu tabloda olası tüm sonuçlar listelenmez):

Uygulamaya erişim riski kararı için örnek yanıt Yorumlama
appsDetected:
["KNOWN_INSTALLED"]
Yalnızca Google Play tarafından tanınan veya cihaz üreticisi tarafından sistem bölümüne önceden yüklenen uygulamalar yüklüdür.
Kayıt, kontrol veya yer paylaşımı kararlarıyla sonuçlanacak şekilde çalışan uygulama yoktur.
appsDetected:
["KNOWN_INSTALLED",
"UNKNOWN_INSTALLED",
"UNKNOWN_CAPTURING"]
Google Play tarafından yüklenen veya cihaz üreticisi tarafından sistem bölümüne önceden yüklenen uygulamalar vardır.
Ekranı görüntülemek veya diğer giriş ve çıkışları yakalamak için kullanılabilecek izinleri etkinleştirilmiş ve çalışan başka uygulamalar vardır.
appsDetected:
["KNOWN_INSTALLED",
"KNOWN_CAPTURING",
"UNKNOWN_INSTALLED",
"UNKNOWN_CONTROLLING"]
Ekranı görüntülemek veya diğer giriş ve çıkışları yakalamak için kullanılabilecek izinlerin etkin olduğu Play veya sistem çalışıyor.
Ayrıca, cihazı kontrol etmek ve uygulamanıza yapılan girişleri doğrudan kontrol etmek için kullanılabilecek izinleri etkinleştirilmiş başka uygulamalar da çalışır.
appAccessRiskVerdict: {} Koşullardan biri karşılanmadığı için uygulama erişimi riski değerlendirilmemiştir. Örneğin, cihaz yeterince güvenilir olmayabilir.

Risk düzeyinize bağlı olarak, devam etmek için hangi karar kombinasyonlarının kabul edilebilir olduğuna ve hangi kararlar için işlem yapmak istediğinize karar verebilirsiniz. Aşağıdaki kod snippet'inde, ekranı kaydedebilecek veya uygulamanızı kontrol edebilecek uygulamaların çalışıp çalışmadığını doğrulama örneği gösterilmektedir:

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!
    }
}
Uygulamaya erişim riski kararlarını düzeltme

Risk düzeyinize bağlı olarak, kullanıcının bir isteği veya işlemi tamamlamasına izin vermeden önce hangi uygulama erişim riski kararları için işlem yapmak istediğinize karar verebilirsiniz. Uygulama erişim riski kararını kontrol ettikten sonra kullanıcıya gösterebileceğiniz isteğe bağlı Google Play istemleri vardır. Kullanıcıdan uygulama erişim riski kararına neden olan bilinmeyen uygulamaları kapatmasını istemek için CLOSE_UNKNOWN_ACCESS_RISK'i veya kullanıcıdan uygulama erişim riski kararına neden olan tüm uygulamaları (bilinen ve bilinmeyen) kapatmasını istemek için CLOSE_ALL_ACCESS_RISK'i gösterebilirsiniz.

Play Protect kararı

Etkinleştirildikten sonra Play Integrity API yükündeki environmentDetails alanında Play Protect kararı görüntülenir:

environmentDetails: {
  playProtectVerdict: "NO_ISSUES"
}

playProtectVerdict aşağıdaki değerlerden biri olabilir:

NO_ISSUES
Play Protect etkindir ve cihazda uygulama ile ilgili herhangi bir sorun tespit edilmemiştir.
NO_DATA
Play Protect etkindir ancak henüz tarama yapılmamıştır. Cihaz ya da Play Store uygulaması kısa süre önce sıfırlanmış olabilir.
POSSIBLE_RISK
Play Protect kapalı.
MEDIUM_RISK
Play Protect etkindir ve cihazda potansiyel olarak zararlı uygulamaların yüklü olduğunu tespit etmiştir.
HIGH_RISK
Play Protect etkindir ve cihazda tehlikeli uygulamaların yüklü olduğunu tespit etmiştir.
UNEVALUATED

Play Protect kararı değerlendirilmemiştir.

Bu durum aşağıdakiler dahil olmak üzere çeşitli nedenlerden kaynaklanabilir:

  • Cihaz yeterince güvenilir değildir.
  • Yalnızca oyunlar: Kullanıcı hesabının oyun için Play lisansı yoktur.

Play Protect kararının kullanımıyla ilgili kılavuz

Uygulamanızın arka uç sunucusu, karara göre risk toleransınıza göre nasıl davranacağına karar verebilir. Aşağıda bazı öneriler ve olası kullanıcı işlemleri verilmiştir:

NO_ISSUES
Play Protect etkindir ve herhangi bir sorun tespit etmediğinden kullanıcının herhangi bir işlem yapması gerekmez.
POSSIBLE_RISK ve NO_DATA
Bu sonuçlar alındığında kullanıcıdan Play Protect'in açık olup olmadığını ve tarama yapıp yapmadığını kontrol etmesini isteyin. NO_DATA yalnızca nadir durumlarda gösterilir.
MEDIUM_RISK ve HIGH_RISK
Risk toleransınıza bağlı olarak kullanıcıdan Play Protect'i başlatmasını ve Play Protect uyarıları hakkında işlem yapmasını isteyebilirsiniz. Kullanıcı bu koşulları karşılayamıyorsa sunucu işlemini engelleyebilirsiniz.