บทนำ
ตัวอย่างนี้สาธิตการใช้ 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"
}