مربّعات حوار المعالجة

توضّح هذه الصفحة كيفية التعامل مع المشاكل المتعلّقة ببيانات السلامة.

بعد طلب رمز مميّز للتحقّق من السلامة، يتوفّر لك خيار عرض مربّع حوار Google Play للمستخدم. يمكنك عرض مربّع الحوار في حال حدوث مشكلة واحدة أو أكثر في بيان السلامة أو في حال حدوث استثناء أثناء طلب بيانات من واجهة برمجة التطبيقات Integrity API. بعد إغلاق مربّع الحوار، يمكنك التحقّق من حلّ المشكلة من خلال طلب رمز مميّز آخر للتحقّق من السلامة. إذا كنت تُجري طلبات عادية، عليك إعادة تهيئة موفّر الرموز المميّزة للحصول على بيان جديد.

طلب مربّع حوار لبيان السلامة من أجل حلّ مشكلة في بيان السلامة

عندما يطلب العميل رمزًا مميّزًا للتحقّق من السلامة، يمكنك استخدام الطريقة المتوفّرة في StandardIntegrityToken (Standard API) و IntegrityTokenResponse (Classic API): showDialog(Activity activity, int integrityDialogTypeCode).

توضّح الخطوات التالية كيفية استخدام واجهة Play Integrity API لعرض مربّع حوار مخصَّص لتصدير البيانات الناقصة باستخدام رمز مربّع الحوار GET_LICENSED. يتم إدراج رموز مربّعات الحوار الأخرى التي يمكن لتطبيقك طلبها بعد هذا القسم.

  1. اطلب رمزًا مميّزًا للسلامة من تطبيقك، وأرسِله إلى خادمك. يمكنك استخدام الطلب العادي أو الكلاسيكي.

    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);
    

    الإعلانات المدمجة مع المحتوى

    /// 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));
    
  2. على الخادم، فُك تشفير الرمز المميّز للسلامة وتحقَّق من حقل appLicensingVerdict. قد يبدو الأمر على النحو التالي:

    // Licensing issue
    {
        ...
        "accountDetails": {
            "appLicensingVerdict": "UNLICENSED"
        }
    }
    
  3. إذا كان الرمز المميّز يحتوي على appLicensingVerdict: "UNLICENSED"، يمكنك الردّ على برنامج تطبيقك العميل، وطلب عرض مربّع حوار الترخيص:

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

    الإعلانات المدمجة مع المحتوى

    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;
    }
    
  4. في تطبيقك، يمكنك استدعاء showDialog باستخدام الرمز المطلوب الذي تم استرداده من الخادم:

    Kotlin

    // Show dialog as indicated by the server
    val showDialogType: Int? = yourServerResponse.integrityDialogTypeCode()
    if (showDialogType == null) {
         return
    }
    
    // Create dialog request
    val dialogRequest = StandardIntegrityDialogRequest.builder()
              .setActivity(activity)
              .setTypeCode(showDialogType)
              .setStandardIntegrityResponse(StandardIntegrityResponse.TokenResponse(token))
              .build()
    
    // Call showDialog, the dialog will be shown on top of the provided activity
    // and the task will complete when the dialog is closed.
    val result: Task<Int> = standardIntegrityManager.showDialog(dialogRequest)
    
    // Handle response code, call the Integrity API again to confirm that the
    // verdict issue has been resolved.
    

    Java

    // Show dialog as indicated by the server
    @Nullable Integer showDialogType = yourServerResponse.integrityDialogTypeCode();
    if (showDialogType == null) {
         return;
    }
    
    // Create dialog request
    StandardIntegrityDialogRequest dialogRequest =
          StandardIntegrityDialogRequest.builder()
              .setActivity(getActivity())
              .setTypeCode(showDialogTypeCode)
              .setStandardIntegrityResponse(new StandardIntegrityResponse.TokenResponse(token))
              .build();
    
    // Call showDialog, the dialog will be shown on top of the provided activity
    // and the task will complete when the dialog is closed.
    Task<Integer> result = standardIntegrityManager.showDialog(dialogRequest);
    
    // Handle response code, call the Integrity API again to confirm that the
    // verdict issue has been resolved.
    

    Unity

    // Initialize the V2 manager. Requires Play Integrity Unity Plugin v2.0.0 or
    // higher.
    var standardIntegrityManager = new StandardIntegrityManagerV2();
    IEnumerator ShowDialogCoroutine() {
        int showDialogType = yourServerResponse.IntegrityDialogTypeCode();
    
        PlayAsyncOperation<IntegrityDialogResponseCode, StandardIntegrityError> showDialogTask;
    
        using (var activity = UnityPlayerHelper.GetCurrentActivity())
        {
            // Create a dialog request
            var dialogRequest = new StandardIntegrityDialogRequest(tokenResponse, activity, showDialogType);
    
            // Call showDialog with the request, the dialog will be shown on top of the
            // provided activity and complete when the dialog is closed.
            showDialogTask = standardIntegrityManager.ShowDialog(dialogRequest);
        }
    
        // Wait for PlayAsyncOperation to complete.
        yield return showDialogTask;
    
        // Handle response code, call the Integrity API again to confirm that the
        // verdict issue been resolved.
    }
    

    Unreal Engine

    // .h
    void MyClass::OnShowDialogCompleted(
        EStandardIntegrityErrorCode Error,
        EIntegrityDialogResponseCode Response)
    {
        // Handle response code, call the Integrity API again to confirm that the
        // verdict issue has 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);
    }
    

    الإعلانات المدمجة مع المحتوى

    // Show dialog as indicated by the server
    int show_dialog_type = yourServerResponse.integrityDialogTypeCode();
    if(show_dialog_type == 0){
      return;
    }
    
    /// Create dialog request
    StandardIntegrityDialogRequest* dialog_request;
    StandardIntegrityDialogRequest_create(&dialog_request);
    StandardIntegrityDialogRequest_setTypeCode(dialog_request, show_dialog_type);
    StandardIntegrityDialogRequest_setActivity(dialog_request, activity);
    StandardIntegrityDialogRequest_setStandardIntegrityToken(dialog_request,
                                                    token_response);
    
    /// Call showDialog with the dialog request. The dialog will be shown on top
    /// of the provided activity and complete when the dialog is closed by the
    /// user.
    StandardIntegrityDialogResponse* dialog_response;
    StandardIntegrityErrorCode error_code =
        StandardIntegrityManager_showDialog(dialog_request, &dialog_response);
    
    /// Use polling to wait for the async operation to complete. Note, the polling
    /// shouldn't block the thread where the StandardIntegrityManager is running.
    IntegrityDialogResponseCode response_code = INTEGRITY_DIALOG_RESPONSE_UNKNOWN;
    while (error_code == STANDARD_INTEGRITY_NO_ERROR) {
        error_code = StandardIntegrityDialogResponse_getResponseCode(dialog_response, &response_code);
        if(response_code != INTEGRITY_DIALOG_RESPONSE_UNKNOWN){
          break;
        }
    }
    
    /// Free memory
    StandardIntegrityDialogRequest_destroy(dialog_request);
    StandardIntegrityDialogResponse_destroy(dialog_response);
    
    /// Handle response code, call the Integrity API again to confirm that the
    /// verdict issues have been resolved.
    
  5. يتم عرض مربّع الحوار في أعلى النشاط المقدَّم. عندما يغلق المستخدم مربّع الحوار، تكتمل المهمة مع رمز استجابة.

  6. (اختياري) اطلب رمزًا مميزًا آخر لعرض أي مربّعات حوار أخرى. إذا كنت تُرسل طلبات عادية، عليك تحضير موفّر الرموز المميّزة مرة أخرى للحصول على بيان جديد.

