App hibrida con Android - parte 2
En la primera parte se veia el ejemplo de creación de una web app sencilla. Al ser este caso una aplicacion sobre un blog, la conexion a internet es obligatoria. Sin embargo, en muchos otros casos no es necesario de dicha conexion, como por ejemplo si almacenamos el codigo web en la propia aplicacion. Ademas no se aprovachaba el potencial de una aplicacion hibrida, como el poder llamar desde el codigo web a codigo nativo de la aplicacion/sistema.
En esta segunda parte, he ampliado un poco el ejemplo anterior convirtiendolo en una autentica aplicacion hibrida. He añadido una pagina almacenada localmente, que se mostrara en caso de que no disponer de conexion a internet. Esta pagina a su vez tienen dos funciones en Javascript que llaman a una parte del codigo "nativo" de Android.
Primero creamos la carpeta de "assets" en el proyecto
Despues incluimos los siguientes archivos en dicha carpeta. Estos seran los que conforman la pagina local: una pagina que nos informa de error de conexión, su correspondiente hoja de estilos y una imagen.
- error.html
<html> <head> <link href="estilos.css" rel="stylesheet"> </head> <body> <div class="mensaje"> <img class="imagen" src="imagen1.png"> <h2 class="texto">Ups... Parece que hay un problema de conexión</h2> </div> <div class="botones" > <input class="boton" type="button" value="Solucionar" onClick="mostrarConsejos()" /> <input class="boton" type="button" value="Reintentar" onClick="lanzarReintento()" /> </div> <script type="text/javascript"> function mostrarConsejos() { Android.consejos(); } function lanzarReintento() { Android.reintentar(); } </script> </body> </html>
- estilos.css
body { background-color: #444; } .mensaje { text-align: center; } .texto { font-family: 'Open Sans'; color: #1abc9c; } .imagen { width: 192px; height: 192px; image-rendering: optimizeSpeed; /* STOP SMOOTHING, GIVE ME SPEED */ image-rendering: -moz-crisp-edges; /* Firefox */ image-rendering: -o-crisp-edges; /* Opera */ image-rendering: -webkit-optimize-contrast; /* Chrome (and eventually Safari) */ image-rendering: pixelated; /* Chrome */ image-rendering: optimize-contrast; /* CSS3 Proposed */ -ms-interpolation-mode: nearest-neighbor; /* IE8+ */ } .botones { text-align: center; } .boton { font: 15px 'Open Sans'; text-transform: uppercase; padding: 10px 20px; background-color: #444; border: 2px solid #fff; color: #fff; margin: 0 auto; display: inline-block; }
- imagen.png
public boolean comprobarConexion(Context context){ ConnectivityManager conManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo i = conManager.getActiveNetworkInfo(); if(i == null || !i.isConnected() || !i.isAvailable()) return false; else return true; } public void cargarPaginaPrincipal() { if(comprobarConexion(this)){ myWebView.loadUrl("https://creandobits.blogspot.com"); } else { myWebView.loadUrl("file:///android_asset/error.html"); } } public class WebAppInterface { Context mContext; WebAppInterface(Context c) { mContext = c; } @JavascriptInterface public void reintentar() { runOnUiThread(new Runnable() { @Override public void run() { cargarPaginaPrincipal(); } }); } @JavascriptInterface public void consejos() { AlertDialog alertDialog = new AlertDialog.Builder(mContext).create(); alertDialog.setTitle("Soluciones"); alertDialog.setMessage(" - Desactiva el modo avion \n - Activa Wi-Fi \n - Activa datos móviles"); alertDialog.show(); } }
Sustituimos lo siguiente en onCreate :
// Cambiamos esto: myWebView.loadUrl("https://creandobits.blogspot.com"); // por esto : myWebView.addJavascriptInterface(new WebAppInterface(this), "Android"); cargarPaginaPrincipal();
Modificamos el metodo shouldOverrideUrlLoading de la clase MyWebViewClient :
public boolean shouldOverrideUrlLoading(WebView view, String url) { if(comprobarConexion(view.getContext())){ // Si la url corresponde a nuestro sitio web, es decir comienza con nuestro dominio, // esta se carga dentro del webview. Si no, se carga en el navegador web del sistema. if (url.startsWith("https://creandobits.blogspot.com")) { return false; } else { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); startActivity(intent); return true; } } else { if(!url.startsWith("file://")) view.loadUrl("file:///android_asset/error.html"); return true; } }
Por ultimo, añadimos el siguiente permiso (necesario para conocer el estado de la conexión a internet) al AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
A partir de aqui tenemos la aplicacion terminada.
La funcion conprobarConexion de MainActivity.java es la encargada de averiguar si disponemos de conexion a Internet, en shouldOverrideUrlLoading redirige a nuestra pagina local de error si nos hemos quedado sin internet. Ahi se muestra la forma de cargar una pagina local, basta con tenerla almacenada en una carpeta de la aplicacion y cargar con:
myWebView.loadUrl("file:///android_asset/" + rutaPaginaHTML);
En las dos funciones Javascript lanzarReintento() y mostrarConsejos() del archivo error.html, podemos ver un objeto llamado "Android", este es el nombre que con el que hemos designado a nuestra interfaz WebAppInterface en:
myWebView.addJavascriptInterface(new WebAppInterface(this), "Android");
Dichas funciones, llaman a las funciones reintentar() y consejo() de WebAppInterface y son los encargados de ejecutar el codigo de Android. La primera reintenta conectar con la pagina web principal y la segunda lanza Dialog con diferentes consejos para recuperar la conexion a internet.
Una cuestion que no se toca aqui y que podria ser util, es el caso contrario: como ejecutar codigo javascript en el webview desde la parte "nativa" de la aplicacion. Seria algo asi:
myWebView.loadUrl("javascript:"+ stringConNuestroCodigoJavascript);
Comentarios
Publicar un comentario