คุณสามารถให้เนื้อหาบนเว็บ เช่น HTML, JavaScript และ CSS - เพื่อให้แอปใช้งานได้ คุณจะทำการคอมไพล์ลงในแอปแบบคงที่แทน ในการเข้าถึงอินเทอร์เน็ต
เนื้อหาในแอปไม่จำเป็นต้องเชื่อมต่ออินเทอร์เน็ตหรือเปลืองแบนด์วิดท์ของผู้ใช้ ถ้า
เนื้อหานี้ออกแบบมาสำหรับ WebView
เท่านั้น กล่าวคือ
ขึ้นอยู่กับการสื่อสารกับแอปที่มาพร้อมเครื่อง ผู้ใช้
โหลดในเว็บเบราว์เซอร์
แต่เนื้อหาในแอปมีข้อเสียบางอย่าง การอัปเดตเนื้อหาบนเว็บ ต้องมีการจัดส่งอัปเดตแอปใหม่ และเป็นไปได้ว่าข้อมูลไม่ตรงกัน เนื้อหาระหว่างสิ่งที่อยู่บนเว็บไซต์กับสิ่งที่อยู่ในแอปพลิเคชันบนอุปกรณ์ของคุณ ผู้ใช้มีแอปเวอร์ชันเก่า
WebViewAssetLoader
WebViewAssetLoader
เป็น
วิธีการที่ยืดหยุ่นและมีประสิทธิภาพในการโหลดเนื้อหาในแอป
ออบเจ็กต์ WebView
คลาสนี้สนับสนุน
ดังต่อไปนี้:
- การโหลดเนื้อหาด้วย URL ของ HTTP(S) เพื่อให้เข้ากันได้กับต้นทางเดียวกัน
- กำลังโหลดทรัพยากรย่อย เช่น JavaScript, CSS, รูปภาพ และ iframe
รวม WebViewAssetLoader
ในไฟล์กิจกรรมหลัก ต่อไปนี้เป็น
ตัวอย่างการโหลดเนื้อหาเว็บแบบง่ายจากโฟลเดอร์เนื้อหา
Kotlin
private class LocalContentWebViewClient(private val assetLoader: WebViewAssetLoader) : WebViewClientCompat() { @RequiresApi(21) override fun shouldInterceptRequest( view: WebView, request: WebResourceRequest ): WebResourceResponse? { return assetLoader.shouldInterceptRequest(request.url) } // To support API < 21. override fun shouldInterceptRequest( view: WebView, url: String ): WebResourceResponse? { return assetLoader.shouldInterceptRequest(Uri.parse(url)) } }
Java
private static class LocalContentWebViewClient extends WebViewClientCompat { private final WebViewAssetLoader mAssetLoader; LocalContentWebViewClient(WebViewAssetLoader assetLoader) { mAssetLoader = assetLoader; } @Override @RequiresApi(21) public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { return mAssetLoader.shouldInterceptRequest(request.getUrl()); } @Override @SuppressWarnings("deprecation") // To support API < 21. public WebResourceResponse shouldInterceptRequest(WebView view, String url) { return mAssetLoader.shouldInterceptRequest(Uri.parse(url)); } }
แอปของคุณต้องกำหนดค่าอินสแตนซ์ WebViewAssetLoader
ให้เหมาะกับความต้องการ
ส่วนถัดไปจะมีตัวอย่าง
สร้างทรัพยากรและชิ้นงานในแอป
WebViewAssetLoader
อาศัย
PathHandler
อินสแตนซ์เพื่อโหลดทรัพยากรที่สอดคล้องกับเส้นทางทรัพยากรที่ระบุ แม้ว่าคุณ
สามารถใช้อินเทอร์เฟซนี้เพื่อดึงข้อมูลทรัพยากรตามที่แอปของคุณต้องการ
แพ็กเกจคลัง Webkit
AssetsPathHandler
และ
ResourcesPathHandler
สำหรับการโหลดเนื้อหาและทรัพยากรของ Android ตามลำดับ
ในการเริ่มต้นใช้งาน ให้สร้างชิ้นงานและทรัพยากรสำหรับแอป โดยทั่วไป การตั้งค่า ดังต่อไปนี้
- ไฟล์ข้อความ เช่น HTML, JavaScript และ CSS จะอยู่ในเนื้อหา
- รูปภาพและไฟล์ไบนารีอื่นๆ จะอยู่ในทรัพยากร
หากต้องการเพิ่มไฟล์เว็บแบบข้อความลงในโครงการ ให้ทำตามขั้นตอนต่อไปนี้
- ใน Android Studio ให้คลิกขวาที่แอป > src > โฟลเดอร์หลัก จากนั้นเลือกใหม่ > ไดเรกทอรี
- ตั้งชื่อโฟลเดอร์ว่า "assets"
- คลิกขวาที่โฟลเดอร์ assets แล้วคลิกใหม่ > ไฟล์
ป้อน
index.html
และกด Return หรือ ปุ่ม Enter - ทำซ้ำขั้นตอนก่อนหน้าเพื่อสร้างไฟล์ว่างสำหรับ
stylesheet.css
- ใส่ไฟล์เปล่าที่คุณสร้างด้วยเนื้อหาในโค้ด 2 โค้ดถัดไป ตัวอย่าง
```html
<!-- index.html content -->
<html>
<head>
<!-- Tip: Use relative URLs when referring to other in-app content to give
your app code the flexibility to change the scheme or domain as
necessary. -->
<link rel="stylesheet" href="/assets/stylesheet.css">
</head>
<body>
<p>This file is loaded from in-app content.</p>
<p><img src="/res/drawable/android_robot.png" alt="Android robot" width="100"></p>
</body>
</html>
```
```css
<!-- stylesheet.css content -->
body {
background-color: lightblue;
}
```
หากต้องการเพิ่มไฟล์เว็บที่เป็นรูปภาพลงในโครงการ ให้ทำตามขั้นตอนต่อไปนี้
ดาวน์โหลด
Android_symbol_green_RGB.png
ไปยังเครื่องภายในของคุณเปลี่ยนชื่อไฟล์เป็น
android_robot.png
ย้ายไฟล์ไปยังไดเรกทอรี
main/res/drawable
ของโปรเจ็กต์ด้วยตนเองใน ฮาร์ดไดรฟ์ของคุณ
รูปที่ 4 แสดงรูปภาพที่คุณเพิ่มและข้อความจากตัวอย่างโค้ดก่อนหน้า ที่แสดงในแอป
ในการทำให้แอปเสร็จสมบูรณ์ ให้ทำตามขั้นตอนต่อไปนี้
ลงทะเบียนเครื่องจัดการและกำหนดค่า
AssetLoader
ด้วยการเพิ่ม โค้ดต่อไปนี้ไปยังเมธอดonCreate()
:Kotlin
val assetLoader = WebViewAssetLoader.Builder() .addPathHandler("/assets/", AssetsPathHandler(this)) .addPathHandler("/res/", ResourcesPathHandler(this)) .build() webView.webViewClient = LocalContentWebViewClient(assetLoader)
Java
final WebViewAssetLoader assetLoader = new WebViewAssetLoader.Builder() .addPathHandler("/assets/", new WebViewAssetLoader.AssetsPathHandler(this)) .addPathHandler("/res/", new WebViewAssetLoader.ResourcesPathHandler(this)) .build(); mWebView.setWebViewClient(new LocalContentWebViewClient(assetLoader));
โหลดเนื้อหาโดยการเพิ่มโค้ดต่อไปนี้ลงในเมธอด
onCreate()
Kotlin
webView.loadUrl("https://appassets.androidplatform.net/assets/index.html")
Java
mWebView.loadUrl("https://appassets.androidplatform.net/assets/index.html");
เพิ่มเนื้อหาในแอปเข้ากับแหล่งข้อมูลจากเว็บไซต์ของคุณ
แอปของคุณอาจต้องโหลดเนื้อหาในแอปและเนื้อหาจาก
เช่น หน้า HTML ในแอปที่จัดรูปแบบโดย CSS ของเว็บไซต์
WebViewAssetLoader
รองรับกรณีการใช้งานนี้ หากไม่มีโดเมนที่จดทะเบียน
อินสแตนซ์ PathHandler
รายการค้นหาทรัพยากรสำหรับเส้นทางที่ระบุได้ WebView
จะตก
กลับไปโหลดเนื้อหาจากอินเทอร์เน็ต หากคุณผสมเนื้อหาในแอปกับ
ทรัพยากรจากเว็บไซต์ จองเส้นทางไดเรกทอรี เช่น /assets/
หรือ
/resources/
สำหรับทรัพยากรในแอป หลีกเลี่ยงการจัดเก็บทรัพยากรใดๆ จาก
เว็บไซต์ในประเทศเหล่านั้น
Kotlin
val assetLoader = WebViewAssetLoader.Builder() .setDomain("example.com") // Replace this with your website's domain. .addPathHandler("/assets/", AssetsPathHandler(this)) .build() webView.webViewClient = LocalContentWebViewClient(assetLoader) val inAppHtmlUrl = "https://example.com/assets/index.html" webView.loadUrl(inAppHtmlUrl) val websiteUrl = "https://example.com/website/data.json" // JavaScript code to fetch() content from the same origin. val jsCode = "fetch('$websiteUrl')" + ".then(resp => resp.json())" + ".then(data => console.log(data));" webView.evaluateJavascript(jsCode, null)
Java
final WebViewAssetLoader assetLoader = new WebViewAssetLoader.Builder() .setDomain("example.com") // Replace this with your website's domain. .addPathHandler("/assets/", new AssetsPathHandler(this)) .build(); mWebView.setWebViewClient(new LocalContentWebViewClient(assetLoader)); String inAppHtmlUrl = "https://example.com/assets/index.html"; mWebView.loadUrl(inAppHtmlUrl); String websiteUrl = "https://example.com/website/data.json"; // JavaScript code to fetch() content from the same origin. String jsCode = "fetch('" + websiteUrl + "')" + ".then(resp => resp.json())" + ".then(data => console.log(data));"; mWebView.evaluateJavascript(jsCode, null);
ดูการสาธิต WebView
เกี่ยวกับ
GitHub
เพื่อดูตัวอย่างหน้า HTML ในแอปที่ดึงข้อมูล JSON ที่โฮสต์บนเว็บ
loadDataWithBaseURL
เมื่อแอปของคุณต้องการโหลดหน้า HTML เท่านั้นและไม่จําเป็นต้องสกัดกั้น
ทรัพยากรย่อย ให้พิจารณาใช้
loadDataWithBaseURL()
ซึ่งไม่ต้องใช้ชิ้นงานแอป คุณสามารถใช้งานบัญชีได้ดังที่แสดงในรหัสต่อไปนี้
ตัวอย่าง:
Kotlin
val html = "<html><body><p>Hello world</p></body></html>" val baseUrl = "https://example.com/" webView.loadDataWithBaseURL(baseUrl, html, "text/html", null, baseUrl)
Java
String html = "<html><body><p>Hello world</p></body></html>"; String baseUrl = "https://example.com/"; mWebView.loadDataWithBaseURL(baseUrl, html, "text/html", null, baseUrl);
เลือกค่าอาร์กิวเมนต์อย่างรอบคอบ ลองพิจารณาสิ่งเหล่านี้
baseUrl
: นี่คือ URL ที่โหลดเนื้อหา HTML ของคุณ ค่านี้ต้องเป็น HTTP(S) URLdata
: นี่คือเนื้อหา HTML ที่คุณต้องการแสดงเป็นสตริงmimeType
: โดยปกติต้องตั้งค่าเป็นtext/html
encoding
: ไม่มีการใช้เมื่อbaseUrl
เป็น URL แบบ HTTP(S) ดังนั้นจึงอาจ ตั้งค่าเป็นnull
historyUrl
: ตั้งค่าเป็นค่าเดียวกับbaseUrl
เราขอแนะนำให้ใช้ URL แบบ HTTP(S) เป็น baseUrl
เพราะจะช่วยได้
ตรวจสอบว่าแอปเป็นไปตามนโยบายต้นทางเดียวกัน
หากไม่พบ baseUrl
ที่เหมาะกับเนื้อหาและต้องการใช้
loadData()
,
คุณต้องเข้ารหัสเนื้อหาด้วย
การเข้ารหัสเปอร์เซ็นต์
หรือ
พื้นฐาน 64
การเข้ารหัส
เราขอแนะนำอย่างยิ่งให้เลือกการเข้ารหัส Base64 และใช้ Android API ในการเข้ารหัส
นี้โดยอัตโนมัติ ดังที่แสดงในตัวอย่างโค้ดต่อไปนี้
Kotlin
val encodedHtml: String = Base64.encodeToString(html.toByteArray(), Base64.NO_PADDING) webView.loadData(encodedHtml, mimeType, "base64")
Java
String encodedHtml = Base64.encodeToString(html.getBytes(), Base64.NO_PADDING); mWebView.loadData(encodedHtml, mimeType, "base64");
สิ่งที่ควรหลีกเลี่ยง
มีวิธีอื่นๆ อีกหลายวิธีในการโหลดเนื้อหาในแอป แต่เราขอแนะนำอย่างยิ่ง เทียบกับคำนั้น:
- URL
file://
รายการและ URLdata:
รายการถือเป็นต้นทางที่ไม่ชัดเจน ซึ่งหมายความว่าพวกเขาก็จะไม่สามารถใช้ประโยชน์จาก Web API ที่มีประสิทธิภาพอย่างเช่นfetch()
หรือXMLHttpRequest
loadData()
ใช้ URLdata:
รายการเป็นการภายใน เราจึงแนะนำให้ใช้WebViewAssetLoader
หรือloadDataWithBaseURL()
แทน - แม้ว่า
WebSettings.setAllowFileAccessFromFileURLs()
และWebSettings.setAllowUniversalAccessFromFileURLs()
ช่วยแก้ปัญหาเกี่ยวกับ URL ของfile://
ได้ เราขอแนะนำให้ไม่ต้องตั้งค่า ไปยังtrue
เนื่องจากจะทำให้แอปมีความเสี่ยงต่อไฟล์ การเจาะช่องโหว่ เราขอแนะนำให้ตั้งค่าเหล่านี้เป็นfalse
อย่างชัดเจนใน API ทุกระดับ เพื่อการรักษาความปลอดภัยที่เข้มงวดที่สุด - ด้วยเหตุผลเดียวกันนี้ เราขอแนะนำให้ใช้
file://android_assets/
และ URLfile://android_res/
รายการAssetsHandler
และResourcesHandler
ชั้นเรียนจะใช้แทนแบบดร็อปอิน - หลีกเลี่ยงการใช้
MIXED_CONTENT_ALWAYS_ALLOW
การตั้งค่านี้มักไม่ใช่สิ่งจำเป็นและทำให้ความปลอดภัยของแอปอ่อนแอลง เราขอแนะนำให้โหลดเนื้อหาในแอปผ่านรูปแบบเดียวกัน ไม่ว่าจะเป็น HTTP หรือ HTTPS เป็นทรัพยากรของเว็บไซต์และการใช้MIXED_CONTENT_COMPATIBILITY_MODE
หรือMIXED_CONTENT_NEVER_ALLOW
, ตามความเหมาะสม