תוכל לספק תוכן מבוסס-אינטרנט כמו HTML, JavaScript CSS — כדי שהאפליקציה תשתמש באיסוף סטטי לתוך האפליקציה, מאשר לאחזר את האינטרנט.
תוכן מתוך האפליקציה לא דורש גישה לאינטרנט או צורך רוחב פס של המשתמש. אם המיקום
שהתוכן מיועד במיוחד ל-WebView
, כלומר
תלויה בתקשורת עם אפליקציית נייטיב, אז המשתמשים לא יוכלו
לטעון אותו בדפדפן אינטרנט.
עם זאת, יש כמה חסרונות לתוכן בתוך האפליקציה. עדכון תוכן מבוסס-אינטרנט צריך לשלוח עדכון חדש לאפליקציה, ויכול להיות שיש אי-התאמות בין התוכן שבאתר לבין מה שמופיע באפליקציה במכשיר, אם למשתמשים יש גרסאות מיושנות של האפליקציה.
WebViewAssetLoader
WebViewAssetLoader
הוא
בדרך גמישה ומתקדמת לטעינה של תוכן בתוך האפליקציה
אובייקט WebView
. הכיתה הזו תומכת
הבאים:
- טעינת תוכן עם כתובת URL מסוג HTTP(S) לצורך תאימות עם Same-origin .
- טעינת משאבי משנה כמו JavaScript , CSS, תמונות ו-iframes.
כוללים את 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, לוחצים לחיצה ימנית על האפליקציה > מקור > התיקייה הראשית ולאחר מכן בוחרים New > (חדש >) Google Directory.
- נותנים לתיקייה את השם 'נכסים'.
- לוחצים לחיצה ימנית על התיקייה נכסים ואז לוחצים על חדש > קובץ.
מזינים
index.html
ומקישים על Return או על מקש Enter. - חוזרים על השלב הקודם כדי ליצור קובץ ריק עבור
stylesheet.css
- ממלאים את הקבצים הריקים שיצרתם עם התוכן בשני הקודים הבאים דוגמאות.
```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 מציג את התמונה שהוספת והטקסט מדוגמאות הקוד הקודמות מעובד באפליקציה.
כדי להשלים את האפליקציה:
רושמים את ה-handlers ומגדירים את
AssetLoader
באמצעות הוספת את הקוד הבא ל-methodonCreate()
: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));
כדי לטעון את התוכן, מוסיפים את הקוד הבא ל-method
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 שלך נטען. זו חייבת להיות כתובת ה-URL של HTTP(S).data
: זהו תוכן ה-HTML שרוצים להציג כמחרוזת.mimeType
: בדרך כלל צריך להגדיר את הערךtext/html
.encoding
: לא נעשה שימוש בהרשאה הזו כאשרbaseUrl
היא כתובת URL מסוג HTTP(S), ולכן היא יכולה להיות מוגדר ל-null
.historyUrl
: מוגדר לערך זהה ל-baseUrl
.
מומלץ מאוד להשתמש בכתובת URL מסוג HTTP(S) בתור baseUrl
, כי זה עוזר
צריך לוודא שהאפליקציה תואמת למדיניות המקור הזהה.
אם לא מצאת baseUrl
מתאים לתוכן שלך וברצונך להשתמש בו
loadData()
,
צריך לקודד את התוכן באמצעות
קידוד באחוזים
או
Base64
בקידוד.
מומלץ מאוד לבחור בקידוד Base64 ולהשתמש בממשקי API של Android לקידוד
זאת באופן פרוגרמטי, כפי שמוצג בדוגמת הקוד הבאה:
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://
וכתובות URL מסוגdata:
נחשבות למקורות אטומים, כלומר, הם לא יכולים לנצל ממשקי API חזקים לאינטרנט,fetch()
אוXMLHttpRequest
. מערכתloadData()
משתמשת ב-data:
כתובות URL באופן פנימי, לכן אנחנו ממליצים להשתמשWebViewAssetLoader
אוloadDataWithBaseURL()
במקום זאת. - למרות
WebSettings.setAllowFileAccessFromFileURLs()
וגםWebSettings.setAllowUniversalAccessFromFileURLs()
יכול לעקוף את הבעיות הקשורות ל-file://
כתובות URL, מומלץ לא להגדיר את ההתראות האלה אלtrue
כי האפליקציה שלך חשופה לפרצת אבטחה שמנצלות לרעה. מומלץ להגדיר במפורש את הערכים האלה כ-false
בכל רמות ה-API כדי לקבל את האבטחה החזקה ביותר. - מאותן סיבות, אנחנו ממליצים להימנע מ
file://android_assets/
וגםfile://android_res/
כתובות URL.AssetsHandler
וResourcesHandler
כיתות אלה נועדו לשמש כהחלפות. - עדיף להימנע משימוש
MIXED_CONTENT_ALWAYS_ALLOW
בדרך כלל ההגדרה הזו לא נחוצה והיא פוגעת באבטחת האפליקציה. אנחנו ממליצים לטעון את התוכן באפליקציה באותה סכמה – HTTP או HTTPS – כמשאבי האתר שלכם ולהשתמש בוMIXED_CONTENT_COMPATIBILITY_MODE
אוMIXED_CONTENT_NEVER_ALLOW
, לפי הצורך.