استخدِم 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. يتيح هذا الإجراء
لـ 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); }
إذا كان التطبيق يستخدم الإصدار AndroidX AppCompat
1.6.0 أو الإصدارات الأحدث، يمكنك تبسيط المقتطف السابق أكثر من ذلك:
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"
في روابطها.