Usa WebView para entregar una aplicación web o una página web como parte de una
app cliente. La clase WebView es una extensión de la clase View
de Android que te permite mostrar páginas web como parte del diseño de tu actividad. No incluye las funciones de un navegador web completamente desarrollado, como controles de navegación o una barra de direcciones. De forma predeterminada, todo lo que hace WebView es mostrar una página web.
WebView puede ayudarte a proporcionar información en tu app que tal vez debas actualizar, como un acuerdo de usuario final o una guía del usuario. Dentro de la app para Android,
puedes crear un Activity que contenga un
WebView y, luego, usarlo para mostrar el documento que está alojado en línea.
WebView también puede ser útil cuando tu app proporciona al usuario datos que requieren una conexión a Internet para recuperarlos, como el correo electrónico. En ese caso, en lugar de realizar una solicitud de red, analizar los datos y renderizarlos en un diseño de Android, posiblemente sea más fácil crear una WebView en tu app para Android que muestre una página web con todos los datos del usuario. Puedes diseñar una página web específica para dispositivos Android y, luego, implementar una WebView en tu app para Android que cargue esa página.
En este documento, se describe cómo comenzar a usar WebView, cómo vincular JavaScript desde tu página web al código del cliente en la app para Android, cómo manejar la navegación de páginas y cómo administrar ventanas cuando se usa WebView.
Trabaja con WebView en versiones anteriores de Android
Para usar de forma segura las capacidades más recientes de WebView en el dispositivo en el que se
ejecuta tu app, agrega la biblioteca AndroidX Webkit. Esta es una biblioteca estática que puedes agregar a tu aplicación para usar las APIs de android.webkit que no están disponibles para versiones anteriores de la plataforma.
Agrega lo siguiente a tu archivo build.gradle:
Kotlin
dependencies { implementation("androidx.webkit:webkit:1.8.0") }
Groovy
dependencies { implementation ("androidx.webkit:webkit:1.8.0") }
Explora el WebView ejemplo en GitHub para obtener más detalles.
Agrega una WebView a tu app
Para agregar un WebView a tu app, puedes incluir el elemento <WebView> en tu
diseño de la actividad o configurar toda la ventana de la Activity como un WebView en
onCreate().
Cómo agregar una WebView en el diseño de la actividad
Para agregar una WebView a tu app en el diseño, incluye el siguiente código en el archivo XML del diseño de la actividad:
<WebView android:id="@+id/webview" android:layout_width="match_parent" android:layout_height="match_parent" />
Para cargar una página web en la WebView, usa loadUrl(), como se muestra en el
siguiente ejemplo:
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");
Cómo agregar una WebView en onCreate()
Para agregar una WebView a tu app en el método onCreate() de una actividad, utiliza una lógica similar a la siguiente:
Kotlin
val myWebView = WebView(activityContext) setContentView(myWebView)
Java
WebView myWebView = new WebView(activityContext); setContentView(myWebView);
Luego, carga la página:
Kotlin
myWebView.loadUrl("http://www.example.com")
Java
myWebView.loadUrl("https://www.example.com");
O carga la URL desde una 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");
Tu app debe tener acceso a Internet. Para obtenerlo, solicita el
INTERNET permiso en tu archivo de manifiesto, como se muestra en el siguiente
ejemplo:
<manifest ... > <uses-permission android:name="android.permission.INTERNET" /> ... </manifest>
Puedes personalizar tu WebView de cualquiera de las siguientes maneras:
- Habilita la compatibilidad con la pantalla completa empleando
WebChromeClient. También se llama a esta clase cuando unaWebViewnecesita permiso para hacer modificaciones en la IU de la app host, como crear o cerrar ventanas y enviar diálogos de JavaScript al usuario. Si deseas obtener más información sobre la depuración en este contexto, consulta el artículo Depuración de aplicaciones web. - Maneja los eventos que afectan el procesamiento del contenido, como los errores en el envío de formularios
o la navegación con
WebViewClient. También puedes usar esta subclase para interceptar la carga de URL. - Habilita JavaScript modificando
WebSettings. - Usa JavaScript para acceder a los objetos del marco de trabajo de Android que insertaste en una
WebView.
Usa JavaScript en WebView
Si la página web que planeas cargar en tu WebView usa JavaScript, debes habilitarlo para la WebView. Después de habilitar JavaScript, puedes crear interfaces entre el código de la app y el de JavaScript.
Habilita JavaScript
De forma predeterminada, JavaScript está inhabilitado en la WebView. Habilítalo a través del objeto WebSettings adjunto a tu WebView. Puedes recuperar el objeto WebSettings con `getSettings()` y habilitar JavaScript con `setJavaScriptEnabled()`. Puedes recuperar el objeto WebSettings con
getSettings() y habilitar JavaScript con
setJavaScriptEnabled().
Consulta el siguiente ejemplo:
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 proporciona acceso a una variedad de otros parámetros de configuración que podrían resultarte útiles. Por ejemplo, si estás desarrollando una aplicación web diseñada específicamente para la WebView en tu app para Android, puedes definir una string de usuario-agente personalizado con setUserAgentString() y, luego, buscar el usuario-agente personalizado en tu página web para verificar que el cliente que solicita la página web sea en efecto tu app para Android.
Cómo vincular el código de JavaScript al código de Android
Cuando desarrollas una aplicación web diseñada específicamente para la WebView en tu app para Android, puedes crear interfaces entre el código de JavaScript y el código de Android del cliente. Por ejemplo, el código de JavaScript puede llamar a un método en
tu código de Android para mostrar un Dialog, en lugar de utilizar la función
alert() de JavaScript.
A fin de vincular una nueva interfaz entre el código de JavaScript y el de Android, llama a
addJavascriptInterface() y pásale una instancia de clase para vincularla al código de
JavaScript y un nombre de interfaz al que pueda llamar el código para acceder a la
clase.
Para obtener más información sobre la comunicación entre JavaScript y el código nativo, incluidas las APIs más modernas y seguras, consulta Accede a las APIs nativas con JSBridge.
Por ejemplo, puedes incluir la siguiente clase en tu 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(); } }
En este ejemplo, la clase WebAppInterface permite que la página web cree un
Toast mensaje mediante el método showToast().
Puedes vincular esta clase al código de JavaScript que se ejecuta en tu WebView con addJavascriptInterface(), como se muestra en el siguiente ejemplo:
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");
Así se crea una interfaz llamada Android para el código de JavaScript que se ejecuta en la WebView. En este punto, tu aplicación web tiene acceso a la clase WebAppInterface. Por ejemplo, a continuación se muestran instrucciones de HTML y JavaScript que crean un mensaje de notificación usando la nueva interfaz cuando el usuario presiona un botón:
<input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" /> <script type="text/javascript"> function showAndroidToast(toast) { Android.showToast(toast); } </script>
No es necesario inicializar la interfaz Android desde JavaScript. La WebView la pone automáticamente a disposición de tu página web. Por lo tanto, cuando un usuario
presiona el botón, la showAndroidToast() función usa la Android interfaz
para llamar al método WebAppInterface.showToast().
Cómo manejar la navegación de páginas
Cuando el usuario presiona un vínculo de una página web en tu WebView, según el comportamiento predeterminado Android inicia una app que maneja las URLs. Por lo general, se abre el navegador web predeterminado y se carga la URL de destino. Sin embargo, puedes anular ese comportamiento para la WebView a fin de que los vínculos se abran dentro de tu WebView. Luego, puedes permitir que el usuario navegue hacia atrás y hacia adelante a través del historial de páginas web que mantiene tu WebView.
Para abrir los vínculos que presiona el usuario, proporciona un WebViewClient para tu WebView
con setWebViewClient(). Todos los vínculos que presiona el usuario se cargan en tu WebView. Si deseas tener más control sobre dónde se carga un vínculo en el que se hizo clic, crea tu
propio WebViewClient que anule el shouldOverrideUrlLoading()
método. En el siguiente ejemplo, se supone que MyWebViewClient es una clase 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; } }
Luego, crea una instancia de este nuevo WebViewClient para la WebView:
Kotlin
val myWebView: WebView = findViewById(R.id.webview) myWebView.webViewClient = MyWebViewClient()
Java
WebView myWebView = (WebView) findViewById(R.id.webview); myWebView.setWebViewClient(new MyWebViewClient());
Ahora, cuando el usuario presiona un vínculo, el sistema llama al método shouldOverrideUrlLoading(), que comprueba si el host de la URL coincide con un dominio específico, como se definió en el ejemplo anterior. Si coincide, el método muestra el valor "false" y no anula la carga de la URL. Permite que la WebView cargue la URL como de costumbre.
Si el host de la URL no coincide, se crea un Intent a fin de iniciar la
predeterminada Activity para manejar las URLs, que se resuelve en el navegador web
predeterminado del usuario.
Cómo manejar URLs personalizadas
WebView aplica restricciones cuando solicita recursos y resuelve vínculos que utilizan un esquema de URL personalizada. Por ejemplo, si implementas devoluciones de llamada como
shouldOverrideUrlLoading() o shouldInterceptRequest(), entonces
WebView las invoca solo para URLs válidas.
Por ejemplo, es posible que WebView no llame a tu método shouldOverrideUrlLoading() para vínculos como este:
<a href="showProfile">Show Profile</a>
Las URLs no válidas, como la que se muestra en el ejemplo anterior, se manejan de manera incoherente en WebView, por lo que te recomendamos que uses una URL bien formada.
Puedes usar un esquema personalizado o una URL HTTPS para un dominio que controle tu organización.
En lugar de usar una string simple en un vínculo, como en el ejemplo anterior, puedes utilizar un esquema personalizado como el siguiente:
<a href="example-app:showProfile">Show Profile</a>
Luego, puedes manejar esta URL en tu método shouldOverrideUrlLoading() de la siguiente manera:
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; }
La API de shouldOverrideUrlLoading() está diseñada principalmente para iniciar intents para URLs específicas. Cuando la implementes, asegúrate de mostrar false para las URLs que maneja la WebView. Sin embargo, no estás limitado a iniciar intents. Puedes reemplazar el inicio de intents con cualquier comportamiento personalizado en los ejemplos de código anteriores.
Cómo navegar por el historial de páginas web
Cuando tu WebView anula la carga de URL, acumula automáticamente un historial de las páginas web visitadas. Puedes navegar hacia atrás y hacia adelante por el
historial con goBack() y goForward().
Por ejemplo, a continuación, se muestra cómo tu Activity puede usar el botón Atrás del dispositivo para navegar hacia atrá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); }
Si tu app usa AndroidX AppCompat 1.6.0 o versiones posteriores, puedes simplificar aún más el fragmento anterior:
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(); } }
El método canGoBack() muestra el valor "true" si hay un historial de páginas web que el
usuario puede visitar. Del mismo modo, puedes usar canGoForward() para verificar si
hay un historial de páginas siguientes. Si no realizas esta verificación, después de que el usuario llegue al final del historial, goBack() y goForward() no harán nada.
Cómo manejar los cambios de configuración del dispositivo
Durante el tiempo de ejecución, se producen cambios en el estado de la actividad cuando se modifica la configuración de un dispositivo, por ejemplo si los usuarios giran el dispositivo o descartan un editor de método de entrada (IME). Estos cambios causarán que se destruya la actividad de un objeto WebView y se cree una actividad nueva, lo que también generará un nuevo objeto WebView que cargará la URL del objeto destruido. Para modificar el comportamiento predeterminado de tu actividad, puedes cambiar la forma en que maneja los cambios de orientation en tu manifiesto. Para obtener más información
sobre cómo manejar los cambios de configuración durante el tiempo de ejecución, consulta el artículo Cómo administrar los cambios de configuración.
Administrar ventanas
De forma predeterminada, las solicitudes para abrir ventanas nuevas se ignoran. Esto es así tanto si las abre JavaScript como si las abre el atributo de destino en un vínculo. Puedes personalizar el WebChromeClient para aplicar tu propio comportamiento cuando se abran varias ventanas.
Para proteger mejor tu app, es recomendable evitar que se abran ventanas emergentes y nuevas. La forma más segura de implementar este comportamiento es pasar "true" a
setSupportMultipleWindows() sin anular el método
onCreateWindow(), del que depende setSupportMultipleWindows().
Esta lógica evita que se cargue cualquier página que use target="_blank" en sus vínculos de
carga.