إدارة كائنات WebView

يوفّر Android واجهات برمجة تطبيقات متعددة لمساعدتك في إدارة WebView أو الكائنات التي تعرض محتوى الويب في تطبيقك.

توضّح هذه الصفحة كيفية استخدام واجهات برمجة التطبيقات هذه للعمل مع WebView. العناصر بفعالية أكبر، ما يحسّن ثبات تطبيقك وأمانه.

واجهة برمجة تطبيقات الإصدار

بدءًا من الإصدار Android 7.0 (المستوى 24 من واجهة برمجة التطبيقات)، يمكن للمستخدمين الاختيار من بين عدة الحزم المختلفة لعرض محتوى الويب في عنصر WebView واجهة AndroidX.webkit المكتبة تتضمن getCurrentWebViewPackage() طريقة لاسترجاع المعلومات المتعلقة بالحزمة التي تعرض محتوى الويب المحتوى في تطبيقك. وهذه الطريقة مفيدة عند تحليل الأخطاء التي تحدث فقط عندما يحاول تطبيقك عرض محتوى الويب باستخدام حزمة تنفيذ WebView.

لاستخدام هذه الطريقة، أضِف المنطق الموضح في مقتطف الرمز التالي:

Kotlin

val webViewPackageInfo = WebViewCompat.getCurrentWebViewPackage(appContext)
Log.d("MY_APP_TAG", "WebView version: ${webViewPackageInfo.versionName}")

Java

PackageInfo webViewPackageInfo = WebViewCompat.getCurrentWebViewPackage(appContext);
Log.d("MY_APP_TAG", "WebView version: " + webViewPackageInfo.versionName);

خدمة التصفح الآمن من Google

لتوفير تجربة تصفُّح أكثر أمانًا للمستخدمين، WebView العناصر للتحقق من عناوين URL باستخدام التصفح الآمن من Google، والذي يسمح لتطبيقك بعرض تحذير للمستخدمين عند محاولة الانتقال إلى الذي يحتمل أن يكون غير آمن.

على الرغم من أن القيمة الافتراضية EnableSafeBrowsing صحيحة، إلا أن هناك هي حالات قد تريد فيها تمكين التصفح الآمن بشكل مشروط أو وتعطيلها. يتيح الإصدار Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات) والإصدارات الأحدث استخدام setSafeBrowsingEnabled() لإيقاف ميزة "التصفُّح الآمن" لعنصر WebView فردي.

إذا كنت تريد إيقاف "التصفُّح الآمن" لجميع كائنات WebView يمكنك إضافة العنصر <meta-data> التالي إلى صفحة تطبيقك ملف البيان:

<manifest>
    <application>
        <meta-data android:name="android.webkit.WebView.EnableSafeBrowsing"
                   android:value="false" />
        ...
    </application>
</manifest>

تحديد الإجراءات الآلية

عندما يحاول مثيل WebView تحميل صفحة ذات يصنّفه محرّك بحث Google على أنّه تهديد معروف، ويشكّل WebView تلقائيًا يعرض إعلانًا بينيًا يحذّر المستخدمين من التهديد المعروف. تعطي هذه الشاشة خيار تحميل عنوان URL على أي حال أو العودة إلى صفحة سابقة آمِن

إذا كنت تستهدف الإصدار 8.1 من نظام التشغيل Android (المستوى 27 من واجهة برمجة التطبيقات) أو إصدارًا أحدث، يمكنك تحديد آليًا استجابة تطبيقك لتهديد معروف في ما يلي الطرق:

  • يمكنك التحكّم في ما إذا كان تطبيقك سيُبلغ عن التهديدات المعروفة للتهديدات الآمنة التصفح.
  • يمكنك ضبط تطبيقك ينفّذ إجراءً معينًا تلقائيًا، على سبيل المثال: كالعودة إلى وضع الأمان - في كل مرة يصادف فيها عنوان URL باعتباره تهديدًا معروفًا.

توضّح مقتطفات الرمز التالية كيفية توجيه نُسخ تطبيقك WebView للعودة إلى وضع الأمان دائمًا بعد مواجهة التهديد:

MyWebActivity.java

Kotlin

private lateinit var superSafeWebView: WebView
private var safeBrowsingIsInitialized: Boolean = false

// ...

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    superSafeWebView = WebView(this)
    superSafeWebView.webViewClient = MyWebViewClient()
    safeBrowsingIsInitialized = false

    if (WebViewFeature.isFeatureSupported(WebViewFeature.START_SAFE_BROWSING)) {
        WebViewCompat.startSafeBrowsing(this, ValueCallback<Boolean> { success ->
            safeBrowsingIsInitialized = true
            if (!success) {
                Log.e("MY_APP_TAG", "Unable to initialize Safe Browsing!")
            }
        })
    }
}