طلب مربع حوار ميزة "توفير السلامة" لإصلاح استثناء من جهة العميل

إذا تعذّر طلب بيانات من واجهة برمجة التطبيقات Integrity API وظهر الخطأ StandardIntegrityException (Standard API) أو IntegrityServiceException (Classic API) وكان من الممكن معالجة الاستثناء، يمكنك استخدام مربّعَي الحوار GET_INTEGRITY أو GET_STRONG_INTEGRITY لإصلاح الخطأ.

توضّح الخطوات التالية كيفية استخدام مربّع الحوار GET_INTEGRITY لإصلاح خطأ يمكن معالجته من جهة العميل أبلغت عنه واجهة Integrity API.

  1. تأكَّد من أنّ الاستثناء الذي تم عرضه من طلب بيانات من واجهة برمجة التطبيقات Integrity API قابل للإصلاح.

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

    Unity

    private bool IsExceptionRemediable(StandardIntegrityError error) {
        // Check if the operation resulted in a remediable error
        if (error != null && error.ErrorCode != StandardIntegrityErrorCode.NoError && error.IsRemediable) {
            return true;
        }
        return false;
    }
    

    الإعلانات المدمجة مع المحتوى

    bool IsErrorRemediable(StandardIntegrityToken* token) {
        /// Check if the error associated with the token is remediable
        bool isRemediable = false;
        if(StandardIntegrityToken_getIsRemediable(response, &isRemediable) == STANDARD_INTEGRITY_NO_ERROR){
          return isRemediable;
        }
        return false;
    }
    
  2. إذا كان الاستثناء قابلاً للمعالجة، اطلب مربّع حوار GET_INTEGRITY باستخدام الاستثناء الذي تم عرضه. سيتم عرض مربّع الحوار فوق النشاط المقدَّم، وستكتمل المهمة التي تم عرضها من خلال رمز استجابة بعد أن يغلق المستخدم مربّع الحوار.

    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);
    }
    

    Unity

    // Initialize the V2 manager. Requires Play Integrity Unity Plugin v2.0.0 or
    // higher.
    var standardIntegrityManager = new StandardIntegrityManagerV2();
    IEnumerator ShowDialogToFixError(StandardIntegrityError error) {
        PlayAsyncOperation<IntegrityDialogResponseCode, StandardIntegrityError> showDialogTask;
    
        using (var activity = UnityPlayerHelper.GetCurrentActivity())
        {
            // Create a dialog request using the error
            var dialogRequest = new StandardIntegrityDialogRequest(error, activity, GET_INTEGRITY_DIALOG);
    
            // Request dialog
            showDialogTask = standardIntegrityManager.ShowDialog(dialogRequest);
        }
    
        // Wait for PlayAsyncOperation to complete.
        yield return showDialogTask;
    }
    

    الإعلانات المدمجة مع المحتوى

    private void showDialogToFixError(StandardIntegrityToken* token) {
        /// If the token request failed, and the underlying error is not fixable
        /// then return early
        if(isErrorRemediable(token)) {
          return;
        }
    
        /// Create dialog request
        StandardIntegrityDialogRequest* dialog_request;
        StandardIntegrityDialogRequest_create(&dialog_request);
        StandardIntegrityDialogRequest_setTypeCode(dialog_request,
                                           kGetIntegrityDialogTypeCode);
        StandardIntegrityDialogRequest_setActivity(dialog_request, activity);
        StandardIntegrityDialogRequest_setStandardIntegrityToken(dialog_request,
                                                        token_response);
    
        /// Call showDialog with the dialog request. The dialog will be shown on
        /// top of the provided activity and complete when the dialog is closed by
        /// the user.
        StandardIntegrityDialogResponse* dialog_response;
        StandardIntegrityErrorCode error_code =
            StandardIntegrityManager_showDialog(dialog_request, &dialog_response);
    
        /// Use polling to wait for the async operation to complete.
        /// Note, the polling shouldn't block the thread where the
        /// StandardIntegrityManager is running.
        IntegrityDialogResponseCode response_code = INTEGRITY_DIALOG_RESPONSE_UNKNOWN;
        while (error_code == STANDARD_INTEGRITY_NO_ERROR) {
            error_code = StandardIntegrityDialogResponse_getResponseCode(response, &response_code);
            if(response_code != INTEGRITY_DIALOG_RESPONSE_UNKNOWN){
              break;
            }
        }
    
        /// Free memory
        StandardIntegrityDialogRequest_destroy(dialog_request);
        StandardIntegrityDialogResponse_destroy(dialog_response);
    
    }
    
  3. إذا كان رمز الاستجابة الذي تم عرضه يشير إلى نجاح العملية، من المفترض أن ينجح الطلب التالي للحصول على رمز مميّز للنزاهة بدون أي استثناءات. إذا كنت تُجري طلبات عادية، عليك إعادة تهيئة موفّر الرموز المميّزة للحصول على بيان جديد.

