Android proporciona varias APIs para ayudarte a administrar la
WebView
objetos que muestran contenido web en tu app.
En esta página, se describe cómo usar estas APIs para trabajar con WebView
de forma más eficaz, lo que mejora la estabilidad y seguridad de tu app.
API de versión
A partir de Android 7.0 (nivel de API 24), los usuarios pueden elegir entre varias
diferentes paquetes para mostrar contenido web en un objeto WebView
.
La función AndroidX.webkit
biblioteca incluye el
getCurrentWebViewPackage()
método para recuperar información relacionada con el paquete que muestra la
contenido de tu app. Este método es útil cuando se analizan errores que solo ocurren
cuando tu app intenta mostrar contenido web usando la interfaz de un paquete
implementación de WebView
.
Para usar este método, agrega la lógica que se muestra en el siguiente fragmento de código:
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);
Servicio de Navegación segura de Google
Para brindar a tus usuarios una experiencia de navegación más segura, WebView
los objetos verifican las URLs con
Navegación segura de Google,
lo que permite que tu app muestre una advertencia a los usuarios cuando intenten navegar a una
un sitio web potencialmente peligroso.
Aunque el valor predeterminado de EnableSafeBrowsing
es verdadero,
son casos en los que quizás desees habilitar solo la Navegación segura de manera condicional o
inhabilitarla. Android 8.0 (nivel de API 26) y versiones posteriores admiten el uso de
setSafeBrowsingEnabled()
si quieres activar o desactivar la Navegación segura para un objeto WebView
individual.
Si deseas inhabilitar la Navegación segura en todos los objetos WebView
agrega el siguiente elemento <meta-data>
al directorio
archivo de manifiesto:
<manifest> <application> <meta-data android:name="android.webkit.WebView.EnableSafeBrowsing" android:value="false" /> ... </application> </manifest>
Cómo definir acciones programáticas
Cuando una instancia de WebView
intenta cargar una página que está
clasificada por Google como una amenaza conocida, WebView
de forma predeterminada
muestra un anuncio intersticial que advierte a los usuarios sobre la amenaza conocida. Esta pantalla te ofrece
a los usuarios la opción de cargar la URL de todas formas o regresar a una página anterior que sea
la seguridad de los recursos aprovisionados.
Si tienes como objetivo Android 8.1 (nivel de API 27) o una versión posterior, puedes definir de manera programática cómo responde tu app a una amenaza conocida en las siguientes situaciones: maneras:
- Puedes controlar si tu app informa amenazas conocidas a Safe Navegación.
- Puedes hacer que tu app realice automáticamente una acción determinada, como como regresar a un estado seguro, cada vez que encuentre una URL clasificada como amenaza conocida.
Los siguientes fragmentos de código muestran cómo dar instrucciones a las instancias de tu app de
WebView
para volver siempre a un estado seguro después de encontrar un mensaje de error
amenaza:
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 de HTML5 Geolocation
Para las apps orientadas a Android 6.0 (nivel de API 23) y versiones posteriores, la API de Geolocation
solo es compatible con orígenes seguros, como HTTPS. Cualquier solicitud a la
La API de Geolocation en orígenes no seguros se rechaza automáticamente sin invocar
el método onGeolocationPermissionsShowPrompt()
correspondiente
Cómo inhabilitar la recopilación de métricas
WebView
tiene la capacidad de subir datos de diagnóstico anónimos para
a Google cuando el usuario otorga su consentimiento. Los datos se recopilan por app
para cada app que cree una instancia de WebView
. Puedes inhabilitar esta opción
esta función creando la siguiente etiqueta en el archivo
Elemento <application>
:
<manifest> <application> ... <meta-data android:name="android.webkit.WebView.MetricsOptOut" android:value="true" /> </application> </manifest>
Los datos solo se suben desde una aplicación si el usuario da su consentimiento y la app no la inhabilita. Más información para inhabilitar los datos de diagnóstico generación de informes, consulta Privacidad del usuario en WebView informes.
API de Termination Handling
La API de Rescisión Handling controla casos en los que el proceso del renderizador para una
WebView
desaparece, ya sea porque el sistema finaliza el renderizador para recuperarlo
la memoria necesaria o porque falla el proceso del renderizador. Con esta API, puedes
permiten que tu app continúe ejecutándose aunque desaparezca el proceso del renderizador.
Si un procesador falla mientras carga una página web determinada, intenta
volver a cargar esa misma página puede provocar que un nuevo objeto WebView
presentan el mismo comportamiento de falla de renderización.
El siguiente fragmento de código ilustra cómo usar esta API dentro de
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 de Renderer Importance
Cuando los objetos WebView
operar en
multiproceso, tienes cierta flexibilidad en cuanto a la forma en que tu app controla
situaciones de falta de memoria. Puedes usar la API de Renderer Importance, que se presentó en
Android 8.0, para establecer una política de prioridad para el procesador asignado a un determinado
WebView
. En particular, quizás quieras que la parte principal de tu
app se siga ejecutando cuando un procesador que muestre
Se cierran WebView
objetos. Podrías hacer esto, por ejemplo, si
esperas no mostrar el objeto WebView
por mucho tiempo para que la
puede recuperar memoria que usaba el procesador.
En el siguiente fragmento de código, se muestra cómo asignar una prioridad al procesador
proceso asociado con los objetos WebView
de tu app:
Kotlin
val myWebView: WebView = ... myWebView.setRendererPriorityPolicy(RENDERER_PRIORITY_BOUND, true)
Java
WebView myWebView; myWebView.setRendererPriorityPolicy(RENDERER_PRIORITY_BOUND, true);
En este fragmento en particular, la prioridad del representador es la misma que, o
a la que está vinculada la prioridad predeterminada para la aplicación. El true
disminuye la prioridad del renderizador a
RENDERER_PRIORITY_WAIVED
Cuando el objeto WebView
asociado deja de estar visible. En otro
palabras, un argumento true
indica que a tu app no le importa si
el sistema mantiene activo el proceso del renderizador. De hecho, este nivel de prioridad más bajo
hace que sea probable que el proceso del renderizador se cierre por falta de memoria.
situaciones.
Para obtener más información sobre la manera en que el sistema maneja situaciones de poca memoria, consulta Procesos y app ciclo de vida.