ใช้ 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
API ที่ไม่
พร้อมใช้งานสำหรับแพลตฟอร์มเวอร์ชันก่อนหน้าได้
เพิ่มลงในไฟล์ 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 ดังที่แสดงในตัวอย่างต่อไปนี้
<manifest ... > <uses-permission android:name="android.permission.INTERNET" /> ... </manifest>
คุณปรับแต่ง WebView
ได้โดยทำอย่างใดอย่างหนึ่งต่อไปนี้
- เปิดใช้การรองรับโหมดเต็มหน้าจอโดยใช้
WebChromeClient
คลาสนี้จะเรียกใช้เมื่อWebView
ต้องมีสิทธิ์ในการแก้ไข UI ของแอปโฮสต์ เช่น การสร้างหรือปิดหน้าต่าง หรือการส่งกล่องโต้ตอบ JavaScript ไปยัง ผู้ใช้ อ่านข้อมูลเพิ่มเติมเกี่ยวกับการแก้ไขข้อบกพร่องในบริบทนี้ได้ที่แก้ไขข้อบกพร่องของเว็บแอป - การจัดการเหตุการณ์ที่มีผลต่อการแสดงเนื้อหา เช่น ข้อผิดพลาดในการส่งแบบฟอร์มหรือการนำทางโดยใช้
WebViewClient
คุณยังใช้คลาสย่อยนี้เพื่อสกัดกั้นการโหลด URL ได้ด้วย - การเปิดใช้ JavaScript โดยการแก้ไข
WebSettings
- การใช้ JavaScript เพื่อเข้าถึงออบเจ็กต์เฟรมเวิร์ก Android ที่คุณแทรกลงใน
WebView
ใช้ JavaScript ใน WebView
หากหน้าเว็บที่ต้องการโหลดใน WebView
ใช้ JavaScript คุณต้อง
เปิดใช้ JavaScript สำหรับ WebView
หลังจากเปิดใช้ JavaScript แล้ว คุณจะ
สร้างอินเทอร์เฟซระหว่างโค้ดแอปกับโค้ด JavaScript ได้
เปิดใช้งาน JavaScript
WebView
จะปิดใช้ JavaScript โดยค่าเริ่มต้น คุณเปิดใช้ได้ผ่าน
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 โดยเฉพาะ คุณก็กําหนดสตริง User Agent ที่กําหนดเองด้วย
setUserAgentString()
จากนั้นค้นหาสตริง User Agent ที่กําหนดเองในหน้าเว็บเพื่อยืนยันว่าไคลเอ็นต์ที่
ขอหน้าเว็บของคุณคือแอป 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 ที่ไม่ถูกต้อง เช่น 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()
API มีไว้สำหรับการเปิดใช้ Intent
สำหรับ URL ที่เฉพาะเจาะจงเป็นหลัก เมื่อใช้งาน API นี้ โปรดตรวจสอบว่าได้ส่งคืน false
สำหรับ URL
ที่ WebView
จัดการ แต่คุณไม่ได้จำกัดอยู่แค่การเปิดใช้ Intent คุณสามารถ
แทนที่ความตั้งใจในการเปิดตัวด้วยลักษณะการทำงานที่กำหนดเองในตัวอย่างโค้ดก่อนหน้า
ได้
ไปยังประวัติหน้าเว็บ
เมื่อ 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
ในไฟล์ Manifest ดูข้อมูลเพิ่มเติม
เกี่ยวกับการจัดการการเปลี่ยนแปลงการกำหนดค่าในระหว่างรันไทม์ได้ที่จัดการการเปลี่ยนแปลง
การกำหนดค่า
จัดการหน้าต่าง
โดยค่าเริ่มต้น ระบบจะละเว้นคำขอเปิดหน้าต่างใหม่ ไม่ว่าหน้าต่างจะเปิดโดย JavaScript หรือโดยแอตทริบิวต์เป้าหมายในลิงก์ คุณปรับแต่ง WebChromeClient
เพื่อกำหนดลักษณะการทำงานของตัวเองสำหรับการเปิดหลายหน้าต่างได้
เพื่อรักษาความปลอดภัยของแอปให้ดียิ่งขึ้น คุณควรป้องกันไม่ให้ป๊อปอัปและหน้าต่างใหม่เปิดขึ้น
วิธีที่ปลอดภัยที่สุดในการใช้ลักษณะการทำงานนี้คือการส่ง "true"
ไปยัง
setSupportMultipleWindows()
แต่ไม่ลบล้างเมธอด
onCreateWindow()
ซึ่ง setSupportMultipleWindows()
ขึ้นอยู่กับ ตรรกะนี้จะป้องกันไม่ให้หน้าเว็บที่ใช้ target="_blank"
ในลิงก์โหลด