Java

private WebView superSafeWebView;
private boolean safeBrowsingIsInitialized;

// ...

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    superSafeWebView = new WebView(this);
    superSafeWebView.setWebViewClient(new MyWebViewClient());
    safeBrowsingIsInitialized = false;

    if (WebViewFeature.isFeatureSupported(WebViewFeature.START_SAFE_BROWSING)) {
        WebViewCompat.startSafeBrowsing(this, new ValueCallback<Boolean>() {
            @Override
            public void onReceiveValue(Boolean success) {
                safeBrowsingIsInitialized = true;
                if (!success) {
                    Log.e("MY_APP_TAG", "Unable to initialize Safe Browsing!");
                }
            }
        });
    }
}

MyWebViewClient.java

Kotlin

class MyWebViewClient : WebViewClientCompat() {
    // Automatically go "back to safety" when attempting to load a website that
    // Google identifies as a known threat. An instance of WebView calls this
    // method only after Safe Browsing is initialized, so there's no conditional
    // logic needed here.
    override fun onSafeBrowsingHit(
            view: WebView,
            request: WebResourceRequest,
            threatType: Int,
            callback: SafeBrowsingResponseCompat
    ) {
        // The "true" argument indicates that your app reports incidents like
        // this one to Safe Browsing.
        if (WebViewFeature.isFeatureSupported(WebViewFeature.SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY)) {
            callback.backToSafety(true)
            Toast.makeText(view.context, "Unsafe web page blocked.", Toast.LENGTH_LONG).show()
        }
    }
}

Java

public class MyWebViewClient extends WebViewClientCompat {
    // Automatically go "back to safety" when attempting to load a website that
    // Google identifies as a known threat. An instance of WebView calls this
    // method only after Safe Browsing is initialized, so there's no conditional
    // logic needed here.
    @Override
    public void onSafeBrowsingHit(WebView view, WebResourceRequest request,
            int threatType, SafeBrowsingResponseCompat callback) {
        // The "true" argument indicates that your app reports incidents like
        // this one to Safe Browsing.
        if (WebViewFeature.isFeatureSupported(WebViewFeature.SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY)) {
            callback.backToSafety(true);
            Toast.makeText(view.getContext(), "Unsafe web page blocked.",
                    Toast.LENGTH_LONG).show();
        }
    }
}

واجهة برمجة تطبيقات HTML5 Geolocation

بالنسبة إلى التطبيقات التي تستهدف Android 6.0 (المستوى 23 من واجهة برمجة التطبيقات) والإصدارات الأحدث، يجب استخدام Geolocation API لا تتوافق إلا مع المصادر الآمنة، مثل HTTPS. سيتم إرسال أي طلب إلى رفض واجهة برمجة التطبيقات Geolocation API على المصادر غير الآمنة تلقائيًا بدون استدعاء طريقة onGeolocationPermissionsShowPrompt() المقابلة.

إيقاف جمع المقاييس

بإمكان خدمة "WebView" تحميل بيانات تشخيصية مجهولة الهوية إلى Google عندما يمنح المستخدِم موافقته. يتم جمع البيانات على أساس كلّ تطبيق. لكل تطبيق ينشئ مثيلاً لـ WebView. يمكنك إيقاف هذه الميزة من خلال إنشاء العلامة التالية في ملف البيان العنصر <application>:

<manifest>
    <application>
    ...
    <meta-data android:name="android.webkit.WebView.MetricsOptOut"
               android:value="true" />
    </application>
</manifest>

لا يتم تحميل البيانات من تطبيق إلا في حال موافقة المستخدم و عدم إيقاف التطبيق. لمزيد من المعلومات عن إيقاف بيانات التشخيص إعداد التقارير، راجِع خصوصية المستخدم في WebView. الإعلام.

واجهة برمجة تطبيقات التعامل مع الإنهاء

تتعامل واجهة برمجة التطبيقات للتعامل مع الإنهاء مع الحالات التي تؤدي فيها عملية العرض إلى WebView يختفي كائن، إما لأن النظام يقتل العارض لاسترداده الذاكرة الضرورية أو بسبب تعطُّل عملية العارض. باستخدام واجهة برمجة التطبيقات هذه، مواصلة تنفيذ تطبيقك، على الرغم من إيقاف عملية العرض نهائيًا

إذا تعطل عارض أثناء تحميل صفحة ويب معينة، أو يحاول إلى تحميل تلك الصفحة نفسها مرة أخرى، إلى عرض كائن WebView جديد يحدث نفس سلوك تعطُّل العرض.

يوضِّح مقتطف الرمز التالي كيفية استخدام واجهة برمجة التطبيقات هذه في Activity:

