Carregar conteúdo no app

Você pode fornecer conteúdo baseado na Web, como HTML, JavaScript e CSS, para seu app usar que você compila estaticamente no app em vez do que buscar na Internet.

O conteúdo no app não precisa de acesso à Internet nem consome a largura de banda do usuário. Se o conteúdo foi desenvolvido especificamente para WebView, ou seja, depende da comunicação com um app nativo, então os usuários não podem acidentalmente carregá-lo em um navegador da Web.

No entanto, o conteúdo no app tem algumas desvantagens. Atualização de conteúdo baseado na Web exige o envio de uma nova atualização do app, e existe a possibilidade de inconsistências conteúdo entre o que está em um site e o que está no app no seu dispositivo, se os usuários têm versões desatualizadas do app.

WebViewAssetLoader.

WebViewAssetLoader é um forma flexível e eficiente de carregar conteúdo no app objeto WebView. Essa classe suporta os seguinte:

  • Carregar conteúdo com um URL HTTP(S) para compatibilidade com a mesma origem política.
  • Carregar sub-recursos como JavaScript, CSS, imagens e iframes.

Inclua WebViewAssetLoader no arquivo de atividade principal. Confira a seguir exemplo de carregamento de conteúdo da Web simples da pasta de recursos:

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));
    }
}

Seu app precisa configurar uma instância de WebViewAssetLoader para atender às necessidades. A a próxima seção tem um exemplo.

Criar recursos no app

WebViewAssetLoader depende de PathHandler instâncias para carregar recursos correspondentes a um determinado caminho de recurso. Embora você pode implementar essa interface para recuperar recursos conforme necessário pelo aplicativo, a Pacotes de bibliotecas do Webkit AssetsPathHandler e ResourcesPathHandler para carregar recursos do Android, respectivamente.

Para começar, crie recursos para seu app. Geralmente, a o seguinte se aplica:

  • Arquivos de texto como HTML, JavaScript e CSS pertencem aos recursos.
  • Imagens e outros arquivos binários pertencem aos recursos.

Para adicionar arquivos da Web baseados em texto a um projeto, faça o seguinte:

  1. No Android Studio, clique com o botão direito do mouse em app > src > pasta principal e escolha Novo > Directory.
    Uma imagem mostrando os menus de diretório de criação do Android Studio
    Figura 1. Crie uma pasta de recursos para seu projeto.
  2. Nomeie a pasta como "assets".
    Uma imagem mostrando a pasta de recursos
    Figura 2. Dê um nome à pasta de recursos.
  3. Clique com o botão direito do mouse na pasta assets e depois em Novo > Arquivo. Digite index.html e pressione a tecla Enter ou Tecla Enter.
  4. Repita a etapa anterior para criar um arquivo vazio para stylesheet.css:
  5. Preencha os arquivos vazios criados com o conteúdo dos próximos dois códigos. de amostra.
```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 adicionar um arquivo da Web baseado em imagem ao seu projeto, faça o seguinte:

  1. Faça o download do Android_symbol_green_RGB.png para sua máquina local.

  2. Renomeie o arquivo como android_robot.png.

  3. Mova manualmente o arquivo para o diretório main/res/drawable do projeto em seu disco rígido.

A Figura 4 mostra a imagem que você adicionou e o texto dos exemplos de código anteriores renderizados em um app.

Uma imagem mostrando a saída renderizada do app
Figura 4. Arquivo HTML no app e arquivo de imagem renderizados em um app.
.

Para concluir o app, faça o seguinte:

  1. Registre os gerenciadores e configure o AssetLoader adicionando o código a seguir para o 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. Carregue o conteúdo adicionando o seguinte código ao método onCreate():

    Kotlin

    webView.loadUrl("https://appassets.androidplatform.net/assets/index.html")
    

    Java

    mWebView.loadUrl("https://appassets.androidplatform.net/assets/index.html");
    

Misture o conteúdo no app com os recursos do seu site

Seu aplicativo pode precisar carregar uma combinação de conteúdo no aplicativo e do Internet, como uma página HTML no aplicativo estilizada pelo CSS do seu site. WebViewAssetLoader oferece suporte a esse caso de uso. Se nenhuma das opções Instâncias de PathHandler podem encontrar um recurso para o caminho especificado, WebView fica o carregamento de conteúdo da Internet. Se você misturar conteúdo no app recursos do seu site, reserve caminhos de diretório, como /assets/ ou /resources/ para recursos no app. Evite armazenar recursos do seu o site nesses locais.

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);

Veja a demonstração do WebView em GitHub para um exemplo de página HTML no app que busca dados JSON hospedados na Web.

loadDataWithBaseURL

Quando seu app só precisa carregar uma página HTML e não precisa interceptar sub-recursos, considere usar loadDataWithBaseURL(), que não requer recursos de link para app. É possível usá-lo conforme mostrado no código a seguir amostra:

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);

Escolha os valores dos argumentos com cuidado. Considere o seguinte:

  • baseUrl: é o URL em que o conteúdo HTML é carregado. Ele precisa ser um URL HTTP(S).
  • data: é o conteúdo HTML que você quer mostrar, como uma string.
  • mimeType: geralmente precisa ser definido como text/html.
  • encoding: não é usado quando baseUrl é um URL HTTP(S), então pode ser Defina como null.
  • historyUrl: definido com o mesmo valor que baseUrl.

Recomendamos usar um URL HTTP(S) como baseUrl, porque isso ajuda garantir que o app obedeça à política de mesma origem.

Se você não encontrar um baseUrl adequado para seu conteúdo e preferir usar loadData(), você deve codificar o conteúdo com codificação por cento ou Base64 e codificação. Recomendamos escolher a codificação Base64 e usar APIs do Android para codificar programaticamente, conforme mostrado neste exemplo 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");

O que deve ser evitado

Há várias outras maneiras de carregar conteúdo no aplicativo, mas recomendamos contra elas:

  • file:// e data: URLs são considerados origens opacas, o que significa que não podem aproveitar as APIs poderosas da Web, como fetch() ou XMLHttpRequest. O loadData() usa internamente URLs data:. Por isso, incentivamos o uso WebViewAssetLoader ou loadDataWithBaseURL().
  • Embora WebSettings.setAllowFileAccessFromFileURLs() e WebSettings.setAllowUniversalAccessFromFileURLs() possa contornar os problemas com URLs file://, recomendamos não configurar para true porque isso deixa seu app vulnerável a ataques explorações de descoberta. Recomendamos defini-los explicitamente como false em todos os níveis da API. para ter a melhor segurança.
  • Pelos mesmos motivos, não recomendamos file://android_assets/ e file://android_res/ de URLs. AssetsHandler e ResourcesHandler classes são destinadas a substituições imediatas.
  • Evite usar MIXED_CONTENT_ALWAYS_ALLOW Geralmente, essa configuração não é necessária e enfraquece a segurança do app. Recomendamos carregar o conteúdo no app com o mesmo esquema: HTTP ou HTTPS, como os recursos do seu site e usando MIXED_CONTENT_COMPATIBILITY_MODE ou MIXED_CONTENT_NEVER_ALLOW, conforme apropriado.