O Android fornece várias APIs para ajudar você a gerenciar
WebView
objetos que exibem conteúdo da Web no seu app.
Esta página descreve como usar essas APIs para trabalhar com WebView
objetos de forma mais eficaz, melhorando a estabilidade e a segurança do aplicativo.
API Version
A partir do Android 7.0 (API de nível 24), os usuários podem escolher entre várias
pacotes diferentes para exibir conteúdo da Web em um objeto WebView
.
A classe AndroidX.webkit
inclui o
getCurrentWebViewPackage()
para buscar informações relacionadas ao pacote que exibe dados da Web
conteúdo no seu app. Esse método é útil ao analisar erros que ocorrem apenas
quando o app tenta exibir conteúdo da Web usando o
implementação de WebView
.
Para usar esse método, adicione a lógica mostrada no snippet de código a seguir:
Kotlin
val webViewPackageInfo = WebViewCompat.getCurrentWebViewPackage(appContext) Log.d("MY_APP_TAG", "WebView version: ${webViewPackageInfo.versionName}")
Java
PackageInfo webViewPackageInfo = WebViewCompat.getCurrentWebViewPackage(appContext); Log.d("MY_APP_TAG", "WebView version: " + webViewPackageInfo.versionName);
Serviço de Navegação segura do Google
Para oferecer aos usuários uma experiência de navegação mais segura, WebView
verificam URLs usando
Navegação segura do Google,
que permite que o app mostre um aviso aos usuários quando eles tentarem navegar para uma
site potencialmente perigoso.
Embora o valor padrão de EnableSafeBrowsing
seja verdadeiro, não há
são casos em que você só quer ativar a Navegação segura condicionalmente ou
desativá-la. O Android 8.0 (nível 26 da API) e versões mais recentes oferecem suporte ao uso
setSafeBrowsingEnabled()
para ativar o recurso Navegação segura para um objeto WebView
individual.
Se você quiser que todos os objetos WebView
desativem o recurso Navegação segura
da conta, adicione o seguinte elemento <meta-data>
ao
arquivo de manifesto:
<manifest> <application> <meta-data android:name="android.webkit.WebView.EnableSafeBrowsing" android:value="false" /> ... </application> </manifest>
Definir ações programáticas
Quando uma instância de WebView
tenta carregar uma página que está
classificadas pelo Google como uma ameaça conhecida, o WebView
, por padrão,
mostra um intersticial que avisa os usuários sobre a ameaça conhecida. Essa tela mostra
aos usuários a opção de carregar o URL mesmo assim ou de retornar à página anterior
seguros.
Se você destinar ao Android 8.1 (API de nível 27) ou posterior, poderá definir de forma programática, como o app responde a uma ameaça conhecida das seguintes maneiras: maneiras:
- É possível controlar se o app reporta as ameaças conhecidas para o Navegação.
- É possível fazer com que o aplicativo execute automaticamente uma ação específica, como para voltar à segurança. Sempre que encontra um URL pode ser classificado como uma ameaça conhecida.
Os snippets de código a seguir mostram como instruir as instâncias de
WebView
para sempre voltar a um local seguro depois de encontrar um
ameaça:
Kotlin
private lateinit var superSafeWebView: WebView private var safeBrowsingIsInitialized: Boolean = false // ... override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) superSafeWebView = WebView(this) superSafeWebView.webViewClient = MyWebViewClient() safeBrowsingIsInitialized = false if (WebViewFeature.isFeatureSupported(WebViewFeature.START_SAFE_BROWSING)) { WebViewCompat.startSafeBrowsing(this, ValueCallback<Boolean> { success -> safeBrowsingIsInitialized = true if (!success) { Log.e("MY_APP_TAG", "Unable to initialize Safe Browsing!") } }) } }
Java
private WebView superSafeWebView; private boolean safeBrowsingIsInitialized; // ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); superSafeWebView = new WebView(this); superSafeWebView.setWebViewClient(new MyWebViewClient()); safeBrowsingIsInitialized = false; if (WebViewFeature.isFeatureSupported(WebViewFeature.START_SAFE_BROWSING)) { WebViewCompat.startSafeBrowsing(this, new ValueCallback<Boolean>() { @Override public void onReceiveValue(Boolean success) { safeBrowsingIsInitialized = true; if (!success) { Log.e("MY_APP_TAG", "Unable to initialize Safe Browsing!"); } } }); } }
Kotlin
class MyWebViewClient : WebViewClientCompat() { // Automatically go "back to safety" when attempting to load a website that // Google identifies as a known threat. An instance of WebView calls this // method only after Safe Browsing is initialized, so there's no conditional // logic needed here. override fun onSafeBrowsingHit( view: WebView, request: WebResourceRequest, threatType: Int, callback: SafeBrowsingResponseCompat ) { // The "true" argument indicates that your app reports incidents like // this one to Safe Browsing. if (WebViewFeature.isFeatureSupported(WebViewFeature.SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY)) { callback.backToSafety(true) Toast.makeText(view.context, "Unsafe web page blocked.", Toast.LENGTH_LONG).show() } } }
Java
public class MyWebViewClient extends WebViewClientCompat { // Automatically go "back to safety" when attempting to load a website that // Google identifies as a known threat. An instance of WebView calls this // method only after Safe Browsing is initialized, so there's no conditional // logic needed here. @Override public void onSafeBrowsingHit(WebView view, WebResourceRequest request, int threatType, SafeBrowsingResponseCompat callback) { // The "true" argument indicates that your app reports incidents like // this one to Safe Browsing. if (WebViewFeature.isFeatureSupported(WebViewFeature.SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY)) { callback.backToSafety(true); Toast.makeText(view.getContext(), "Unsafe web page blocked.", Toast.LENGTH_LONG).show(); } } }
API HTML5 Geolocation
Para apps destinados ao Android 6.0 (nível 23 da API) e versões mais recentes, a API Geolocation
é compatível apenas com origens seguras, como HTTPS. Qualquer solicitação feita ao
A API Geolocation em origens não seguras é automaticamente negada sem invocar
o método onGeolocationPermissionsShowPrompt()
correspondente.
Desativar a coleta de métricas
O WebView
consegue fazer o upload de dados de diagnóstico anônimos para o
Google quando o usuário dá o consentimento. Os dados são coletados por app
para cada app que instancia um WebView
. É possível desativar essa opção
recurso criando a seguinte tag no arquivo
Elemento <application>
:
<manifest> <application> ... <meta-data android:name="android.webkit.WebView.MetricsOptOut" android:value="true" /> </application> </manifest>
O upload de dados de um app só é feito com o consentimento do usuário e que o app não desative. Para mais informações sobre como desativar os dados de diagnóstico relatórios, consulte Privacidade do usuário na WebView geração de relatórios.
API Termination Handling
A API Terminal Handling lida com casos em que o processo do renderizador para um
WebView
desaparece, seja porque o sistema encerra o renderizador para recuperá-lo
memória necessária ou porque o processo do renderizador falha. Ao usar essa API, você
permite que o app continue em execução, mesmo que o processo do renderizador desapareça.
Se um renderizador falhar ao carregar uma página da Web específica, tentar
carregar a mesma página novamente pode fazer com que um novo objeto WebView
exibem o mesmo comportamento de falha de renderização.
O snippet de código a seguir ilustra como usar essa API em uma
Activity
:
Kotlin
inner class MyRendererTrackingWebViewClient : WebViewClient() { private var mWebView: WebView? = null override fun onRenderProcessGone(view: WebView, detail: RenderProcessGoneDetail): Boolean { if (!detail.didCrash()) { // Renderer is killed because the system ran out of memory. The app // can recover gracefully by creating a new WebView instance in the // foreground. Log.e("MY_APP_TAG", ("System killed the WebView rendering process " + "to reclaim memory. Recreating...")) mWebView?.also { webView -> val webViewContainer: ViewGroup = findViewById(R.id.my_web_view_container) webViewContainer.removeView(webView) webView.destroy() mWebView = null } // By this point, the instance variable "mWebView" is guaranteed to // be null, so it's safe to reinitialize it. return true // The app continues executing. } // Renderer crashes because of an internal error, such as a memory // access violation. Log.e("MY_APP_TAG", "The WebView rendering process crashed!") // In this example, the app itself crashes after detecting that the // renderer crashed. If you handle the crash more gracefully and let // your app continue executing, you must destroy the current WebView // instance, specify logic for how the app continues executing, and // return "true" instead. return false } }
Java
public class MyRendererTrackingWebViewClient extends WebViewClient { private WebView mWebView; @Override public boolean onRenderProcessGone(WebView view, RenderProcessGoneDetail detail) { if (!detail.didCrash()) { // Renderer is killed because the system ran out of memory. The app // can recover gracefully by creating a new WebView instance in the // foreground. Log.e("MY_APP_TAG", "System killed the WebView rendering process " + "to reclaim memory. Recreating..."); if (mWebView != null) { ViewGroup webViewContainer = (ViewGroup) findViewById(R.id.my_web_view_container); webViewContainer.removeView(mWebView); mWebView.destroy(); mWebView = null; } // By this point, the instance variable "mWebView" is guaranteed to // be null, so it's safe to reinitialize it. return true; // The app continues executing. } // Renderer crashes because of an internal error, such as a memory // access violation. Log.e("MY_APP_TAG", "The WebView rendering process crashed!"); // In this example, the app itself crashes after detecting that the // renderer crashed. If you handle the crash more gracefully and let // your app continue executing, you must destroy the current WebView // instance, specify logic for how the app continues executing, and // return "true" instead. return false; } }
API Renderer Importance
Quando objetos WebView
operar em
no modo multiprocesso, você tem alguma flexibilidade na forma como o app
em situações de falta de memória. É possível usar a API Renderer Importance, introduzida no
Android 8.0, para definir uma política de prioridade para o renderizador atribuído a um determinado
WebView
. Em particular, talvez você queira que a parte principal
continue a execução quando um renderizador que exibir
WebView
objeto foi encerrado. Você pode fazer isso, por exemplo, se
esperar não mostrar o objeto WebView
por muito tempo para que o
sistema pode recuperar a memória que o renderizador estava usando.
O snippet de código a seguir mostra como atribuir uma prioridade ao renderizador
processo associado aos objetos WebView
do seu app:
Kotlin
val myWebView: WebView = ... myWebView.setRendererPriorityPolicy(RENDERER_PRIORITY_BOUND, true)
Java
WebView myWebView; myWebView.setRendererPriorityPolicy(RENDERER_PRIORITY_BOUND, true);
Nesse snippet específico, a prioridade do renderizador é a mesma que...
está vinculado: a prioridade padrão do app. O true
diminui a prioridade do renderizador para
RENDERER_PRIORITY_WAIVED
quando o objeto WebView
associado não estiver mais visível. Em outras
palavras, um argumento true
indica que o app não se importa se
o sistema mantém o processo do renderizador ativo. Na verdade, esse nível de prioridade mais baixo
torna provável que o processo do renderizador seja eliminado na falta de memória
em diferentes situações.
Para saber mais sobre como o sistema lida com situações de pouca memória, consulte Processos e app de desenvolvimento de software.