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:
- No Android Studio, clique com o botão direito do mouse em app > src > pasta principal e escolha Novo > Directory.
- Nomeie a pasta como "assets".
- 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. - Repita a etapa anterior para criar um arquivo vazio para
stylesheet.css
: - 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:
Faça o download do
Android_symbol_green_RGB.png
para sua máquina local.Renomeie o arquivo como
android_robot.png
.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.
Para concluir o app, faça o seguinte:
Registre os gerenciadores e configure o
AssetLoader
adicionando o código a seguir para o 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));
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 comotext/html
.encoding
: não é usado quandobaseUrl
é um URL HTTP(S), então pode ser Defina comonull
.historyUrl
: definido com o mesmo valor quebaseUrl
.
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://
edata:
URLs são considerados origens opacas, o que significa que não podem aproveitar as APIs poderosas da Web, comofetch()
ouXMLHttpRequest
. OloadData()
usa internamente URLsdata:
. Por isso, incentivamos o usoWebViewAssetLoader
ouloadDataWithBaseURL()
.- Embora
WebSettings.setAllowFileAccessFromFileURLs()
eWebSettings.setAllowUniversalAccessFromFileURLs()
possa contornar os problemas com URLsfile://
, recomendamos não configurar paratrue
porque isso deixa seu app vulnerável a ataques explorações de descoberta. Recomendamos defini-los explicitamente comofalse
em todos os níveis da API. para ter a melhor segurança. - Pelos mesmos motivos, não recomendamos
file://android_assets/
efile://android_res/
de URLs.AssetsHandler
eResourcesHandler
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 usandoMIXED_CONTENT_COMPATIBILITY_MODE
ouMIXED_CONTENT_NEVER_ALLOW
, conforme apropriado.