رموز مربّعات حوار واجهة برمجة التطبيقات Integrity API

GET_LICENSED (رمز النوع 1)

مشكلة في البيان

هذا المربع الحواري مناسب لمشكلتين:

  • الوصول غير المصرَّح به: appLicensingVerdict: "UNLICENSED" يعني ذلك أنّ حساب المستخدم ليس لديه إذن الوصول إلى تطبيقك، وقد يحدث ذلك إذا ثبَّت المستخدم التطبيق من مصدر غير معروف أو حصل عليه من متجر تطبيقات آخر غير Google Play.
  • التطبيق الذي تم التلاعب به: appRecognitionVerdict: "UNRECOGNIZED_VERSION". ويعني ذلك أنّ البرنامج الثنائي لتطبيقك قد تم تعديله أو أنّه ليس إصدارًا يتعرّف عليه Google Play.

تصدير البيانات الناقصة

يمكنك عرض مربّع الحوار "GET_LICENSED" لتطلب من المستخدم الحصول على التطبيق الأصلي من Google Play. يتناول مربّع الحوار هذا كلا السيناريوهَين:

  • بالنسبة إلى المستخدم غير المرخَّص له، يمنحه هذا الإجراء ترخيصًا من Google Play. يتيح ذلك للمستخدم تلقّي تحديثات التطبيقات من Google Play.
  • بالنسبة إلى المستخدم الذي لديه إصدار تطبيق تم التلاعب به، يوجّهه هذا الإجراء إلى تثبيت التطبيق غير المُعدَّل من Google Play.

