Vous pouvez fournir à votre application du contenu Web (HTML, JavaScript et CSS, par exemple) que vous pourrez compiler de manière statique dans l'application plutôt que de le récupérer sur Internet.
Le contenu intégré à l'application ne nécessite pas d'accès à Internet et ne consomme pas de bande passante. Si le contenu est conçu spécifiquement pour WebView
, c'est-à-dire qu'il dépend de la communication avec une application native, les utilisateurs ne pourront pas le charger accidentellement dans un navigateur Web.
Cependant, ce type de contenu présente quelques inconvénients. La mise à jour du contenu Web nécessite la livraison d'une nouvelle mise à jour de l'application, et il est possible que le contenu d'un site Web ne corresponde pas au contenu de l'application sur votre appareil si les utilisateurs disposent de versions obsolètes de l'application.
Composant WebViewAssetLoader
WebViewAssetLoader
est un moyen flexible et performant de charger du contenu dans une application dans un objet WebView
. Cette classe prend en charge les éléments suivants:
- Chargement de contenu avec une URL HTTP(S) pour assurer la compatibilité avec la règle d'origine identique.
- Chargement des sous-ressources telles que JavaScript, CSS, images et iFrames
Incluez WebViewAssetLoader
dans le fichier d'activité principal. Voici un exemple de chargement de contenu Web simple à partir du dossier d'éléments:
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)); } }
Votre application doit configurer une instance WebViewAssetLoader
en fonction de ses besoins. La section suivante contient un exemple.
Créer des composants et des ressources intégrés à l'application
WebViewAssetLoader
s'appuie sur des instances PathHandler
pour charger les ressources correspondant à un chemin d'accès à une ressource donné. Bien que vous puissiez implémenter cette interface pour récupérer des ressources selon les besoins de votre application, la bibliothèque Webkit regroupe AssetsPathHandler
et ResourcesPathHandler
pour charger les éléments et les ressources Android, respectivement.
Pour commencer, créez des composants et des ressources pour votre application. En général, les conditions suivantes s'appliquent:
- Les fichiers texte (HTML, JavaScript et CSS, par exemple) appartiennent aux éléments.
- Les images et les autres fichiers binaires appartiennent aux ressources.
Pour ajouter des fichiers Web texte à un projet, procédez comme suit:
- Dans Android Studio, effectuez un clic droit sur le dossier app > src > main, puis sélectionnez New > Directory (Nouveau > Répertoire).
- Nommez le dossier "assets".
- Effectuez un clic droit sur le dossier assets, puis cliquez sur New > File (Nouveau > Fichier).
Saisissez
index.html
, puis appuyez sur la touche Retour ou Entrée. - Répétez l'étape précédente afin de créer un fichier vide pour
stylesheet.css
. - Remplissez les fichiers vides que vous avez créés avec le contenu des deux exemples de code suivants.
```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;
}
```
Pour ajouter un fichier Web basé sur une image à votre projet, procédez comme suit:
Téléchargez le fichier
Android_symbol_green_RGB.png
sur votre ordinateur local.Renommez le fichier
android_robot.png
.Déplacez manuellement le fichier dans le répertoire
main/res/drawable
de votre projet sur votre disque dur.
La figure 4 montre l'image que vous avez ajoutée et le texte des exemples de code précédents affiché dans une application.
Pour terminer l'application, procédez comme suit:
Enregistrez les gestionnaires et configurez le
AssetLoader
en ajoutant le code suivant à la méthodeonCreate()
: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));
Chargez le contenu en ajoutant le code suivant à la méthode
onCreate()
:Kotlin
webView.loadUrl("https://appassets.androidplatform.net/assets/index.html")
Java
mWebView.loadUrl("https://appassets.androidplatform.net/assets/index.html");
Combinez le contenu de l'application avec des ressources de votre site Web
Votre application peut avoir besoin de charger un mélange de contenu intégré et de contenu provenant d'Internet, comme une page HTML intégrée au style CSS de votre site Web.
WebViewAssetLoader
prend en charge ce cas d'utilisation. Si aucune des instances PathHandler
enregistrées ne parvient à trouver une ressource pour le chemin d'accès donné, WebView
se rabat sur le chargement du contenu depuis Internet. Si vous combinez du contenu intégré à l'application avec des ressources de votre site Web, réservez les chemins d'accès au répertoire, tels que /assets/
ou /resources/
, pour les ressources intégrées à l'application. Évitez de stocker les ressources
de votre site Web à ces emplacements.
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);
Consultez la démonstration de WebView
sur GitHub pour voir un exemple de page HTML intégrée à l'application récupérant des données JSON hébergées sur le Web.
loadDataWithBaseURL
Lorsque votre application a uniquement besoin de charger une page HTML et n'a pas besoin d'intercepter des sous-ressources, envisagez d'utiliser loadDataWithBaseURL()
, qui ne nécessite pas de composants d'application. Vous pouvez l'utiliser comme indiqué dans l'exemple de code suivant:
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);
Choisissez les valeurs d'argument avec précaution. Réfléchissez aux points suivants :
baseUrl
: URL sous laquelle votre contenu HTML est chargé. Il doit s'agir d'une URL HTTP(S).data
: contenu HTML que vous souhaitez afficher, sous forme de chaîne.mimeType
: il doit généralement être défini surtext/html
.encoding
: cet élément n'est pas utilisé lorsquebaseUrl
est une URL HTTP(S). Il peut donc être défini surnull
.historyUrl
: défini sur la même valeur quebaseUrl
.
Nous vous recommandons vivement d'utiliser une URL HTTP(S) comme baseUrl
, car cela permet de garantir que votre application respecte les règles concernant les mêmes origines.
Si vous ne trouvez pas de baseUrl
adapté à votre contenu et que vous préférez utiliser loadData()
, vous devez encoder le contenu à l'aide d'un encodage-pourcent ou d'encodage en base64.
Nous vous recommandons vivement de choisir l'encodage Base64 et d'utiliser les API Android pour l'encoder par programmation, comme illustré dans l'exemple de code suivant:
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");
Ce qu'il faut éviter
Il existe plusieurs autres façons de charger du contenu intégré à l'application, mais nous vous recommandons vivement de les utiliser:
- Les URL
file://
etdata:
sont considérées comme des origines opaques, ce qui signifie qu'elles ne peuvent pas bénéficier d'API Web puissantes telles quefetch()
ouXMLHttpRequest
.loadData()
utilise des URLdata:
en interne. Nous vous recommandons donc d'utiliserWebViewAssetLoader
ouloadDataWithBaseURL()
à la place. - Bien que
WebSettings.setAllowFileAccessFromFileURLs()
etWebSettings.setAllowUniversalAccessFromFileURLs()
puissent contourner les problèmes liés aux URLfile://
, nous vous recommandons de ne pas les définir surtrue
, car cela rend votre application vulnérable aux failles basées sur les fichiers. Pour plus de sécurité, nous vous recommandons de les définir explicitement surfalse
pour tous les niveaux d'API. - Pour les mêmes raisons, nous vous déconseillons d'utiliser les URL
file://android_assets/
etfile://android_res/
. Les classesAssetsHandler
etResourcesHandler
sont destinées à être remplacées. - Évitez d'utiliser
MIXED_CONTENT_ALWAYS_ALLOW
. De manière générale, ce paramètre affaiblit la sécurité de votre application. Nous vous recommandons de charger le contenu de votre application sur le même schéma (HTTP ou HTTPS) que les ressources de votre site Web, et d'utiliserMIXED_CONTENT_COMPATIBILITY_MODE
ouMIXED_CONTENT_NEVER_ALLOW
, selon le cas.