استخدِم 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. هذه مكتبة ثابتة يمكنك إضافتها إلى تطبيقك لاستخدام واجهات برمجة تطبيقات 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. ويسمح لعنوان 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 أو من خلال السمة المستهدفة في رابط. يمكنك تخصيص
WebChromeClient
لتقديم سلوكك الخاص عند فتح نوافذ
متعددة.
للحفاظ على أمان تطبيقك، يُفضَّل منع فتح النوافذ المنبثقة والنوافذ الجديدة. والطريقة الأكثر أمانًا لتنفيذ هذا السلوك هي تمرير "true"
إلى
setSupportMultipleWindows()
بدون تجاوز الطريقة
onCreateWindow()
التي تعتمد عليها setSupportMultipleWindows()
. يمنع هذا المنطق تحميل أي صفحة تستخدم target="_blank"
في روابطها.