عندما يكمل المستخدم مربّع الحوار، ستعرض عمليات التحقّق من السلامة اللاحقة appLicensingVerdict: "LICENSED" وappRecognitionVerdict: "PLAY_RECOGNIZED".

مثال على تجربة المستخدم

الشكل 1: مربّع حوار GET_LICENSED في Play

‫CLOSE_UNKNOWN_ACCESS_RISK (الرمز من النوع 2)

مشكلة في البيان

عندما يحتوي environmentDetails.appAccessRiskVerdict.appsDetected على "UNKNOWN_CAPTURING" أو "UNKNOWN_CONTROLLING"، يعني ذلك أنّ هناك تطبيقات أخرى (لم يتم تثبيتها من خلال Google Play أو لم يتم تحميلها مسبقًا على قسم النظام من قِبل الشركة المصنّعة للجهاز) تعمل على الجهاز ويمكنها أخذ لقطات للشاشة أو التحكّم في الجهاز.

تصدير البيانات الناقصة

يمكنك عرض مربّع الحوار "CLOSE_UNKNOWN_ACCESS_RISK" لمطالبة المستخدم بإغلاق جميع التطبيقات غير المعروفة التي قد تلتقط محتوى الشاشة أو تتحكّم في الجهاز. إذا نقر المستخدم على الزر Close all، يتم إغلاق جميع هذه التطبيقات.

مثال على تجربة المستخدم

