Programación Android, Creación de Widgets I

Share if you like...Share on Facebook0Tweet about this on TwitterShare on Google+0Share on LinkedIn0

widgets

En muchas ocasiones podemos encontrarnos en Google Play aplicaciones que tienen sus propios Widgets, incluso aplicaciones que sólo contienen Widgets para mostrar cierta información al usuario.

En este tutorial vamos a explicar cómo podemos crear y utilizar estos Widgets, que nos pueden ser muy útiles, e incluso necesarios, en nuestras aplicaciones.

En primer lugar debemos saber que un Widget es un cuadro gráfico que ocupa 1 o más espacios en el escritorio del dispositivo, permitiendo a una aplicación mostrar información de forma dinámica a través de su Widget, o al usuario interactuar de una forma más sencilla y rápida con la aplicación. Por ejemplo una aplicación puede mostrar datos de consumo de llamadas realizadas de forma dinámica en el Widget, de manera que el usuario pueda visualizar esta información de una forma más sencilla, o bien puede tratarse de un Widgetcuya finalidad sea la de silenciar el teléfono, de manera que las sucesivas pulsaciones sobre el Widgetpor parte del usuario irá alternando entre el estado “silencio” y “con sonido” del terminal.

Creación de Widgets

Para diseñar un Widget de forma eficiente, antes debemos dar respuestas a las siguientes preguntas:

  • ¿Qué queremos mostrar en el Widget?
  • ¿Se puede configurar la información que deseamos mostrar en el Widget?
  • ¿Cada cuánto tiempo necesitamos que se refresque la información del Widget?
  • ¿Cómo va a interactuar el usuario con el Widget?

Una vez que tenemos esta información clara, podemos pasar a la creación de Widgets. Para ello en primer lugar debemos definir una interfaz gráfica (a través de un layout) para cada uno de nuestros Widgets, en segundo lugar crearemos su archivo de configuración en XML, que contendrá una configuración básica como por ejemplo la tasa de refresco del Widget (cada cuanto se actualiza su información de forma automática), en tercer lugar debemos crear una clase en Java en la que se codificará la lógica del Widget, acciones que debe llevar a cabo, rellenar los datos para poder mostrarlos, etc. Y por último debemos declarar cada widget en el manifest.xml de nuestro proyecto.

En este tutorial vamos a crear un sencillo Widgetque simplemente va a lanzar una determinada Activity de nuestra aplicación, por lo que la apariencia del Widget no se modificará en ningún momento, para que resulte más sencillo de entender una implementación inicial.

Crear el Layout del Widget

Como hemos dicho, lo primero es definir la interfaz que queremos que tenga nuestro Widget, en este caso un RelativeLayout que contiene un TextView:

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent"
    android:background="@drawable/shape"
    android:id="@+id/widget">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/tvWidget"
        android:id="@+id/tvWidget"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" />
</RelativeLayout>

Como vemos en el xml, al Layout le hemos asignado un shape y una id. El shape es simplemente para mostrar un cuadro en el borde de nuestro Widget, y el id veremos más adelante cuándo lo necesitaremos. El proceso de creación del shape lo tenemos en esta entrada, en este caso hemos utilizado el siguiente:

<?xml version="1.0" encoding="utf-8"?>

<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#FFFFFF"/>
    <stroke android:color="#FF0000" android:width="5dp"/>
</shape>

A la hora de crear el Layout para nuestro Widgetdebemos tener en cuenta una serie de limitaciones en cuanto al tipo de Layout que podemos utilizar, y qué controles le podemos utilizar:

  • Layouts: FrameLayout, LinearLayout, RelativeLayout, y en versiones a partir de Android 4.0 también GridLayout.
  • Controles: AnalogClock, Button, Chronometer, ImageButton, ImageView, ProgressBar y ViewFlipper. En versiones a partir de Android 3.0 también podemos utilizar AdapterViewFlipper, GridView, ListView y StackViewListView.

Para más información acerca de este tema, puedes revisar la documentación oficial de Android.

Una vez que tenemos el Layout de nuestro Widget, el siguiente paso en el proceso de creación de Widgets dijimos que era crear su archivo de configuración.

Crear el archivo de configuración del Widget

Este archivo de configuración es un recurso xml que debemos definir en nuestro proyecto dentro de la carpeta /res/xml/, y él vamos a añadir una etiqueta que contará con una serie de atributos que definirán la configuración inicial de nuestro Widget:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:initialLayout="@layout/widget"
    android:minWidth="40dip"
    android:minHeight="40dip"
    android:label="@string/tvWidget"
    android:updatePeriodMillis="3600000"
    />

El significado de estos atributos es el siguiente:

  • initialLayout: Aquí indicamos el Layout, que ya hemos creado, que representará la interfaz gráfica de nuestro Widget.
  • minWidth: El ancho mínimo que ocupará nuestro Widget en pantalla.
  • minHeight: La altura mínima que ocupará nuestro Widget en pantalla.
  • label: El nombre con el que identificaremos nuestro Widget en el listado de Widgets disponibles en el terminal.
  • updatePeriodMillis: Cada cuanto tiempo, en milésimas de segundo, se debe actualizar de forma automática la información de nuestro widget.

Para más información acerca de estos, y otros posibles atributos, puedes revisar la documentación oficial de Android.

Un pequeño truco para saber qué dimensiónes darle a nuestro Widget es utilizar la siguiente fórmula, tanto para el ancho como para el alto del Widget:

  • dip = (num_celdas * 70) – 30

