Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Android

วิธีฟังเหตุการณ์ WebView โหลดเสร็จ URL ใน Android Kotlin

บทนำ

ตัวอย่างนี้สาธิตการใช้ WebViewClient และ WebChromeClient เพื่อติดตามสถานะการโหลดหน้าเว็บใน WebView

ขั้นตอนที่ 1: สร้างโปรเจกต์

สร้างโปรเจกต์ Android ใหม่ใน Android Studio

ขั้นตอนที่ 2: Layout (activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="4dp"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="5dp"
        android:textColor="#000000"
        android:textSize="16sp"
        android:text="Loading status..." />

    <WebView
        android:id="@+id/webView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@id/btnLoad"
        android:layout_below="@id/textView" />

    <Button
        android:id="@+id/btnLoad"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="16dp"
        android:text="Load URL" />
</RelativeLayout>

ขั้นตอนที่ 3: MainActivity.kt

import android.os.Bundle
import android.webkit.WebChromeClient
import android.webkit.WebView
import android.webkit.WebViewClient
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {
    private lateinit var webView: WebView
    private lateinit var textView: TextView
    private lateinit var btnLoad: Button

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        title = "WebView Loading Demo"

        textView = findViewById(R.id.textView)
        btnLoad = findViewById(R.id.btnLoad)
        webView = findViewById(R.id.webView)

        // เปิดใช้งาน JavaScript
        webView.settings.javaScriptEnabled = true
        webView.settings.domStorageEnabled = true
        webView.settings.setSupportZoom(true)
        webView.settings.builtInZoomControls = true
        webView.settings.displayZoomControls = false

        // WebViewClient - จัดการ Navigation และ Loading
        webView.webViewClient = object : WebViewClient() {
            override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
                view.loadUrl(url)
                return true
            }

            override fun onPageStarted(view: WebView?, url: String?, favicon: android.graphics.Bitmap?) {
                super.onPageStarted(view, url, favicon)
                textView.text = "Loading: $url..."
            }

            override fun onPageFinished(view: WebView?, url: String?) {
                super.onPageFinished(view, url)
                textView.text = "Page Loaded: $url"
                Toast.makeText(this@MainActivity, "WebView Loaded Successfully!", Toast.LENGTH_SHORT).show()
            }

            override fun onReceivedError(view: WebView?, request: android.webkit.WebResourceRequest?, error: android.webkit.WebResourceError?) {
                super.onReceivedError(view, request, error)
                textView.text = "Error: ${error?.description}"
                Toast.makeText(this@MainActivity, "Loading Failed: ${error?.description}", Toast.LENGTH_LONG).show()
            }
        }

        // WebChromeClient - จัดการ UI Progress, Title, Favicon
        webView.webChromeClient = object : WebChromeClient() {
            override fun onProgressChanged(view: WebView?, newProgress: Int) {
                super.onProgressChanged(view, newProgress)
                textView.text = "Loading: $newProgress%"
                if (newProgress == 100) {
                    textView.text = "Page Loaded (100%)"
                }
            }

            override fun onReceivedTitle(view: WebView?, title: String?) {
                super.onReceivedTitle(view, title)
                // this@MainActivity.title = title ?: "WebView"
            }

            override fun onReceivedIcon(view: WebView?, icon: android.graphics.Bitmap?) {
                super.onReceivedIcon(view, icon)
                // ใช้เป็น Favicon ได้
            }
        }

        btnLoad.setOnClickListener {
            webView.loadUrl("https://www.tutorialspoint.com")
        }
    }

    // จัดการ Back Button ให้ย้อนกลับใน WebView
    override fun onBackPressed() {
        if (webView.canGoBack()) {
            webView.goBack()
        } else {
            super.onBackPressed()
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        webView.destroy() // ป้องกัน Memory Leak
    }
}

ขั้นตอนที่ 4: Manifest (ต้องมี Internet Permission)

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
    package="com.example.webviewdemo">
    <uses-permission android:name="android.permission.INTERNET" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

WebViewClient vs WebChromeClient

Classหน้าที่หลัก
WebViewClientจัดการการโหลดเนื้อหา: onPageStarted, onPageFinished, shouldOverrideUrlLoading, onReceivedError, onReceivedHttpError
WebChromeClientจัดการ UI Chrome: onProgressChanged, onReceivedTitle, onReceivedIcon, onCreateWindow, onJsAlert, onConsoleMessage

Best Practices สำหรับ WebView

  • JavaScript Interface ใช้ addJavascriptInterface() สำหรับสื่อสาร Native ↔ Web (ระวัง Security)
  • Mixed Content Android 9+ บล็อก HTTP ใน HTTPS ใช้ webView.settings.mixedContentMode = WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE
  • Cache ตั้งค่า Cache Mode ตามต้องการ
  • User Agent ปรับแต่งได้ด้วย webView.settings.userAgentString
  • Safe Browsing เปิดใช้ด้วย WebView.setSafeBrowsingEnabled(true)

โค้ดเต็มรูปแบบพร้อม Progress Bar

<ProgressBar
    android:id="@+id/progressBar"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="match_parent"
    android:layout_height="4dp"
    android:layout_below="@id/textView"
    android:max="100"
    android:progress="0"
    android:visibility="gone" />

// ใน WebChromeClient
override fun onProgressChanged(view: WebView?, newProgress: Int) {
    progressBar.progress = newProgress
    progressBar.visibility = if (newProgress < 100) View.VISIBLE else View.GONE
    if (newProgress == 100) textView.text = "Done"
}