Use WebView
para exibir um aplicativo da Web
ou uma página da Web como parte de um aplicativo cliente. A classe WebView
é uma
extensão da classe View
do Android que permite
mostrar páginas da Web como parte do layout da atividade. Ela não inclui os
recursos de um navegador da Web totalmente desenvolvido, como controles de navegação ou uma
barra de endereço. Por padrão, tudo o que o WebView
mostra é uma página da Web.
O WebView
pode ajudar você a fornecer informações que talvez precisem ser
atualizadas no app, como um contrato de usuário final ou um guia do usuário. No seu app Android,
você pode criar uma Activity
que contenha um
WebView
e usá-la para exibir seu documento hospedado on-line.
O WebView
também pode ajudar quando o app fornece dados ao usuário que exigem uma
conexão de Internet para extrair dados, como e-mails. Nesse caso, pode
ser mais fácil criar uma WebView
no app Android que mostre uma página
da Web com todos os dados do usuário, em vez de executar uma solicitação de rede, analisar os dados e renderizá-los em um layout do Android. Em vez disso, é possível criar
uma página da Web personalizada para dispositivos com tecnologia Android e implementar um
WebView
que carregue a página no seu app Android.
Este documento descreve como começar a usar o WebView
, vincular
o JavaScript da sua página da Web ao código do lado do cliente no seu app Android, como
processar a navegação nas páginas e como gerenciar janelas ao usar WebView
.
Trabalhar com o WebView em versões anteriores do Android
Para usar os recursos do WebView
mais recentes com segurança no dispositivo em que o app está
em execução, adicione a biblioteca AndroidX
Webkit. Essa é uma biblioteca
estática que pode ser adicionada ao seu aplicativo para usar APIs android.webkit
que não estão
disponíveis para versões anteriores da plataforma.
Adicione-o ao seu arquivo build.gradle
da seguinte maneira:
Kotlin
dependencies { implementation("androidx.webkit:webkit:1.8.0") }
Groovy
dependencies { implementation ("androidx.webkit:webkit:1.8.0") }
Confira o exemplo
WebView
(link em inglês)
no GitHub para mais detalhes.
Adicionar uma WebView ao app
Para adicionar uma WebView
ao app, você pode incluir o elemento <WebView>
no
layout da atividade ou definir toda a janela Activity
como uma WebView
em
onCreate()
.
Adicionar uma WebView ao layout da atividade
Para adicionar um WebView
ao app no layout, adicione o seguinte código ao
arquivo XML do layout da atividade:
<WebView android:id="@+id/webview" android:layout_width="match_parent" android:layout_height="match_parent" />
Para carregar uma página da Web na WebView
, use
loadUrl()
, conforme
mostrado no exemplo a seguir:
Kotlin
val myWebView: WebView = findViewById(R.id.webview) myWebView.loadUrl("http://www.example.com")
Java
WebView myWebView = (WebView) findViewById(R.id.webview); myWebView.loadUrl("http://www.example.com");
Adicionar uma WebView a onCreate()
Para adicionar um WebView
ao app no método onCreate()
de uma atividade, use
uma lógica semelhante a esta:
Kotlin
val myWebView = WebView(activityContext) setContentView(myWebView)
Java
WebView myWebView = new WebView(activityContext); setContentView(myWebView);
Em seguida, carregue a página:
Kotlin
myWebView.loadUrl("http://www.example.com")
Java
myWebView.loadUrl("https://www.example.com");
Ou carregue o URL a partir de uma string HTML:
Kotlin
// Create an unencoded HTML string, then convert the unencoded HTML string into // bytes. Encode it with base64 and load the data. val unencodedHtml = "<html><body>'%23' is the percent code for ‘#‘ </body></html>"; val encodedHtml = Base64.encodeToString(unencodedHtml.toByteArray(), Base64.NO_PADDING) myWebView.loadData(encodedHtml, "text/html", "base64")
Java
// Create an unencoded HTML string, then convert the unencoded HTML string into // bytes. Encode it with base64 and load the data. String unencodedHtml = "<html><body>'%23' is the percent code for ‘#‘ </body></html>"; String encodedHtml = Base64.encodeToString(unencodedHtml.getBytes(), Base64.NO_PADDING); myWebView.loadData(encodedHtml, "text/html", "base64");
O app precisa ter acesso à Internet. Para ter acesso à Internet, solicite a permissão
INTERNET
no seu
arquivo de manifesto, conforme mostrado no exemplo a seguir:
<manifest ... > <uses-permission android:name="android.permission.INTERNET" /> ... </manifest>
Você pode personalizar o WebView
seguindo um destes procedimentos:
- Ativando o suporte a tela cheia usando
WebChromeClient
. Essa classe também é chamada quando umWebView
precisa de permissão para mudar a interface do app host, por exemplo, para criar ou fechar janelas ou enviar caixas de diálogo JavaScript para o usuário. Para saber mais sobre a depuração nesse contexto, leia Depurar apps da Web. - Processamento de eventos que afetam a renderização de conteúdo, como erros no envio
de formulários ou na navegação, usando
WebViewClient
. Você também pode usar essa subclasse para interceptar o carregamento do URL. - Ativar o JavaScript modificando
WebSettings
. - Usar o JavaScript para acessar objetos do framework do Android injetados
em um
WebView
.
Usar JavaScript na WebView
Se a página da Web que você quer carregar na WebView
usa JavaScript, é necessário ativar o JavaScript para a WebView
. Depois de ativar o JavaScript, é possível
criar interfaces entre o código do app e o código JavaScript.
Ativar o JavaScript
Por padrão, o JavaScript fica desativado em uma WebView
. É possível ativá-la usando o
WebSettings
anexado ao WebView
. Recupere WebSettings
com
getSettings()
e ative
o JavaScript com
setJavaScriptEnabled()
.
Confira este exemplo:
Kotlin
val myWebView: WebView = findViewById(R.id.webview) myWebView.settings.javaScriptEnabled = true
Java
WebView myWebView = (WebView) findViewById(R.id.webview); WebSettings webSettings = myWebView.getSettings(); webSettings.setJavaScriptEnabled(true);
WebSettings
fornece acesso a uma variedade de outras configurações que podem ser
úteis. Por exemplo, se você estiver desenvolvendo um aplicativo da Web projetado
especificamente para WebView
no seu app Android, é possível definir uma string
de user agent personalizada com
setUserAgentString()
e, em seguida, consultar o user agent personalizado na sua página da Web para verificar se o cliente
que solicita a página da Web é o seu app Android.
Vincular o código JavaScript ao código do Android
Ao desenvolver um aplicativo da Web projetado especificamente para a WebView
no seu app Android, você pode criar interfaces entre o código JavaScript e
o código Android do lado do cliente. Por exemplo, o código JavaScript pode chamar um método no
código do Android para exibir um Dialog
,
em vez de usar a função alert()
do JavaScript.
Para vincular uma nova interface entre o código JavaScript e o Android, chame
addJavascriptInterface()
,
transmitindo uma instância de classe para vincular ao JavaScript e um nome de interface
que o JavaScript possa chamar para acessar a classe.
Por exemplo, você pode incluir a seguinte classe no app para Android:
Kotlin
/** Instantiate the interface and set the context. */ class WebAppInterface(private val mContext: Context) { /** Show a toast from the web page. */ @JavascriptInterface fun showToast(toast: String) { Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show() } }
Java
public class WebAppInterface { Context mContext; /** Instantiate the interface and set the context. */ WebAppInterface(Context c) { mContext = c; } /** Show a toast from the web page. */ @JavascriptInterface public void showToast(String toast) { Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show(); } }
Neste exemplo, a classe WebAppInterface
permite que a página da Web crie uma mensagem
Toast
usando o método
showToast()
.
É possível vincular essa classe ao JavaScript executado na WebView
com
addJavascriptInterface()
, conforme mostrado no exemplo a seguir.
Kotlin
val webView: WebView = findViewById(R.id.webview) webView.addJavascriptInterface(WebAppInterface(this), "Android")
Java
WebView webView = (WebView) findViewById(R.id.webview); webView.addJavascriptInterface(new WebAppInterface(this), "Android");
Isso cria uma interface chamada Android
para o JavaScript em execução na
WebView
. Nesse ponto, seu aplicativo da Web tem acesso à
classe WebAppInterface
. Por exemplo, confira alguns HTML e JavaScript que
criam uma mensagem de aviso usando a nova interface quando o usuário toca em um botão:
<input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" /> <script type="text/javascript"> function showAndroidToast(toast) { Android.showToast(toast); } </script>
Não é necessário inicializar a interface Android
do JavaScript. O WebView
o disponibiliza automaticamente na sua página da Web. Assim, quando um usuário
toca no botão, a função showAndroidToast()
usa a interface Android
para chamar o método WebAppInterface.showToast()
.
Processar a navegação nas páginas
Quando o usuário toca em um link de uma página da Web na WebView
, por padrão, o Android
inicia um app que gerencia URLs. Normalmente, o navegador da Web padrão abre e
carrega o URL de destino. No entanto, você pode substituir esse comportamento na
WebView
para que os links sejam abertos no WebView
. Você pode permitir que o usuário
navegue para trás e para frente pelo histórico da página da Web mantido
pelo WebView
.
Para abrir os links tocados pelo usuário, forneça um WebViewClient
para seu WebView
usando
setWebViewClient()
.
Todos os links em que o usuário toca são carregados na WebView
. Se você quiser ter mais controle sobre
onde um link clicado é carregado, crie seu próprio WebViewClient
que modifique o
método
shouldOverrideUrlLoading()
. O exemplo a seguir pressupõe que MyWebViewClient
é uma classe interna
de Activity
.
Kotlin
private class MyWebViewClient : WebViewClient() { override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean { if (Uri.parse(url).host == "www.example.com") { // This is your website, so don't override. Let your WebView load // the page. return false } // Otherwise, the link isn't for a page on your site, so launch another // Activity that handles URLs. Intent(Intent.ACTION_VIEW, Uri.parse(url)).apply { startActivity(this) } return true } }
Java
private class MyWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { if ("www.example.com".equals(request.getUrl().getHost())) { // This is your website, so don't override. Let your WebView load the // page. return false; } // Otherwise, the link isn't for a page on your site, so launch another // Activity that handles URLs. Intent intent = new Intent(Intent.ACTION_VIEW, request.getUrl()); startActivity(intent); return true; } }
Em seguida, crie uma instância desse novo WebViewClient
para a WebView
:
Kotlin
val myWebView: WebView = findViewById(R.id.webview) myWebView.webViewClient = MyWebViewClient()
Java
WebView myWebView = (WebView) findViewById(R.id.webview); myWebView.setWebViewClient(new MyWebViewClient());
Agora, quando o usuário tocar em um link, o sistema chamará o
método shouldOverrideUrlLoading()
, que verifica se o host do URL corresponde a
um domínio específico, como definido no exemplo anterior. Se corresponder, o método retornará "false" e não modificará o carregamento do URL. Ele permite que a
WebView
carregue o URL normalmente. Se o host do URL não for correspondente, uma
Intent
será criada para iniciar o
Activity
padrão para processar URLs, que é resolvido para o navegador da Web padrão do usuário.
Processar URLs personalizados
WebView
aplica restrições ao solicitar recursos e resolver links
que usam um esquema de URL personalizado. Por exemplo, se você implementar callbacks como
shouldOverrideUrlLoading()
ou
shouldInterceptRequest()
,
o WebView
os invocará apenas para URLs válidos.
Por exemplo, WebView
pode não chamar seu método shouldOverrideUrlLoading()
para links como estes:
<a href="showProfile">Show Profile</a>
URLs inválidos, como o mostrado no exemplo anterior, são tratados
de maneira inconsistente em WebView
. Por isso, recomendamos o uso de um URL bem formatado.
É possível usar um esquema personalizado ou um URL HTTPS para um domínio controlado pela sua organização.
Em vez de usar uma string simples em um link, como no exemplo anterior, você pode usar um esquema personalizado como o seguinte:
<a href="example-app:showProfile">Show Profile</a>
Você pode processar esse URL no método shouldOverrideUrlLoading()
desta
maneira:
Kotlin
// The URL scheme must be non-hierarchical, meaning no trailing slashes. const val APP_SCHEME = "example-app:" override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean { return if (url?.startsWith(APP_SCHEME) == true) { urlData = URLDecoder.decode(url.substring(APP_SCHEME.length), "UTF-8") respondToData(urlData) true } else { false } }
Java
// The URL scheme must be non-hierarchical, meaning no trailing slashes. private static final String APP_SCHEME = "example-app:"; @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.startsWith(APP_SCHEME)) { urlData = URLDecoder.decode(url.substring(APP_SCHEME.length()), "UTF-8"); respondToData(urlData); return true; } return false; }
A API shouldOverrideUrlLoading()
é destinada principalmente a iniciar intents
para URLs específicos. Ao implementá-la, retorne false
para os URLs
processados por WebView
. No entanto, você não está limitado a iniciar intents. É possível
substituir intents de inicialização por qualquer comportamento personalizado nos exemplos de código
anteriores.
Navegar pelo histórico de páginas da Web
Quando sua WebView
substitui o carregamento do URL, ela acumula automaticamente um histórico de páginas da Web visitadas. É possível voltar e avançar no
histórico com goBack()
e
goForward()
.
Por exemplo, a imagem abaixo mostra como o Activity
pode usar o botão "Voltar" do dispositivo
para navegar para trás:
Kotlin
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { // Check whether the key event is the Back button and if there's history. if (keyCode == KeyEvent.KEYCODE_BACK && myWebView.canGoBack()) { myWebView.goBack() return true } // If it isn't the Back button or there isn't web page history, bubble up to // the default system behavior. Probably exit the activity. return super.onKeyDown(keyCode, event) }
Java
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { // Check whether the key event is the Back button and if there's history. if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) { myWebView.goBack(); return true; } // If it isn't the Back button or there's no web page history, bubble up to // the default system behavior. Probably exit the activity. return super.onKeyDown(keyCode, event); }
Se o app usa o AndroidX AppCompat
1.6.0 ou versões mais recentes, você pode simplificar o snippet
anterior ainda mais:
Kotlin
onBackPressedDispatcher.addCallback { // Check whether there's history. if (myWebView.canGoBack()) { myWebView.goBack() } }
Java
onBackPressedDispatcher.addCallback { // Check whether there's history. if (myWebView.canGoBack()) { myWebView.goBack(); } }
O método canGoBack()
retornará "true" se houver um histórico da página da Web para o usuário visitar. Da mesma forma, você
pode usar canGoForward()
para
verificar se há um histórico de avanço. Se você não fizer essa verificação, depois que o usuário chegar ao fim do histórico, goBack()
e goForward()
não terão efeito.
Processar mudanças de configuração do dispositivo
Durante o tempo de execução, as mudanças no estado da atividade ocorrem quando a configuração
de um dispositivo é alterada, por exemplo, quando os usuários giram o dispositivo ou dispensam um Editor de método de entrada
(IME, na sigla em inglês). Essas mudanças fazem com que a atividade de um objeto WebView
seja destruída e uma
nova atividade seja criada, o que também cria um novo objeto WebView
que carrega
o URL do objeto destruído. Para modificar o comportamento padrão da atividade, você pode
mudar a forma como ela processa mudanças de orientation
no manifesto. Para saber mais
sobre como lidar com mudanças de configuração durante a execução, leia Gerenciar mudanças
de configuração.
Gerenciar janelas
Por padrão, as solicitações para abrir novas janelas são ignoradas. Isso acontece independentemente
de elas serem abertas por JavaScript ou pelo atributo de destino em um link. É possível personalizar
o WebChromeClient
para fornecer seu próprio comportamento ao abrir várias
janelas.
Para manter seu app mais seguro, é melhor evitar que pop-ups e novas janelas sejam
abertos. A maneira mais segura de implementar esse comportamento é transmitir "true"
para
setSupportMultipleWindows()
,
mas sem substituir o método
onCreateWindow()
,
do qual setSupportMultipleWindows()
depende. Essa lógica impede que qualquer
página que use target="_blank"
nos links carregue.