En esta fórmula num_celdas equivale al número de espacios de nuestro escritorio que deseamos ocupar.

El tercer paso de la creación de Widgets consistía en crear una clase Java, que va a extender de AppWidgetProvider, y que recoge la lógica que debe ejecutar nuestro Widget, es decir, qué queremos que haga nuestro Widget:

public class Widget extends AppWidgetProvider {
    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        // Acciones que debe realizar nuestro widget cada vez que pase el periodo de actualización.
    }
}

Como vemos, hemos sobreescrito el método onUpdate, que se lanzará automáticamente cada vez que pase el tiempo que hemos indicado en el xml de configuración a través del atributo updatePeriodMillis. En este método tendremos que codificar la acción que debe llevar a cabo el Widgetpara actualizarse, en el caso de querer mostrar información que cambie al usuario, o qué acciones debe llevar a cabo el Widgetcuando se pulse sobre él. En nuestro caso tenemos que indicar que cuando se pulse sobre el Widgetse lance nuestra aplicación, mostrando una Activity distinta a la principal de nuestra aplicación. Para este ejemplo simplemente debes crear una nueva Activity que contenga un TextView en el que ponga “Activity del Widget”, para comprobar que se ejecuta de forma correcta la acción del Widget.

El código que debemos añadir a nuestro Widget es el siguiente:

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
    final int N = appWidgetIds.length;

    for (int i=0; i<N; i++) {
        int appWidgetId = appWidgetIds[i];

        Intent intent = new Intent(context, WidgetActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);

        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget);
        views.setOnClickPendingIntent(R.id.widget, pendingIntent);

        appWidgetManager.updateAppWidget(appWidgetId, views);
    }
}

Como vemos en primer lugar hemos creado un bucle, que va a recorrer todos los id de los Widgets que pueda haber puesto el usuario en el escritorio (y que nos viene como parámetro en el método onUpdate). De esta manera podremos actualizar de todos los Widgets que existan en el escritorio.

Después hemos creado un Intent que va a abrir la Activity que hemos creado para nuestro Widget, y después lo incluiremos en un PendingIntent (recordemos que en tutoriales anteriores explicamos de una forma muy sencilla el PendingIntent como un Intent creado a la espera de ser ejecutado en un momento posterior).

Ahora aparece una nueva clase en Proyecto Simio, la clase RemoteViews. Esta clase la implementa Android para que establezca un canal de comunicación entre nuestra aplicación y el propio Widget, cuya ejecución va al margen de la ejecución de la propia aplicación. Esto es fácil de entender en el momento en que pensamos que tenemos un Widgeten pantalla, que cada cierto tiempo puede estar ejecutando determinadas acciones en background, mientras que nuestra aplicación está cerrada, por lo que sus ejecuciones se realizan totalmente por separado. Para poder conectar de alguna manera el Widgetque hemos creado con la aplicación que tenemos, debemos hacerlo obligatoriamente a través de este objeto RemoteViews (vista remota). Para inicializar el objeto RemoteViews necesitamos pasar como primer parámetro un String con el package de nuestra aplicación, que obtenemos a través de context.getPackageName() y en segundo lugar el Layout del Widget.

Una vez inicializado este objeto indicamos que cuando se realice un click sobre el Widgetse lance el Intent que hemos definido, y que contiene nuestro PendingIntent. Esto lo hemos hecho a través de views.setOnClickPendingIntent(R.id.widget, pendingIntent). Y este es el punto en el que necesitabamos que nuestro Layout del Widgettuviera un id asignado, pues como se puede ver es el primero de los parámetros que hemos pasado al método.

Por último, a través del AppWidgetMannager, hemos actualizado nuestro Widget.

Para ver más información acerca del resto de métodos de AppWidgetProvider, puedes revisar la documentación oficial de Android.

Definir el Widget en el manifest.xml

El último paso que nos queda en la creación de Widgets es añadir nuestro Widgetal manifest.xml de nuestro proyecto. Esto es tan sencillo como añadir una etiqueta (al igual que hacíamos cuando creábamos un BroadcastReceiver), dentro de la etiqueta <application>:

<receiver
    android:name="com.iae.gps.first_widget.widget.Widget"
    android:label="Mi Widget">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>

    <meta-data
        android:name="android.appwidget.provider"
        android:resource="@xml/appwidget_provider" />
</receiver>

En el siguiente tutorial profundizaremos un poco más en el uso del Widget, creando un ejemplo en el que podremos silenciar nuestro teléfono, o volver a ponerlo con sonido, pulsando el Widget, y cambiando además su apariencia para indicar al usuario si el sonido está activado o desactivado.

Descargas

Puedes descargar el proyecto completo aquí.

Share if you like...Share on Facebook0Tweet about this on TwitterShare on Google+0Share on LinkedIn0
The following two tabs change content below.
Reborn as IT Developer. Desarrollador Android y fundador de Proyecto Simio. "En realidad, yo no puedo enseñar nada a nadie, sólo puedo hacerles pensar." - Sócrates.

3 thoughts on “Programación Android, Creación de Widgets I

  1. “Este archivo de configuración es un recurso xml que debemos definir en nuestro proyecto dentro de la carpeta /res/xml/, y él vamos a añadir una etiqueta que contará con una serie de atributos que definirán la configuración inicial de nuestro Widget.”

    En donde se coloca este codigo? en la carpeta /res no tengo /xml , no comprendo donde va eso. ayuda porfavor

Deja un comentario