Kotlin

    
inner class MyRendererTrackingWebViewClient : WebViewClient() {
    private var mWebView: WebView? = null

    override fun onRenderProcessGone(view: WebView, detail: RenderProcessGoneDetail): Boolean {
        if (!detail.didCrash()) {
            // Renderer is killed because the system ran out of memory. The app
            // can recover gracefully by creating a new WebView instance in the
            // foreground.
            Log.e("MY_APP_TAG", ("System killed the WebView rendering process " +
                "to reclaim memory. Recreating..."))

            mWebView?.also { webView ->
                val webViewContainer: ViewGroup = findViewById(R.id.my_web_view_container)
                webViewContainer.removeView(webView)
                webView.destroy()
                mWebView = null
            }

            // By this point, the instance variable "mWebView" is guaranteed to
            // be null, so it's safe to reinitialize it.

            return true // The app continues executing.
        }

        // Renderer crashes because of an internal error, such as a memory
        // access violation.
        Log.e("MY_APP_TAG", "The WebView rendering process crashed!")

        // In this example, the app itself crashes after detecting that the
        // renderer crashed. If you handle the crash more gracefully and let
        // your app continue executing, you must destroy the current WebView
        // instance, specify logic for how the app continues executing, and
        // return "true" instead.
        return false
    }
}

Java

public class MyRendererTrackingWebViewClient extends WebViewClient {
    private WebView mWebView;

    @Override
    public boolean onRenderProcessGone(WebView view,
            RenderProcessGoneDetail detail) {
        if (!detail.didCrash()) {
            // Renderer is killed because the system ran out of memory. The app
            // can recover gracefully by creating a new WebView instance in the
            // foreground.
            Log.e("MY_APP_TAG", "System killed the WebView rendering process " +
                    "to reclaim memory. Recreating...");

            if (mWebView != null) {
                ViewGroup webViewContainer =
                        (ViewGroup) findViewById(R.id.my_web_view_container);
                webViewContainer.removeView(mWebView);
                mWebView.destroy();
                mWebView = null;
            }

            // By this point, the instance variable "mWebView" is guaranteed to
            // be null, so it's safe to reinitialize it.

            return true; // The app continues executing.
        }

        // Renderer crashes because of an internal error, such as a memory
        // access violation.
        Log.e("MY_APP_TAG", "The WebView rendering process crashed!");

        // In this example, the app itself crashes after detecting that the
        // renderer crashed. If you handle the crash more gracefully and let
        // your app continue executing, you must destroy the current WebView
        // instance, specify logic for how the app continues executing, and
        // return "true" instead.
        return false;
    }
}

واجهة برمجة التطبيقات الأهمية في Renderer

عند اعتراض WebView العمل في الوضع المتعدّد العمليات، سيكون لديك بعض المرونة في كيفية معالجة تطبيقك المواقف خارج الذاكرة. يمكنك استخدام واجهة برمجة التطبيقات Renderer الْمُزوّدة بأهمية البيانات Android 8.0، لتحديد سياسة أولوية للعارض الذي تم تخصيصه لعرض معيّن عنصر WebView. على وجه الخصوص، قد ترغب في الجزء الرئيسي من لمواصلة تنفيذ عملية الإعداد عند عرض عارض يعرض محتوى تطبيقك تم قتل WebView غرض. يمكنك القيام بذلك، على سبيل المثال، إذا نتوقع عدم عرض الكائن WebView لمدة طويلة بحيث لا يمكن بإمكان النظام استرداد الذاكرة التي كان يستخدمها العارض.

يوضح مقتطف الرمز التالي كيفية تعيين أولوية العارض العملية المرتبطة بعناصر WebView في تطبيقك:

Kotlin

val myWebView: WebView = ...
myWebView.setRendererPriorityPolicy(RENDERER_PRIORITY_BOUND, true)

Java

WebView myWebView;
myWebView.setRendererPriorityPolicy(RENDERER_PRIORITY_BOUND, true);

في هذا المقتطف بالتحديد، تكون أولوية العارض نفسها مثل — الأولوية الافتراضية للتطبيق. true تقلل الوسيطة من أولوية العارض إلى RENDERER_PRIORITY_WAIVED عندما لا يعود كائن WebView المرتبط مرئيًا بعبارة أخرى، فإن الوسيطة true تشير إلى أن تطبيقك لا يهتم بما إذا يحافظ النظام على تنشيط عملية العرض. في الواقع، سيؤدي هذا المستوى الأدنى من الأولوية من المرجح أن يتم إنهاء عملية العرض خارج الذاكرة المواقف المختلفة.

لمزيد من المعلومات عن كيفية تعامل النظام مع مواقف انخفاض الذاكرة، يمكنك الاطّلاع على العمليات والتطبيقات دورة حياة المنتج.