AppWidget Android: Ejemplo usando BroadcastReceiver y Localización

Introducción

En este tutorial vamos a realizar un Widget embebido en el escritorio (AppWidget) cuya funcionalidad será la de mostrar la calle actual en la que estamos ubicados de manera que cuando hagamos clic en el mismo se nos abrirá un navegador Web con la información que nos provee la wikipedia sobre la persona a la cual se le dedicó la calle.

En el medio de la imagen que se muestra a la derecha se muestra la apariencia visual que tendrá el Widget, de manera que el texto del botón estará en color rojo cuando el GPS esté apagado o fuera de cobertura y en negro en caso contrario cambiándose el texto del botón por el nombre de la calle en la cual nos ubicamos al desplazarnos.

Este ejemplo servirá para conocer algunos de los conceptos y posibilidades que nos ofrece Android, como por ejemplo:

  • Configuración y arquitectura de las aplicaciones en Android
  • BroadcastReceiver
  • Widget
  • Localización
  • RemoteViews

Si quieres trastear, puedes descargarte el código fuente desde clic aquí. Si quieres probarlo directamente en tu dispositivo puedes descargarte la aplicación desde clic aquí

Se presupone que el lector ya tiene ciertos conocimientos sobre Android.

Manos a la obra... el ejemplo paso a paso:

AndroidManifest.xml

A continuación puede observar:

  1. Lineas 30 y 31: La aplicación necesita permisos para conectarse a Internet así como tener acceso a un método de localización exacto como el GPS.
  2. La aplicación está basada completamente en eventos pues sólo estará viva cuando el sistema lance eventos relacionados con el ciclo de vida de un Widget (APPWIDGET_UPDATE, APPWIDGET_ENABLED, APPWIDGET_DISABLED) o cuando se generen notificaciones relacionadas con el posicionamiento. En este segundo caso, nos hemos creado una acción propia (com.autentia.intent.GPS_LOCATION_CHANGED) y posteriormente le diremos a Android que genere una notificación con ese action cuando existan eventos de localización. Nos hemos tenido que crear una acción propia, porque no existe ninguna definida en Android para este tipo de notificaciones.
  3. Linea 27: La versión mínima de SDK que debe tener el dispositivo es la versión 3 que es la que tienen la gran mayoría (Android 1.5).
  4. Linea 14: Indicamos al WidgetProvider las propiedades del Widget (tiempo de refresco, dimensiones que debe reservar para el mismo, ventana GUI inicial, etc.)

res/xml/widget_properties.xml

Después de dias enteros acostándome a horas poco normales no he conseguido activar/desactivar el GPS desde programación. Nadie en ningún foro contesta esta pregunta... por favor, si tú sabes como hacerlo, compártelo con todos ;-)
Por cierto, creo que es de las pocas cosas que no puedes controlar desde programación... el resto no he visto limitaciones hasta la fecha.

Bueno, la cuestión es que al colocar el Widget en el escritorio, es posible que el GPS no esté activo, y si no está activo no puedes registrar un oyente de eventos de localización... por lo que cada 20 segundos hago que salte el evento WIDGET_UPDATE y así solvento este problema.

res/layout/widget_main.xml

La ventana principal del Widget que consta de una imagen con el Logo de Autentia y un botón en donde se mostrará la calle en la que nos ubicamos.

Si te fijas, en ambos controles gráficos uso estilos (tag style) para configurar la apariencia.

Ojo!!, en los GUI de este tipo de Widgets (AppWidgets) no puedes colocar cualquier control gráfico de Android (Spinner, etc) están muy limitados!! (como es lógico pues se supone que es para ver información... que no quita que al hacer clic se abra una ventana de configuración, etc.)

res/values/styles.xml

Definición de los estilos... recuerda que esto es un tutorial... tiene miga todo esto, pueden hederarse, etc.

res/values/colors.xml

Definición de colores (por supuesto todo esto no es obligatorio...)

res/values/strings.xml

En este archivo definimos los recursos de cadenas de caracteres... internacionalización por medio del típico mecanismo de prefijos _es, etc..

res/values/arrays.xml

Definición de un array que nos servirá para posteriormente en el código fuente quitar de los resultados de ubicación que nos de el GPS las palabras que contenga este array, por ejemplo si el GPS nos dice que estamos en la calle "Plaza de Manuel Becerra" en el botón mostraremos "Manuel Becerra".

src/com.autentia.android.widget.streetinfo.StreetInfoWidget.java

El siguiente BroadcastReceiver (Receptor de eventos o notificaciones) será invocado cuando se produzcan los eventos que fueron definidos anteriormente en el archivo de configuración AndroidManifest.xml

Si el evento es ACTION_APPWIDGET_UPDATE o ACTION_APPWIDGET_ENABLED, solicitaremos el LocationManager que lance la notificación "com.autentia.intent.GPS_LOCATION_CHANGED"... que tratará nuestro siguiente BroadcastReceiver...

En caso de que no sea ninguno de esos dos eventos, será el evento ACTION_APPWIDGET_DISABLED (el usuario ha quitado el Widget de la pantalla u otros motivos) y desregistraremos la notificación de eventos.

Los valores 0,0 de la instrucción requestLocationUpdates.... indican el tiempo y los metros transcurridos entre evento y evento.. dejándolos a 0 ahorramos energía, ya que dejamos que el sistema lo gestione y lance eventos cuando crea necesario (si estamos parados no lanzará).

src/com.autentia.android.widget.streetinfo.LocationUpdatesBroadcastReceiver.java

Bueno, en esta clase hay más chicha... empecemos

  • Esta clase tratará los eventos de localización: GPS habilitado, deshabilitado, temporalmente fuera de servicio y cambio de localización.
  • Cada evento tiene unos datos asociados (Bundle).
  • Para modificar la vista del Widget y sus controles desde este proceso, usaremos RemoteView.
    La variable widgetView apuntará a la ventana widget_main y luego con instrucciones como ésta: widgetView.setTextColor(R.id.street, context.getResources().getColor(R.color.enabled)); modificaremos uno de los controles que contiene (en este caso modificaremos el color del botón) y posteriormente con la instrucción manager.updateAppWidget(streetInfoWidget, widgetView) le diremos al administrador de Widget que lo repinte.
  • La clase android.location.Geocoder nos servirá para traducir puntos geográficos (latitud, longitud) en direcciones legibles para las personas (calle, pais, ciudad, etc).

Conclusiones

Sin lugar a dudas, Android es sorprendente... nos ofrece un abanico de posibilidades inmensas, está bien diseñado y es relativamente fácil de programar..

Bueno, eso es todo, un saludo.
Carlos García.

Categorías del artículo

Comentarios de los lectores