Carga contenido integrado en la app

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:

  1. En Android Studio, haz clic con el botón derecho en la app > src > carpeta principal y, luego, selecciona Nuevo > Directory.
    Imagen que muestra los menús de creación de directorios de Android Studio
    Figura 1: Crea una carpeta de recursos para tu en un proyecto final.
  2. Asigna el nombre "assets" a la carpeta.
    Una imagen que muestra la carpeta de recursos
    Figura 2: Asigna un nombre a la carpeta de recursos.
  3. 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.
  4. Repite el paso anterior para crear un archivo vacío para stylesheet.css
  5. 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:

  1. Descarga el Android_symbol_green_RGB.png en tu máquina local.

  2. Cambia el nombre del archivo a android_robot.png.

  3. 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.

Una imagen que muestra el resultado renderizado de la app
Figura 4: Archivo de imagen y archivo HTML en la aplicación renderizado en una app.

Para completar la app, haz lo siguiente:

  1. Registra los controladores y configura AssetLoader agregando siguiente código al método 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));
    
  2. 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 como text/html.
  • encoding: No se usa cuando baseUrl es una URL HTTP(S), por lo que se puede se define en null.
  • historyUrl: Se establece en el mismo valor que baseUrl.

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:// y data: URLs se consideran orígenes opacos. lo que significa que no pueden aprovechar APIs web potentes, como fetch() o XMLHttpRequest loadData() utiliza URLs data: de forma interna, por lo que te recomendamos que utilices WebViewAssetLoader o loadDataWithBaseURL() en su lugar.
  • Si bien WebSettings.setAllowFileAccessFromFileURLs() y WebSettings.setAllowUniversalAccessFromFileURLs() los problemas con las URLs de file://, te recomendamos que no configures estos a true porque, si lo haces, tu app quedará vulnerable a ataques las vulnerabilidades. Recomendamos configurarlos de forma explícita como false en todos los niveles de API para obtener la seguridad más sólida.
  • Por las mismas razones, recomendamos no utilizar file://android_assets/ ni file://android_res/ URLs. AssetsHandler y ResourcesHandler 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 web MIXED_CONTENT_COMPATIBILITY_MODE o MIXED_CONTENT_NEVER_ALLOW, según corresponda.