Un receptor de anuncios recibe anuncios broadcast y reacciona ante ellos. Los anuncios broadcast pueden ser originados por el sistema (por ejemplo: Batería baja, Llamada entrante) o por las aplicaciones. Las aplicaciones también pueden crear y lanzar nuevos tipos de anuncios broadcast. Los receptores de anuncios no disponen de interfaz de usuario, aunque pueden iniciar una actividad si lo estiman oportuno. Los receptores de anuncios se estudian en el CAPÍTULO 8.
En muchas ocasiones, las aplicaciones instaladas en un terminal Android necesitan compartir información. Android define un mecanismo estándar para que las aplicaciones puedan compartir datos sin necesidad de comprometer la seguridad del sistema de ficheros. Con este mecanismo podremos acceder a datos de otras aplicaciones, como la lista de contactos, o proporcionar datos a otras aplicaciones. Los ContentProvider se estudian en el capítulo 9.
Preguntas de repaso: Componentes de una aplicación
Aunque en este libro vas a aprender mucho, resultaría imposible tocar todos los aspectos de Android y con un elevado nivel de profundidad. Por lo tanto, resulta imprescindible que dispongas de fuentes de información para consultar los aspectos que vayas necesitando. En este apartado te proponemos dos alternativas: el acceso a documentación sobre Android y el estudio de ejemplos.
Puedes encontrar una completa documentación del SDK localmente en:
…\sdk\docs\index.html
Se incluye la descripción de todas las clases (Develop > Reference), conceptos clave y otros tipos de recursos. Esta documentación también está disponible en línea a través de Internet:
Muchos de los recursos utilizados en este libro puedes encontrarlos en:
Para resolver dudas puntuales sobre programación te recomendamos la siguiente web de preguntas y respuestas:
Otra opción muy interesante para aprender nuevos aspectos de programación consiste en estudiar ejemplos. Google ha preparado un repositorio de ejemplos en GitHub que pueden ser instalados desde Android Studio.
Ejercicio: Instalación de un ejemplo desde GitHub
1. Selecciona File > New > Import Sample… Aparecerá la siguiente ventana:
Los proyectos se encuentran clasificados en categorías: Admin, Background, Connectivity, Content, Input, Media, Notification, … Selecciona un proyecto de alguna de estas categorías. A la derecha podrás leer una breve descripción o ver una vista previa.
2. Pulsa Next para pasar a la siguiente ventana. Podrás configurar el nombre de la aplicación, explorar el proyecto accediendo a su sitio web en GitHub e indicar la carpeta donde quieres descargarlo:
3. Pulsa Finish y a continuación ejecuta el proyecto seleccionado.
Programación y errores de código son un binomio inseparable. Por lo tanto, resulta fundamental sacar el máximo provecho a las herramientas de depuración.
Android Studio integra excelentes herramientas para la depuración de código. Para probarlas, introduce un error en tu código modificando MainActivity de forma que en método onCreate() tenga este código:
Este cambio introduce en Java un NullPointerException y en Kotlin un UninitializedPropertyAccessException. Si ahora ejecutas tu aplicación, te aparecerá algo similar a:
Pulsa Cerrar para finalizar la aplicación. Para averiguar más sobre el error, inserta un punto de ruptura (breakpoint) en el código fuente en la línea o.toString() (el breakpoint se introduce haciendo clic en la barra de la izquierda).
Entonces selecciona Run > Debug ‘app’ (Mayús+F9) o pulse en para ejecutarlo en modo Debug. Tu aplicación se reiniciará mostrando el siguiente mensaje:
Pero esta vez quedará suspendida cuando alcance el punto de ruptura que has introducido. Entonces puedes recorrer el código en modo Debug, igual que se haría en cualquier otro entorno de programación. Pulsa en Run > Step Over (F8) para ir ejecutando las líneas una a una.
Vídeo[tutorial]: Depurar con Android Studio
El sistema Android utiliza el fichero LogCat para registrar todos los problemas y eventos principales que ocurren en el sistema. Ante cualquier error resulta muy interesante consultarlo para tratar de encontrar su origen.
La clase Log proporciona un mecanismo para introducir mensajes desde nuestro código en este fichero. Puede ser muy útil para depurar nuestros programas o para verificar el funcionamiento del código. Disponemos de varios métodos para generar distintos tipos de mensajes:
Log.e(): Errors
Log.w(): Warnings
Log.i(): Information
Log.d(): Debugging
Log.v(): Verbose
Ejercicio: Depurar con mensajes Log
1. Modifica la clase MainActivity introduciendo la línea que aparece subrayada:
Nota sobre Java/Kotlin: Para poder utilizar la clase Log has de importar un nuevo paquete. Para ello añade al principio import android.util.Log; Otra alternativa es pulsar Alt-Intro para que se añadan automáticamente los paquetes que faltan. En algunos casos, el sistema puede encontrar dos paquetes con la clase Log, y puede tener dudas sobre cual importar. En estos casos te preguntará.
2. Ejecuta la aplicación. Aparecerá un error.
3. En Android Studio aparecerá automáticamente en la parte inferior:
En la primera línea de la captura anterior, comprobamos que se pudo entrar dentro de onCreate(). Dos líneas más abajo se indica una excepción. La información mostrada suele ser excesiva. Te recomendamos que busques las palabras “Caused by” para ver el tipo de excepción y la primera referencia a un paquete escrito por nosotros, “com.example.jtomas.myapplication”. En este ejemplo, las líneas clave son: en Java “Cased by: java.lang.NullPointerException at conm.example.jtomas.myapplication.MainActivity.onCreate(MainActivity.java:17)”. En Kotlin “Caused by: kotlin.UninitializedPropertyAccessException: lateinit property o has not been initialized at com.example.myapplication.MainActivity.onCreate (MainActivity.kt:14)”
4. Haz clic en (MainActivity.java:17) o (MainActivity.kt:14). Te abrirá la actividad MainActivity y te situará en la línea donde se ha producido el error.
Vídeo[tutorial]: LogCat con Android Studio
Si no dominas el lenguaje de programación Java o Kotlin, puede ser una buena idea repasar los conceptos más importantes de uno de estos lenguajes antes de comenzar a realizar aplicaciones en Android. Existe una gran cantidad de libros8 y tutoriales en Internet que pueden ayudarte en este propósito. También puede ser de utilidad una consulta al Anexo C.
Hemos preparado un conjunto de breves tutoriales que te mostrarán lo esencial de Java y Kotlin. Suponemos que ya tienes conocimientos de programación. De no ser así, puede que tengas dificultades en seguirlos.
Vídeo[tutorial]: Características de Java
Vídeo[tutorial]: Creación y utilización de clases9
Enlaces de interés: Comentarios y documentación javadoc
http://www.androidcurso.com/index.php/27
Vídeo[tutorial]: Encapsulamiento y visibilidad en Java10
A lo largo de este libro vamos a crear un par de aplicaciones. Una de ellas será Mis Lugares, que nos permitirá recordar los lugares donde hemos estado o que más nos gustan. Tras realizar los tutoriales que aparecen en este apartado, dispondrás de varias clases que te serán de utilidad en la aplicación Mis Lugares (estas clases son: Lugar, RepositorioLugares, TipoLugar y Geopunto).
Vídeo[tutorial]: La aplicación Mis Lugares
Aunque ya tengas experiencia en Java o Kotlin, te recomendamos que realices los tutoriales que incluimos a continuación. De esta forma, podrás familiarizarte con las clases que usaremos en Mis Lugares.
La aplicación Mis Lugares permite gestionar una colección de lugares. Para cada lugar vamos a poder almacenar mucha información: nombre, dirección, posición geográfica, etc. El primer paso a realizar va a ser crear una clase que nos permita trabajar con este tipo de información. Este tipo de clase se conoce muchas veces como POJO o clase de datos.
Ejercicio: Creación de la clase Lugar en Android Studio
Android Studio está pensado exclusivamente para crear aplicaciones Android. Sin embargo, si sigues los siguientes pasos podrás crear una aplicación 100% Java o Kotlin.
1. Crea un nuevo proyecto (File > New > New Project...) con los siguientes datos:
Phone and Tablet / Add No Activity
Name: Mis Lugares Java ó Mis Lugares Kotlin
Package name: com.example.mislugares
Language: Java ó Kotlin
Minimum API level: API 19 Android 4.4 (KitKat)
NOTA: Deja el resto de los parámetros con su valor por defecto.
2. Pulsa en File > New > New Module. Selecciona Java Library y pulsa Next.
3. Introduce en Library name: MisLugares, como Java pakage name: com.example.mislugares y en Java class name: Lugar. Pulsa el botón Finish. Se creará un nuevo módulo Java dentro de tu proyecto Android.
4. Para Kotlin, en el explorador de proyecto busca la clase Java y, con el botón derecho, selecciona Convert Java File to Kotlin File.
5. Reemplaza el código de la clase Lugar por el siguiente:
Para Java observa cómo se definen los atributos de la clase y como en el constructor se inicializa para un objeto concreto según los parámetros indicados. En estos parámetros no se indica el atributo fecha. Este representa el día y la hora en que visitamos ese lugar por última vez. Se codifica mediante un long (número entero de 64 bits), que supondremos en formato Epoch time o tiempo Unix11. Es decir, número de milisegundos transcurridos desde 1970. El método System.currentTimeMillis() nos devuelve la fecha y la hora actuales en este formato. Por lo tanto, siempre que usemos este constructor, en fecha se almacenará el instante en que el objeto fue creado.
Para Kotlin en el constructor principal indicamos directamente los atributos de la clase y en algunos casos los valores por defecto. Los getters y setters son creados automáticamente. Además, al haber indicado data class se crean otras funciones como toString(). Por lo tanto, podrás saltarte los siguientes dos puntos.
6. Solo para Java, crea los métodos getters y setters para acceder a todos los atributos de la clase. Solo tienes que pulsar con el botón derecho y seleccionar la opción Generate… > Getter and Setter y selecciona todos los atributos mientras mantienes pulsada la tecla Ctrl.
7. Solo para Java, pulsa con el botón derecho sobre el código y selecciona la opción Generate… > toString(). Selecciona todos los atributos y pulsa OK. Se añadirá un método similar a:
NOTA: El significado de @Override se explica más adelante.
8. Dentro del explorador del módulo MisLugares / java / com.example.mislugares pulsa con el botón derecho y selecciona New > Java Class o Kotlin File/Class.
9. Introduce en el campo Name: GeoPunto y pulsa Ok. Reemplaza el código por el siguiente (dejando la línea del package):
El objeto SIN_POSICION será utilizado cuando se quiera indicar que un lugar no tiene posición asignada. Observa que es un objeto de tipo estático. En Java se indica con static y en Kotlin con companion object. Esto significa que solo va a haber una instancia de este objeto creada desde el principio. Para acceder a ella usaremos GeoPunto.SIN_POSICION.
10. Solo para Java, crea en esta clase los métodos getters y setters para acceder a los dos atributos. Igual que antes, pulsa con el botón derecho y seleccionar la opción Generate… > Getter and Setter. Realiza la misma operación para equals() and hasCode().
11. Para Java y Kotlin, crea una nueva clase Java con nombre: Principal. Android Studio no permite que la clase principal esté en Kotlin.
12. Reemplaza el código por el mostrado (dejando la línea del package):
La clase Principal es algo atípica: no tiene atributos ni constructor, únicamente el método main. Cuando en un proyecto existe una clase que tiene un método con este perfil, es el que se llama para comenzar la ejecución. Como parámetros, este método recibe un array de Strings. Esta información tiene interés cuando el programa se ejecuta desde la línea de comandos con parámetros.
13. Pulsa en el botón desplegable a la derecha del botón Run . Selecciona Edit Configurations...
14. En la nueva ventana, haz clic en el signo + de la esquina superior izquierda y selecciona Application. Aparecerá una nueva configuración de aplicación. Selecciona en Name: mislugares, en Main class: com.example.mislugares.Principal y en Use classpath of module: MisLugares. Pulsa en OK.
15. Pulsa el botón Ejecución y verifica que el resultado que aparece en la ventana de Run es similar a:
“C\Program ...
Lugar {nombre=Escuela Politécnica Superior de Gandía,
direccion=C/ Paranimf, 1 46730 Gandia (SPAIN),
posicion=longitud:-0.166093, latitud:38.995656, foto=null,
telefono=962849300, url=http://www.epsg.upv.es,
comentario=Uno de los mejores lugares para formarse.,
fecha=1392332854758, valoracion=3.0}
Process finished with exit code 0
Vídeo[tutorial]: La Herencia en Java12
Enlaces de interés: Sobrecarga:
http://www.androidcurso.com/index.php/30
Vídeo[tutorial]: El polimorfismo en Java13 14
Vídeo[tutorial]: Tipos enumerados en Java15
Vídeo[tutorial]: Clases enumeradas en Kotlin
Ejercicio: El enumerado TipoLugar
En este ejercicio vamos a crear un tipo enumerado para diferenciar entre diferentes tipos de establecimientos en la aplicación Mis Lugares. Además, a cada tipo de lugar le asociaremos un String con el nombre y un recurso gráfico.
1. Vamos a crear un nuevo tipo enumerado. Para ello pulsa con el botón derecho en el paquete com.example.mislugares. Selecciona New > Java Class e introduce en Name: TipoLugar, en Kind: Enum y pulsa OK.
2. Reemplaza el código por el siguiente (dejando la línea del package):
Si quieres puedes definir otros tipos de lugares para adaptar la aplicación a tus necesidades. Observa como a cada constante le asociamos un String con el nombre del tipo de lugar y un entero. El entero se utilizará más adelante para indicar un recurso gráfico en Android con un icono representativo del tipo.
3. Abre la clase Lugar. En Kotlin añade el código subrayado y salta al punto 8:
En Java añade el siguiente atributo a la clase:
4. Añade el parámetro TipoLugar en el constructor de la clase e inicializa el atributo anterior con este parámetro:
5. Añade los métodos getter y setter correspondientes. Para ello pulsa con el botón derecho y seleccionar la opción Generate > Getter and Setter.
6. Vamos a volver a generar el método toString(). Para ello pulsa con el botón derecho y seleccionar la opción Generate > toString(). Pulsa Yes para reemplazar el método actual.
7. Abre la clase Principal y modifica la inicialización del objeto para que se incluya el nuevo parámetro, TipoLugar.EDUCACION, en el constructor.
8. Verifica el resultado ejecutando el proyecto.
Ejercicio: La interfaz RepositorioLugares
En este ejercicio vamos a crear una interfaz que nos permita almacenar una lista de objetos Lugar. A lo largo del curso esta interfaz será implementada por dos clases. En esta unidad usaremos una lista almacenada en memoria y en la última unidad una base de datos. Usar esta interface nos va a permitir desacoplar la forma en la que almacenamos los datos del resto de la aplicación. Por ejemplo, si en un futuro queremos que los datos se almacenen en la nube, solo será necesario cambiar la implementación de esta interface, dejando idéntica el resto de la aplicación.
1. Dentro del explorador del proyecto mislugares / java / com.example.mislugares, pulsa con el botón derecho y selecciona New > Java Class o New > Kotlin File/Class.
2. Introduce en el campo Name: RepositorioLugares y en Kind: Interface.
3. Reemplaza el código por el siguiente (dejando la línea del package):
Una clase que implemente esta interfaz va a almacenar una lista de objetos de tipo Lugar. Mediante los métodos indicados vamos a poder acceder y modificar esta lista. Una interfaz también puede tener funciones estáticas, como añadeEjemplos(). En Java solo está permitido con API mínima >24, por lo que lo añadiremos esta función en una clase no abstracta.
4. Esta interface será usada en uno de los siguientes apartados.
Vídeo[tutorial]: Las colecciones en Java16
Vídeo[tutorial]: Colecciones en Kotlin: introducción
Vídeo[tutorial]: Colecciones en Kotlin: List, Set y Map
Ejercicio: La clase LugaresLista
En este ejercicio vamos a crear la clase LugaresLista, que tiene como finalidad almacenar y gestionar un conjunto de objetos Lugar dentro de una lista.
1. Dentro del paquete com.example.mislugares añade la clase LugaresLista y reemplaza el código por el siguiente:
2. Pulsa Alt-Intro para que se añadan los import de las clases utilizadas.
3. Para Java, añade la siguiente sobrecarga al constructor a la clase Lugar:
Esto nos permitirá crear un nuevo lugar sin indicar sus atributos.
4. Abre la clase Principal y reemplaza el código del método main() por:
5. Verifica que el resultado es similar al siguiente:
__________
1 http://www.openhandsetalliance.com
2 Para más información consultar el Gran Libro de Android Avanzado
3 http://developer.android.com/tools/support-library
4 https://developer.android.com/guide/topics/ui/shortcuts.html
5 https://developer.android.com/jetpack/androidx?hl=ES
6 https://developer.android.com/jetpack?hl=ES
7 Se describe con detalle en el capítulo 10.
8 Recomendamos: Piensa en Java, de Bruce Eckel, Ed.Prentice Hall y Kotlin for Android Developers de Antonio Leiva.
9 Tutorial web: http://www.androidcurso.com/index.php/24 y http://www.androidcurso.com/index.php/25
10 Tutorial web: http://www.androidcurso.com/index.php/32
11 http://es.wikipedia.org/wiki/Tiempo_Unix
12 Tutorial web: http://www.androidcurso.com/index.php/29
13 Tutorial web: http://www.androidcurso.com/index.php/31
14 Tutorial web: http://www.androidcurso.com/index.php/31
15 Tutorial web: http://www.androidcurso.com/index.php/461
16 Tutorial web: http://www.androidcurso.com/index.php/462