الشكل 2. مربّع حوار لإغلاق خطر الوصول غير المعروف

CLOSE_ALL_ACCESS_RISK (رمز النوع 3)

مشكلة في البيان

عندما يحتوي environmentDetails.appAccessRiskVerdict.appsDetected على أي من "KNOWN_CAPTURING" أو "KNOWN_CONTROLLING" أو "UNKNOWN_CAPTURING" أو "UNKNOWN_CONTROLLING"، يعني ذلك أنّ هناك تطبيقات قيد التشغيل على الجهاز قد تكون تلتقط الشاشة أو تتحكّم في الجهاز.

تصدير البيانات الناقصة

يمكنك عرض مربّع الحوار "CLOSE_ALL_ACCESS_RISK" لمطالبة المستخدم بإغلاق جميع التطبيقات التي يمكنها أخذ لقطات للشاشة أو التحكم في الجهاز. إذا نقر المستخدم على الزر Close all، سيتم إغلاق جميع هذه التطبيقات على الجهاز.

مثال على تجربة المستخدم

الشكل 3. مربّع حوار لإغلاق جميع مخاطر الوصول

GET_INTEGRITY (رمز النوع 4)

مشكلة في البيان

هذا مربّع الحوار مناسب لأي من المشاكل التالية:

  • سلامة الجهاز ضعيفة: عندما لا يحتوي الحقل deviceRecognitionVerdict على القيمة MEETS_DEVICE_INTEGRITY، قد لا يكون الجهاز جهازًا أصليًا ومعتمدًا يعمل بنظام التشغيل Android. يمكن أن يحدث ذلك، على سبيل المثال، إذا كان برنامج الإقلاع في الجهاز مفتوحًا أو إذا كان نظام التشغيل Android المحمَّل عليه ليس صورة معتمَدة من الشركة المصنّعة.

  • الوصول غير المصرَّح به: appLicensingVerdict: "UNLICENSED" يعني ذلك أنّ حساب المستخدم ليس لديه إذن الوصول إلى تطبيقك، وقد يحدث ذلك إذا ثبَّت المستخدم التطبيق من مصدر غير معروف أو حصل عليه من متجر تطبيقات آخر غير Google Play.

  • التطبيق الذي تم التلاعب به: appRecognitionVerdict: "UNRECOGNIZED_VERSION". ويعني ذلك أنّ البرنامج الثنائي لتطبيقك قد تم تعديله أو أنّه ليس إصدارًا يتعرّف عليه Google Play.

  • استثناءات من جهة العميل: عند حدوث استثناء يمكن معالجته أثناء طلب بيانات من واجهة برمجة التطبيقات Integrity API. الاستثناءات القابلة للإصلاح هي استثناءات في Integrity API تتضمّن رموز خطأ مثل ‎PLAY_SERVICES_VERSION_OUTDATED وNETWORK_ERROR وPLAY_SERVICES_NOT_FOUND وما إلى ذلك. يمكنك استخدام طريقة exception.isRemediable() للتحقّق مما إذا كان الاستثناء قابلاً للإصلاح من خلال مربّع الحوار.

تصدير البيانات الناقصة

تم تصميم مربّع الحوار "GET_INTEGRITY" لتبسيط تجربة المستخدم من خلال تنفيذ خطوات متعددة لتصدير البيانات الناقصة ضمن مسار واحد متواصل. يمنع هذا المستخدم من الاضطرار إلى التفاعل مع مربعات حوار منفصلة متعددة لإصلاح مشكلات مختلفة.

