استخدِم WebView
لعرض تطبيق ويب أو صفحة ويب كجزء من تطبيق عميل. فئة WebView
هي إضافة لفئة View
في Android تتيح لك عرض صفحات الويب كجزء من تصميم نشاطك. ولا يتضمّن ميزات متصفّح الويب المتكامل، مثل عناصر التحكّم في التنقّل أو شريط العناوين. كل ما يفعله WebView
تلقائيًا هو عرض صفحة ويب.
يمكن أن تساعدك WebView
في توفير معلومات في تطبيقك قد تحتاج إلى تعديلها، مثل اتفاقية المستخدم النهائي أو دليل المستخدم. يمكنك إنشاء Activity
يتضمّن WebView
داخل تطبيق Android، ثم استخدامه لعرض المستند المستضاف على الإنترنت.
يمكن أن يساعد WebView
أيضًا عندما يوفّر تطبيقك للمستخدم بيانات تتطلّب الاتصال بالإنترنت لاستردادها، مثل البريد الإلكتروني. في هذه الحالة، قد تجد أنّه من الأسهل إنشاء WebView
في تطبيق Android يعرض صفحة ويب تتضمّن جميع بيانات المستخدم، بدلاً من تنفيذ طلب شبكة، ثم تحليل البيانات وعرضها في تصميم Android. يمكنك بدلاً من ذلك تصميم صفحة ويب مخصّصة للأجهزة التي تعمل بنظام التشغيل Android، ثم تنفيذ WebView
في تطبيق Android لتحميل صفحة الويب.
يوضّح هذا المستند كيفية بدء استخدام WebView
، وكيفية ربط JavaScript من صفحة الويب بالرمز البرمجي من جهة العميل في تطبيق Android، وكيفية التعامل مع التنقّل بين الصفحات، وكيفية إدارة النوافذ عند استخدام WebView
.
استخدام WebView على إصدارات Android السابقة
لاستخدام إمكانات WebView
الأحدث بأمان على الجهاز الذي يتم تشغيل تطبيقك عليه، أضِف مكتبة AndroidX
Webkit. هذه مكتبة ثابتة يمكنك إضافتها إلى تطبيقك لاستخدام واجهات برمجة التطبيقات android.webkit
غير المتاحة لإصدارات النظام الأساسي السابقة.
أضِفها إلى ملف build.gradle
على النحو التالي:
Kotlin
dependencies { implementation("androidx.webkit:webkit:1.8.0") }
Groovy
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 يتطابق مع
نطاق معيّن، كما هو موضّح في المثال السابق. وفي حال تطابُقها، تعرض الطريقة القيمة "false" ولا تتجاهل عملية تحميل عنوان 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"
في روابطها.