استخدِم WebView
لتقديم تطبيق ويب
أو صفحة ويب كجزء من تطبيق عميل. فئة WebView
هي
إضافة إلى فئة View
في Android التي تتيح
لك عرض صفحات الويب كجزء من تنسيق نشاطك. ولا يتضمّن
ميزات متصفح ويب مطوّر بالكامل، مثل عناصر التحكّم في التنقّل أو
شريط العناوين. لا يؤدي WebView
تلقائيًا إلا إلى عرض صفحة ويب.
يمكن أن تساعدك WebView
في تقديم معلومات في تطبيقك قد تحتاج إلى
تعديلها، مثل اتفاقية المستخدم النهائي أو دليل المستخدم. ضمن تطبيق Android،
يمكنك إنشاء Activity
يحتوي على
WebView
، ثم استخدامه لعرض المستند المستضاف على الإنترنت.
يمكن أن يساعدك WebView
أيضًا عندما يقدّم تطبيقك بيانات للمستخدم تتطلّب
الاتصال بالإنترنت لاسترداد البيانات، مثل البريد الإلكتروني. في هذه الحالة، قد
تجد أنّه من الأسهل إنشاء WebView
في تطبيق Android يعرض
صفحة ويب تتضمّن جميع بيانات المستخدمين، بدلاً من تنفيذ طلب شبكة، ثم
تحليل البيانات وعرضها بتنسيق Android. بدلاً من ذلك، يمكنك تصميم
صفحة ويب مخصّصة للأجهزة التي تعمل بنظام التشغيل Android، ثم تنفيذ
WebView
في تطبيق Android الذي يحمّل صفحة الويب.
يوضّح هذا المستند كيفية بدء استخدام WebView
وكيفية ربط
JavaScript من صفحة الويب برمز جهة العميل في تطبيق Android وكيفية
معالجة التنقّل في الصفحة وكيفية إدارة النوافذ عند استخدام WebView
.
استخدام WebView على الإصدارات السابقة من Android
لاستخدام إمكانات WebView
الأحدث بأمان على الجهاز الذي يعمل عليه
تطبيقك، أضِف مكتبة AndroidX
Webkit. هذه مكتبة static
يمكنك إضافتها إلى تطبيقك لاستخدام واجهات برمجة تطبيقات android.webkit
التي لا
تتوفّر لإصدارات النظام الأساسي السابقة.
أضِفه إلى ملف build.gradle
على النحو التالي:
Kotlin
dependencies { implementation("androidx.webkit:webkit:1.8.0") }
رائع
dependencies { implementation ("androidx.webkit:webkit:1.8.0") }
يمكنك الاطّلاع على WebView
مثال
على GitHub للحصول على مزيد من التفاصيل.
إضافة WebView إلى تطبيقك
لإضافة WebView
إلى تطبيقك، يمكنك تضمين عنصر <WebView>
في
تنسيق النشاط أو ضبط نافذة Activity
بأكملها على أنّها WebView
في
onCreate()
.
إضافة WebView في تنسيق النشاط
لإضافة WebView
إلى تطبيقك في التنسيق، أضِف الرمز التالي إلىملف XML لتنسيق
نشاطك:
<WebView android:id="@+id/webview" android:layout_width="match_parent" android:layout_height="match_parent" />
لتحميل صفحة ويب في WebView
، استخدِم
loadUrl()
، كما هو موضح في المثال التالي:
Kotlin
val myWebView: WebView = findViewById(R.id.webview) myWebView.loadUrl("http://www.example.com")
Java
WebView myWebView = (WebView) findViewById(R.id.webview); myWebView.loadUrl("http://www.example.com");
إضافة WebView في onCreate()
لإضافة WebView
إلى تطبيقك في طريقة onCreate()
لنشاط معيّن بدلاً من ذلك، استخدِم
منطقًا مشابهًا لما يلي:
Kotlin
val myWebView = WebView(activityContext) setContentView(myWebView)
Java
WebView myWebView = new WebView(activityContext); setContentView(myWebView);
بعد ذلك، حمِّل الصفحة:
Kotlin
myWebView.loadUrl("http://www.example.com")
Java
myWebView.loadUrl("https://www.example.com");
أو يمكنك تحميل عنوان URL من سلسلة HTML:
Kotlin
// Create an unencoded HTML string, then convert the unencoded HTML string into // bytes. Encode it with base64 and load the data. val unencodedHtml = "<html><body>'%23' is the percent code for ‘#‘ </body></html>"; val encodedHtml = Base64.encodeToString(unencodedHtml.toByteArray(), Base64.NO_PADDING) myWebView.loadData(encodedHtml, "text/html", "base64")
Java
// Create an unencoded HTML string, then convert the unencoded HTML string into // bytes. Encode it with base64 and load the data. String unencodedHtml = "<html><body>'%23' is the percent code for ‘#‘ </body></html>"; String encodedHtml = Base64.encodeToString(unencodedHtml.getBytes(), Base64.NO_PADDING); myWebView.loadData(encodedHtml, "text/html", "base64");
يجب أن يكون تطبيقك متصلاً بالإنترنت. للوصول إلى الإنترنت، اطلب إذن
INTERNET
فيملف
البيان، كما هو موضّح في المثال التالي:
<manifest ... > <uses-permission android:name="android.permission.INTERNET" /> ... </manifest>
يمكنك تخصيص WebView
من خلال تنفيذ أيٍّ ممّا يلي:
- تفعيل إمكانية استخدام وضع ملء الشاشة باستخدام
WebChromeClient
يتم أيضًا استدعاء هذه الفئة عندما يحتاجWebView
إلى إذن لتغيير واجهة مستخدم التطبيق المضيف، مثل إنشاء النوافذ أو إغلاقها أو إرسال مربّعات حوار JavaScript إلى المستخدِم. لمزيد من المعلومات عن تصحيح الأخطاء في هذا السياق، اطّلِع على تصحيح أخطاء تطبيقات الويب. - التعامل مع الأحداث التي تؤثّر في عرض المحتوى، مثل الأخطاء في عمليات إرسال النموذج
أو التنقل باستخدام
WebViewClient
ويمكنك أيضًا استخدام هذه الفئة الفرعية لاعتراض تحميل عناوين URL. - تفعيل JavaScript من خلال تعديل
WebSettings
- استخدام JavaScript للوصول إلى كائنات إطار عمل Android التي تم إدخالها
في
WebView
استخدام JavaScript في WebView
إذا كانت صفحة الويب التي تريد تحميلها في WebView
تستخدم JavaScript، عليك
تفعيل JavaScript في WebView
. بعد تفعيل JavaScript، يمكنك
إنشاء واجهات بين رمز تطبيقك ورمز JavaScript.
تفعيل JavaScript
تكون JavaScript غير مفعّلة في WebView
تلقائيًا. يمكنك تفعيلها من خلال
WebSettings
المرفق بجهاز WebView
. استردّ WebSettings
باستخدام
getSettings()
، ثم فعِّل
JavaScript باستخدام
setJavaScriptEnabled()
.
راجِع المثال التالي:
Kotlin
val myWebView: WebView = findViewById(R.id.webview) myWebView.settings.javaScriptEnabled = true
Java
WebView myWebView = (WebView) findViewById(R.id.webview); WebSettings webSettings = myWebView.getSettings(); webSettings.setJavaScriptEnabled(true);
WebSettings
يتيح الوصول إلى مجموعة متنوعة من الإعدادات الأخرى التي قد تجدها مفيدة. على سبيل المثال، إذا كنت تُطوّر تطبيق ويب مصمّمًا
خصيصًا لـ WebView
في تطبيق Android، يمكنك تحديد سلسلة مخصّصة
لوكيل المستخدم باستخدام
setUserAgentString()
، ثم طلب معلومات من وكيل المستخدم المخصّص في صفحة الويب للتحقّق من أنّ العميل
الذي يطلب صفحة الويب هو تطبيق Android.
ربط رمز JavaScript برمز Android
عند تطوير تطبيق ويب مصمّم خصيصًا للصفحة WebView
في تطبيق Android، يمكنك إنشاء واجهات بين رمز JavaScript و
رمز Android من جهة العميل. على سبيل المثال، يمكن لرمز JavaScript استدعاء طريقة في
رمز Android لعرض Dialog
،
بدلاً من استخدام دالة alert()
في JavaScript.
لربط واجهة جديدة بين رمز JavaScript ورمز Android، استخدِم addJavascriptInterface()
، مع تمرير مثيل فئة لربطه برمز JavaScript واسم واجهة يمكن لرمز JavaScript الاتصال به للوصول إلى الفئة.
على سبيل المثال، يمكنك تضمين الفئة التالية في تطبيق Android:
Kotlin
/** Instantiate the interface and set the context. */ class WebAppInterface(private val mContext: Context) { /** Show a toast from the web page. */ @JavascriptInterface fun showToast(toast: String) { Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show() } }
Java
public class WebAppInterface { Context mContext; /** Instantiate the interface and set the context. */ WebAppInterface(Context c) { mContext = c; } /** Show a toast from the web page. */ @JavascriptInterface public void showToast(String toast) { Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show(); } }
في هذا المثال، تسمح فئة WebAppInterface
لصفحة الويب بإنشاء رسالة
Toast
باستخدام الطريقة showToast()
.
يمكنك ربط هذه الفئة برمز JavaScript الذي يتم تشغيله في WebView
باستخدام
addJavascriptInterface()
، كما هو موضّح في المثال التالي:
Kotlin
val webView: WebView = findViewById(R.id.webview) webView.addJavascriptInterface(WebAppInterface(this), "Android")
Java
WebView webView = (WebView) findViewById(R.id.webview); webView.addJavascriptInterface(new WebAppInterface(this), "Android");
يؤدي ذلك إلى إنشاء واجهة تُسمى Android
لبرنامج JavaScript الذي يتم تشغيله في
WebView
. في هذه المرحلة، يمكن لتطبيق الويب الوصول إلى فئة
WebAppInterface
. على سبيل المثال، إليك بعض ترميز HTML وJavaScript الذي ينشئ
رسالة إشعار منبثق باستخدام الواجهة الجديدة عندما ينقر المستخدم على أحد الأزرار:
<input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" /> <script type="text/javascript"> function showAndroidToast(toast) { Android.showToast(toast); } </script>
ما مِن حاجة إلى إعداد واجهة Android
من JavaScript. توفّر علامة
WebView
المحتوى تلقائيًا على صفحة الويب. لذلك، عندما ينقر مستخدم
على الزر، تستخدِم الدالة showAndroidToast()
واجهة Android
لاستدعاء طريقة WebAppInterface.showToast()
.
التعامل مع التنقل في الصفحات
عندما ينقر المستخدم على رابط من صفحة ويب في WebView
، يبدأ Android تلقائيًا في
تشغيل تطبيق يعالج عناوين URL. وعادةً ما يتم فتح متصفّح الويب التلقائي ويحمل عنوان URL الوجهة. ويمكنك إلغاء هذا السلوك في
WebView
ليتم فتح الروابط داخل WebView
. يمكنك بعد ذلك السماح للمستخدم بالتنقّل للأمام والخلف من خلال سجلّ صفحات الويب الذي يحتفظ به WebView
.
لفتح الروابط التي ينقر عليها المستخدم، قدِّم WebViewClient
لWebView
باستخدام
setWebViewClient()
.
يتم تحميل جميع الروابط التي ينقر عليها المستخدم في WebView
. إذا أردت التحكّم بشكل أكبر في مكان تحميل الرابط الذي تم النقر عليه، يمكنك إنشاء WebViewClient
خاصة بك تلغي طريقة
shouldOverrideUrlLoading()
. يفترض المثال التالي أن MyWebViewClient
هي فئة داخلية في Activity
.
Kotlin
private class MyWebViewClient : WebViewClient() { override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean { if (Uri.parse(url).host == "www.example.com") { // This is your website, so don't override. Let your WebView load // the page. return false } // Otherwise, the link isn't for a page on your site, so launch another // Activity that handles URLs. Intent(Intent.ACTION_VIEW, Uri.parse(url)).apply { startActivity(this) } return true } }
Java
private class MyWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { if ("www.example.com".equals(request.getUrl().getHost())) { // This is your website, so don't override. Let your WebView load the // page. return false; } // Otherwise, the link isn't for a page on your site, so launch another // Activity that handles URLs. Intent intent = new Intent(Intent.ACTION_VIEW, request.getUrl()); startActivity(intent); return true; } }
بعد ذلك، أنشئ مثيلًا لهذا WebViewClient
الجديد للWebView
:
Kotlin
val myWebView: WebView = findViewById(R.id.webview) myWebView.webViewClient = MyWebViewClient()
Java
WebView myWebView = (WebView) findViewById(R.id.webview); myWebView.setWebViewClient(new MyWebViewClient());
الآن عندما ينقر المستخدم على رابط، يستدعي النظام الأسلوب
shouldOverrideUrlLoading()
الذي يتحقّق مما إذا كان مضيف عنوان URL يتطابق مع
نطاق معيّن، كما هو محدّد في المثال السابق. وفي حال تطابقهما، تعرِض الوسيطة قيمة خاطئة ولا تلغي تحميل عنوان URL. ويسمح ذلك لعلامة
WebView
بتحميل عنوان URL كالمعتاد. إذا لم يتطابق مضيف عنوان URL، يتم إنشاء
Intent
لتشغيل
Activity
التلقائي لمعالجة عناوين URL، والذي يُحلّ إلى متصفّح الويب التلقائي للمستخدم.
التعامل مع عناوين URL المخصَّصة
WebView
تفرض قيودًا عند طلب الموارد وتحليل الروابط
التي تستخدم مخطّط عنوان URL مخصّصًا. على سبيل المثال، في حال تنفيذ وظائف الاستدعاء مثل
shouldOverrideUrlLoading()
أو
shouldInterceptRequest()
،
لن يستدعي WebView
هذه الدوال إلا لعناوين URL الصالحة.
على سبيل المثال، قد لا يستدعي WebView
طريقة shouldOverrideUrlLoading()
للروابط التالية:
<a href="showProfile">Show Profile</a>
يتم التعامل مع عناوين URL غير الصالحة، مثل العنوان المعروض في المثال السابق،
بشكل غير متّسق في WebView
، لذا ننصحك باستخدام عنوان URL صالح بدلاً من ذلك.
يمكنك استخدام مخطّط مخصّص أو عنوان URL لبروتوكول HTTPS لنطاق تديره مؤسستك.
بدلاً من استخدام سلسلة بسيطة في رابط، كما في المثال السابق، يمكنك استخدام مخطَّط مخصّص مثل ما يلي:
<a href="example-app:showProfile">Show Profile</a>
يمكنك بعد ذلك التعامل مع عنوان URL هذا في طريقة shouldOverrideUrlLoading()
على النحو التالي:
Kotlin
// The URL scheme must be non-hierarchical, meaning no trailing slashes. const val APP_SCHEME = "example-app:" override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean { return if (url?.startsWith(APP_SCHEME) == true) { urlData = URLDecoder.decode(url.substring(APP_SCHEME.length), "UTF-8") respondToData(urlData) true } else { false } }
Java
// The URL scheme must be non-hierarchical, meaning no trailing slashes. private static final String APP_SCHEME = "example-app:"; @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.startsWith(APP_SCHEME)) { urlData = URLDecoder.decode(url.substring(APP_SCHEME.length()), "UTF-8"); respondToData(urlData); return true; } return false; }
تهدف واجهة برمجة التطبيقات shouldOverrideUrlLoading()
في المقام الأول إلى إطلاق النِيّات
لعناوين URL معيّنة. عند تنفيذها، احرص على عرض false
لعناوين URL
المعرّفات WebView
. لا تقتصر على إطلاق النوايا. يمكنك استبدال أغراض الإطلاق بأي سلوك مخصّص في عيّنات التعليمات البرمجية السابقة.
التنقّل في سجلّ صفحات الويب
عندما يلغي WebView
تحميل عنوان URL، يتم تلقائيًا تجميع سجلّ
من صفحات الويب التي تمت زيارتها. يمكنك التنقّل للأمام وللخلف باستخدام
السجلّ باستخدام goBack()
و
goForward()
.
على سبيل المثال، يوضّح ما يلي كيفية استخدام Activity
زر الرجوع
في الجهاز للتنقّل للخلف:
Kotlin
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { // Check whether the key event is the Back button and if there's history. if (keyCode == KeyEvent.KEYCODE_BACK && myWebView.canGoBack()) { myWebView.goBack() return true } // If it isn't the Back button or there isn't web page history, bubble up to // the default system behavior. Probably exit the activity. return super.onKeyDown(keyCode, event) }
Java
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { // Check whether the key event is the Back button and if there's history. if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) { myWebView.goBack(); return true; } // If it isn't the Back button or there's no web page history, bubble up to // the default system behavior. Probably exit the activity. return super.onKeyDown(keyCode, event); }
إذا كان تطبيقك يستخدم الإصدار 1.6.0 من نظام التشغيل AndroidX AppCompat
أو الإصدارات الأحدث، يمكنك تبسيط المقتطف السابق بشكل أكبر:
Kotlin
onBackPressedDispatcher.addCallback { // Check whether there's history. if (myWebView.canGoBack()) { myWebView.goBack() } }
Java
onBackPressedDispatcher.addCallback { // Check whether there's history. if (myWebView.canGoBack()) { myWebView.goBack(); } }
تُعرِض الطريقة canGoBack()
قيمة صحيحة إذا كان هناك سجلّ لصفحات الويب التي زارها المستخدم. وبالمثل، يمكنك استخدام canGoForward()
للتحقّق مما إذا كان هناك سجلّ للرسائل المُرسَلة. في حال عدم إجراء هذا التحقّق، لن يؤديgoBack()
وgoForward()
إلى أي إجراء بعد وصول المستخدم إلى نهاية السجلّ.
التعامل مع التغييرات في إعدادات الجهاز
أثناء التشغيل، تحدث تغييرات في حالة النشاط عند تغيُّر إعدادات الجهاز، مثل عندما يدير المستخدمون الجهاز أو يغلِقون "أداة التعديل الخاصة بطريقة الإدخال" (IME). تؤدي هذه التغييرات إلى إتلاف نشاط كائن WebView
وإنشاء
نشاط جديد، ما يؤدي أيضًا إلى إنشاء كائن WebView
جديد يحمِّل
عنوان URL للكائن الذي تم إتلافه. لتعديل السلوك التلقائي لنشاطك، يمكنك
تغيير طريقة تعامله مع تغييرات orientation
في البيان. لمزيد من المعلومات حول التعامل مع تغييرات الضبط أثناء وقت التشغيل، يمكنك الاطّلاع على تغييرات ضبط الاسم المعرِّف.
إدارة النوافذ
يتم تلقائيًا تجاهل طلبات فتح نوافذ جديدة. وينطبق ذلك سواءً
تم فتحها باستخدام JavaScript أو باستخدام سمة target في الرابط. يمكنك تخصيص
WebChromeClient
لتحديد السلوك الذي تريده عند فتح عدة
نوافذ.
للحفاظ على أمان تطبيقك، من الأفضل منع فتح النوافذ المنبثقة والنوافذ الجديدة. إنّ الطريقة الأكثر أمانًا لتنفيذ هذا السلوك هي تمرير "true"
إلى
setSupportMultipleWindows()
ولكن بدون إلغاء الطريقة
onCreateWindow()
التي تعتمد عليها setSupportMultipleWindows()
. يمنع هذا المنطق تحميل أي صفحة تستخدم target="_blank"
في روابطها.