يوفّر 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
هي true، قد تحتاج في بعض الحالات إلى تفعيل "التصفّح الآمن" بشكل مشروط أو إيقافه. يتيح الإصدار 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 على أي حال أو العودة إلى صفحة سابقة آمنة.
إذا كنت تستهدف الإصدار Android 8.1 (مستوى واجهة برمجة التطبيقات 27) أو إصدارًا أحدث، يمكنك تحديد طريقة استجابة تطبيقك لتهديد معروف بشكل آلي من خلال الطرق التالية:
- يمكنك التحكّم في ما إذا كان تطبيقك يُبلغ عن التهديدات المعروفة للتصفّح الآمن.
- يمكنك ضبط تطبيقك تلقائيًا لتنفيذ إجراء محدّد، مثل الرجوع إلى وضع الأمان، في كل مرة يصادف فيها عنوان URL مصنّف على أنه تهديد معروف.
توضّح مقتطفات الرمز التالية كيفية توجيه مثيلات تطبيقك WebView
إلى وضع الأمان في أي وقت بعد مواجهة تهديد معروف:
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!"); } } }); } }
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
بالنسبة إلى التطبيقات التي تستهدف الإصدار 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.
واجهة برمجة تطبيقات معالجة الإنهاء
تتعامل واجهة برمجة تطبيقات Finish Handling API مع الحالات التي تتوقف فيها عملية العرض لكائن 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 المميزة في الإصدار 8.0 من Android لضبط سياسة الأولوية للعارض الذي تم تحديده لكائن 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
إلى أنّ تطبيقك لا يهتم بما إذا كان النظام يُبقي عملية العارض أم لا. في الواقع، يؤدي مستوى الأولوية الأدنى هذا إلى خسارة عملية العرض في حالات خارج الذاكرة.
لمعرفة المزيد من المعلومات حول كيفية تعامل النظام مع حالات انخفاض الذاكرة، راجِع العمليات ومراحل نشاط التطبيقات.