عند طلب مربّع الحوار، يرصد تلقائيًا المشاكل المتعلّقة بالبيانات المستهدَفة ويقدّم خطوات الحلّ المناسبة. وهذا يعني أنّ طلبًا واحدًا من مربّع الحوار يمكن أن يعالج مشاكل متعدّدة في آنٍ واحد، بما في ذلك:

  • سلامة الجهاز: إذا تم رصد مشكلة في سلامة الجهاز، سيوجّه مربّع الحوار المستخدم إلى تحسين حالة أمان الجهاز لتلبية متطلبات بيان السلامة MEETS_DEVICE_INTEGRITY.
  • سلامة التطبيق: إذا تم رصد مشاكل مثل الوصول غير المصرَّح به أو التلاعب بالتطبيق، سيوجه مربّع الحوار المستخدمين إلى الحصول على التطبيق من "متجر Google Play" لحلّ هذه المشاكل.
  • الاستثناءات من جهة العميل: يتحقّق مربّع الحوار من أي مشاكل أساسية تسبّبت في حدوث استثناء في واجهة Integrity API ويحاول حلّها. على سبيل المثال، قد يطلب من المستخدم تحديث إصدار قديم من "خدمات Google Play".

مثال على تجربة المستخدم

الشكل 4. سير عملية تصدير البيانات الناقصة في مربّع حوار GET_INTEGRITY عند حدوث خطأ في الشبكة

GET_STRONG_INTEGRITY (رمز النوع 5)

مشكلة في البيان

تم تصميم مربّع الحوار هذا لحلّ جميع المشاكل نفسها التي يعالجها GET_INTEGRITY، مع إمكانية إضافية لحلّ المشاكل التي تمنع الجهاز من تلقّي بيان MEETS_STRONG_INTEGRITY وحلّ مشاكل بيان "Play للحماية".

تصدير البيانات الناقصة

تم تصميم GET_STRONG_INTEGRITY لتبسيط تجربة المستخدم من خلال التعامل مع خطوات متعددة لتصدير البيانات الناقصة ضمن مسار واحد مستمر. يتحقّق مربّع الحوار تلقائيًا من مشاكل السلامة التي تنطبق على العنوان، بما في ذلك:

  • سلامة الجهاز: إذا تم رصد مشكلة في سلامة الجهاز، سيوجّه مربّع الحوار المستخدم إلى تحسين حالة أمان الجهاز لتلبية متطلبات بيان السلامة MEETS_STRONG_INTEGRITY.
  • حالة "Play للحماية": إذا أشار الرمز playProtectVerdict إلى مشكلة، سيوجّه مربّع الحوار المستخدم إلى حلّها:

    • إذا كانت خدمة "Google Play للحماية" غير مفعَّلة (playProtectVerdict == POSSIBLE_RISK)، سيطلب مربّع الحوار من المستخدم تفعيلها وفحص جميع التطبيقات على الجهاز.
    • إذا تم رصد تطبيقات ضارة (playProtectVerdict == MEDIUM_RISK أو HIGH_RISK)، سيوجه مربّع الحوار المستخدم إلى إلغاء تثبيتها باستخدام خدمة "Google Play للحماية".
  • سلامة التطبيق: إذا تم رصد مشاكل مثل الوصول غير المصرَّح به أو التلاعب بالتطبيق، سيطلب مربّع الحوار من المستخدم الحصول على التطبيق من "متجر Google Play" لحلّ المشكلة.

  • الاستثناءات من جهة العميل: يحاول مربّع الحوار أيضًا حلّ أي مشاكل أساسية تسبّبت في حدوث استثناء في Integrity API. على سبيل المثال، قد تطلب من المستخدم تفعيل "خدمات Google Play" إذا تبيّن أنّها غير مفعَّلة. الاستثناءات القابلة للإصلاح هي استثناءات Integrity API التي تتضمّن رموز خطأ مثل PLAY_SERVICES_VERSION_OUTDATED أو NETWORK_ERROR أو PLAY_SERVICES_NOT_FOUND. يمكنك استخدام طريقة exception.isRemediable() للتحقّق مما إذا كان يمكن إصلاح الخطأ من خلال مربّع الحوار.

مثال على تجربة المستخدم

الشكل 5. مربّع حوار GET_STRONG_INTEGRITY لتحديث خدمات Play