Puedes proporcionar contenido basado en la Web, como HTML, JavaScript y CSS, para que tu app lo use y lo compiles estáticamente en la app que la recuperación a través de Internet.
El contenido integrado en la app no requiere acceso a Internet ni consume el ancho de banda del usuario. Si
el contenido está diseñado específicamente para WebView
, es decir,
depende de la comunicación con una aplicación nativa; los usuarios no podrán
cargarlo en un navegador web.
Sin embargo, existen algunas desventajas en el contenido integrado en la app. Cómo actualizar el contenido basado en la Web el envío de una nueva actualización de la app, y existe la posibilidad de que no contenido entre lo que hay en un sitio web y lo que hay en la app en tu dispositivo si usuarios tienen versiones desactualizadas de la app.
WebViewAssetLoader
WebViewAssetLoader
es un
es una forma flexible y eficaz de cargar contenido integrado en la app
objeto WebView
. Esta clase admite el
lo siguiente:
- Carga de contenido con una URL HTTP(S) para verificar la compatibilidad con el mismo origen política.
- Carga de subrecursos como JavaScript, CSS, imágenes o iframes.
Incluye WebViewAssetLoader
en tu archivo de actividad principal. A continuación, se muestra un
Ejemplo de carga de contenido web sencillo desde la carpeta de elementos:
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)); } }
Tu app debe configurar una instancia de WebViewAssetLoader
para satisfacer sus necesidades. El
la siguiente sección tiene un ejemplo.
Crea recursos y recursos integrados en la app
WebViewAssetLoader
se basa en
PathHandler
las instancias para cargar los recursos correspondientes a una ruta de recurso determinada. Aunque tú
implementar esta interfaz para recuperar recursos según lo necesite tu app,
Paquetes de la biblioteca de Webkit
AssetsPathHandler
y
ResourcesPathHandler
para cargar recursos y recursos de Android, respectivamente.
Para comenzar, crea elementos y recursos para tu app. En general, el se aplica lo siguiente:
- Los archivos de texto, como HTML, JavaScript y CSS, pertenecen a los recursos.
- Las imágenes y otros archivos binarios pertenecen a los recursos.
Para agregar archivos web basados en texto a un proyecto, haz lo siguiente:
- En Android Studio, haz clic con el botón derecho en la app > src > carpeta principal y, luego, selecciona Nuevo > Directory.
- Asigna el nombre "assets" a la carpeta.
- Haz clic con el botón derecho en la carpeta assets y, luego, haz clic en New > Archivo.
Ingresa
index.html
y presiona Return o Tecla Intro. - Repite el paso anterior para crear un archivo vacío para
stylesheet.css
- Completa los archivos vacíos que creaste con el contenido en los siguientes dos códigos de muestra.
```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;
}
```
Para agregar un archivo web basado en imágenes a tu proyecto, haz lo siguiente:
Descarga el
Android_symbol_green_RGB.png
en tu máquina local.Cambia el nombre del archivo a
android_robot.png
.Mueve el archivo de forma manual al directorio
main/res/drawable
de tu proyecto en tu disco duro.
En la Figura 4, se muestran la imagen que agregaste y el texto de las muestras de código anteriores renderizado en una app.
Para completar la app, haz lo siguiente:
Registra los controladores y configura
AssetLoader
agregando siguiente código al métodoonCreate()
: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));
Para cargar el contenido, agrega el siguiente código al método
onCreate()
:Kotlin
webView.loadUrl("https://appassets.androidplatform.net/assets/index.html")
Java
mWebView.loadUrl("https://appassets.androidplatform.net/assets/index.html");
Mezcla el contenido en la aplicación con los recursos de tu sitio web
Es posible que tu app deba cargar una combinación de contenido integrado en la app y contenido desde la
como una página HTML en la aplicación que tenga el estilo del CSS de tu sitio web.
WebViewAssetLoader
admite este caso de uso. Si ninguno de los registros
PathHandler
instancias pueden encontrar un recurso para la ruta de acceso determinada, WebView
falla
volver a cargar contenido de Internet. Si combinas el contenido integrado en la app con
recursos de tu sitio web, reservar rutas de acceso a directorios, como /assets/
o
/resources/
para los recursos de la app. Evita almacenar recursos de tus
sitio web en esas ubicaciones.
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);
Consulta la demostración de WebView
en
GitHub
para ver un ejemplo de una página HTML integrada en la app que recupera datos JSON alojados en la Web.
loadDataWithBaseURL
Cuando tu app solo necesita cargar una página HTML y no necesita interceptarla
subrecursos, considera usar
loadDataWithBaseURL()
:
que no requieren recursos de aplicación. Puedes usarla como se muestra en el siguiente código
muestra:
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);
Elige los valores de argumento con cuidado. Ten en cuenta lo siguiente:
baseUrl
: Esta es la URL en la que se carga tu contenido HTML. Debe ser un URL HTTP(S).data
: Es el contenido HTML que deseas mostrar, como una cadena.mimeType
: Por lo general, se debe configurar comotext/html
.encoding
: No se usa cuandobaseUrl
es una URL HTTP(S), por lo que se puede se define ennull
.historyUrl
: Se establece en el mismo valor quebaseUrl
.
Recomendamos usar una URL HTTP(S) como baseUrl
, ya que esto ayuda
asegúrate de que tu app satisfaga la política del mismo origen.
Si no encuentras un baseUrl
adecuado para tu contenido y prefieres usarlo
loadData()
,
debes codificar el contenido con
codificación por ciento
o
Base64
codificación.
Recomendamos enfáticamente elegir la codificación Base64 y usar las APIs de Android para codificar
de manera programática, como se observa en la siguiente muestra de código:
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");
Elementos que debes evitar
Existen muchas otras formas de cargar contenido integrado en la app, pero te recomendamos en su contra:
- Las URLs
file://
ydata:
URLs se consideran orígenes opacos. lo que significa que no pueden aprovechar APIs web potentes, comofetch()
oXMLHttpRequest
loadData()
utiliza URLsdata:
de forma interna, por lo que te recomendamos que utilicesWebViewAssetLoader
oloadDataWithBaseURL()
en su lugar. - Si bien
WebSettings.setAllowFileAccessFromFileURLs()
yWebSettings.setAllowUniversalAccessFromFileURLs()
los problemas con las URLs defile://
, te recomendamos que no configures estos atrue
porque, si lo haces, tu app quedará vulnerable a ataques las vulnerabilidades. Recomendamos configurarlos de forma explícita comofalse
en todos los niveles de API para obtener la seguridad más sólida. - Por las mismas razones, recomendamos no utilizar
file://android_assets/
nifile://android_res/
URLs.AssetsHandler
yResourcesHandler
son reemplazos directos. - Evita el uso
MIXED_CONTENT_ALWAYS_ALLOW
Por lo general, este parámetro de configuración no es necesario y debilita la seguridad de tu app. Te recomendamos que cargues el contenido de la app con el mismo esquema (HTTP o HTTPS, como los recursos del sitio webMIXED_CONTENT_COMPATIBILITY_MODE
oMIXED_CONTENT_NEVER_ALLOW
, según corresponda.