إنشاء تطبيقات ويب في WebView

استخدام 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")
}

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.
  • تمكين جافا سكريبت عن طريق تعديل 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" للجهاز Back زر للانتقال للخلف:

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" في الروابط الخاصة بها من التحميل.