Na tej stronie opisujemy, jak rozwiązywać problemy z wynikami weryfikacji integralności.
Po wysłaniu żądania tokena integralności możesz wyświetlić użytkownikowi okno Google Play. Możesz wyświetlić okno, gdy wystąpią co najmniej 1 problem z wynikiem oceny integralności lub wyjątek podczas żądania interfejsu Integrity API. Po zamknięciu okna możesz sprawdzić, czy problem został rozwiązany, wysyłając kolejne żądanie tokena integralności. Jeśli wysyłasz standardowe żądania, musisz ponownie rozgrzać dostawcę tokenów, aby uzyskać nową decyzję.
Prośba o wyświetlenie okna integralności w celu rozwiązania problemu z oceną
Gdy klient zażąda tokena integralności, możesz użyć metody oferowanej w interfejsach StandardIntegrityToken
(standardowy interfejs API) i IntegrityTokenResponse
(klasyczny interfejs API):
showDialog(Activity activity, int integrityDialogTypeCode)
.
Poniżej znajdziesz instrukcje, jak za pomocą interfejsu Play Integrity API wyświetlić okno na temat działań naprawczych, używając kodu okna GET_LICENSED
.
Inne kody okien, o które może poprosić Twoja aplikacja, są wymienione po tej sekcji.
Wyślij z aplikacji prośbę o token integralności i prześlij go na serwer. Możesz użyć żądania standardowego lub klasycznego.
Kotlin
// Request an integrity token val tokenResponse: StandardIntegrityToken = requestIntegrityToken() // Send token to app server and get response on what to do next val yourServerResponse: YourServerResponse = sendToServer(tokenResponse.token())
Java
// Request an integrity token StandardIntegrityToken tokenResponse = requestIntegrityToken(); // Send token to app server and get response on what to do next YourServerResponse yourServerResponse = sendToServer(tokenResponse.token());
Unity
// Request an integrity token StandardIntegrityToken tokenResponse = RequestIntegrityToken(); // Send token to app server and get response on what to do next YourServerResponse yourServerResponse = sendToServer(tokenResponse.Token);
Unreal Engine
// Request an integrity token StandardIntegrityToken* Response = RequestIntegrityToken(); // Send token to app server and get response on what to do next YourServerResponse YourServerResponse = SendToServer(Response->Token);
Rodzimy użytkownik
/// Request an integrity token StandardIntegrityToken* response = requestIntegrityToken(); /// Send token to app server and get response on what to do next YourServerResponse yourServerResponse = sendToServer(StandardIntegrityToken_getToken(response));
Odszyfruj token integralności na serwerze i sprawdź pole
appLicensingVerdict
. Może to wyglądać mniej więcej tak:// Licensing issue { ... "accountDetails": { "appLicensingVerdict": "UNLICENSED" } }
Jeśli token zawiera znak
appLicensingVerdict: "UNLICENSED"
, odpowiedz klientowi aplikacji, prosząc go o wyświetlenie okna licencji:Kotlin
private fun getDialogTypeCode(integrityToken: String): Int{ // Get licensing verdict from decrypted and verified integritytoken val licensingVerdict: String = getLicensingVerdictFromDecryptedToken(integrityToken) return if (licensingVerdict == "UNLICENSED") { 1 // GET_LICENSED } else 0 }
Java
private int getDialogTypeCode(String integrityToken) { // Get licensing verdict from decrypted and verified integrityToken String licensingVerdict = getLicensingVerdictFromDecryptedToken(integrityToken); if (licensingVerdict.equals("UNLICENSED")) { return 1; // GET_LICENSED } return 0; }
Unity
private int GetDialogTypeCode(string IntegrityToken) { // Get licensing verdict from decrypted and verified integrityToken string licensingVerdict = GetLicensingVerdictFromDecryptedToken(IntegrityToken); if (licensingVerdict == "UNLICENSED") { return 1; // GET_LICENSED } return 0; }
Unreal Engine
private int GetDialogTypeCode(FString IntegrityToken) { // Get licensing verdict from decrypted and verified integrityToken FString LicensingVerdict = GetLicensingVerdictFromDecryptedToken(IntegrityToken); if (LicensingVerdict == "UNLICENSED") { return 1; // GET_LICENSED } return 0; }
Rodzimy użytkownik
private int getDialogTypeCode(string integrity_token) { /// Get licensing verdict from decrypted and verified integrityToken string licensing_verdict = getLicensingVerdictFromDecryptedToken(integrity_token); if (licensing_verdict == "UNLICENSED") { return 1; // GET_LICENSED } return 0; }
W aplikacji wywołaj funkcję
showDialog
z kodem pobranym z serwera:Kotlin
// Show dialog as indicated by the server val showDialogType: Int? = yourServerResponse.integrityDialogTypeCode() if (showDialogType != null) { // Call showDialog with type code, the dialog will be shown on top of the // provided activity and complete when the dialog is closed. val integrityDialogResponseCode: Task<Int> = tokenResponse.showDialog(activity, showDialogType) // Handle response code, call the Integrity API again to confirm that // verdicts have been resolved. }
Java
// Show dialog as indicated by the server @Nullable Integer showDialogType = yourServerResponse.integrityDialogTypeCode(); if (showDialogType != null) { // Call showDialog with type code, the dialog will be shown on top of the // provided activity and complete when the dialog is closed. Task<Integer> integrityDialogResponseCode = tokenResponse.showDialog(activity, showDialogType); // Handle response code, call the Integrity API again to confirm that // verdicts have been resolved. }
Unity
IEnumerator ShowDialogCoroutine() { int showDialogType = yourServerResponse.IntegrityDialogTypeCode(); // Call showDialog with type code, the dialog will be shown on top of the // provided activity and complete when the dialog is closed. var showDialogTask = tokenResponse.ShowDialog(showDialogType); // Wait for PlayAsyncOperation to complete. yield return showDialogTask; // Handle response code, call the Integrity API again to confirm that // verdicts have been resolved. }
Unreal Engine
// .h void MyClass::OnShowDialogCompleted( EStandardIntegrityErrorCode Error, EIntegrityDialogResponseCode Response) { // Handle response code, call the Integrity API again to confirm that // verdicts have been resolved. } // .cpp void MyClass::RequestIntegrityToken() { UStandardIntegrityToken* Response = ... int TypeCode = YourServerResponse.integrityDialogTypeCode(); // Create a delegate to bind the callback function. FShowDialogStandardOperationCompletedDelegate Delegate; // Bind the completion handler (OnShowDialogCompleted) to the delegate. Delegate.BindDynamic(this, &MyClass::OnShowDialogCompleted); // Call ShowDialog with TypeCode which completes when the dialog is closed. Response->ShowDialog(TypeCode, Delegate); }
Rodzimy użytkownik
// Show dialog as indicated by the server int show_dialog_type = yourServerResponse.integrityDialogTypeCode(); if (show_dialog_type != 0) { /// Call showDialog with type code, the dialog will be shown on top of the /// provided activity and complete when the dialog is closed. StandardIntegrityErrorCode error_code = IntegrityTokenResponse_showDialog(response, activity, show_dialog_type); /// Proceed to polling iff error_code == STANDARD_INTEGRITY_NO_ERROR if (error_code != STANDARD_INTEGRITY_NO_ERROR) { /// Remember to call the *_destroy() functions. return; } /// Use polling to wait for the async operation to complete. /// Note, the polling shouldn't block the thread where the IntegrityManager /// is running. IntegrityDialogResponseCode* response_code; error_code = StandardIntegrityToken_getDialogResponseCode(response, response_code); if (error_code != STANDARD_INTEGRITY_NO_ERROR) { /// Remember to call the *_destroy() functions. return; } /// Handle response code, call the Integrity API again to confirm that /// verdicts have been resolved. }
Okno dialogowe jest wyświetlane nad podaną aktywnością. Gdy użytkownik zamknie okno, zadanie zostanie ukończone z kodem odpowiedzi.
(Opcjonalnie) Poproś o kolejny token, aby wyświetlić kolejne okna. Jeśli wysyłasz standardowe żądania, musisz ponownie rozgrzać dostawcę tokenów, aby uzyskać nową decyzję.
Wysyłanie prośby o wyświetlenie okna ochrony integralności w celu naprawienia wyjątku po stronie klienta
Jeśli żądanie do interfejsu Integrity API zakończy się niepowodzeniem z błędem StandardIntegrityException
(standardowy interfejs API) lub IntegrityServiceException
(klasyczny interfejs API) i wyjątek można naprawić, możesz użyć okna GET_INTEGRITY
lub GET_STRONG_INTEGRITY
, aby rozwiązać problem.
Z tych instrukcji dowiesz się, jak za pomocą okna GET_INTEGRITY
naprawić błąd po stronie klienta, który można naprawić i który został zgłoszony przez interfejs Integrity API.
Sprawdź, czy wyjątek zwrócony przez żądanie interfejsu Integrity API można naprawić.
Kotlin
private fun isExceptionRemediable(exception: ExecutionException): Boolean { val cause = exception.cause if (cause is StandardIntegrityException && cause.isRemediable) { return true } return false }
Java
private boolean isExceptionRemediable(ExecutionException exception) { Throwable cause = exception.getCause(); if (cause instanceof StandardIntegrityException integrityException && integrityException.isRemediable()) { return true; } return false; }
Jeśli wyjątek można naprawić, poproś o wyświetlenie
GET_INTEGRITY
okna dialogowego za pomocą zwróconego wyjątku. Okno dialogowe zostanie wyświetlone nad podaną aktywnością, a zwrócone zadanie zakończy się kodem odpowiedzi po zamknięciu okna przez użytkownika.Kotlin
private fun showDialog(exception: StandardIntegrityException) { // Create a dialog request val standardIntegrityDialogRequest = StandardIntegrityDialogRequest.builder() .setActivity(activity) .setType(IntegrityDialogTypeCode.GET_INTEGRITY) .setStandardIntegrityResponse(ExceptionDetails(exception)) .build() // Request dialog val responseCode: Task<Int> = standardIntegrityManager.showDialog(standardIntegrityDialogRequest) }
Java
private void showDialog(StandardIntegrityException exception) { // Create a dialog request StandardIntegrityDialogRequest standardIntegrityDialogRequest = StandardIntegrityDialogRequest.builder() .setActivity(this.activity) .setType(IntegrityDialogTypeCode.GET_INTEGRITY) .setStandardIntegrityResponse(new ExceptionDetails(exception)) .build(); // Request dialog Task<Integer> responseCode = standardIntegrityManager.showDialog(standardIntegrityDialogRequest); }
Jeśli zwrócony kod odpowiedzi wskazuje powodzenie, kolejne żądanie tokena integralności powinno się powieść bez żadnych wyjątków. Jeśli wysyłasz standardowe żądania, musisz ponownie rozgrzać dostawcę tokenów, aby uzyskać nową decyzję.
Kody okna integralności
GET_LICENSED (typ kodu 1)
Problem z oceną
To okno dialogowe jest odpowiednie w przypadku 2 problemów:
- Nieautoryzowany dostęp:
appLicensingVerdict: "UNLICENSED"
Oznacza to, że konto użytkownika nie ma uprawnień do korzystania z aplikacji. Może się tak zdarzyć, jeśli użytkownik zainstalował ją z innego urządzenia lub pozyskał ją z innego sklepu z aplikacjami niż Google Play. - Zmodyfikowana aplikacja:
appRecognitionVerdict: "UNRECOGNIZED_VERSION"
. Oznacza to, że plik binarny aplikacji został zmodyfikowany lub nie jest wersją rozpoznawaną przez Google Play.
Działania naprawcze
Możesz wyświetlić okno GET_LICENSED
, aby poprosić użytkownika o pobranie oryginalnej aplikacji z Google Play. To okno dialogowe obejmuje oba scenariusze:
- W przypadku użytkownika bez licencji przyznaje mu licencję Google Play. Dzięki temu użytkownik będzie otrzymywać aktualizacje aplikacji z Google Play.
- W przypadku użytkownika, który ma zmodyfikowaną wersję aplikacji, wyświetla instrukcje instalacji niezmodyfikowanej aplikacji z Google Play.
Gdy użytkownik zamknie okno, kolejne weryfikacje integralności zwrócą wartości appLicensingVerdict: "LICENSED"
i appRecognitionVerdict: "PLAY_RECOGNIZED"
.
Przykładowy UX

CLOSE_UNKNOWN_ACCESS_RISK (kod typu 2)
Problem z oceną
Gdy environmentDetails.appAccessRiskVerdict.appsDetected
zawiera
"UNKNOWN_CAPTURING"
lub "UNKNOWN_CONTROLLING"
, oznacza to, że na urządzeniu działają inne aplikacje (niezainstalowane przez Google Play ani niezaładowane wstępnie na partycji systemowej przez producenta urządzenia), które mogą przechwytywać ekran lub sterować urządzeniem.
Działania naprawcze
Możesz wyświetlić okno CLOSE_UNKNOWN_ACCESS_RISK
, aby poprosić użytkownika o zamknięcie wszystkich nieznanych aplikacji, które mogą przechwytywać ekran lub sterować urządzeniem.
Jeśli użytkownik kliknie przycisk Close all
, wszystkie takie aplikacje zostaną zamknięte.
Przykładowy UX

CLOSE_ALL_ACCESS_RISK (Type Code 3)
Problem z oceną
Gdy environmentDetails.appAccessRiskVerdict.appsDetected
zawiera którykolwiek z tych sygnałów: "KNOWN_CAPTURING"
, "KNOWN_CONTROLLING"
, "UNKNOWN_CAPTURING"
lub "UNKNOWN_CONTROLLING"
, oznacza to, że na urządzeniu są uruchomione aplikacje, które mogą przechwytywać ekran lub sterować urządzeniem.
Działania naprawcze
Możesz wyświetlić CLOSE_ALL_ACCESS_RISK
, aby poprosić użytkownika o zamknięcie wszystkich aplikacji, które mogą przechwytywać ekran lub sterować urządzeniem. Jeśli użytkownik kliknie przycisk Close all
, wszystkie takie aplikacje zostaną zamknięte na urządzeniu.
Przykładowy UX

GET_INTEGRITY (kod typu 4)
Problem z oceną
To okno dialogowe jest odpowiednie w przypadku każdego z tych problemów:
Słaba integralność urządzenia: gdy
deviceRecognitionVerdict
nie zawieraMEETS_DEVICE_INTEGRITY
, urządzenie może nie być oryginalnym i certyfikowanym urządzeniem z Androidem. Może się tak zdarzyć na przykład wtedy, gdy program rozruchowy urządzenia jest odblokowany lub załadowany system operacyjny Android nie jest certyfikowanym obrazem producenta.Nieautoryzowany dostęp:
appLicensingVerdict: "UNLICENSED"
Oznacza to, że konto użytkownika nie ma uprawnień do korzystania z Twojej aplikacji. Może się tak zdarzyć, jeśli użytkownik zainstalował ją z zewnętrznego źródła lub pobrał z innego sklepu z aplikacjami niż Google Play.Zmodyfikowana aplikacja:
appRecognitionVerdict: "UNRECOGNIZED_VERSION"
. Oznacza to, że plik binarny aplikacji został zmodyfikowany lub nie jest wersją rozpoznawaną przez Google Play.Wyjątki po stronie klienta: gdy podczas żądania interfejsu Integrity API wystąpi wyjątek, który można naprawić. Wyjątki, które można naprawić, to wyjątki interfejsu Integrity API z kodami błędów, takimi jak
PLAY_SERVICES_VERSION_OUTDATED
,NETWORK_ERROR
,PLAY_SERVICES_NOT_FOUND
itp. Za pomocą metodyexception.isRemediable()
możesz sprawdzić, czy wyjątek można naprawić za pomocą okna.
Działania naprawcze
Okno GET_INTEGRITY
zostało zaprojektowane tak, aby uprościć obsługę przez użytkownika, ponieważ umożliwia wykonanie wielu czynności naprawczych w ramach jednego, ciągłego procesu. Dzięki temu użytkownik nie musi wchodzić w interakcję z wieloma oddzielnymi oknami, aby rozwiązać różne problemy.
Gdy poprosisz o wyświetlenie okna, automatycznie wykryje ono, które z problemów z decyzją o kierowaniu są obecne, i poda odpowiednie kroki naprawcze. Oznacza to, że jedno żądanie dialogu może rozwiązywać jednocześnie wiele problemów, w tym:
- Integralność urządzenia: jeśli zostanie wykryty problem z integralnością urządzenia, okno dialogowe pomoże użytkownikowi poprawić stan bezpieczeństwa urządzenia, aby spełniało ono wymagania dotyczące wyniku
MEETS_DEVICE_INTEGRITY
. - Integralność aplikacji: jeśli zostaną wykryte problemy, takie jak nieautoryzowany dostęp lub manipulowanie aplikacją, okno przekieruje użytkowników do Sklepu Play, aby mogli pobrać aplikację i rozwiązać te problemy.
- Wyjątki po stronie klienta: okno dialogowe sprawdza i próbuje rozwiązać wszelkie problemy, które spowodowały wyjątek interfejsu Integrity API. Może na przykład poprosić użytkownika o zaktualizowanie nieaktualnej wersji Usług Google Play.
Przykładowy UX

GET_STRONG_INTEGRITY (kod typu 5)
Problem z oceną
To okno ma na celu rozwiązanie wszystkich problemów, które rozwiązuje interfejs GET_INTEGRITY, a także problemów, które uniemożliwiają urządzeniu otrzymanie wyniku MEETS_STRONG_INTEGRITY
, oraz problemów z wynikiem Play Protect.
Działania naprawcze
GET_STRONG_INTEGRITY
ma na celu usprawnienie obsługi przez użytkownika poprzez wykonywanie wielu czynności naprawczych w ramach jednego, ciągłego procesu. W oknie dialogowym automatycznie sprawdzane są problemy z integralnością adresu, w tym:
- Integralność urządzenia: jeśli zostanie wykryty problem z integralnością urządzenia, okno dialogowe pomoże użytkownikowi poprawić stan bezpieczeństwa urządzenia, aby spełniało ono wymagania dotyczące wyniku
MEETS_STRONG_INTEGRITY
. Stan ochrony w Google Play: jeśli
playProtectVerdict
wskazuje problem, okno dialogowe pomoże użytkownikowi go rozwiązać:- Jeśli Play Protect jest wyłączona (
playProtectVerdict == POSSIBLE_RISK
), w oknie pojawi się prośba o włączenie tej usługi i zeskanowanie wszystkich aplikacji na urządzeniu. - Jeśli zostaną wykryte szkodliwe aplikacje (
playProtectVerdict == MEDIUM_RISK
lubHIGH_RISK
), okno dialogowe przekieruje użytkownika do odinstalowania ich za pomocą Google Play Protect.
- Jeśli Play Protect jest wyłączona (
Integralność aplikacji: jeśli zostaną wykryte problemy, takie jak nieautoryzowany dostęp lub zmodyfikowanie aplikacji, okno poprosi użytkownika o pobranie aplikacji ze Sklepu Play, aby rozwiązać problem.
Wyjątki po stronie klienta: okno dialogowe próbuje też rozwiązać wszelkie problemy, które spowodowały wyjątek interfejsu Integrity API. Na przykład może wyświetlić użytkownikowi prośbę o włączenie Usług Google Play, jeśli okaże się, że są wyłączone. Wyjątki, które można naprawić, to wyjątki interfejsu Integrity API z kodami błędów takimi jak
PLAY_SERVICES_VERSION_OUTDATED
,NETWORK_ERROR
lubPLAY_SERVICES_NOT_FOUND
. Za pomocą metodyexception.isRemediable()
możesz sprawdzić, czy błąd można naprawić za pomocą okna.
Przykładowy UX
