El
presente
d ocumento
trata
de
introducir
al
alumno
al
desarrollo
de
aplicaciones
Android,
guindolo
en
el
desarrollo
de
una
aplicacin
con
varios
ejemplos
bsicos
que
abarca
en
gran
medida
los
conceptos
bsicos
en
el
desarrollo
de
aplicaciones
Android
utilizando
el
ADT
(Android
Developer
Tools)
de
Eclipse.
Tabla
de
contenido
Qu
es
Android?
..................................................................................................................................
8
El
sistema
operativo
Android
.......................................................................................................................
8
Task
(tarea)
..................................................................................................................................................
8
Componentes
de
la
plataforma
Android
......................................................................................................
8
Google
Play
..................................................................................................................................................
9
Android
Development
Tools
..........................................................................................................
10
Android
SDK
...............................................................................................................................................
10
Android
debug
bridge
(adb)
.......................................................................................................................
10
Android
Developer
Tools
y
Android
Studio
................................................................................................
10
Dalvik
Virtual
Machine
...............................................................................................................................
11
Android
Runtime
........................................................................................................................................
11
Como
desarrollar
aplicaciones
Android
.....................................................................................................
11
Proceso
de
conversin
desde
cdigo
fuente
hasta
una
aplicacin
Android
..............................................
11
Seguridad
y
permisos
.......................................................................................................................
12
Concepto
de
seguridad
en
Android
...........................................................................................................
12
Concepto
de
permiso
en
Android
..............................................................................................................
12
Instalacin
...........................................................................................................................................
13
Consideraciones
previas
y
de
instalacin
...................................................................................................
13
Preparar
IDE
...............................................................................................................................................
14
Emulador
de
dispositivo
Android
y
Dispositivo
Virtual
Android
(Android
Virtual
Devices,
AVD)
......................................................................................................................................
16
Emulador
Android
y
Android
Virtual
Device
..............................................................................................
16
Atajos
para
el
emulador
de
dispositivos
Android
......................................................................................
17
Google
vs.
Android
AVD
.............................................................................................................................
18
Optimizacin
de
Velocidad
........................................................................................................................
18
Emulador
Intel
............................................................................................................................................
19
Emulador
Alternativo
.................................................................................................................................
20
Ejercicio:
Crear
e
iniciar
Android
Virtual
Device
...................................................................
20
Target
(objetivo)
........................................................................................................................................
20
Crear
el
AVD
...............................................................................................................................................
20
Iniciar
tu
AVD
.............................................................................................................................................
22
Ejercicio:
Crear
aplicacin
Android
en
Eclipse
.......................................................................
23
Asistente
de
proyectos
Android
.................................................................................................................
23
Crear
proyecto
Android
.............................................................................................................................
23
Ejercicio:
Inicie
la
aplicacin
Android
generada
....................................................................
28
Iniciar
AVD
..................................................................................................................................................
28
Inicicar
la
aplicacin
...................................................................................................................................
29
Qu
es
Android?
El
sistema
operativo
Android
Android
es
un
sistema
operativo
basado
en
el
kernel
de
Linux.
El
proyecto
responsable
del
desarrollo
del
sistema
Android
es
llamado
Android
Open
Source
Project
(AOSP)
y
es
principalmente
liderado
por
Google.
El
sistema
operativo
Android
soporta
procesamiento
en
background;
proporciona
una
librera
de
interfaces
de
usuario
enriquecida,
soporta
grficos
2D
y
3D
usando
el
estndar
OpenGL-ES
y
garantiza
acceso
a
los
archivos
del
sistema
as
como
la
base
de
datos
embebida
SQLite
Una
aplicacin
Android
tpicamente
consiste
de
diferentes
componentes
visuales
y
no
visuales
y
se
pueden
volver
a
utilizar
componentes
de
otras
aplicaciones.
Task
(tarea)
La
reutilizacin
de
los
componentes
de
otras
aplicaciones
nos
lleva
al
concepto
de
task
(tarea)
en
Android.
Una
aplicacin
puede
acceder
a
otros
componentes
de
Android
para
lograr
una
task.
Por
ejemplo,
a
partir
de
un
componente
de
nuestra
aplicacin,
puede
desencadenar
otro
componente
en
el
sistema
Android,
el
cual
gestiona
sus
fotos,
aunque
este
componente
no
es
parte
de
su
aplicacin.
En
este
componente
se
selecciona
una
foto
y
volver
a
la
aplicacin
para
utilizar
la
foto
seleccionada.
Tal
flujo
de
eventos
se
representa
en
el
siguiente
grfico.
2.-
inicia
galera
1.-
Usuario
dispara
Recoger
foto
va
botn
3.-
Usuario
selecciona
una
foto
El
sistema
Android
es
una
completa
pila
de
software,
que
suele
estar
dividido
en
las
cuatro
reas
como
se
muestra
en
el
siguiente
grfico.
Los
niveles
pueden
ser
descritos
como:
Applications
(Aplicaciones)
-
El
Proyecto
Open
Source
Android
contiene
varias
aplicaciones
por
defecto,
como
el
Navegador,
Cmara,
Galera,
Msica,
telfono
y
mucho
ms.
Application
framework
(Marco
de
aplicacin)
-
API
que
permite
la
interaccin
de
alto
nivel
con
el
sistema
Android
desde
las
aplicaciones
de
Android.
Libraries
and
runtime
(Libreras
y
tiempo
de
ejecucin)
-
Bibliotecas
para
Application
framework
con
muchas
funciones
comunes
(renderizado
grfico,
almacenamiento
de
datos,
navegacin
web,
etc),
as
como
el
runtime
Dalvik
y
las
bibliotecas
fundamentales
de
Java
para
la
ejecucin
de
aplicaciones
Android.
Kernel
Linux
-
capa
de
la
Comunicacin
para
el
hardware
subyacente.
Google
Play
Google
ofrece
el
servicio
de
Google
Play,
un
mercado
en
el
que
los
programadores
pueden
ofrecer
sus
aplicaciones
Android
para
los
usuarios
de
Android.
Los
clientes
utilizan
la
aplicacin
Google
Play
lo
que
les
permite
comprar
e
instalar
las
aplicaciones
del
servicio
Google
Play.
Google
Play
tambin
ofrece
un
servicio
de
actualizacin.
Si
un
programador
carga
una
nueva
versin
de
su
aplicacin
a
Google
Play,
este
servicio
avisa
a
los
usuarios
existentes
que
hay
una
actualizacin
disponible
y
permite
que
se
instalen
la
actualizacin.
Google
Play
permite
el
acceso
a
los
servicios
y
bibliotecas
para
los
programadores
de
aplicaciones
para
Android,
tambin.
Por
ejemplo,
se
ofrece
un
servicio
para
usar
y
mostrar
Google
Maps
y
otro
para
sincronizar
el
estado
de
la
aplicacin
entre
las
diferentes
instalaciones
Android.
La
provisin
de
estos
servicios
a
travs
de
Google
Play
tiene
la
ventaja
de
que
estn
disponibles
para
las
versiones
de
Android
ms
viejas
y
pueden
ser
actualizados
por
Google
sin
la
necesidad
de
una
actualizacin
de
la
versin
de
Android
en
el
telfono.
10
Ambos
IDEs
contienen
toda
la
funcionalidad
necesaria
para
crear,
compilar,
depurar
y
desplegar
aplicaciones
de
Android.
Tambin
permiten
a
los
desarrolladores
crear
e
iniciar
los
dispositivos
Android
virtuales
para
pruebas.
Android
Runtime
Aplicaciones
de
Android
estn
escritas
principalmente
en
el
lenguaje
de
programacin
Java.
Con
Android
4.4,
Google
present
el
Android
Runtime
(ART)
como
un
runtime
opcional
para
Android
4.4.
Se
espera
que
las
versiones
posteriores
4.4
usarn
ART
como
runtime
predeterminado.
ART
utiliza
Ahead
Of
Time
compilation.
Durante
el
despliegue
de
una
aplicacin
en
un
dispositivo
Android,
el
cdigo
de
la
aplicacin
es
traducida
a
cdigo
mquina.
Esto
da
lugar
a
aprox.
30%
de
cdigo
de
compilacin
ms
grande,
pero
permite
una
ejecucin
ms
rpida
desde
el
principio
de
la
aplicacin.
Recordemos
que,
para
efectos
de
este
curso
estaremos
usando
Android
4.0
(API
14),
esto
es
slo
para
informacin.
11
Los
archivos
de
cdigo
fuente
de
Java
son
convertidos
en
archivos
de
clases
de
Java
por
el
compilador
Java.
El
SDK
de
Android
contiene
una
herramienta
llamada
dx
que
convierte
archivos
de
clase
Java
en
un
archivo
.dex
(Dalvik
ejecutable).
Todos
los
archivos
de
clase
de
la
aplicacin
se
colocan
en
el
archivo
.dex.
Durante
este
proceso
de
conversin
la
informacin
redundante
en
los
archivos
de
clase
sern
optimizados
en
el
archivo
.dex.
Por
ejemplo,
si
la
misma
String
se
encuentra
en
archivos
de
clase
diferentes,
el
archivo
.dex
contiene
slo
una
referencia
a
esta
String.
Estos
archivos
.dex
son
por
lo
tanto
mucho
ms
pequeo
en
tamao
que
los
archivos
de
clases
correspondientes.
El
archivo
de
.dex
y
los
recursos
de
un
proyecto
Android,
esto
es,
las
imgenes
y
los
archivos
XML,
se
empaquetan
en
un
archivo
.apk
(Android
Package).
El
programa
aapt
(Android
Asset
Packaging
Tool)
realiza
este
paso.
El
archivo
.apk
resultante
contiene
todos
los
datos
necesarios
para
ejecutar
la
aplicacin
Android
y
se
puede
implementar
en
un
dispositivo
Android
a
travs
de
la
herramienta
adb.
Seguridad
y
permisos
Concepto
de
seguridad
en
Android
El
sistema
Android
instala
cada
aplicacin
Android
con
un
nico
usuario
y
ID
de
grupo.
Cada
archivo
de
aplicacin
es
privado
para
este
usuario
generado,
esto
es,
otras
aplicaciones
no
pueden
acceder
a
estos
archivos.
Adems,
cada
aplicacin
Android
se
inicia
en
su
propio
proceso.
Por
lo
tanto
por
medio
del
kernel
de
Linux
subyacente,
cada
aplicacin
Android
se
asla
de
otras
aplicaciones
en
ejecucin.
Si
se
deben
compartir
los
datos,
la
aplicacin
debe
hacer
esto
de
manera
explcita
a
travs
de
un
componente
de
Android
que
se
encarga
de
la
distribucin
de
los
datos,
por
ejemplo,
a
travs
de
un
servicio
o
de
un
proveedor
de
contenido.
12
se
presentan
al
usuario
antes
de
instalar
la
aplicacin.
El
usuario
tiene
que
decidir
si
estos
permisos
sern
otorgados
a
la
aplicacin.
Si
el
usuario
deniega
una
autorizacin
necesaria,
la
aplicacin
relacionada
no
se
puede
instalar.
La
comprobacin
de
la
autorizacin
slo
se
realiza
durante
la
instalacin,
los
permisos
no
pueden
ser
negados
u
otorgados
despus
de
la
instalacin.
Una
aplicacin
Android
declara
los
permisos
necesarios
en
su
archivo
de
configuracin
AndroidManifest.xml.
Tambin
puede
definir
los
permisos
adicionales
que
puede
utilizar
para
restringir
el
acceso
a
determinados
componentes.
Nota
No
todos
los
usuarios
presten
atencin
a
los
permisos
requeridos
durante
la
instalacin.
Sin
embargo,
algunos
usuarios
hacen
y
escriben
comentarios
negativos
en
Google
Play
si
creen
que
la
aplicacin
es
demasiado
invasiva.
Instalacin
Consideraciones
previas
y
de
instalacin
1.
2.
Para
los
fines
de
este
curso
se
considera
que
se
debe
de
tener
instalado
java
con
la
versin
jdk1.7.0_51,
en
caso
de
no
tenerlo
instalado
ir
al
siguiente
enlace
http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-
1880260.html
y
escoger
la
opcin
que
ms
se
apegue
a
su
sistema.
Verificar
tener
instalado
el
ADT
(Android
Developer
Tool),
que
es
la
herramienta
(IDE)
de
desarrollo
basada
en
Eclipse
que
nos
servir
para
el
desarrollo
de
nuestra
aplicacin,
en
este
punto
tambin
es
bueno
verificar
que
se
tenga
instalado
el
SDK
de
Android.
En
caso
de
no
tenerla
instalado
nada
de
esto,
esta
es
la
url
que
nos
lleva
a
la
pgina
de
descarga
oficial
del
ADT
http://developer.android.com/sdk/index.html.
a. En
esta
pgina
hacer
click
en
el
botn
que
se
muestra
en
la
Imagen
1.
Imagen
1
b. Aceptar
los
trminos
y/o
condiciones
adems
de
escoger
la
versin
de
32-bit
o
de
64-
bit,
como
se
muestra
en
la
Imagen
2
esto
se
define
basndose
en
la
versin
de
java
que
tengan
instalado
en
su
sistema.
Es
importante
que
escoger
bien
porque
si
no
coinciden
las
versiones
del
jdk
con
el
ADT
no
se
podr
ni
instalar.
13
Imagen
2
Imagen
3
Preparar
IDE
1. Para
consideraciones
de
este
manual
se
trabajar
con
la
versin
de
Android
4.0
Ice
Cream
Sandwich
(API
14).
2. Lo
primero
ser
ejecutar
la
aplicacin
ADT
(Imagen
4).
Imagen
4
14
Imagen
5
4. La
ventana
mostrada
en
la
Imagen
6
nos
muestra
todos
los
SDKs
existentes
y
algunas
herramientas
disponibles,
pero
lo
que
nos
interesa
es
lo
que
est
encerrado
en
el
cuadro
rojo,
hay
dos
opciones
una
que
ya
est
instalado
el
SDK
que
ocupamos
(y
diga
Installed),
y
la
otra
es
que
an
no
lo
est
que
es
el
caso
que
muy
probablemente
tengamos
por
ser
de
reciente
instalacin,
para
tal
caso
debemos
de
marcar
las
casillas
de
los
checkboxes
en
las
opciones
SDK
Platform,
ARM
EABI
v7a
System
Image
y
Google
APIs,
seleccionadas
estas
opciones
se
procede
a
seleccionar
el
botn
Install
que
ahora
debe
de
decir
Install
2
packages,
Imagen
6
a. Aparecer
en
este
momento
una
ventana
que
nos
pide
que
aceptemos
las
condiciones
de
uso
de
los
paquetes
a
instalar
y
seleccionamos
Accept
All,
y
luego
click
al
botn
Install,
como
se
muestra
en
la
Imagen
7
15
Imagen
7
16
AVDs
le
permiten
probar
sus
aplicaciones
de
Android
en
diferentes
versiones
y
configuraciones
de
Android
sin
acceso
al
hardware
real.
Durante
la
creacin
de
su
AVD
se
define
la
configuracin
para
el
dispositivo
virtual.
Esto
incluye,
por
ejemplo,
la
resolucin,
la
versin
de
la
API
de
Android
y
la
densidad
de
la
pantalla.
Se
pueden
definir
varios
AVDs
con
diferentes
configuraciones
y
comenzar
en
paralelo.
Esto
le
permite
probar
diferentes
configuraciones
de
los
dispositivos
a
la
vez.
17
ATAJO
DESCRIPCIN
Optimizacin
de
Velocidad
Durante
la
creacin
de
un
emulador
se
puede
elegir
si
se
desea,
ya
sea
Snapshot
o
habilitar
Use
Host
GPU.
Si
selecciona
la
opcin
de
Snapshot,
la
segunda
vez
que
se
inicia
el
dispositivo
se
inicia
muy
rpido,
debido
a
que
la
AVD
almacena
su
estado
en
caso
que
lo
cierre.
Si
selecciona
Usar
Host
GPU
la
AVD
utiliza
la
tarjeta
grfica
de
su
ordenador
directamente,
hace
el
renderizado
en
el
dispositivo
emulado
mucho
ms
rpido.
18
Emulador
Intel
El
emulador
de
Intel
que
puede
ser
instalado
a
travs
del
Administrador
SDK
de
Android
es
mucho
ms
rpido
en
la
ejecucin
en
el
hardware
de
Intel
/
AMD.
Si
lo
instala
a
travs
del
SDK,
es
necesario
instalar
tambin
el
controlador
que
se
encuentra
en
el
directorio
de
instalacin
del
dispositivo.
19
Emulador
Alternativo
Hay
alternativas
disponibles
al
emulador
por
defecto
de
Android.
Por
ejemplo,
el
emulador
Genymotion
es
relativamente
rpido
en
la
puesta
en
marcha
y
ejecucin
de
proyectos
de
Android
Crear
el
AVD
Definir
un
nuevo
Android
Virtual
Device
(AVD)
abriendo
el
AVD
Manager
via
Window>Android
Virtual
Device
Manager
y
presionar
el
botn
New
Ingresar
valores
similares
a
los
de
la
siguiente
toma
de
pantalla.
20
Nota
Asegurarse
que
la
opcin
Use
Host
GPU
este
seleccionada.
Esto
permite
que
el
AVD
use
la
unidad
de
procesamiento
grfico
(GPU)
de
su
computadora
y
hace
el
renderizado
mucho
ms
rpido.
Despus
presionar
el
botn
OK.
Esto
crear
la
configuracin
del
AVD
y
lo
desplegar
bajo
la
lista
de
dispositivos
virtuales
disponibles.
21
Iniciar
tu
AVD
Seleccionar
la
nueva
entrada
y
presionar
el
botn
Start.
Seleccionar
Launch
en
el
siguiente
dialogo.
Advertencia
No
interrumpa
el
proceso
de
inicio,
esto
podra
corrompir
el
AVD.
El
primer
inicio
puede
tomar
arriba
de
10
minutos
en
mquinas
viejas.
En
una
maquina
moderna
tpicamente
toma
1
3
minutos
para
un
nuevo
AVD
al
iniciar.
Despus
de
iniciado
el
AVD,
puedes
controlar
la
GUI
con
el
mouse.
El
emulador
puede
proveer
acceso
a
los
botones
del
telfono
va
un
men
del
lado
derecho
del
emulador.
22
Tip
Una
vez
inicializado,
no
detener
el
AVD
durante
el
desarrollo.
Si
se
cambia
algo
en
la
aplicacin
y
quiere
probar
una
nueva
versin,
simplemente
hay
que
correr
o
ejecutar
de
nuevo
la
aplicacin
en
el
AVD.
23
Para
crear
un
nuevo
proyecto
Android
seleccione
File
New
Other...
Android
Android
Project
en
el
men.
Introduzca
los
datos
de
ajuste
de
la
siguiente
tabla
en
la
primera
pgina
del
asistente.
Tabla
2.
Ajuste
para
su
proyecto
Android
Property
Value
Application Name
Test App
Project Name
com.utm.primero
Package Name
com.utm.primero
Pulse
el
botn
Siguiente
y
asegrese
de
habilitar
la
opcin
Create
a
launcher
icon
(Crear
un
icono
de
lanzador
)
y
Create
activity
(Crear
actividad).
24
Pulse
el
botn
Next
y
seleccione
la
plantilla
BlankActivity.
Pulse
el
botn
Next
para
proceder.
25
Introduce
los
siguientes
datos
en
el
cuadro
de
dilogo
para
la
plantilla
BlankActivity.
La
seleccin
se
representa
en
la
pantalla
despus
de
la
tabla.
Tabla
3.
Valores
para
la
plantilla
Parameter
Value
Activity
MainActivity
Layout
activity_main
26
Pulse
el
botn
Finish.
El
asistente
le
puede
pedir
que
instale
la
biblioteca
de
compatibilidad.
Si
es
as,
seleccione
para
instalarla.
27
Una
vez
que
est
listo,
desbloque
su
emulador.
28
Inicicar
la
aplicacin
Seleccione
el
proyecto
Android,
haga
clic
derecho
sobre
l
y
seleccione
Run-As
Android
Aplication.
29
Se
le
puede
pedir
si
el
Android
Developer
Tools
deben
supervisar
los
mensajes.
Seleccione
Yes
en
este
caso
y
pulse
el
botn
OK.
As
se
inicia
la
aplicacin
en
la
AVD.
La
aplicacin
iniciada
es
una
aplicacin
muy
simple
que
slo
muestra
la
cadena
Hola,
mundo!
.
30
Asistentes
de
Android
Se
encontrarn
los
asistentes
especficos
de
Android
bajo
File
New
Other...
Android
como
se
muestra
en
la
siguiente
captura
de
pantalla.
Estos
asistentes
le
permiten
crear
proyectos
para
Android.
Perspectiva
DDMS
31
Perspectiva
Android
ADT
agrega
la
perspectiva
DDMS
(Dalvik
Device
Monitoring
Service)
para
interactuar
con
tu
dispositivo
Android
(virtual)
y
tu
aplicacin
Android.
Selecciona
Window
Open
Perspective
Other...
DDMS
para
abrir
esta
perspectiva.
Aqu
se
agrupan
varias
vistas
que
pueden
ser
usadas
de
forma
independiente.
En
la
parte
izquierda
se
muestran
los
dispositivos
Android
conectados
y
los
procesos
en
ejecucin
en
el
dispositivo.
El
lado
derecho
es
un
conjunto
de
vistas
con
diferentes
propsitos.
Puede
seleccionar
procesos
y
desencadenar
acciones
de
la
barra
de
herramientas,
por
ejemplo,
iniciar
una
traza
o
detener
el
proceso.
File
Explorer
El
explorar
de
archivos
permite
navegar
el
sistema
de
archivos
del
dispositivo
de
Android
ya
sea
virtual
o
real
conectado.
32
Activities
(Actividades)
Services
(Servicios)
Broadcast
Receivers
(receivers)
Content
providers
(providers)
Contexto
Instancia
de
la
clase
android.content.Context
que
proporciona
la
conexin
con
el
sistema
Android
el
cual
ejecuta
la
aplicacin.
Por
ejemplo,
se
puede
revisar
el
tamao
de
la
pantalla
del
dispositivo
actual
via
el
Context.
Tambin
da
acceso
a
los
recursos
del
proyecto.
Es
la
interfaz
a
la
informacin
global
sobre
el
entorno
de
la
aplicacin.
La
clase
Context
tambin
proporciona
acceso
a
los
servicios,
esto
es,
el
manejador
de
alarmas
para
disparar
eventos
basados
en
el
tiempo.
Las
actividades
y
servicios
extienden
de
la
clase
Context.
Por
lo
tanto,
se
pueden
utilizar
directamente
para
acceder
al
Context.
BroadcastReceiver
Un
broadcast
receiver
(receiver)
puede
ser
registrado
para
escuchar
los
mensajes
del
sistema
y
los
intents.
Un
receiver
ser
notificado
por
el
sistema
Android
si
el
evento
especificado
ocurre
33
Por
ejemplo,
se
puede
registrar
un
receiver
para
el
vento
en
el
que
el
sistema
android
finaliza
el
proceso
de
arranque.
O
se
puede
registrar
para
el
evento
en
el
que
el
estado
del
telefono
cambia,
esto
es,
que
alguien
llama.
Service
(Servicio)
Un
servicio
realiza
tareas
sin
proporcionar
una
interfaz
de
usuario.
Se
pueden
comunicar
con
otros
componentes
Android,
por
ejemplo,
a
travs
de
los
receptores
de
radiodifusin
y
notificar
al
usuario
a
travs
del
marco
de
la
notificacin
de
Android.
ContentProvider
Un
content
provider
(provider)
define
una
interfaz
estructurada
de
datos
de
la
aplicacin.
Un
proveedor
puede
ser
utilizado
para
acceder
a
datos
dentro
de
una
aplicacin,
pero
tambin
se
puede
utilizar
para
compartir
datos
con
otras
aplicaciones.
Acitivity
(Actividad)
Las
activities
son
la
base
para
las
aplicaciones
de
usuario
en
Android.
Estas
ya
fueron
vistas
en
la
seccin
anterior.
Fragments
(Fragmentos)
Los
Fragments
son
componentes
los
cuales
corren
en
el
contexto
de
una
activity.
Un
fragment
encapsula
cdigo
de
aplicaciones
as
qu
es
ms
fcil
reutilizar
y
soportar
dispositivos
de
diferentes
tamaos.
La
siguiente
imagen
muestra
una
activity
llamada
MainActivity.
En
una
pantalla
ms
pequea
que
muestra
slo
un
fragmento
y
permite
que
el
usuario
se
desplaza
a
otro
fragmento.
En
una
pantalla
panormica
que
muestra
dos
fragmentos.
34
Los
fragmentos
son
componentes
opcionales
que
le
permiten
reutilizar
los
componentes
de
interfaz
de
usuario
para
diferentes
configuraciones
de
dispositivos.
35
Live
Wallpapers
Los
Live
Wallpapers
permiten
crear
fondos
animados
para
la
pantalla
de
inicio
de
Android.
El
Android
Manifest
La
configuracin
de
la
aplicacin
para
Android
Los
componentes
y
configuracin
de
una
aplicacin
para
Android,
se
describen
en
el
archivo
AndroidManifest.xml.
Este
archivo
se
conoce
como
el
archivo
de
manifiesto
o
el
manifiesto.
El
manifiesto
tambin
especifica
metadatos
adicionales
para
la
aplicacin,
por
ejemplo,
iconos
y
el
nmero
de
versin
de
la
aplicacin.
Este
archivo
es
ledo
por
el
sistema
Android
durante
la
instalacin
de
la
aplicacin.
El
sistema
Android
evala
este
archivo
de
configuracin
y
determina
las
capacidades
de
la
aplicacin.
36
Todas
las
activities,
servicios
y
contenido
de
los
content
provider
de
la
aplicacin
se
deben
declarar
de
forma
esttica
en
este
archivo.
Los
broadcast
receivers
pueden
ser
definidos
estticamente
en
el
archivo
de
manifiesto
o
dinmicamente
al
tiempo
de
ejecucin
de
la
aplicacin.
Permisos
El
archivo
de
manifiesto
de
Android
tambin
debe
contener
los
permisos
necesarios
para
la
aplicacin.
Por
ejemplo,
si
la
aplicacin
requiere
acceso
a
la
red,
se
debe
especificar
aqu.
37
El
manifiesto
de
Android
Versin
y
paquete
El
atributo
de
package
define
el
paquete
base
para
los
objetos
Java
que
se
hace
referencia
en
este
archivo.
Si
un
objeto
de
Java
se
encuentra
dentro
de
un
paquete
diferente,
se
debe
declarar
con
el
nombre
completo
del
paquete
calificado.
Google
Play
requiere
que
cada
aplicacin
Android
utilice
su
propio
nombre
nico
de
paquete.
Por
lo
tanto
es
un
buen
hbito
el
usar
su
nombre
de
dominio
inverso
aqu.
Esto
evitar
colisiones
con
otras
aplicaciones
de
Android.
android:versionName y
android:versionCode especifican
la
version
de
su
aplicacin.
versionName es
lo
que
ve
el
usuario
y
puede
ser
cualquier
cadena.
versionCode debe
ser
un
entero.
El
Android
Market
determina
si
se
debe
llevar
a
cabo
una
actualizacin
de
las
aplicaciones
para
la
instalacin
existente
basado
en
el
versionCode.
Por
lo
general,
comienza
con
"1"
y
aumenta
este
valor
por
uno
si
sale
una
nueva
versin
de
su
aplicacin.
Aplicacin
y
componentes
La
seccin
<application>
permite
definir
metadatos
para
su
aplicacin
y,
opcionalmente,
definir
una
clase
de
aplicacin
explcita.
Tambin
es
un
contenedor
para
la
declaracin
de
los
componentes
de
su
Android.
La
etiqueta
<activity> define
un
componente
activity.
El
atributo
de
nombre
seala
a
la
clase,
la
cual
(si
no
es
totalmente
calificado)
es
relativa
al
paquete
definido
en
el
atributo
del
paquete.
La
parte
de
intent
filter
en
el
archivo
de
manifiesto
de
Android,
dice
a
Android
en
tiempo
de
ejecucin
que
esta
actividad
debe
registrarse
como
un
posible
punto
de
entrada
a
la
aplicacin
y
puesta
a
disposicin
en
el
lanzador
del
sistema
Android.
La
accin
que
define
esto
(android: name =
"android.intent.action.MAIN")
se
puede
iniciar
y
el
parmetro
category android:
name = parmetro "android.intent.category.LAUNCHER"
le
dice
al
sistema
Android
para
agregar
la
actividad
al
lanzador.
El
valor
@string/app_name
se
refiere
a
los
archivos
de
recursos
que
contienen
el
valor
real
del
nombre
de
la
aplicacin.
El
uso
de
un
archivo
de
recursos
hace
que
sea
fcil
para
proporcionar
diferentes
recursos
(por
ejemplo,
secuencias,
colores,
iconos)
los
diferentes
dispositivos
y
hace
que
sea
fcil
de
traducir
las
aplicaciones.
Al
igual
que
en
la
etiqueta <activity>,
puede
utilizar
el
service,
el
receiver
y
provider
para
declarar
otros
componentes
Android.
38
Valor
Descripcin
minSdkVersion
Permisos
Su
aplicacin
puede
declarar
permisos
con
la
etiqueta
<permission>
y
declarar
que
se
requiere
un
permiso
de
operaciones
con
la
etiqueta
<uses-permission>.
La
seccin
uses-feature
le
permite
especificar
la
configuracin
del
hardware
requerida
para
su
dispositivo.
Por
ejemplo,
el
siguiente
fragmento
sera
necesario
que
el
dispositivo
disponga
una
cmara.
<uses-feature android:name="android.hardware.camera" />
Localizacin
de
instalacin
A
travs
del
atributo
installLocation de
su
aplicacin,
puede
especificar
si
la
aplicacin
se
puede
instalar
en
la
memoria
externa
del
dispositivo.
Utilice
auto
o
preferExternal
para
permitir
esto.
Advertencia
39
En
realidad
esta
opcin
se
utiliza
muy
poco,
como
una
aplicacin
instalada
en
el
almacenamiento
externo
se
detiene
una
vez
que
el
dispositivo
est
conectado
a
un
ordenador
y
se
monta
como
almacenamiento
USB.
Ms
informacin
Se
puede
encontrar
ms
informacin
acerca
de
los
atributos
y
secciones
del
manifesto
en
la
documentacin
del
Android
Manifest.
Recursos
Archivos
de
recursos
Recursos,
como
imgenes
y
archivos
de
configuracin
XML,
se
mantienen
separados
a
partir
del
cdigo
fuente
de
las
aplicaciones
de
Android.
Los
archivos
de
recursos
se
deben
colocar
en
el
directorio
en
la
subcarpeta
predefinida
/res.
La
subcarpeta
especfica
depende
del
tipo
de
recurso
que
se
almacena.
La
siguiente
tabla
ofrece
una
visin
general
de
los
recursos
admitidos
y
sus
prefijos
de
carpetas
estndar.
Tabla
5.
Recusros
Recursos
Folder
Description
Drawables
/res/drawables
Las
imgenes
(por
ejemplo,
JPEG
o
PNG
archivos)
o
archivos
XML
que
describen
un
objeto
Drawable.
Valores
Simples
/res/values
Layouts
/res/layout
Archivos
XML
con
descripciones
de
los
layout
que
se
utilizan
para
definir
la
interfaz
de
usuario
para
las
Actividades
y
fragmentos.
/res/values
Estilos
temas
Animaciones
/res/animator
Define
animaciones
en
XML
para
la
API
de
animacin
que
permite
animar
40
Recursos
Folder
Description
las
propiedades
arbitrarias
de
objetos
con
el
tiempo.
Raw data
/res/raw
Menus
/res/menu
Ejemplo
de
recurso
La
siguiente
lista
es
un
ejemplo
para
el
archivo
llamado
values.xml
en
los
/res/values
que
definen
un
par
de
constantes
de
cadena,
una
matriz
de
String,
un
color
y
una
dimensin.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Test</string>
<string name="action_settings">Settings</string>
<string name="hello_world">Hello world!</string>
<string-array name="operationsystems">
<item>Ubuntu</item>
<item>Android</item>
<item>Microsoft Windows</item>
</string-array>
<color name="red">#ffff0000</color>
<dimen name="mymargin">10dp</dimen>
</resources>
Calificadores
de
recursos
Tambin
es
posible
aadir
calificadores
adicionales
a
nombre
de
la
carpeta
para
indicar
que
los
recursos
relacionados
se
deben
usar
para
configuraciones
especiales.
Por
ejemplo,
se
puede
especificar
que
archivo
de
diseo
slo
es
vlido
para
un
determinado
tamao
de
la
pantalla.
41
Views
(vistas)
Clase
View
Un
view
en
Android
representa
un
widget,
por
ejemplo,
un
botn,
o
un
layout
manager.
Todos
los
views
en
Android
extienden
de
la
clase
android.view.View.
Esta
clase
es
relativamente
grande
(ms
de
18
000
lneas
de
cdigo)
y
proporciona
una
gran
cantidad
de
funcionalidad
base
para
las
subclases.
El
cliente
puede
implementar
sus
propios
views
extendiendo
android.view.View.
Views personalizadas
42
Los
desarrolladores
son
libres
de
desarrollar
sus
propios
views
mediante
la
ampliacin
de
la
clase
android.view.View.
Definicin
de
los
layouts
a
travs
de
archivos
de
diseo
de
XML
es
la
manera
preferida.
Esto
separa
la
lgica
de
programacin
a
partir
de
la
definicin
de
diseo.
Tambin
permite
la
definicin
de
diferentes
diseos
para
diferentes
dispositivos.
Un
layout
se
asigna
a
una
actividad
a
travs
de
la
llamada
del
mtodo
setContentView,
como
se
demuestra
en
el
siguiente
ejemplo
de
cdigo.
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
public class MainActivity extends Activity {
43
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
Definiendo
Ids
Si
un
view
debe
accederse
a
travs
de
cdigo
Java,
se
tiene
que
dar
a
la
View
un
identificador
nico
a
travs
del
atributo
android:id.
Para
asignar
un
nuevo
ID
a
una
View
de
utilizar
el
atributo
android:id
del
elemento
correspondiente
en
el
archivo
layout.
A
continuacin
se
muestra
un
ejemplo
en
el
que
un
botn
recibe
el
ID
boton1
establecida
desde
el
parmetro
android:id="@+id/button1".
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Show Preferences" >
</Button>
Esto
permite
utilizar
el
ID
en
el
archivo
layout.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
44
tools:context=".MainActivity" >
<Button
android:id="@id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_marginRight="27dp"
android:text="Button" />
</RelativeLayout>
Cambiar
el
color
de
fondo
del
linear
layout
a
plata
(#C0C0C0).
Usar
para
esto
la
propiedad
android:background.
45
Implementar
el
siguiente
mtodo
en
su
clase
MainActivity.
public void onClick (View view) {
Toast.makeText(this, "Botn 1 presionado",
Toast.LENGTH_LONG).show();
}
46
Tip
47
Para
asignar
Ids
las
views,
usar
el
atributo
android:id,
android:id="@+id/orientacion
Asignarlos
basados
en
la
siguiente
tabla
Tabla
6
Asignacin
de
ID
ID
View
Parte
del
resultado
del
layout
sera
similar
al
siguiente
listado
<!-- Este fragmento es parte del archivo de layout ms grande -->
<RadioGroup
android:id="@+id/orientacion"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<RadioButton
android:id="@+id/horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Horizontal" >
</RadioButton>
<RadioButton
android:id="@+id/vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="Vertical" >
</RadioButton>
</RadioGroup>
El
layout
resultante
debe
ser
similar
a
la
siguiente
captura
de
pantalla.
48
por
ejemplo:
49
break;
}
}
});
Validar
Correr
la
aplicacin
y
seleccionar
los
diferentes
radio
buttons.
Asegurarse
que
la
orientacin
de
los
botones
cambie
en
base
a
la
seleccin.
Usando
Resources
Referencias
a
recursos
en
cdigo
La
clase
Reosurces permite
acceder
a
recursos
individules.
Una
instancia
de
la
clase
Reosurces
puede
ser
recuperado
va
el
mtodo
getRosurces() de
la
clase
Context.
Como
actividades
y
servicios
extienden
de
la
clase
de
Context,
puede
utilizar
este
mtodo
directamente
en
las
implementaciones
de
estos
componentes.
Una
instancia
de
la
clase
de
Reosurces tambin
es
requerida
por
otras
clases
del
framework
de
Android.
Por
ejemplo,
el
siguiente
cdigo
muestra
cmo
crear
un
archivo
de
Bitmap a
partir
de
un
ID
de
referencia.
// BitmapFactory requires an instance of the Resource class
BitmapFactory.decodeResource(getResources(), R.drawable.ic_action_search);
50
Assets
Qu
son
los
assets?
Mientras
el
directorio
res
contiene
valores
estructurados
los
cuales
son
conocidos
por
la
plataforma
Android,
el
directorio
assets
puede
ser
usado
para
almacenar
cualquier
tipo
de
dato.
Se
pueden
acceder
a
los
archivos
almacenados
en
esta
carpeta
basandose
en
su
ruta.
El
directorio
assets tambin
permite
tener
sub-
carpetas.
Nota
51
Tambin
se
podra
almacenar
datos
estructurados
en
la
carpeta
/res/raw,
pero
es
considerada
buena
practica
usar
el
directorio
assets
para
tales
datos.
Accesando
assets
Para
accesar
a
estos
datos
se
hace
va
el
AssetsManager
el
cual
puede
accesar
va
el
mtodo
getAssets()
desde
una
instancia
de
la
clase
Context.
La
clase
AssetsManager
te
permite
leer
un
archivo
en
la
carpeta
assets
como
un
InputStream
con
el
mtodo
open(). El
sisguiente
cdifo
muestra
un
ejemplo
de
esto.
// get the AssetManager
AssetManager manager = getAssets();
// read the "logo.png" bitmap from the assets folder
InputStream open = null;
try {
open = manager.open("logo.png");
Bitmap bitmap = BitmapFactory.decodeStream(open);
// assign the bitmap to an ImageView in this layout
ImageView view = (ImageView) findViewById(R.id.imageView1);
view.setImageBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (open != null) {
try {
open.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Tip
Si
no
se
tiene
algn
archivo
.png
a
la
mano,
usa
el
buscador
de
Google
para
Android
png
files.
52
Validar
Asegurate
que
si
presionas
el
nuevo
botn,
la
imagen
es
reemplazada.
Valor
Nombre Aplicacin
Convertidor Temperatura
Nombre Proyecto
com.utm.android.convertidortemperatura
53
Propiedad
Valor
Nombre paquete
com.utm.android.convertidortemperatura
BlankActivity
Activity
MainActivity
Layout
activity_main
Despus
de
que
el
asistente
termina,
un
proyecto
con
una
estructura
similar
al
de
la
siguiente
imagen
es
creado.
54
Crear
atributos
Android
permite
crear
recursos
estticos
para
definir
atributos,
por
ejemplo,
Strings
o
colores.
Esos
atributos
pueden
ser
usados
en
otros
archivos
XML
o
por
un
cdigo
fuente
de
Java.
Selecciona
el
archivo
res/values/string.xml
para
editarlo.
Si
se
quiere
agregar
una
definicin
al
archivo.
Presionar
el
botn
Add
Seleccionar
la
entrada
Color
en
el
siguiente
dialogo
y
presionar
el
botn
OK
55
Agregar
ms
atributos,
en
esta
ocasin
del
tipo
String.
El
atributo
string
pernite
al
desarrollador
traducir
la
aplicacin
en
un
punto
posterior.
Nombre
Valor
celsius
a Celsius
fahrenheit
a
Fahrenheit
calc
Calcular
Cambiar
a
la
representacin
XML
y
validar
que
los
valores
son
los
correctos.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Convertidor Temperatura</string>
<string name="action_settings">Settings</string>
<string name="hello_world">Hello world!</string>
<string name="celsius">a Celsius</string>
<string name="fahrenheit">a Fahrenheit</string>
<string name="calcular">Calcular</string>
<color name="myColor">#F5F5F5</color>
</resources>
56
Nota
La
vista
Paleta
cambia
frecuentemente,
as
que
la
vista
podri
ser
un
poco
diferente.
57
Click
en
la
cabecera
de
la
seccin
Text
Fields
para
ver
todos
los
text
fields.
Arrastrar
el
widget
Plain
Text
dentro
del
layout
para
crear
un
campo
de
entrada
de
texto.
Nota
Todas
la
entradas
en
la
seccin
Text
Fields
define
campos
de
texto.
Las
diferentes
entradas
define
atributos
adicionales
para
ellos,
por
ejemplo,
si
el
campo
de
texto
debera
de
contener
solo
nmeros.
A
continuacin
seleccionamos
la
seccin
Form
Widgets
en
la
Paleta
(Palette)
y
arrastar
y
soltar
una
entrada
RadioGroup
dentro
del
layout.
El
nmero
de
radio
buttons
agregados
al
grupo
de
radio
buttons
depende
de
la
versin
de
Eclipse.
Aseguremonos
de
que
haya
dos
radio
buttons,
ya
sea
borrando
o
agregando
radio
buttons
al
grupo.
58
Arrastrar
un
Button
desde
la
seccin
Form
Widgets
dentro
del
layout.
El
resultado
debera
de
lucir
similar
a
la
siguiente
captura
de
pantalla.
Cambiando
a
la
pestaa
XML
del
archivo
layout
y
verificando
que
el
archivo
luzca
similar
al
siguiente
listado.
ADT
cambia
los
templates
muy
rpido,
as
que
el
XML
podra
lucir
un
poco
diferente.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
59
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<EditText
android:id="@+id/editText1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:ems="10" />
<RadioGroup
android:id="@+id/radioGroup1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/editText1"
android:layout_below="@+id/editText1" >
<RadioButton
android:id="@+id/radio0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="RadioButton" />
<RadioButton
android:id="@+id/radio1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="RadioButton" />
</RadioGroup>
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/radioGroup1"
android:layout_below="@+id/radioGroup1"
android:layout_marginTop="22dp"
android:text="Button" />
</RelativeLayout>
Nota
Podran
verse
algunos
mensajes
de
advertencias
porque
se
tienen
algunas
Strings
como
hard-coded.
Esto
se
soluciona
en
la
siguiente
seccin
de
este
ejercicio.
60
Los
atributos
de
una
view
pueden
tambin
ser
cambiados
va
las
view
Eclipse
Properties
o
va
el
men
de
contexto
de
la
view.
Pero
cambiar
propiedades
en
el
archivo
XML
es
tipcamente
ms
rpido
si
sabes
lo
que
deseas
cambiar.
Cambiando
al
archivo
XML
y
asignando
el
valor
@string/celsius
a
la
propiedad
android:text
del
primer
radio
button.
Asignar
el
atributo
@string/fahrenheit
a
la
propiedad
android:text
del
segundo
radio
button.
<RadioGroup
android:id="@+id/radioGroup1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/editText1"
android:layout_below="@+id/editText1"
android:layout_marginLeft="16dp"
android:layout_marginTop="41dp" >
<RadioButton
android:id="@+id/radio0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="@string/celsius" />
<RadioButton
android:id="@+id/radio1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/fahrenheit" />
</RadioGroup>
Nota
Desde
ahora
se
asume
que
ya
se
es
capaz
de
modificar
las
propiedades
de
las
vistas
en
un
archivo
layout.
Asegurarse
que
la
propiedad
Checked
est
puesta
a
true
para
el
primer
RadioButton.
Asignar
@string/calc
a
la
propiedad
texto
de
su
botn
y
asignar
el
valor
onClick
a
la
propiedad
onClick.
Poner
la
propiedad
inputType
a
numberSigned
y
numberDecimal
en
el
EditText.
Como
un
ejemplo
se
puede
usar
la
ltima
lnea
en
el
siguiente
segmente
de
XML.
<EditText
android:id="@+id/editText1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="19dp"
android:layout_marginTop="16dp"
61
android:ems="10"
android:inputType="numberSigned|numberDecimal" >
Todos
los
componentes
de
la
interfaz
de
usuario
estn
contenidos
en
un
layout.
Asignar
el
color
de
fondo
a
este
Layout.
Seleccionar
Color
y
entonces
seleccionar
myColor
en
el
dialogo.
Como
un
ejemplo
se
puede
usar
la
ltima
lnea
del
siguiente
segmento
de
XML.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity"
android:background="@color/myColor" >
A
continuacin
el
background
debera
de
cambiar
al
color
whitesmoke
.
Podra
ser
dificil
notar
la
diferencia.
Cambiar
a
la
tab
activity_main.xml
y
verificar
que
el
XML
est
correcto.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity"
android:background="@color/myColor" >
<EditText
android:id="@+id/editText1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="19dp"
android:layout_marginTop="16dp"
android:ems="10"
android:inputType="numberSigned|numberDecimal" >
<requestFocus />
</EditText>
<RadioGroup
android:id="@+id/radioGroup1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/editText1"
android:layout_below="@+id/editText1"
android:layout_marginLeft="16dp"
62
android:layout_marginTop="41dp" >
<RadioButton
android:id="@+id/radio0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="@string/celsius" />
<RadioButton
android:id="@+id/radio1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/fahrenheit" />
</RadioGroup>
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/radioGroup1"
android:layout_below="@+id/radioGroup1"
android:layout_marginTop="15dp"
android:onClick="onClick"
android:text="@string/calc" />
</RelativeLayout>
63
import
import
import
import
android.view.View;
android.widget.EditText;
android.widget.RadioButton;
android.widget.Toast;
64
Nota
El
onClick
es
llamado
por
un
click
en
el
botn
a
causa
de
la
propiedad
onClick
del
botn.
Iniciar
aplicacin
Click
derecho
sobre
el
proyecto
y
seleccionar
Run-As
Android
Application.
Si
un
emulador
an
no
est
corriendo,
entonces
se
iniciar.
Escribir
un
nmero,
seleccionar
la
conversin
y
presionar
el
botn.
El
resultado
debera
ser
desplegadoy
la
otra
opcin
debera
ser
seleccionada.
65
Advertencia
Atributo
Descripcin
66
FrameLayout
FrameLayout
es
un
manejador
de
layout
el
cual
dibuja
todos
los
elementos
hijos
uno
arriba
del
otro.
LinearLayout
LinearLayout
coloca
a
sus
elementos
hijos
dentro
de
una
simple
columna
o
fila
dependiendo
del
atributo
android:orientation.
Los
posibles
valores
para
este
atributo
son
horizontal
y
vertical,
horizontal
es
el
valor
por
default.
Si
horizontal
es
usado,
los
elementos
hijos
son
dispuestos
como
se
indica
en
la
siguiente
imagen.
67
Vertical
podra
resultar
en
un
layout
como
se
muestra
en
la
siguiente
imagen.
LinearLayout
puede
ser
anidado
para
lograr
layouts
ms
complejos.
LinearLayout
soporta
asignar
un
peso
individual
por
hijo
va
el
parmetro
del
layout
android:layout_weight.
Este
valor
especifica
cunto
de
espacio
extra
en
el
layout
es
asignado
al
View.
Si,
por
ejemplo,
tienes
dos
widgets
y
el
primero
define
un
layout_weight
de
1
y
el
segundo
de
2,
el
primero
tendr
1/3
de
espacio
disponible
y
el
otro
2/3.
Tambin
se
puede
poner
layout_width
a
cero
para
tener
una
cierta
proporcin.
RelativeLayout
RelativeLayout
permite
posicionar
el
widget
relativo
uno
con
otro.
Esto
puede
ser
usado
para
layouts
complejos.
Un
uso
simple
para
RelativeLayout
es
si
se
quiere
centrar
un
simple
componente.
Slo
se
agrega
un
componente
al
RelativeLayout
y
se
pone
el
atributo
android:layout_centerInParent
a
true.
<?xml version="1.0" encoding="utf-8"?>
68
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ProgressBar
android:id="@+id/progressBar1"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
/>
</RelativeLayout>
GridLayout
GridLayout
fue
introducido
con
Android
4.0.
Este
layout
permite
orgnizar
una
vista
dentro
de
un
Grid.
GridLayout
separa
sus
reas
de
dibujo
en:
filas,
columnas,
y
celdas.
Se
pueden
especificar
cuantas
columnas
se
desean
por
cada
una
de
las
View,
en
cual
fila
o
columna
debera
ser
colocada
as
como
cuantas
columnas
y
filas
se
deberan
de
usar.
Si
no
se
especifican,
GridLayout
usa
defaults,
esto
es,
una
columna,
una
fila
y
la
posicin
de
una
View
depende
del
order
de
la
declaracin
de
las
Views.
El
siguiente
archivo
de
layout
define
una
layout
usando
GridLayout.
<?xml version="1.0" encoding="utf-8"?>
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/GridLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:columnCount="4"
android:useDefaultMargins="true" >
<TextView
android:layout_column="0"
android:layout_columnSpan="3"
android:layout_gravity="center_horizontal"
android:layout_marginTop="40dp"
android:layout_row="0"
android:text="User Credentials"
android:textSize="32dip" />
<TextView
android:layout_column="0"
android:layout_gravity="right"
android:layout_row="1"
android:text="User Name: " >
</TextView>
<EditText
android:id="@+id/input1"
69
android:layout_column="1"
android:layout_columnSpan="2"
android:layout_row="1"
android:ems="10" />
<TextView
android:layout_column="0"
android:layout_gravity="right"
android:layout_row="2"
android:text="Password: " >
</TextView>
<EditText
android:id="@+id/input1"
android:layout_column="1"
android:layout_columnSpan="2"
android:layout_row="2"
android:ems="8" />
<Button
android:id="@+id/button1"
android:layout_column="2"
android:layout_row="3"
android:text="Login" />
</GridLayout>
Esto
crea
una
interfaz
de
usuario
como
en
la
siguiente
toma
de
pantalla.
70
ScrollView
La
clase
ScrollView
puede
ser
usada
para
contener
un
View
que
podra
ser
ms
grande
o
ancha
que
la
pantalla.
En
este
caso
ScrollView
desplegar
una
barra
de
scroll
para
desplazarse
en
el
contexto.
Por
supuesto
este
View
puede
ser
un
layout
que
puede
contener
otros
elementos.
El
siguiente
cdigo
muestra
un
ejemplo
de
un
archivo
de
layout
el
cual
usa
un
ScrollView.
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:orientation="vertical" >
<TextView
android:id="@+id/TextView01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="8dip"
android:paddingRight="8dip"
android:paddingTop="8dip"
android:text="This is a header"
android:textAppearance="?android:attr/textAppearanceLarge" >
</TextView>
</ScrollView>
71
android:orientation="vertical" >
<TextView
android:id="@+id/TextView01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="8dip"
android:paddingRight="8dip"
android:paddingTop="8dip"
android:text="This is a header"
android:textAppearance="?android:attr/textAppearanceLarge" >
</TextView>
<TextView
android:id="@+id/TextView02"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1.0"
android:text="@+id/TextView02" >
</TextView>
<LinearLayout
android:id="@+id/LinearLayout02"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<Button
android:id="@+id/Button01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:text="Submit" >
</Button>
<Button
android:id="@+id/Button02"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:text="Cancel" >
</Button>
</LinearLayout>
</LinearLayout>
</ScrollView>
Cambiar
la
clase
ScrollViewActivity
a
como
se
muestra
el
siguiente
cdigo.
package de.vogella.android.scrollview;
import
import
import
import
android.app.Activity;
android.os.Bundle;
android.view.View;
android.widget.TextView;
72
Iniciar
su
aplicacin
y
asegurarse
que
se
pueda
desplazar
hacia
abajo
a
los
botones.
Desplegar
Revisin
general
En
general
hay
restricciones
de
como
desplegar
una
aplicacin
Android
a
tu
dispositivo.
Puedes
usar
el
USB,
un
correo
a
ti
mismo
con
la
aplicacin
o
usar
uno
de
los
muchos
mercados
de
Android
para
instalar
la
apliacin.
La
siguiente
descripcin
resalta
las
ms
comunes.
73
Despliegue
va
ADT
Habilitar
el
USB
Debugging
en
los
settigs
del
dispositivo.
Seleccionar
Settings
Development
Options,
y
habilitar
la
opcin
USB-Debugging.
Podra
tambier
ser
necesario
instalar
el
driver
para
el
telefono
mvil.
Linux
y
Mac
OS
usualmente
trabajan
fuera
de
la
caja,
mientras
Windows
tpicamente
requiere
la
instalacin
de
un
driver.
Para
detalles
sobre
la
installacin
en
Windows
por
favor
ver
la
gua
Google
de
despliegue
para
dispositivos.
Nota
La
versin
minima
de
la
aplicacin
Android
necesita
ajustarse
a
la
versin
Android
de
tu
dispositivo.
Si
se
tienen
varios
dispositivos
conectados
a
la
computaodra,
se
puede
seleccionar
el
que
se
desea
usar.
Si
solamente
un
dispositivo
est
conectado,
la
aplicacin
es
automaticamente
desplegada
en
ese
dispositivo.
74
Exportar
aplicaciones
Las
aplicaciones
android
deben
ser
firmadas
antes
de
que
sean
instaladas
en
un
dispositivo
Android.
Durante
el
desarrallo
ADT
firma
las
aplicaciones
automticamente
con
una
llave
de
pruebas.
Si
se
desea
instalar
la
aplicacin
sin
el
IDE
de
ADT,
se
puede
hacer
click
derecho
sobre
el
proyecto
y
seleccionar
Android
Tools
Export
Signed
Application
Package.
Este
asistente
permite
usar
una
llave
existente
o
crear
una
nueva.
Es
necesario
tener
en
cuenta
que
se
usa
la
misma
llave
para
firmar
en
Google
Play
para
las
actualizaciones
de
las
aplicaciones.
Si
se
pierde
la
llave,
no
se
podr
actualizar
nunca
ms
la
actualizacin.
Es
necesario
asegurarse
de
respaldar
la
llave.
Va
fuentes
externas
Android
tambin
permite
instalar
las
aplicaciones
directamente.
Slo
haciendo
click
en
un
una
liga
la
cual
apunte
un
archivo
.apk,
esto
es,
en
un
adjunto
de
email
o
en
una
pgina
web.
Android
preguntar
si
deseas
instalar
dicha
aplicacin.
Esti
requiere
que
se
configure
en
el
dispositivo
Android
que
permita
la
instalacin
de
aplicaciones
que
no
sean
del
market
(Google
Play).
Tpicamente
esta
caracterstica
puede
ser
encontrada
bajo
los
settings
de
Seguridad.
75
Dentro
de
los
mtodos
de
llamadas
del
ciclo
de
vida,
puedes
declarar
cmo
se
comportar
tu
activity
cuando
el
usuario
abandone
o
reingrese
a
la
activity.
Por
ejemplo,
si
se
est
construyendo
un
reproductor
de
vdeo
con
streaming,
se
podra
hacer
una
pausa
al
vdeo
y
terminar
la
conexin
de
red
cuando
el
usuario
cambia
a
otra
aplicacin.
Cuando
el
usuario
vuelve,
puede
volver
a
conectarse
a
la
red
y
permitir
al
usuario
reanudar
el
vdeo
desde
el
mismo
punto.
Imagen
8
No
bloquee
si
el
usuario
recibe
una
llamada
telefnica
o
cambia
a
otra
aplicacin
mientras
se
utiliza
la
aplicacin.
No
consume
valiosos
recursos
del
sistema
cuando
el
usuario
no
est
usando
activamente.
No
pierde
el
progreso
del
usuario
si
salen
de
su
aplicacin
y
volver
a
ella
ms
adelante.
No
bloquee
o
perder
el
progreso
del
usuario
cuando
la
pantalla
cambia
entre
orientacin
vertical
u
horizontal.
76
Hay
varias
situaciones
en
las
que
las
transiciones
de
una
activity
entre
los
diferentes
estados
ocurren
como
se
ilustran
en
la
Imagen
8.
Sin
embargo,
slo
tres
de
estos
estados
puede
ser
esttico.
Es
decir,
la
activity
puede
existir
en
uno
de
los
tres
estados
para
un
perodo
de
tiempo
prolongado:
Resumed:
En
este
estado,
la
activity
est
en
el
primer
plano
y
el
usuario
puede
interactuar
con
l.
(Tambin
se
refiere
a
veces
como
el
estado
"corriendo").
Paused:
En
este
estado,
la
activity
est
parcialmente
oculta
por
otra
activity,
la
otra
activity
que
est
en
el
primer
plano
es
semi-transparente
o
no
cubre
toda
la
pantalla.
La
activity
que
se
detuvo
no
recibe
la
entrada
del
usuario
y
no
se
puede
ejecutar
ningn
cdigo.
Stopped:
En
este
estado,
la
activity
est
completamente
oculta
y
no
visible
para
el
usuario,
sino
que
se
considera
que
est
en
el
fondo.
Mientras
est
detenida,
la
instancia
de
la
activity
y
toda
la
informacin
de
su
estado
como
variables
de
miembros
se
mantiene,
pero
no
se
puede
ejecutar
ningn
cdigo.
Los
otros
estados
(creado
e
iniciado)
son
transitorios
y
el
sistema
rpidamente
cambia
de
ellos
al
siguiente
estado
llamando
al
siguiente
ciclo
de
vida.
Es
decir,
despus
de
que
el
sistema
llama
onCreate
(),
rpidamente
se
llama
OnStart
(),
que
rpidamente
es
seguido
por
onResume
().
77
Imagen
9
Imagen
10
3. Para
crear
la
tabla
que
requerimos
hacemos
doble-click
en
la
nueva
conexin
recin
creada,
despus
aparece
una
opcin
que
dice
main,
tambin
a
esta
le
damos
doble-click
y
se
78
despliegan
varias
opciones
en
la
que
dice
Tables
hacemos
click
con
el
botn
derecho
y
del
men
desplegable
seleccionamos
la
opcin
New
Table
(Ver
Imagen
11).
Imagen
11
4.
Crearemos
los
campos
que
llevar
la
BD,
debe
de
quedar
igual
a
como
se
muestra
en
la
Imagen
12.
Imagen
12
5. Ahora
crearemos
una
ndice,
esto
es
necesario
que
sea
realizado
para
todas
las
llaves
primarias
que
sean
creadas
con
auto
incremento,
para
realizar
esto
seleccionamos
la
pestaa
Indexes,
en
79
la
columna
Name
pondremos
un
nombre
al
ndice
en
este
caso
ser
id_alumno,
en
la
columna
Fields
al
seleccionarla
cambia
a
como
se
muestra
en
la
Imagen
13
y
damos
un
click
al
botn
encerrado
en
el
cuadro
rojo.
Imagen
13
6. En
la
ventana
que
es
mostrada
ahora,
ver
Imagen
14,
marcamos
el
checkbox
de
la
llave
primaria
y
en
la
columna
Sort
Order,
seleccionamos
la
opcin
ASC
y
aceptamos
los
cambios
dando
click
en
el
botn
encerrado
en
el
cuadro
rojo.
Imagen
14
7. Al
guardar
las
modificaciones
si
no
exista
previamente
la
tabla
entonces
nos
pide
que
le
pongamos
un
nombre
a
la
tabla
as
como
se
muestra
en
la
Imagen
15.
80
Imagen
15
8. En
este
punto
al
crear
la
nueva
tabla
ctl_alumnos
se
crea
una
tabla
dinmica
sqlite_sequence,
esta
tabla
lleva
el
control
de
la
secuencia
de
las
llaves
principales,
por
favor
de
no
modificar
esta
tabla
(Imagen
16).
Imagen
16
9. Android
solicita
que
la
base
de
datos
incluya
una
tabla
que
se
llama
android_metadata,
esta
tabla
debe
de
contener
un
solo
campo
de
nombre
locale
y
en
la
Imagen
17
se
muestra
cmo
debe
de
quedar
configurada
dicha
tabla.
81
Imagen
17
Imagen
18
82
openDataBase()
close()
Funcionalidad
Constructor
Crea
una
base
de
datos
vaca
en
el
sistema
y
la
reescribe
con
tu
propia
base
de
datos
Verifica
si
la
base
de
datos
ya
existe
para
evitar
re-copiar
el
archivo
cada
vez
que
abres
la
aplicacin
Copia
tu
base
de
datos
desde
la
carpeta
local
assets
a
la
base
de
datos
vaca
recientemente
creada
en
el
sistema
de
carpetas,
para
que
pueda
ser
accesada
y
manipulada.
Esto
es
hecho
por
transferencia
de
flujo
de
bytes
Abre
la
base
de
datos
Cierra
la
base
de
datos
Tabla
10
3. Lo
primero
que
haremos
ser
declarar
unas
variables
globales
que
sern
utilizadas
en
diferentes
partes
de
la
clase,
como
se
muestra
en
la
Imagen
19.
Imagen
19
4. Lo
siguiente
que
haremos
ser
declarar
el
constructor
de
la
clase
como
lo
vemos
en
la
Imagen
20.
83
Imagen
20
5. Ahora
crearemos
una
mtodo
que
verificar
si
la
base
de
datos
ya
existe,
esta
clase
solo
regresa
true
si
ya
existe
o
false
en
caso
de
no
existir,
dicho
mtodo
se
llamar
checkDataBase(),
el
cdigo
necesario
en
esta
clase
se
muestra
en
la
Imagen
21.
Imagen
21
6. El
siguiente
mtodo
necesario
es
uno
que
nos
ayude
a
copiar
la
base
de
datos
que
tenemos
en
la
carpeta
assets
al
sistema
de
archivos
del
proyecto
para
que
pueda
ser
usada
y
manipulada
nuestra
base
de
datos,
este
mtodo
tendr
el
nombre
copyDataBase(),
y
la
copia
del
archivo
de
la
base
de
datos
desde
assets
haca
el
sistema
de
archivos
de
la
aplicacin
se
realiza
a
travs
de
un
flujo
de
bytes,
el
cdigo
de
dicho
mtodo
lo
podemos
ver
en
la
Imagen
22.
84
Imagen
22
7. Los
dos
mtodos
anteriores
son
necesarios
puesto
que
son
utilizados
por
el
mtodo
createDataBase()
ya
que
primero
valida
si
la
base
de
datos
ya
existe
y
en
caso
de
que
no
exista
entonces
copia
la
base
de
datos.
Esto
lo
podemos
ver
en
la
Imagen
23.
Imagen
23
85
8. Por
ltimo
falta
agregar
dos
mtodos
muy
importantes
para
abrir
y
cerrar
la
base
de
datos,
estos
mtodos
son
openDataBase()
y
close(),
en
la
Imagen
24
podemos
observar
el
cdigo
de
estos
dos
mtodos.
Imagen
24
9. Ahora
que
ya
tenemos
todo
lo
necesario
para
agregar
nuestra
base
de
datos
a
nuestra
aplicacin
ser
necesario
que
creemos
un
mtoodo
que
inicie
todo
el
proceso
de
revisin
y
creacin
de
la
base
de
datos,
una
buena
opcin
es
hacerlo
en
el
momento
en
el
que
se
pone
en
marcha
la
aplicacin,
digamos
que
podemos
crear
un
Splash
y
en
este
momento
hacer
lo
relacionado
con
la
base
de
datos,
esto
con
ayuda
de
la
clase
AsyncTask
10. Lo
primero
ser
crear
una
activity
llamada
SplashScreen.java, y
declararla
como
la
pantalla
de
inicio
de
nuestra
aplicacin
dentron
del
Manifest
de
nuestra
aplicacin
(en
realidad
el
Asynctask
lo
podemos
usar
en
el
momento
que
lo
deseemos,
podramos
no
usar
una
pantalla
de
Splash,
y
hacerlo
directamente
en
nuestra
pantalla
de
inicio,
esto
es
a
decisin
suya
y
de
las
necesidades
del
proyecto).
11. Ahora
es
cuestin
y
decisin
de
su
proyecto
como
disear
la
interfaz
del
layout
del
Splash
que
se
a
creado,
activity_splash_screen.xml,
por
cuestiones
de
economa
de
tiempo
yo
lo
disear
muy
simple:
86
12.
Y
quedando
el
layout activity_splash_screen.xml
continuacin:
como se muestra a
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:background="#CECECE"
tools:context=".SplashScreen" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:gravity="center"
android:text="@string/hello_world"
android:textSize="40sp" />
</RelativeLayout>
87
android.os.AsyncTask;
android.os.Bundle;
android.app.Activity;
android.content.Intent;
android.view.Menu;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash_screen);
/*
* Se manda llamar o ejecutar la subclase que hereda
* de la clase AsynTask
* */
new VerificarBaseDatos().execute();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it
is present.
getMenuInflater().inflate(R.menu.splash_screen, menu);
return true;
}
/*
* Creamos la subclase que hereda de AsyncTask
* */
private class VerificarBaseDatos extends AsyncTask<Void, Void,
88
Void> {
/*
* No realizamos nada en el mtodo onPreExecute
* */
@Override
protected void onPreExecute() {
super.onPreExecute();
}
/*
* En el mtodo doInBackground es el momento
* donde verificaremos la existencia de la base de datos
* */
@Override
protected Void doInBackground(Void... params) {
DataBaseManager myDbHelper = new
DataBaseManager(SplashScreen.this);
try {
myDbHelper.createDataBase();
} catch (IOException e) {
throw new Error("Imposible crear la base de
datos");
}
return null;
}
/*
* Al momento de terminar la ejecucin del mtodo
* doInBackground ser momento de ejecutar al mtodo
* onPostExecute*/
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
// Despus de ejecutar la verificacin de la base de
datos
// cerrarremos esta actividad y lanzaremos la nnueva
actividad
Intent i = new Intent(SplashScreen.this,
MainActivity.class);
startActivity(i);
// cerrar definitivamente esta actividad
// para evitar que en el momento de dar Back se
ejecute de nuevo
}
}
}
16. Cabe
recordar
o
hacer
notar
algunas
cosas:
89
a. Esta
es
slo
una
forma
de
poder
verificar
si
ya
existe
la
base
de
datos
instalada
en
nuestro
telfono,
no
basta
con
que
la
base
de
datos
este
en
el
proyecto
o
en
la
aplicacin,
tienen
que
estar
instalada
en
el
telfono
y
esto
es
lo
que
hace
todo
este
procedimiento.
b. La
clase
AsyncTask
es
una
forma
mucho
ms
fcil
de
hacer
tareas
asncronas,
y
puede
ser
utiizada
en
cualquier
parte
de
nuestro
sistema,
no
solo
en
el
splash
o
para
verificar
que
la
base
de
datos
est
ya
instalada.
Veamos
que
contienen
las
clases
que
acabamos
de
crear,
la
primera
en
analizar
es
la
clase
DataBaseHelper.java dicha
clase
extiende
(hereda)
de
la
clase
SQLiteOpenHelper. A
continuacin
tenemos
el
contenido
completo
de
la
clase
la
cul
vamos
a
ir
explicando
lneas
abajo:
package com.example.tareasqlite.database;
import
import
import
import
android.content.Context;
android.database.sqlite.SQLiteDatabase;
android.database.sqlite.SQLiteOpenHelper;
android.util.Log;
90
android.content.ContentValues;
android.content.Context;
android.database.Cursor;
android.database.SQLException;
android.database.sqlite.SQLiteDatabase;
91
92
//Borrar la tarea
public boolean deleteTarea(long rowId){
return database.delete(DATABASE_TABLE, KEY_ROWID + "="
+rowId, null) > 0;
}
// Retorna un cursor que contiene todos los items
public Cursor recuperaTodos(){
String[] columnas = {KEY_ROWID, KEY_CATEGORY, KEY_SUMMARY,
KEY_DESCRIPTION};
return database.query(DATABASE_TABLE, columnas, null, null,
null, null, null);
}
// Retorna un Cursor que contiene la info de una tarea
public Cursor recuperaTarea(long rowId) throws SQLException{
String[] columnas = {KEY_ROWID, KEY_CATEGORY, KEY_SUMMARY,
KEY_DESCRIPTION};
Cursor mCursor = database.query(true, DATABASE_TABLE,
columnas, KEY_ROWID + "=" +rowId, null, null, null, null, null);
if(mCursor != null){
mCursor.moveToFirst();
}
return mCursor;
}
private ContentValues crearContentValues(String categoria, String
resumen,
String descripcion) {
ContentValues values = new ContentValues();
values.put(KEY_CATEGORY, categoria);
values.put(KEY_DESCRIPTION, descripcion);
values.put(KEY_SUMMARY, resumen);
return values;
}
}
Vamos
a
explicar
cada
uno
de
los
mtodos
que
estamos
creando.
La
primera
parte
corresponde
a
la
creacin
de
las
constantes
y
variables
que
vamos
a
utilizar.
Las
constantes
son
cada
una
de
las
columnas
de
la
tabla
que
almacenar
la
informacin
de
la
aplicacin.
Despus
tenemos
tres
variables
que
corresponden
al
contexto
de
la
aplicacin,
a
la
base
de
datos
y
al
helper
para
manipular
las
consultas
y
funciones
con
SQLite.
En
el
constructor
nicamente
definiremos
el
contexto
de
la
aplicacin.
Despus,
tenemos
el
mtodo
open()
que
sirve
para
preparar
la
base
de
datos
a
modo
que
podamos
escribir
datos
en
ella,
para
ello
93
se
abre
la
base
de
datos
a
travs
del
objeto
de
tipo
DBHelper.
En
este
mtodo
ocupamos
una
SQLException
pues
es
probable
que
a
veces
ocurran
errores
en
esta
parte
y
esto
nos
servir
para
conocerlos.
El
mtodo
close()
sirve
para
cerrar
el
helper.
Si
has
trabajado
con
Java
y
MySQL,
vers
que
es
algo
muy
parecido
a
lo
que
tenemos
que
hacer
para
manejar
bases
de
datos
a
travs
de
un
conector.
Posteriormente,
tenemos
los
mtodos
para
crear,
actualizar,
borrar
y
consultar
los
elementos
de
la
base
de
datos
a
travs
de
la
clase
ContentValues
nos
permitirn
crear
y
actualizar
valores
dentro
de
la
base
de
datos.
A
travs
de
esta
clase
podemos
manipular
la
correspondencia
entre
identificador/valor,
utilizando
el
nombre
de
la
columna
como
el
identificador
al
cul
nicamente
le
definiremos
el
valor
para
actualizar
o
crear
un
nuevo
elemento
dentro
de
la
base
de
datos.
SQLiteOpenHelper
Para
crear
y
trabajar
con
bases
de
datos
en
Android,
es
necesario
hacer
uso
de
la
clase
SQLiteOpenHelper.
En
esta
clase
es
necesario
sobrescribir
los
mtodos
onCreate()
para
crear
la
base
de
datos,
y
onUpgrade()
para
actualizar
la
base
de
datos
en
caso
de
que
existan
cambios
en
el
esquema
de
la
misma.
Ambos
mtodos
reciben
como
parmetro
un
objeto
SQLiteDatabase.
SQLiteOpenHelper
ofrece
los
mtodos
getReadableDatabase()
y
getWriteableDatabase()
para
trabajar
con
un
objeto
SQLiteDatabase
y
poder
tener
acceso
de
lectura
y
escritura
sobre
una
base
de
datos.
SQLDatabase
y
Cursor
La
clase
SQLiteDatabase
provee
los
mtodos
insert(),
update()
y
delete()
y
execSQL()
que
nos
ayuda
a
ejecutar
sentencias
SQL
directamente.
El
objeto
ContentValues
permite
definir
claves
y
valores
en
las
sentencias
Insert
y
Update.
La
clave
(key)
corresponde
a
la
columna
y
el
valor
es
el
valor
para
la
columna.
94
Las
consultas
se
pueden
crear
a
travs
del
mtodo
rawQuery()
que
acepta
como
parmetro
una
sentencia
en
SQL
o
el
mtodo
query()
que
proporciona
una
interfaz
para
especificar
los
datos
dinmicos
o
un
objeto
de
tipo
SQLiteQueryBuilder.
SQLiteBuilder
es
similar
a
la
interfaz
de
un
proveedor
de
contenidos
por
lo
que
suele
utilizarse
con
Content Providers.
Hay
que
saber
tambin
que
toda
consulta
que
realicemos
nos
retornar
un
objeto
de
tipo
Cursor.
Para
definir
la
llave
primaria
de
una
base
de
datos
es
indispensable
hacer
uso
del
identificador
_id
ya
que
muchas
de
las
funciones
con
las
que
trabajaremos
toman
en
cuenta
este
estndar.
En
Android,
la
forma
tpica
para
crear,
actualizar,
y
conectar
con
una
base
de
datos
SQLite
ser
a
travs
de
una
clase
auxiliar
llamada
SQLiteOpenHelper,
o
para
ser
ms
exactos,
de
una
clase
propia
que
derive
de
ella
y
que
debemos
personalizar
para
adaptarnos
a
las
necesidades
concretas
de
nuestra
aplicacin.
La
API
de
SQLite
de
Android
proporciona
dos
alternativas
para
realizar
operaciones
sobre
la
base
de
datos
que
no
devuelven
resultados
(entre
ellas
la
insercin/actualizacin/eliminacin
de
registros,
pero
tambin
la
creacin
de
tablas,
de
ndices,
etc).
El
primero
de
ellos,
es
el
mtodo
execSQL()
de
la
clase
SQLiteDatabase.
Este
mtodo
permite
ejecutar
cualquier
sentencia
SQL
sobre
la
base
de
datos,
siempre
que
sta
no
devuelva
resultados.
Para
ello,
simplemente
aportaremos
como
parmetro
de
entrada
de
este
mtodo
la
cadena
de
texto
correspondiente
con
la
sentencia
SQL.
La
segunda
de
las
alternativas
disponibles
en
la
API
de
Android
es
utilizar
los
mtodos
insert(),
update()
y
delete()
proporcionados
tambin
con
la
clase
SQLiteDatabase.
Estos
mtodos
permiten
realizar
las
tareas
de
insercin,
actualizacin
y
eliminacin
de
registros
de
una
forma
algo
ms
paramtrica
que
execSQL(),
separando
tablas,
valores
y
condiciones
en
parmetros
independientes
de
estos
mtodos.
Empecemos
por
el
mtodo
insert()
para
insertar
nuevos
registros
en
la
base
de
datos.
Este
mtodo
recibe
tres
parmetros,
el
primero
de
ellos
ser
el
nombre
de
la
tabla,
el
tercero
sern
los
valores
del
registro
a
insertar,
y
el
segundo
lo
obviaremos
por
el
momento
ya
que
tan
slo
se
hace
necesario
en
casos
muy
puntuales
(por
ejemplo
para
poder
insertar
registros
completamente
vacos),
en
cualquier
otro
caso
pasaremos
con
valor
null
este
segundo
parmetro.
Los
valores
a
insertar
los
pasaremos
como
elementos
de
una
coleccin
de
tipo
ContentValues.
Esta
coleccin
es
de
tipo
diccionario,
donde
almacenaremos
parejas
de
clave-valor,
donde
la
clave
ser
el
nombre
de
cada
campo
y
el
valor
ser
el
dato
correspondiente
a
insertar
en
dicho
campo.
Veamos
la
Imagen
26:
Imagen
25
95
Los
mtodos
update()
y
delete()
se
utilizarn
de
forma
muy
parecida
a
sta,
con
la
salvedad
de
que
recibirn
un
parmetro
adicional
con
la
condicin
WHERE
de
la
sentencia
SQL.
Por
ejemplo,
para
actualizar
el
email
del
usuario
de
nombre
usu1
haramos
lo
siguiente:
Imagen
26
Como
podemos
ver,
como
tercer
parmetro
del
mtodo
update()
pasamos
directamente
la
condicin
del
UPDATE
tal
como
lo
haramos
en
la
clusula
WHERE
en
una
sentencia
SQL
normal.
El
mtodo
delete()
se
utilizara
de
forma
anloga.
Por
ejemplo
para
eliminar
el
registro
del
usuario
usu2
haramos
lo
siguiente:
Imagen
27
Como
vemos,
volvemos
a
pasar
como
primer
parmetro
el
nombre
de
la
tabla
y
en
segundo
lugar
la
condicin
WHERE.
Por
supuesto,
si
no
necesitramos
ninguna
condicin,
podramos
dejar
como
null
en
este
parmetro.
Un
ltimo
detalle
sobre
estos
mtodos.
Tanto
en
el
caso
de
execSQL()
como
en
los
casos
de
update()
o
delete()
podemos
utilizar
argumentos
dentro
de
las
condiciones
de
la
sentencia
SQL.
Esto
no
es
ms
que
partes
variables
de
la
sentencia
SQL
que
aportaremos
en
un
array
de
valores
aparte,
lo
que
nos
evitar
pasar
por
la
situacin
tpica
en
la
que
tenemos
que
construir
una
sentencia
SQL
concatenando
cadenas
de
texto
y
variables
para
formar
el
comando
SQL
final.
Estos
argumentos
SQL
se
indicarn
con
el
smbolo
?,
y
los
valores
de
dichos
argumentos
deben
pasarse
en
el
array
en
el
mismo
orden
que
aparecen
en
la
sentencia
SQL.
As,
por
ejemplo,
podemos
escribir
instrucciones
como
la
siguiente:
Imagen
28
Esta
forma
de
pasar
a
la
sentencia
SQL
determinados
datos
variables
puede
ayudarnos
adems
a
escribir
cdigo
ms
limpio
y
evitar
posibles
errores.
96
De
forma
anloga
a
lo
que
vimos
para
las
sentencias
de
modificacin
de
datos,
vamos
a
tener
dos
opciones
principales
para
recuperar
registros
de
una
base
de
datos
SQLite
en
Android.
La
primera
de
ellas
utilizando
directamente
un
comando
de
seleccin
SQL,
y
como
segunda
opcin
utilizando
un
mtodo
especfico
donde
parametrizremos
la
consulta
a
la
base
de
datos.
Para
la
primera
opcin
utilizaremos
el
mtodo
rawQuery()
de
la
clase
SQLiteDatabase.
Este
mtodo
recibe
directamente
como
parmetro
un
comando
SQL
completo,
donde
indicamos
los
campos
a
recuperar
y
los
criterios
de
seleccin.
El
resultado
de
la
consulta
lo
obtendremos
en
forma
de
cursor,
que
posteriormente
podremos
recorrer
para
procesar
los
registros
recuperados.
Sirva
la
siguiente
consulta
a
modo
de
ejemplo:
Imagen
29
Como
en
el
caso
de
los
mtodos
de
modificacin
de
datos,
tambin
podemos
aadir
a
este
mtodo
una
lista
de
argumentos
variables
que
hayamos
indicado
en
el
comando
SQL
con
el
smbolo
?,
por
ejemplo
as:
Imagen
30
Como
segunda
opcin
para
recuperar
datos
podemos
utilizar
el
mtodo
query()
de
la
clase
SQLiteDatabase.
Este
mtodo
recibe
varios
parmetros:
el
nombre
de
la
tabla,
un
array
con
los
nombre
de
campos
a
recuperar,
la
clusula
WHERE,
un
array
con
los
argumentos
variables
incluidos
en
el
WHERE
(si
los
hay,
null
en
caso
contrario),
la
clusula
GROUP
BY
si
existe,
la
clusula
HAVING
si
existe,
y
por
ltimo
la
clusula
ORDER
BY
si
existe.
Opcionalmente,
se
puede
incluir
un
parmetro
al
final
ms
indicando
el
nmero
mximo
de
registros
que
queremos
que
nos
devuelva
la
consulta.
Veamos
el
mismo
ejemplo
anterior
utilizando
el
mtodo
query():
Imagen
31
Como
vemos,
los
resultados
se
devuelven
nuevamente
en
un
objeto
Cursor
que
deberemos
recorrer
para
procesar
los
datos
obtenidos.
Para
recorrer
y
manipular
el
cursor
devuelto
por
cualquiera
de
los
dos
mtodos
mencionados
tenemos
a
nuestra
disposicin
varios
mtodos
de
la
clase
Cursor,
entre
los
que
destacamos
dos
de
los
dedicados
a
recorrer
el
cursor
de
forma
secuencial
y
en
orden
natural:
97
Los
mtodos
moveToFirst()
y
moveToNext()
devuelven
TRUE
en
caso
de
haber
realizado
el
movimiento
correspondiente
del
puntero
sin
errores,
es
decir,
siempre
que
exista
un
primer
registro
o
un
registro
siguiente,
respectivamente.
Una
vez
posicionados
en
cada
registro
podremos
utilizar
cualquiera
de
los
mtodos
getXXX(ndice_columna)
existentes
para
cada
tipo
de
dato
para
recuperar
el
dato
de
cada
campo
del
registro
actual
del
cursor.
As,
si
queremos
recuperar
por
ejemplo
la
segunda
columna
del
registro
actual,
y
sta
contiene
un
campo
alfanumrico,
haremos
la
llamada
getString(1)
[NOTA:
los
ndices
comienzan
por
0,
por
lo
que
la
segunda
columna
tiene
ndice
1],
en
caso
de
contener
un
dato
de
tipo
real
llamaramos
a
getDouble(1),
y
de
forma
anloga
para
todos
los
tipos
de
datos
existentes.
Con
todo
esto
en
cuenta,
veamos
cmo
podramos
recorrer
el
cursor
devuelto
por
el
ejemplo
anterior:
Imagen
32
Adems
de
los
mtodos
comentados
de
la
clase
Cursor
existen
muchos
ms
que
nos
pueden
ser
tiles
en
muchas
ocasiones.
Por
ejemplo,
getCount()
te
dir
el
nmero
total
de
registros
devueltos
en
el
cursor,
getColumnName(i)
devuelve
el
nombre
de
la
columna
con
ndice
i,
moveToPosition(i)
mueve
el
puntero
del
cursor
al
registro
con
ndice
i,
etc.
Podemos
consultar
la
lista
completa
de
mtodos
disponibles
en
la
clase
Cursor
en
la
documentacin
oficial
de
Android.
98
Lo
primero
que
debemos
de
hacer
es
asegurarnos
de
que
tenemos
la
versin
r19.0.1
de
Android
Support
Library
en
el
SDK
Manager,
en
el
caso
de
no
tenerlo
debemos
de
instalarla
desde
el
SDK
Manager.
Nota
Para
casos
de
este
manual
supondremos
que
ya
tenemos
un
proyecto
creado,
en
el
caso
de
que
no
sea
as
ser
necesario
que
se
cree
uno
nuevo
y
seguir
el
manual
desde
este
punto.
Despus
de
verificar
de
que
tenemos
la
Support
Library
instalada
y
disponible
para
nuestro
proyecto
vamos
a
crear
nuestro
layout
que
ser
el
esqueleto
de
nuestra
UI.
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<!-- Vista para el contenido principal -->
<FrameLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"/>
<!-- Navigation Drawer -->
<ListView
android:id="@+id/drawerIzquierdo"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="@android:color/transparent"
android:dividerHeight="0dp"
android:background="#E5E5E5" >
</ListView>
</android.support.v4.widget.DrawerLayout>
El
contenedor
principal
es
el
DrawerLayout
este
bsicamente
es
el
que
permite
deslizar
la
vista
en
este
caso
ser
el
ListView.
99
La
posicin
de
deslizamiento
dentro
del
layout
es
controlado
por
la
sig.
propiedad
android:layout_gravity este
puede
ser:
left , right o start y end.
Para
darnos
una
idea
al
finalizar
el
tutorial
seremos
capaces
de
implementar
una
UI
de
este
tipo.
FrameLayout
ListView
Como
ven
dentro
del
FrameLayout
ira
el
contenido
principal
mientras
que
el
Listview
ser
el
que
se
desplace
horizontalmente
ya
sea
clickeando
en
el
botn
del
ActionBar
o
arrastrndolo
tocando
la
pantalla.
Ahora
vamos
a
la
parte
de
la
Activity
principal
import
import
import
import
import
android.app.Activity;
android.os.Bundle;
android.support.v4.widget.DrawerLayout;
android.view.Menu;
android.widget.ListView;
100
101
A
continuacin
veremos
el
diseo
del
Men
Vertical
y
como
agregar
opciones,
el
manejo
de
esto
es
igual
que
en
cualquier
aplicacin
comn
definiendo
su
layout,
implementar
un
Adaptador
especifico
para
este
en
el
caso
que
fuese
necesario,
etc..
Diseo:
La
idea
es
que
por
mas
que
sea
un
ejemplo
puedan
adquirir
conocimientos
para
dotar
a
sus
aplicaciones
con
una
interfaz
moderna
similar
a
las
que
ya
todos
conocemos,
obviamente
no
llegaremos
a
tanto
ya
que
se
necesita
mucho
diseo
pero
podemos
tratar
de
inspirarnos
de
ellas,
en
este
caso
est
basado
en
la
de
Google+
como
lo
vemos
en
la
siguiente
imagen.
102
Para
nuestro
ejemplo
lo
que
tendremos
es
lo
siguiente:
encabezado_drawer.xml
item_drawer.xml
103
Como
se
puede
ver
al
principio
se
incluye
un
header
que
solamente
cumple
una
funcin
esttica
pero
podra
incluirse
la
foto
de
perfil
del
usuario,
nombre,
etc.
Mas
adelante
veremos
como
integrarlos
dentro
del
ListView.
/res/layout/encabezado_drawer.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ImageView
android:id="@+id/headerBackground"
android:layout_width="fill_parent"
android:layout_height="150dp"
android:scaleType="centerCrop"
android:src="@drawable/header" />
</FrameLayout>
Como
podemos
ver
nada
del
otro
mundo
un
FrameLayout
con
una
imagen
dentro.
/res/layout/tem_drawer.xml
104
android:text="@string/app_name" />
</RelativeLayout>
Para
pode
agregar
opciones
al
men
se
agregan
tanto
las
opciones
como
la
imagen
que
cada
botn
debe
tener
dentro
del
/res/values/string.xml.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">ToDoSQLite</string>
<string name="hello_world">Hello world!</string>
<string name="title_activity_tareas">TareasActivity</string>
<!-- Lista de elementos que aparecen en la navegacin -->
<string-array name="nav_options">
<item >ToDo</item>
<item >Conversor</item>
<item >Perfil</item>
<item >Configuracin</item>
<item >Conversor</item>
</string-array>
<!-- Lista de iconos de navegacion -->
<string-array name="nav_iconos">
<item >@drawable/ic_action_go_to_today</item>
<item >@drawable/ic_action_merge</item>
<item >@drawable/ic_action_person</item>
<item >@drawable/ic_action_good</item>
<item >@drawable/ic_action_cloud</item>
</string-array>
</resources>
En
la
primera
seccin
he
declarado
un
array
de
Strings
nav_options
luego
otro
de
drawables
nav_iconos,
esta
es
una
forma
fcil
y
rpida
de
poder
declarar
estos
aunque
tambin
pudo
haberse
declarado
mediante
java
en
la
actividad
principal,
en
el
caso
que
el
contenido
fuese
dinmico
esta
opcin
del
xml
no
seria
viable.
Para
poder
facilitar
el
uso
del
men
en
el
adaptador
que
veremos
luego
he
creado
una
clase
llamada
Items.java
en
esta
bsicamente
se
declaran
los
mtodos
para
asignarle
un
nombre
y
una
imagen.
public class Items {
private String titulo;
private int icono;
public Items(String titulo, int icono) {
this.titulo = titulo;
this.icono = icono;
}
105
android.app.Activity;
android.content.res.TypedArray;
android.os.Bundle;
android.support.v4.widget.DrawerLayout;
android.view.Menu;
android.view.View;
android.widget.ListView;
106
107
listado
siguiente
podemos
ver
el
Adapter
que
se
disea
para
nuestro
ejemplo.
Primero
habr
crear
una
nueva
clase
que
herede
de
la
clase
BaseAdapter,
dicha
clase
la
llamaremos
NavigationAdapter.java
import java.util.ArrayList;
import
import
import
import
import
import
import
android.app.Activity;
android.view.LayoutInflater;
android.view.View;
android.view.ViewGroup;
android.widget.BaseAdapter;
android.widget.ImageView;
android.widget.TextView;
108
@Override
public View getView(int position, View convertView, ViewGroup
arg2) {
Fila view;
LayoutInflater inflator = mActivity.getLayoutInflater();
if(convertView == null){
view = new Fila();
//Crear objeto item y obtenerlo del array
Items item = arrayItems.get(position);
convertView = inflator.inflate(R.layout.item_drawer,
null);
//Titulo
view.tituloItem = (TextView)
convertView.findViewById(R.id.title_item);
//Establecer en el campo titulo el nombre
correspondiente obtenido del objeto item
view.tituloItem.setText(item.getTitulo());
//Icono
view.icono = (ImageView)
convertView.findViewById(R.id.icon);
//Seteo del icono
view.icono.setImageResource(item.getIcono());
convertView.setTag(view);
}else {
view = (Fila) convertView.getTag();
}
return convertView;
}
}
Lo
que
simplemente
hace
es
tomar
del
objeto
extrado
del
Arraylist
el
texto
y
la
imagen
para
luego
asignrsela
a
su
correspondiente
elemento.
En
este
punto
nuestra
aplicacin
permite
utilizar
la
navegacin
deslizable
de
momento
solo
funcionara
con
versiones
de
Android
superiores
o
iguales
a
4.0,
en
el
caso
de
que
se
necesite
o
se
dese
implementar
este
control
para
versiones
anteriores
ser
necesario
seguir
otro
procedimiento
para
agregar
libreras
para
hacerla
compatible
con
versiones
anteriores
de
Android.
Al
ejecutar
nuestro
proyecto
esto
es
lo
que
veramos:
109
El
siguiente
paso
ser
el
de
incorporar
el
botn
para
abrir
y
cerrar
el
men
de
navegacin
y
como
asignarle
una
accin
a
la
pulsacin
sobre
un
item
del
men.
android.app.Activity;
android.os.Bundle;
android.support.v4.app.ActionBarDrawerToggle;
android.support.v4.widget.DrawerLayout;
android.util.Log;
110
import android.view.Menu;
import android.view.View;
public class MainActivity extends Activity {
NavigationAdapter NavAdapter;
private ActionBarDrawerToggle mDrawerToggle;
private DrawerLayout mDrawerLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Aqu va el resto del cdigo previamente escrito...
//Declaramos mDrawableToggle y las imgs a utilizar
mDrawerToggle = new ActionBarDrawerToggle(
this,
/* Activity huesped*/
mDrawerLayout,
/* objeto DrawerLayout */
R.drawable.ic_drawer, /* imagen del nav drawer */
R.string.app_name,
/* "abrir drawer" descripcin
para accesibilidad */
R.string.hello_world
/* "cerrar drawer" descripcin
para accesibilidad */
) {
public void onDrawerClosed(View view) {
Log.e("Cerrado completo", "!!");
}
public void onDrawerOpened(View drawerView) {
Log.e("Apertura completa", "!!");
}
};
//Establecemos que mDrawerToggle declarado anteriormente
el DrawerListener
mDrawerLayout.setDrawerListener(mDrawerToggle);
//Establecemos que el ActionBar muestre el botn
getActionBar().setDisplayHomeAsUpEnabled(true);
sea
home
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it
is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
111
}
En
el
mtodo
onCreate()
se
declara
la
variable
mDrawerToggle
a
la
cual
hay
que
especificar
el
contexto,
el
drawerLayout,
el
icono
que
se
mostrar
en
el
botn
(disponible
en
el
pack
de
iconos
para
Actionbar
),
y
2
Strings
de
descripcin
(que
en
realidad
no
se
usan
en
este
ejemplo
pero
que
hay
que
especificarlos).
Tambin
podemos
especificar
una
accin
al
abrir
y
cerrar
el
men
en
onDrawerClosed()
y
onDrawerOpened(),
dar
un
vistazo
al
Logcat
durante
el
funcionamiento
de
la
aplicacin.
Mediante
mDrawerLayout.setDrawerListener(mDrawerToggle;
asignamos
cual
ser
el
DrawerListener
que
utilizara
en
este
caso
ser
nuestro
mDrawerToggle
.
Luego
en
getActionBar().setDisplayHomeAsUpEnabled(true);
Establecemos
que
el
ActionBar
muestre
el
botn
del
Home
de
nuestra
aplicacin.
Si
corremos
la
aplicacin
en
esta
parte
podemos
ver
como
al
presionar
el
icono
el
men
se
cierra
y
abre
tambin
podrn
observar
que
este
se
desplaza
segn
este
el
men
abierto
o
no.
android.app.Fragment;
android.os.Bundle;
android.view.LayoutInflater;
android.view.View;
android.view.ViewGroup;
112
}
Ya
cuando
se
tiene
listo
el
fragment
el
cdigo
que
necesitamos
que
traiga
nuestra
clase
principal
ser
el
siguiente:
//Establecemos la accion al clickear sobre cualquier item del menu.
//De la misma forma que hariamos en una app comun con un
listview.
mDrawerList.setOnItemClickListener(new
AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1,
int position, long id) {
MostrarFragment(position);
}
});
//Cuando la aplicacion
MostrarFragment(1);
cargue
por
defecto
mostrar
la
opcin
Home
cargue
por
defecto
mostrar
la
opcin
Home
Ver
los
comentarios
en
cada
lnea
par
entender
como
funciona
el
mtodo
MostrarFragment(int
position)que
a
continuacin
se
muestra,
este
mtodo
tambin
va
en
la
clase
MainActivity.java
de
nuestro
proyecto:
/*Pasando la posicion de la opcion en el menu nos mostrara el Fragment
correspondiente*/
private void MostrarFragment(int position) {
// update the main content by replacing fragments
Fragment fragment = null;
switch (position) {
case 1:
fragment = new TareasFragment();
break;
/*case 2:
fragment = new ProfileFragment();
break;*/
113
default:
//si no esta la opcion mostrara un toast y nos mandara a
Home
Toast.makeText(getApplicationContext(),"Opcion
"+titulos[position-1]+"no disponible!", Toast.LENGTH_SHORT).show();
fragment = new TareasFragment();
position=1;
break;
}
//Validamos si el fragment no es nulo
if (fragment != null) {
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_frame,
fragment).commit();
// Actualizamos el contenido segun la opcion elegida
mDrawerList.setItemChecked(position, true);
mDrawerList.setSelection(position);
//Cambiamos el titulo en donde decia "
setTitle(titulos[position-1]);
//Cerramos el menu deslizable
mDrawerLayout.closeDrawer(mDrawerList);
} else
//Si el fragment es nulo mostramos un mensaje de
error.
Log.e("Error
", "MostrarFragment"+position);
}
Con
esto
bsicamente
ya
podemos
dotar
a
nuestra
aplicacin
de
la
lgica
necesaria
para
poder
mostrar
cada
opcin
del
men,
luego
depende
de
cada
uno
lo
que
desee
mostrar
en
sus
aplicaciones.
Por
ltimo
hay
que
agregar
los
siguientes
mtodos:
onPostCreate,
onConfigurationChanged, onOptionsItemSelected
para
sobrescribirlos.
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync el estado del toggle despues de onRestoreInstanceState
haya ocurrido.
mDrawerToggle.syncState();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mDrawerToggle.onConfigurationChanged(newConfig);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Pasar el evento al ActionBarDrawerToggle, si este
114
android.app.Activity;
android.app.Fragment;
android.app.FragmentManager;
android.content.res.Configuration;
android.content.res.TypedArray;
android.os.Bundle;
android.support.v4.app.ActionBarDrawerToggle;
android.support.v4.widget.DrawerLayout;
android.util.Log;
android.view.Menu;
android.view.MenuItem;
android.view.View;
android.widget.AdapterView;
android.widget.ListView;
android.widget.Toast;
115
//Lista
mDrawerList = (ListView) findViewById(R.id.drawerIzquierdo);
//Declaramos el header el cual ser el layout de
encabezado_drawer.xml
View encabezado =
getLayoutInflater().inflate(R.layout.encabezado_drawer, null);
//Establecer el encabezado
mDrawerList.addHeaderView(encabezado);
//Tomamos listado de imgs desde drawable
NavIconos =
getResources().obtainTypedArray(R.array.nav_iconos);
//Tomamos listado de titulos desde el string-array de los
recursos @string/nav_options
titulos = getResources().getStringArray(R.array.nav_options);
//Listado de titulos de barra de navegacion
NavItems = new ArrayList<Items>();
//Agregamos objetos Item_objct al array
//ToDo
NavItems.add(new Items(titulos[0], NavIconos.getResourceId(0,
-1)));
//Conversor
NavItems.add(new Items(titulos[1], NavIconos.getResourceId(1,
-1)));
//Eventos
NavItems.add(new Items(titulos[2], NavIconos.getResourceId(2,
-1)));
//Lugares
NavItems.add(new Items(titulos[3], NavIconos.getResourceId(3,
-1)));
//Etiquetas
NavItems.add(new Items(titulos[4], NavIconos.getResourceId(4,
-1)));
//Declaramos y seteamos nuestrp adaptador al cual le pasamos
el array con los titulos
NavAdapter= new NavigationAdapter(this,NavItems);
mDrawerList.setAdapter(NavAdapter);
//Siempre vamos a mostrar el mismo titulo
mTitle = mDrawerTitle = getTitle();
//Declaramos mDrawableToggle y las imgs a utilizar
mDrawerToggle = new ActionBarDrawerToggle(
this,
/* Activity huesped*/
mDrawerLayout,
/* objeto DrawerLayout */
R.drawable.ic_drawer, /* imagen del nav drawer */
R.string.app_name,
/* "abrir drawer" descripcin
para accesibilidad */
R.string.hello_world
/* "cerrar drawer" descripcin
para accesibilidad */
) {
public void onDrawerClosed(View view) {
116
sea
home
117
", "MostrarFragment"+position);
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync el estado del toggle despues de onRestoreInstanceState
haya ocurrido.
mDrawerToggle.syncState();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mDrawerToggle.onConfigurationChanged(newConfig);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Pasar el evento al ActionBarDrawerToggle, si este
// regresa true, entonces este manejara el evento del touch
// en el icono de la app
if (mDrawerToggle.onOptionsItemSelected(item)) {
Log.e("mDrawerToggle presionado", "x");
return true;
}
// Maneja los otros items de la action bar...
return super.onOptionsItemSelected(item);
}
@Override
118
119
android:orderInCategory="100"
android:showAsAction="never"
android:title="@string/action_insertar"/>
</menu>
El
archivo
strings.xml
que
ya
tenemos
como
parte
de
nuestro
proyecto
en
el
directorio
res
>
values
deber
de
lucir
y/o
contener
todo
el
siguiente
cdigo:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string
<string
<string
<string
name="app_name">ToDoSQLite</string>
name="action_insertar">Insertar</string>
name="hello_world">Hello world!</string>
name="title_activity_tareas">TareasActivity</string>
<string-array name="prioridades">
<item>Urgente</item>
<item>Recordatorio</item>
</string-array>
<!-- Lista de elementos que aparecen en la navegacin -->
<string-array name="nav_options">
<item>ToDo</item>
<item>Conversor</item>
<item>Perfil</item>
<item>Configuracin</item>
<item>Conversor</item>
</string-array>
<!-- Lista de iconos de navegacion -->
<string-array name="nav_iconos">
<item>@drawable/ic_action_go_to_today</item>
<item>@drawable/ic_action_merge</item>
<item>@drawable/ic_action_person</item>
<item>@drawable/ic_action_good</item>
<item>@drawable/ic_action_cloud</item>
</string-array>
<string name="menu_insert">Agregar Tarea</string>
<string name="menu_delete">Borrar Tarea</string>
<string name="tarea_resumen">Nombre</string>
<string name="tarea_descripcion">Borrar</string>
<string name="tarea_editar_resumen">Nombre</string>
<string name="tarea_editar_descripcion">Descripcin</string>
<string name="tarea_editar_confirmar">Aceptar</string>
<string name="no_todos">An no existen elementos en la
lista</string>
</resources>
120
Diseo
de
layouts
Vamos
a
definir
dos
archivos
de
layout,
uno
para
la
lista,
y
uno
para
las
filas.
A
continuacin
veremos
el
cdigo
del
archivo
activity_tareas.xml
del
directorio
res
>
layout
que
define
la
apariencia
de
la
lista
que
desplegar
la
informacin
de
la
base
de
datos.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@color/list_color"
android:orientation="vertical" >
<ListView
android:id="@android:id/list"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</ListView>
<TextView
android:id="@android:id/empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/no_todos" />
</LinearLayout>
En
el
siguiente
layout
vamos
a
hacer
uso
de
un
icono,
se
puede
utilizar
el
que
deseen
incluso
se
puede
omitir
y
no
hay
ningn
problema.
El
siguiente
archivo
de
layout
se
llama
row.xml
y
se
usar
para
darle
estilo
a
cada
una
de
las
filas
de
la
lista:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="@+id/icon"
android:src="@drawable/reminder"
android:layout_marginLeft="4dp"
android:layout_marginTop="8dp"
android:layout_marginRight="8dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/label"
android:text="@string/hello_world"
android:layout_height="wrap_content"
android:textSize="20sp"
121
android:layout_marginTop="6dp"
android:layout_width="wrap_content"
android:textColor="@color/negro" />
</LinearLayout>
Ahora
que
ya
hemos
definido
los
recursos,
layouts
y
las
clases
que
nos
ayudarn
a
manipular
la
parte
de
SQLite
en
Android.
Estamos
listos
para
crear
las
clases
que
nos
ayudarn
a
juntar
cada
una
de
estas
piezas.
Si
vemos
el
cdigo
del
xml
veremos
esto:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
122
android:layout_height="fill_parent"
android:background="@color/list_color"
android:orientation="vertical" >
<Spinner
android:id="@+id/category"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:entries="@array/prioridades" />
<LinearLayout
android:id="@+id/LinearLayout01"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<EditText
android:id="@+id/todo_edit_summary"
android:layout_width="wrap_content"
android:layout_height="0dip"
android:layout_weight="1"
android:hint="Nombre" >
</EditText>
</LinearLayout>
<EditText
android:id="@+id/todo_edit_description"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:gravity="top"
android:hint="Descripcin" >
</EditText>
<Button
android:id="@+id/todo_edit_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/tarea_editar_confirmar" />
</LinearLayout>
Ya
tenemos
diseada
la
parte
del
cmo
se
ver
la
activity,
es
momento
de
pasar
a
la
etapa
en
la
que
escribiremos
el
cdigo
que
controlar
el
proceso
de
consultas
a
la
base
de
datos,
de
insercin
y
modificacin
de
datos
as
como
el
de
llenado
del
formulario
en
el
momento
que
hagamos
alguna
edicin
de
una
tarea
previamente
creada.
123
android.app.Activity;
android.database.Cursor;
android.os.Bundle;
android.util.Log;
android.view.View;
android.widget.Button;
android.widget.EditText;
android.widget.Spinner;
EditText mTitleText;
EditText mBodyText;
Long mRowId;
DBAdapter mDbHelper;
Spinner mCategory;
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
// Cargamos el layout de nuestro fragment
setContentView(R.layout.activity_details);
/*
* Inicializamos los objetos y los enlazamos con
* los elementos (views) del layout
* */
mCategory = (Spinner) findViewById(R.id.category);
mTitleText = (EditText)
findViewById(R.id.todo_edit_summary);
mBodyText = (EditText)
findViewById(R.id.todo_edit_description);
Button confirmButton = (Button)
findViewById(R.id.todo_edit_button);
/*
* Recuperamos los parmetros que enviamos a esta
* activity
* */
mRowId = null;
Bundle extras = getIntent().getExtras();
mRowId = (bundle == null) ? null : (Long)
124
bundle.getSerializable(DBAdapter.KEY_ROWID);
if (extras != null) {
mRowId = extras.getLong(DBAdapter.KEY_ROWID);
}
// Mandamos llamar al mtodo que se encargar de llenar los
campos en caso de ser una edicin
populateFields();
/*
* Le asignamos el evento de OnClickListener a nuetro botn
* esto con la finalidad de que guarde los valores que
tenemos
* en nuestro formulario
* */
confirmButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View view) {
setResult(RESULT_OK);
saveState();
finish();
}
});
}
/*
* Mtodo que permite llenar los campos del formulario
* en el caso de que sea una edicin, si no es una
* edicin los campos ser dejados vacos
* */
private void populateFields() {
/*
* Confirmamos que a variable mRowId no est nula,
* esto confirma que se trata de una edicin
* */
if (mRowId != null) {
/*Recuperamos los datos de la tarea que coincide con
la variable mRowId*/
Cursor todo = mDbHelper.recuperaTarea(mRowId);
/*
* El mtodo startManagingCursor que se hereda de la
clase Activity
* nos sirve o nos ayuda para tener un mejor control
del cursor, pues
* este se adaptar al ciclo de vida de la activity,
esto es que si
* la activity es detenida el cursor automticamente
llamar al mtodo
* deactivate(), y cuando la activity se reinicie se
llamr al mtodo
125
126
127
}
} else {
mDbHelper.updateTarea(mRowId, category, summary,
description);
}
}
}
Es
momento
de
realizar
otras
modificaciones,
es
turno
de
TareasFragment.java,
el
primero
y
que
es
muy
importante
es
cambiar
la
clase
de
la
cual
hereda,
en
este
momento
debera
de
estar
extendiendo
de
Fragment,
pero
ahora
vamos
a
modificarlo
por
ListFragment
esto
se
debe
a
que
esta
clase
muestra
una
lista
de
elementos
que
son
administrados
por
un
adaptador
(como
un
SimpleCursorAdapter),
similar
a
ListActivity.
Proporciona
varios
mtodos
para
la
gestin
de
una
vista
de
lista,
como
la
devolucin
de
llamada
onListItemClick
()
para
gestionar
clic
eventos
sobre
la
lista,
esta
es
una
de
las
casusas
por
la
que
en
este
caso
heredaremos
de
esta
clase
(ListFragment).
Ser
necesario
que
se
revise
el
cdigo
que
se
muestra
a
continuacin
pues
aqu
ya
se
muestran
todas
las
modificaciones
y
anexiones
que
se
le
hicieron
a
la
clase,
para
su
mayor
entendimiento
se
le
agregaron
varios
comentarios
para
que
sean
estudiados.
import
import
import
import
import
import
import
import
import
import
import
import
import
import
android.app.ListFragment;
android.content.Intent;
android.database.Cursor;
android.os.Bundle;
android.view.ContextMenu;
android.view.LayoutInflater;
android.view.Menu;
android.view.MenuItem;
android.view.View;
android.view.ViewGroup;
android.view.ContextMenu.ContextMenuInfo;
android.widget.ListView;
android.widget.SimpleCursorAdapter;
android.widget.AdapterView.AdapterContextMenuInfo;
import com.android.utm.todosqlite.database.DBAdapter;
public class TareasFragment extends ListFragment {
private static final int ACTIVITY_CREATE = 0;
private static final int ACTIVITY_EDIT = 1;
private static final int DELETE_ID = Menu.FIRST + 1;
private DBAdapter dbHelper;
private Cursor cursor;
public TareasFragment(){}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup
128
container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View rootView = inflater.inflate(R.layout.activity_tareas,
container, false);
/**
* Se crea una instancia de la clase DBAdapter,
* el constructor de la clase mandar a crear la BD si no
existe,
* en caso de ya existir solo crear la conexin a la BD
* */
dbHelper = new
DBAdapter(getActivity().getApplicationContext());
// Abre la conexin a la BD
dbHelper.open();
return rootView;
}
/*
* Este mtodo nos ayuda a saber cuando la
* activity de nuestro fragment ha terminado de
* ejecutar su mtodo onCreate()*/
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
fillData();
registerForContextMenu(getListView());
}
/*
* Se llama cada vez que se selecciona un elemento en un men
contextual
* */
@Override
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()) {
case DELETE_ID:
AdapterContextMenuInfo info = (AdapterContextMenuInfo)
item
.getMenuInfo();
dbHelper.deleteTarea(info.id);
fillData();
return true;
}
return super.onContextItemSelected(item);
}
129
130
131
case R.id.insertar:
createTodo();
return true;
}
return super.onMenuItemSelected(featureId, item);
}
private void createTodo() {
Intent i = new Intent(this, DetailsActivity.class);
startActivityForResult(i, ACTIVITY_CREATE);
}
//El siguiente metodo se llama con el resultado de otra actividad
// requestCode es el codigo original que se manda a la actividad
// resultCode es el codigo de retorno, 0 significa que todo sali
bien
// intent es usado para obtener alguna informacin del caller
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
//fillData();
//Cuando la aplicacion cargue por defecto mostrara la opcion
Home
MostrarFragment(1);
}
132
con
ayuda
del
GPS
o
de
la
red
WIFI,
por
lo
que
deberemos
de
agregar
los
siguientes
permisos
en
la
seccin
de
permisos
del
Manifest:
<!-- permite a la aplicacin conocer la ubicacin de manera "menos"
precisa. Por ejemplo, utilizando WIFI. -->
<uses-permission
android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- permite a la aplicacin que conozca de manera "precisa" la
ubicacin. Por ejemplo, utilizando GPS. -->
<uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION" />
por
lo
que
todo
nuestro
Manifest
quedar
como
se
muestra
a
continuacin:
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.utm.todosqlite"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="14" />
<permission
android:name="com.android.utm.todosqlite.java.permission.MAPS_REC
EIVE"
android:protectionLevel="signature" />
<uses-permission
android:name="com.android.utm.todosqlite.java.permission.MAPS_REC
EIVE" />
<uses-permission
android:name="com.google.android.providers.gsf.permission.READ_GS
ERVICES" />
<!-- permitimos abrir conexiones de red. -->
<uses-permission android:name="android.permission.INTERNET"
/>
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission
android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- permite a la aplicacin conocer la ubicacin de manera
"menos" precisa. Por ejemplo, utilizando WIFI. -->
<uses-permission
android:name="android.permission.ACCESS_COARSE_LOCATION" />
133
134
android:windowSoftInputMode="stateVisible|adjustResize" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.android.utm.todosqlite.TareasFragment" />
</activity>
<activity
android:name="com.android.utm.todosqlite.TrazarRutaFragment"
android:label="@string/title_activity_trazar_ruta" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.android.utm.todosqlite.MainActivity" />
</activity>
</application>
</manifest>
Como
se
podr
notar
en
este
momento
ya
hay
varias
actividades
declaradas
pero
que
an
no
las
hemos
codificado,
podemos
ir
adelantando
esto
para
que
no
se
nos
olvide
ms
adelante,
o
si
lo
desean
al
momento
que
sean
declaradas
y/o
creadas
las
actividades
podramos
venir
a
esta
seccin
para
confirmar
la
manera
en
la
que
se
declaran,
Nota
Es
momento
de
recordar
que
todas
las
actividades,
fragments
(pantallas)
o
cualquier
tipo
de
View
que
se
muestre
en
la
pantalla
de
nuestro
mvil
debe
de
ser
declarado
en
el
Manifest
de
nuestro
proyecto,
de
lo
contrario
en
el
momento
que
deseemos
abrir
o
mostrarla
en
pantalla
la
aplicacin
completa
fallar
y
se
cerrar.
En
muchas
ocasiones
es
necesario
que
se
declare
un
nuevo
paquete
en
el
cual
se
colocan
ciertas
clases
que
se
pueden
considerar
individuales,
puesto
que
realizan
una
funcin
en
especfico,
y
esta
funcin
en
muchos
de
los
casos
pueden
ser
usados
por
una
gran
cantidad
de
las
otras
clases,
a
este
tipo
de
clases
se
les
suele
llamar
que
son
utileras,
y
lo
nico
que
comparten
con
algunas
otras
clases
es
su
caracterstica
de
ser
solas
o
nicas
por
lo
que
se
acostumbra
crear
un
paquete
con
terminacin
util
para
nuestro
caso
ser
el
siguiente: com.android.utm.todosqlite.util
(recordemos
que
estos
nombre
son
los
que
tengo
para
mi
proyecto,
deberan
de
usar
los
que
tengan
para
el
suyo,
no
tienen
por
qu
ser
iguales),
para
este
proyecto
vamos
a
tener
tres
clases
en
este
paquete
las
cuales
sern
Utils.java,
ConnectionDetecter.java
y
GMapsDirection.java
a
continuacin
explicar
a
grandes
rasgos
de
que
tratan
cada
una,
pero
cabe
mencionar
que
este
tipo
de
clases
pueden
reutilizarse
en
diferentes
proyectos
prcticamente
sin
ningn
tipo
de
modificacin
salvo
pequeas
adecuaciones
segn
las
necesidades
especificas
de
algn
proyecto.
135
Utils.java
De
esta
clase
lo
que
nos
interesa
y
ser
lo
nico
que
explique
sern
los
mtodos
AdjustWidthScreen() y AdjustHeightScreen(), el
primero
de
ellos
lo
que
hace
es
recibir
de
parmetros
el
alto,
ancho
de
un
elemento
view
de
un
layout
as
como
un
valor
que
representa
el
ancho
que
deseamos
que
tenga
el
objeto
con
respecto
a
la
pantalla,
este
valor
representa
el
porcentaje
del
ancho
de
la
pantalla
y
tambin
se
recibe
como
parmetro,
el
ltimo
parmetro
recibido
es
el
objeto
al
cual
queremos
calcular
el
ancho.
El
segundo
hace
lo
mismo
pero
en
el
alto
del
elemento
recibido
como
parmetro.
Aqu
presento
el
cdigo
que
tendr
esta
clase:
package com.android.utm.todosqlite.util;
import
import
import
import
import
import
import
android.annotation.TargetApi;
android.os.Build;
android.os.StrictMode;
android.widget.Button;
android.widget.ImageView;
android.widget.LinearLayout;
android.widget.TextView;
/**
* Class containing some static utility methods.
*/
public class Utils {
public Utils() {};
@TargetApi(11)
public static void enableStrictMode() {
if (Utils.hasGingerbread()) {
StrictMode.ThreadPolicy.Builder threadPolicyBuilder =
new StrictMode.ThreadPolicy.Builder()
.detectAll()
.penaltyLog();
StrictMode.VmPolicy.Builder vmPolicyBuilder =
new StrictMode.VmPolicy.Builder()
.detectAll()
.penaltyLog();
StrictMode.setThreadPolicy(threadPolicyBuilder.build());
StrictMode.setVmPolicy(vmPolicyBuilder.build());
}
}
public static boolean hasFroyo() {
// Can use static final constants like FROYO, declared in
later versions
// of the OS since they are inlined at compile time. This is
guaranteed behavior.
136
137
138
139
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import
import
import
import
import
import
import
import
import
org.apache.http.HttpResponse;
org.apache.http.client.HttpClient;
org.apache.http.client.methods.HttpPost;
org.apache.http.impl.client.DefaultHttpClient;
org.apache.http.protocol.BasicHttpContext;
org.apache.http.protocol.HttpContext;
org.w3c.dom.Document;
org.w3c.dom.Node;
org.w3c.dom.NodeList;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import com.android.utm.todosqlite.TrazarRutaInternaFragment;
import com.google.android.gms.maps.model.LatLng;
public class GMapsDirection {
public final static String MODE_DRIVING = "driving";
public final static String MODE_WALKING = "walking";
private TrazarRutaInternaFragment fragment;
public ProgressDialog progress;
/**
* El constructor recibe como parmetro
* el fragment sobre el cual se est ejecutando
* o mostrando el mapa y sobre el cual se va a
* pintar la ruta de nuestro punto de origen a
* nuestro punto de destino
* */
public GMapsDirection(TrazarRutaInternaFragment fragment) {
this.fragment = fragment;
}
public void getDocument(LatLng start, LatLng end, String mode) {
/**
* Armamos la url de peticin a Google
* donde le pedimos que nos de las indicaciones
* de cmo llegar desde nuestro punto de origen
* hasta nuestro punto de destino, para lo cual
* necesitamos las coordenadas de inicio y de
* destino
* */
String url =
"http://maps.googleapis.com/maps/api/directions/xml?"
+ "origin=" + start.latitude + "," +
start.longitude
+ "&destination=" + end.latitude + "," +
end.longitude
140
+
"&sensor=false&units=metric&mode="+MODE_DRIVING;
// Usamos nuestra clase ConnectionDetector para verificar la
conectividad a internet
ConnectionDetector connectionDetector = new
ConnectionDetector(fragment.getActivity());
if(connectionDetector.isConnectedToInternet()){
new RetrieveData().execute(url);
}
}
/**
* Clase interna que hereda de AsyncTask la cual recibe
* la url de peticin para Google y entrega un objeto del
* tipo Document el cual contiene los pasos y coordenadas
* de los puntos para llegar al destino especificado
* */
class RetrieveData extends AsyncTask<String, Void, Document> {
/**
* En este mtodo lo nico que haremos ser iniciar
* un PogressDialog, este estar visible mientras
* se ejecuta el proceso de preguntar a Google y de
* que de su respuesta y as mismo de trazar la ruta
* sobre el mapa
* */
@Override
protected void onPreExecute() {
progress = new ProgressDialog(fragment.getActivity());
progress.setTitle("Cargando");
progress.setMessage("Por favor, espera...");
progress.setCanceledOnTouchOutside(false);
progress.show();
}
/**
* Este mtodo recibe como parmetro la url para realizar
* la consulta a Google, y como resultado de su ejecucin
* dar un objeto del tipo Document el cual contendr la
* estructura del documento XML que responde Google y que
* contiene la informacin de cmo llegar
* */
protected Document doInBackground(String... urls) {
try {
// Interfaz para un cliente HTTP.
HttpClient httpClient = new DefaultHttpClient();
141
142
// Ocultamos el ProgressDialog
progress.hide();
}
}
/**
* Este mtodo recibe el obejto Document con toda
* la informacin del XML de Google
* y lo que hace es obtener la informacin contenida
* en l para obtener nicamente los puntos con sus
* coordenadas y que sern puestos en el mapa para
* representar la ruta
* */
public ArrayList<LatLng> getDirection(Document doc) {
NodeList nl1, nl2, nl3;
ArrayList<LatLng> listGeopoints = new ArrayList<LatLng>();
nl1 = doc.getElementsByTagName("step");
if (nl1.getLength() > 0) {
for (int i = 0; i < nl1.getLength(); i++) {
Node node1 = nl1.item(i);
nl2 = node1.getChildNodes();
Node locationNode = nl2
.item(getNodeIndex(nl2,
"start_location"));
nl3 = locationNode.getChildNodes();
Node latNode = nl3.item(getNodeIndex(nl3,
"lat"));
double lat =
Double.parseDouble(latNode.getTextContent());
Node lngNode = nl3.item(getNodeIndex(nl3,
"lng"));
double lng =
Double.parseDouble(lngNode.getTextContent());
listGeopoints.add(new LatLng(lat, lng));
locationNode = nl2.item(getNodeIndex(nl2,
"polyline"));
nl3 = locationNode.getChildNodes();
latNode = nl3.item(getNodeIndex(nl3, "points"));
ArrayList<LatLng> arr =
decodePoly(latNode.getTextContent());
for (int j = 0; j < arr.size(); j++) {
listGeopoints.add(new
LatLng(arr.get(j).latitude, arr
.get(j).longitude));
}
locationNode = nl2.item(getNodeIndex(nl2,
"end_location"));
nl3 = locationNode.getChildNodes();
143
144
}
}
Ahora
es
momento
ya
de
empezar
a
trabajar
la
parte
que
ser
visible
en
nuestra
aplicacin,
empezaremos
con
el
diseo
de
los
layouts
de
las
interfaces
de
cada
uno
de
los
fragments
que
aparecern
en
nuestras
pestaas,
a
continuacin
muestro
una
captura
de
pantalla
de
cmo
se
vera
nuestra
aplicacin
al
terminar:
Lo
que
vemos
es
una
pantalla
que
tiene
dos
tabs,
en
una
tenemos
un
mapa
con
una
ruta
marcada
sobre
de
l,
y
en
la
otra
pestaa
es
un
pequeo
formulario
en
el
cual
vemos
unos
parametros
con
las
posiciones
actuales
y
la
de
destino
y
un
botn,
la
pantalla
se
ve
as
por
que
en
el
momento
de
tomar
la
captura
de
pantalla
se
est
haciendo
un
swipe
entre
las
pestaas,
es
decir
esta
aplicacin
tiene
un
ViewPager.
Creacin
de
elementos
visuales
En
esta
seccin
nos
dedicaremos
a
slo
crear
todo
los
layouts
y/o
archivos
de
configuracin
que
necesitemos
para
la
creacin
de
nuestra
aplicacin
Procederemos
ahora
a
crear
los
diferentes
layouts,
el
primero
que
crearemos
se
llamar
como_llegar_interna_fragment.xml,
dicho
layout
pertenece
al
fragment
que
nos
mostrar
la
ruta
de
cmo
llegar
entre
dos
puntos
directamente
en
el
mapa,
es
muy
simple,
se
ocupa
un
view
o
elemento
en
el
cual
se
muestra
un
mapa
(con
los
datos
obtenidos
del
servicio
de
Google
Maps).
Una
vez
enfocado,
capturar
las
pulsaciones
de
teclas
y
gestos
tctiles
para
mover
el
mapa.
Tambin
145
contiene
un
ImageView
que
tiene
el
atributo
visibility
en
invisible
esto
es
un
truco
que
se
necesita
para
poder
hacer
swipe
entre
las
pestaas,
de
no
ser
as
en
algunas
versiones
nuevas
de
Android
mostrar
unas
secciones
en
negro
al
momento
de
cambiar
las
pestaas,
si
su
aplicacin
no
ocupa
hacer
swipe
con
el
mapa,
entonces
no
es
necesario
que
tenga
el
ImageView.
Este
es
el
cdigo:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<!-- Un view que muestra un mapa
(con los datos obtenidos del servicio de Google Maps).
Una vez enfocado, capturar las pulsaciones de teclas
y gestos tctiles para mover el mapa. -->
<com.google.android.gms.maps.MapView
android:id="@+id/mapa"
android:layout_width="match_parent"
android:layout_height="match_parent"
map:uiZoomControls="true" />
<!-- Este ImageView tiene el atributo visibility
en invisible esto es un truco que se necesita
para poder hacer swipe entre las pestaas, de no
ser as en algunas versiones nuevas de Android
mostrar unas secciones en negro al momento de
cambiar las pestaas-->
<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:visibility="invisible" />
</RelativeLayout>
Para
el
layout
de
la
otra
pestaa
que
lo
que
hace
es
pedir
a
una
aplicacin
externa
que
muestre
el
trazo
de
la
ruta
que
se
desea,
para
este
caso
se
desea
sea
mostrada
por
a
aplicacin
Maps
de
Google,
pero
en
muchos
casos
podra
pasar
que
existan
varias
aplicaciones
que
puedan
abrir
la
ruta
solicitida
(es
algo
complicado
especificar
una
aplicacin
en
especial),
en
ese
caso
lo
que
hace
android
de
forma
automtica
es
algo
como
lo
que
se
muestra
en
la
imagen
de
siguiente:
146
En
este
caso
ya
es
decisin
personal
que
opcin
tomar,
pero
yo
aconsejo
hacerlo
con
la
aplicacin
de
Maps,
ya
que
nos
dar
como
resultado
lo
que
vemos
en
las
siguientes
imgenes:
147
El
segundo
layout
ser
demasiado
simple
pues
los
elementos
que
utilizaremos
son
varios
que
ya
hemos
usado
varias
veces
en
otros
ejemplos,
pero
aqu
dejo
el
cdigo
como
ejemplo,
el
layout
se
llamar
como_llegar_externa_fragment.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:background="#CECECE" >
<TextView
android:id="@+id/latitud_origen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/longitud_origen"
android:layout_below="@+id/longitud_origen"
android:layout_marginTop="28dp"
android:text="Latitud Origen" />
<TextView
android:id="@+id/longitud_origen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="18dp"
android:layout_marginTop="16dp"
android:text="Longitud Origen" />
<!-- Aqu se va a mostrar la longitud de origen obtenida del GPS
del mvil -->
<TextView
android:id="@+id/longitud_origen_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/latitud_origen"
android:layout_centerHorizontal="true"
android:text="TextView" />
<!-- Aqu se va a mostrar la latitud de origen obtenida del GPS
del mvil -->
<TextView
android:id="@+id/latitud_origen_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/latitud_origen"
android:layout_alignLeft="@+id/longitud_origen_txt"
android:text="TextView" />
148
<TextView
android:id="@+id/longitud_destino"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/latitud_origen"
android:layout_below="@+id/latitud_origen"
android:layout_marginTop="27dp"
android:text="Longitud Destino" />
<!-- Aqu se muestra la longitud de destino -->
<TextView
android:id="@+id/longitud_destino_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/longitud_destino"
android:layout_alignBottom="@+id/longitud_destino"
android:layout_alignLeft="@+id/latitud_origen_txt"
android:text="-99.131111" />
<TextView
android:id="@+id/latitud_destino"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/longitud_destino"
android:layout_below="@+id/longitud_destino"
android:layout_marginTop="24dp"
android:text="Latitud Destino" />
<!-- Aqu se muestra la latitud de destino -->
<TextView
android:id="@+id/latitud_destino_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/latitud_destino"
android:layout_alignBottom="@+id/latitud_destino"
android:layout_alignLeft="@+id/longitud_destino_txt"
android:text="19.4325" />
<!-- Botn que realizar el proceso de armar la URL para
solicitar el trazado de la ruta de un punto de origen a uno
de destino -->
<Button
android:id="@+id/btn_trazar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/latitud_destino_txt"
android:layout_centerHorizontal="true"
android:layout_marginTop="86dp"
android:text="Trazar Ruta" />
</RelativeLayout>
149
En
nuestro
ejemplo
las
pestaas
tendrn
dos
colores,
una
para
cuando
estn
seleccionados
(#558e33),
y
otro
para
cuando
no
lo
estn
(#adab21),
es
por
esta
razn
que
registraremos
dos
colores
en
el
archivo
colors.xml,
adems
tambin
registraremos
un
color
para
la
lnea
a
trazar
de
la
ruta
en
el
mapa,
por
lo
que
nuestro
archivo
de
configuracin
de
colores
quedar
cmo
se
muestra
en
el
listado
siguiente:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="list_color">#94A65D</color>
<color name="negro">#000000</color>
<!-- Estos son las tres nuevas definiciones de colores -->
<color name="tab_trazar_on">#558e33</color>
<color name="tab_trazar_off">#adab21</color>
<color name="route">#65b4f1</color>
</resources>
Android
tiene
una
forma
muy
fcil
para
controlar
el
estilo
de
los
elementos
que
deben
de
mostrar
cuando
sean
tocados,
seleccionados
o
enfocados
entre
otros.
Para
lograr
que
de
forma
automtica
se
cambin
los
colores
de
las
pestaas
ser
necesario
crear
un
nuevo
archivo
xml
pero
este
estar
en
la
carpeta
drawable
y
llevar
por
nombre
tab_selector_trazar.xml,
en
este
archivo
se
declararn
las
reglas
que
se
deben
de
cumplir
cada
vez
que
una
de
las
pestaas
es
tocada
o
cada
vez
que
su
estado
cambie
ha
seleccionado,
a
continuacin
se
muestra
el
cdigo
de
este
archivo
(en
lugar
de
colores
pueden
ser
definidas
imgenes):
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- Active tab -->
<!-- Lo que se dice aqu es que cuando el estado de seleccionado
de una tab sea verdadero
se deber de aplicar a la pestaa el color definido con el nombre
tab_trazar_on -->
<item android:drawable="@color/tab_trazar_on"
android:state_selected="true"/>
<!-- Inactive tab -->
<!-- Lo que se dice aqu es que cuando una tab no est
seleccionado
se deber de aplicar a la pestaa el color definido con el nombre
tab_trazar_off -->
<item android:drawable="@color/tab_trazar_off"/>
</selector>
Si
no
queremos
que
las
pestaas
de
nuestra
aplicacin
luzcan
de
la
forma
por
default
como
en
el
estilo
de
Android
ser
necesario
que
sea
creado
un
layout
nuevo
en
donde
se
especifique
el
nuevo
estilo
o
apariencia,
como
ese
es
el
caso
del
proyecto
que
estamos
desarrollando
entonces
ser
necesario
que
sea
creado
un
nuevo
layout
de
nombre
tab_layout_trazar.xml, este
nuevo
diseo
es
muy
simple
consta
de
un
RelativeLayout
al
cual
le
aplicaremos
como
valor
del
atributo
background
el
archivo
150
previamente
creado,
esto
har
que
si
la
pestaa
est
seleccionada
tenga
un
color
y
si
no
lo
est
tenga
otro
color,
el
otro
elemento
que
aparecer
es
un
TextView
en
el
cual
aparecer
el
texto
que
deseemos
en
cada
pestaa.
Este
layout
ser
aplicado
a
cada
una
de
las
pestaas
que
tengamos
en
pantalla
al
momento,
este
es
el
cdigo
del
layout:
<?xml version="1.0" encoding="utf-8"?>
<!-- Lo interesante en este caso es la aplicacin en el atributo
background del archivo tab_selector_trazar.xml para cambiarle
los colores segn el status de la pestaa -->
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/tab_selector_trazar" >
<TextView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFF"
android:gravity="center"
android:layout_centerInParent="true" />
</RelativeLayout>
Ya
definimos
como
se
debe
de
ver
cada
una
de
las
pestaas
que
deber
de
tener
nuestra
aplicacin,
ahora
vamos
a
definir
la
estructura
completa,
esto
qu
significa?,
pues
definir
mediante
un
layout
la
ubicacin
de
donde
deben
de
aparecer
las
pestaas
(tabs),
la
cantidad
de
pestaas
a
mostrar,
definir
un
espacio
para
que
sean
mostrados
los
contenidos
de
cada
pestaa,
y
en
el
caso
de
este
ejemplo
agregar
el
elemento
de
ViewPager
para
poder
hacer
el
movimiento
de
swipe
entre
pestaas.
En
Android,
el
elemento
principal
de
un
conjunto
de
pestaas
ser
el
control
TabHost.
ste
va
a
ser
el
contenedor
principal
de
nuestro
conjunto
de
pestaas
y
deber
tener
obligatoriamente
como
id
el
valor
@android:id/tabhost.
Dentro
de
ste
vamos
a
incluir
un
LinearLayout
que
nos
servir
para
distribuir
verticalmente
las
secciones
principales
del
layout:
la
seccin
de
pestaas
en
la
parte
superior
y
la
seccin
de
contenido
en
la
parte
inferior.
La
seccin
de
pestaas
se
representar
mediante
un
elemento
TabWidget,
que
deber
tener
como
id
el
valor
@android:id/tabs,
y
como
contenedor
para
el
contenido
de
las
pestaas
aadiremos
un
FrameLayout
con
el
id
obligatorio
@android:id/tabcontent.
Por
ltimo,
dentro
del
FrameLayout
incluiremos
el
contenido
de
cada
pestaa,
normalmente
cada
uno
dentro
de
su
propio
layout
principal
(en
mi
caso
he
utilizado
FrameLayout)
y
con
un
id
nico
que
nos
permita
posteriormente
hacer
referencia
a
ellos
fcilmente
(en
mi
caso
he
utilizado
por
ejemplo
los
ids
tab_1_interna
,
tab_2_externa
,
).
En
nuestro
caso
es
necesario
agregar
el
controlador
que
permite
al
usuario
mover
de
un
tirn
a
la
izquierda
y
derecha
a
travs
de
diferentes
ventanas
dicho
control
es
android.support.v4.view.ViewPager,el
nombre
de
este
layout
ser
view_tabs_layout_trazar.xm.
151
<?xml version="1.0" encoding="utf-8"?>
<!-- Contenedor para las pestaas en una ventana, este contiene dos
hijos, uno es el
un conjunto de etiquetas para las pestaas que el usuario hace
clic para seleccionar
una pestaa especfica, el otro hijo es un objeto FrameLayout el
cual muestra el
contenido de la pgina -->
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
android:id="
@android:id/tabhost"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@null" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<!-- Aqu ser la seccin de las pestaas y siempre el id
deber de tener el valor
de android:id="@android:id/tabs" -->
<TabWidget
android:id="@android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="top"
android:tabStripEnabled="false" >
</TabWidget>
<!-- contenedor para el contenido de las pestaas con el id
obligatorio "@android:id/tabcontent" -->
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:background="@null" >
<!-- Por cada pestaa que contenga la vista se deber
de incluir un FrameLayout -->
<FrameLayout
android:id="@+id/tab_1_interna"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<FrameLayout
android:id="@+id/tab_2_externa"
152
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</FrameLayout>
<!-- Controlador que permite al usuario mover de un tirn a la
izquierda y derecha a travs de
diferentes ventanas -->
<android.support.v4.view.ViewPager
android:id="@+id/pager_trazar_ruta"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null" />
</LinearLayout>
</TabHost>
Para
terminar
con
la
fase
de
diseo
de
interfaz
ser
necesario
tener
un
layout
en
el
cual
tengamos
un
concentrador
de
todos
los
dems
layouts
hechos
pues
son
esos
layouts
una
parte
del
diseo
general
dicho
layout
se
llamar
fragment_trazar.xml que
en
verdad
es
demasiado
sencillo
su
diseo
pues
solo
tiene
un
LinearLayout
como
contenedor
principal
pero
es
aqu
en
donde
se
usa
un
nuevo
elemento,
se
llama
include
y
de
lo
que
se
encarga
o
para
lo
que
sirve
es
para
incluir
un
layout
dentro
de
otro
slo
es
necesario
usar
el
atributo
layout
y
especificarle
el
nombre
del
layout
a
incluir.
Para
caso
de
nuestro
ejemplo
mostramos
el
siguiente
cdigo
que
ilustrar
de
mejor
manera
lo
que
se
dice:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#12ac56"
android:orientation="vertical"
android:baselineAligned="false" >
<!-- El elemento include nos sirve para incluir otros layouts
dentro de este
slo basta con indicar el nombre del layout a incluir -->
<include
android:layout_width="wrap_content"
android:layout_height="0dip"
android:layout_weight="1"
layout="@layout/view_tabs_layout_trazar" />
</LinearLayout>
Por
fin
se
ha
terminado
la
fase
de
diseo
de
la
interfaz
es
necesario
ahora
entrar
al
cdigo
en
java
para
poder
agregar
la
funcionalidad
necesaria
para
que
nuestra
aplicacin
funcione
de
la
mejor
manera
posible.
153
154
import java.util.ArrayList;
import org.w3c.dom.Document;
import
import
import
import
import
import
import
import
import
import
import
android.app.AlertDialog;
android.content.Context;
android.location.Criteria;
android.location.Location;
android.location.LocationManager;
android.os.Bundle;
android.support.v4.app.Fragment;
android.view.LayoutInflater;
android.view.View;
android.view.ViewGroup;
android.widget.Toast;
import com.android.utm.todosqlite.util.ConnectionDetector;
import com.android.utm.todosqlite.util.GMapsDirection;
import
com.google.android.gms.common.GooglePlayServicesNotAvailableException;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.MapsInitializer;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.PolylineOptions;
/*
* En esta clase heredamos de la clase Fragment de android y vamos
* a implementar la interfaz publica LocationListener
* */
public class TrazarRutaInternaFragment extends Fragment implements
LocationListener{
private
private
private
private
private
private
private
private
private
private
private
private
MapView mMapView;
GoogleMap map;
final double latitude = 19.4325;
final double longitude = -99.131111;
Context context;
LocationManager locationManager;
String provider;
Location location;
GMapsDirection md;
LatLng currentLocation;
double currentLatitude;
double currentLongitude;
155
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup
container,
Bundle savedInstanceState) {
// Cargar el layout en el fragment
View rootView =
inflater.inflate(R.layout.como_llegar_interna_fragment,
container, false);
/**
* Hacer referencia al elemento
com.google.android.gms.maps.MapView
* del layout aqu ser donde se mostrar el mapa
* */
mMapView = (MapView) rootView.findViewById(R.id.mapa);
// inflar y regresar el layout
mMapView.onCreate(savedInstanceState);
// Necesario para desplegar el mapa obtenido inmediatamente
mMapView.onResume();
try {
/**
* Inicializa la API de Google Maps Android y as
* obtener las caractersticas necesarias para poder
* usar en el mapa ya obtenido
* */
MapsInitializer. initialize(getActivity());
} catch (GooglePlayServicesNotAvailableException e) {
e.printStackTrace();
}
map = mMapView.getMap();
map.setMyLocationEnabled(true);
CameraUpdate center = CameraUpdateFactory.newLatLng(new
LatLng(latitude, longitude));
CameraUpdate zoom = CameraUpdateFactory.zoomTo(12);
map.moveCamera(center);
map.animateCamera(zoom);
context = getActivity();
// Obtener los proveedores de localizacin que existane en
nuestro dispositivo mvil
locationManager = (LocationManager)
context.getSystemService(Context.LOCATION_SERVICE);
// Una clase indicando los criterios de aplicacin para la
seleccin de un proveedor de ubicacin.
Criteria criteria = new Criteria();
156
157
/**
* Se agrega un listener al snipet (la informacin
* que aparece al tocar el marker), de esta
* manera se puede controlar si se desea que
* haga alguna accin, como por ejemplo mostrar
* otra vista
* */
map.setOnInfoWindowClickListener(new
OnInfoWindowClickListener() {
@Override
public void onInfoWindowClick(Marker marker) {
Toast.makeText(
context,
"Snipet pulsado:\n" +
marker.getTitle(),
Toast.LENGTH_SHORT).show();
}
});
/**
* Instanciamos un objeto de la clase
* GMapsDirection
* */
md = new GMapsDirection(this);
// Crear un nuevo objeto LatLng con la longitud y latitud
destino
LatLng location = new LatLng(latitude, longitude);
/**
* Ejecutamos el mtodo getDocument, dicho mtodo
* empezar el proceso de armar la url de consulta
* a Google Maps y de interpretacin de la respuesta
* */
md.getDocument(currentLocation, location,
GMapsDirection.MODE_DRIVING);
return rootView;
}
@Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setRetainInstance(true);
/**
* En esta parte lo que hacemos es instanciar un
* objeto de la clase ConnectionDetector, para
* usar uno de sus mtodos y comprobar si mi
* dispositivo mvil tiene acceso a interntet, en
158
159
PolylineOptions().width(8).color(getResources().getColor(R.color.route
));
/*
* En este for agregamos los puntos con sus
* coordenadas a la Polyline
* */
for(int i = 0 ; i < directionPoint.size() ; i++) {
rectLine.add(directionPoint.get(i));
}
// Agregar la Polyline al mapa para su visualizacin
map.addPolyline(rectLine);
}
@Override
public void onResume() {
super.onResume();
if (null != mMapView)
mMapView.onResume();
}
@Override
public void onPause() {
super.onPause();
if (null != mMapView)
mMapView.onPause();
}
@Override
public void onDestroy() {
super.onDestroy();
if (null != mMapView)
mMapView.onDestroy();
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (null != mMapView)
mMapView.onSaveInstanceState(outState);
}
@Override
public void onLowMemory() {
super.onLowMemory();
if (null != mMapView)
mMapView.onLowMemory();
}
/*
160
161
Es
muy
simple
el
cdigo
de
esta
nueva
clase
que
se
llamar
TrazarRutaExternaFragment.java,
aqu
muestro
todo
el
cdigo
de
esta
clase:
package com.android.utm.todosqlite;
import
import
import
import
import
import
import
import
import
import
import
import
import
import
android.content.Context;
android.content.Intent;
android.location.Location;
android.location.LocationManager;
android.net.Uri;
android.os.Bundle;
android.support.v4.app.Fragment;
android.view.LayoutInflater;
android.view.View;
android.view.View.OnClickListener;
android.view.ViewGroup;
android.widget.Button;
android.widget.TextView;
android.widget.Toast;
TextView latitudDestino;
TextView longitudDestino;
TextView latitudOrigen;
TextView longitudOrigen;
Button btnTrazar;
Context context;
LocationManager locManager;
Location loc;
android.location.LocationListener locListener;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup
container,
Bundle savedInstanceState) {
View rootView =
inflater.inflate(R.layout.como_llegar_externa_fragment, container,
false);
/*
* Instanciar los elementos del layout
* con objetos para poder interactuar
* con ellos desde el cdigo
* */
latitudDestino = (TextView)
rootView.findViewById(R.id.latitud_destino_txt);
longitudDestino = (TextView)
rootView.findViewById(R.id.longitud_destino_txt);
latitudOrigen = (TextView)
rootView.findViewById(R.id.latitud_origen_txt);
162
longitudOrigen = (TextView)
rootView.findViewById(R.id.longitud_origen_txt);
btnTrazar = (Button) rootView.findViewById(R.id.btn_trazar);
context = getActivity();
// Manda llamar el mtodo para obtener la posicin actual
comenzarLocalizacion();
// Se agrega una accin al botn para llamar el mtodo
trazarRuta()
btnTrazar.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
trazarRuta();
}
});
return rootView;
}
/*
* En este mtodo se crea la URL para
* solicitar la ruta, esto se hace
* mediante un Intent*/
protected void trazarRuta() {
Intent intentMap = new
Intent(android.content.Intent.ACTION_VIEW,
Uri.parse("http://maps.google.com/maps?addr="+loc.getLatitude()+"
, "+loc.getLongitude() +
"&daddr=" + latitudDestino.getText()
+", " + longitudDestino.getText()));
startActivity(intentMap);
}
/*
* Mtodo para obtener la posicin actual
* mediante el GPS del dispositivo mvil
* */
private void comenzarLocalizacion() {
// Obtenemos una referencia al LocationManager
locManager = (LocationManager)
context.getSystemService(Context.LOCATION_SERVICE);
//Si el GPS no est activado
if(!locManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
163
mostrarAvisoGpsDesahibilitado();
}
// Obtenemos la ltima posicin conocida
loc =
locManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
// Nos registramos para recibir actualizaciones de la
posicin
locListener = new android.location.LocationListener() {
@Override
public void onLocationChanged(Location location) {
loc = location;
latitudOrigen.setText(loc.getLatitude()+"");
longitudOrigen.setText(loc.getLongitude()+"");
}
@Override
public void onProviderDisabled(String arg0) {
// TODO Auto-generated method stub
}
@Override
public void onProviderEnabled(String arg0) {
// TODO Auto-generated method stub
}
@Override
public void onStatusChanged(String arg0, int arg1,
Bundle arg2) {
// TODO Auto-generated method stub
}
};
locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
10000, 0, locListener);
}
// Mtodo que se usa para mostrar un mensaje de que el GPS est
deshabilitado
private void mostrarAvisoGpsDesahibilitado() {
Toast.makeText(getActivity().getApplicationContext(), "El
GPS se encuentra deshabilitado, por favor habilitar",
Toast.LENGTH_LONG).show();
}
164
}
Las
clases
anteriores
fueron
creadas
para
dar
control
a
los
fragments
que
tendramos
en
cada
una
de
las
pestaas,
ahora
es
necesario
agregar
las
clases
que
se
encargaran
de
controlar
el
funcionamiento
de
las
tabs
y
del
ViewPager.
Para
implementar
ViewPager
ser
necesario
un
adaptador,
el
cual
se
encargara
de
administrar
todas
las
vistas.
Lo
ideal
ser
implementar
una
clase
que
se
extienda
de
FragmentPagerAdapter
la
cual
lanzar
los
Fragments
(Vistas)
necesarios.
Hablemos
un
poco
de
FragmnetPagerAdapter
y
de
Fragments
para
entenderlos
mejor
y
as
saber
de
que
estamos
haciendo
uso.
FragmenPagerAdapter
es
una
implementacin
de
PagerAdapter
que
facilita
el
uso
de
Fragments
dentro
de
un
ViewPager.
Esta
versin
de
pager
es
comnmente
usada
en
el
manejo
de
fragments
estticos
parecido
al
manejo
de
Tabs.
FragmentPagerAdapter
mantiene
los
fragments
visitados
en
memoria
por
lo
cual
es
til
para
cuando
se
manejan
un
nmero
reducido
de
Fragments.
La
clase
creada
se
llama
TrazarRutaPagerAdapter.java,
y
a
continuacin
veremos
el
cdigo:
package com.android.utm.todosqlite;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
165
case 0:
TrazarRutaInternaFragment trazarInternaFragment = new
TrazarRutaInternaFragment();
data.putInt("current_page", arg0+1);
trazarInternaFragment.setArguments(data);
fragment = trazarInternaFragment;
break;
/** Pestaa para TrazarRutaExternaFragment es seleccionada
*/
case 1:
TrazarRutaExternaFragment trazarExternaFragment = new
TrazarRutaExternaFragment();
data.putInt("current_page", arg0+1);
trazarExternaFragment.setArguments(data);
fragment = trazarExternaFragment;
break;
}
return fragment;
}
/** Retorna el nmero de pginas */
@Override
public int getCount() {
return PAGE_COUNT;
}
}
Con
esto
ya
tendramos
montada
toda
la
estructura
de
controles
necesaria
para
nuestra
interfaz
de
pestaas.
Sin
embargo,
con
esto
no
es
suficiente.
Necesitamos
asociar
de
alguna
forma
cada
pestaa
con
su
contenido,
de
forma
que
el
control
se
comporte
correctamente
cuando
cambiamos
de
pestaa.
Y
esto
tendremos
que
hacerlo
mediante
cdigo.
package com.android.utm.todosqlite;
import com.android.utm.todosqlite.util.Utils;
import
import
import
import
import
import
import
import
import
import
import
import
import
import
android.app.ActionBar;
android.content.Intent;
android.os.Bundle;
android.support.v4.app.FragmentActivity;
android.support.v4.app.FragmentManager;
android.support.v4.view.ViewPager;
android.util.DisplayMetrics;
android.view.LayoutInflater;
android.view.Menu;
android.view.MenuItem;
android.view.View;
android.view.ViewGroup;
android.widget.TabHost;
android.widget.TabHost.TabSpec;
166
import android.widget.TextView;
/**
* @author NelsonPadilla
*
*/
public class TrazarRutaFragment extends FragmentActivity implements
TabHost.OnTabChangeListener{
private
private
private
private
private
private
private
private
private
private
public TrazarRutaFragment() {
// TODO Auto-generated constructor stub
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_trazar);
// Calcular la resolucin del dispositivo
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
DeviceWidth = metrics.widthPixels;
DeviceHeight = metrics.heightPixels;
// Obtener el ActionBar
ActionBar actionBar = getActionBar();
// Establecer si queremos que la accin del icono sea
habilitado como ir a Home
actionBar.setDisplayHomeAsUpEnabled(true);
/**
* Obtener una referencia al ViewPager en el layout
* con esto lograremos hacer el swipe
* */
mPager = (ViewPager) findViewById(R.id.pager_trazar_ruta);
/**
* Cuando se usa un FragmetnActivity es necesario
167
168
/*
* Mtodo en el que se establece
* la accin a realizar al momento
* de seleccionar algn elemento de
* la ActionBar
* */
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
/*
* En caso de haber seleccionado el botn
* habilitado como Home cargar la clase
* MainActivity
* */
case android.R.id.home:
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
break;
// Something else
}
return super.onOptionsItemSelected(item);
}
/*
* Mtodo que se encargar de actualizar la vista,
* esto es que cambiar de fragment segn sea la
* tab seleccionada
* */
private void updateTab(String arg0, int placeholder) {
if (supportFragmentManager.findFragmentByTag(arg0) == null)
{
if (arg0.equals(TAB_TRAZAR_INTERNA)) {
new TrazarRutaInternaFragment();
}
if (arg0.equals(TAB_TRAZAR_EXTERNA)) {
new TrazarRutaExternaFragment();
}
}
}
/*
* Mtodo encargado de */
private void setupTabs() {
/*
* Llamar setup() antes de aadir pestaas si se carga
TabHost usando findViewById ().
* */
mTabHost.setup(); // Importante!!!
169
170
Crear
un
lector
QR
La
inclusin
de
software
que
lee
cdigos
QR
en
telfonos
mviles,
ha
permitido
nuevos
usos
orientados
al
consumidor,
que
se
manifiestan
en
comodidades
como
el
dejar
de
tener
que
introducir
datos
de
forma
manual
en
los
telfonos.
Las
direcciones
y
los
URLs
se
estn
volviendo
cada
vez
ms
comunes
en
revistas
y
anuncios
.
El
agregado
de
cdigos
QR
en
tarjetas
de
presentacin
tambin
se
est
haciendo
comn,
simplificando
en
gran
medida
la
tarea
de
introducir
detalles
individuales
de
un
nuevo
cliente
en
la
agenda
de
un
telfono
mvil.
Es
por
esto
que
he
decidido
hacer
un
ejemplo
simple
y
bsico
de
cmo
crear
uno.
Este
ejemplo
estar
incluido
dentro
de
la
aplicacin
que
hemos
venido
desarrollando
a
lo
largo
del
curso,
es
por
eso
que
en
nuestro
men
(NavigationDrawer),
agregaremos
una
nueva
opcin
para
desde
ah
mandar
ejecutar
el
lector.
El
ejemplo
consistira
en
que
el
lector
creado
podr
leer
cdigos
QR,
estos
cdigos
sern
los
ids
de
los
registros
que
tenemos
en
la
base
de
datos
de
nuestro
ejemplo,
por
lo
que
al
leer
el
cdigo
(que
ser
un
id),
podremos
hacer
una
consulta
a
la
base
de
datos,
obtener
los
datos
y
presentarlos
en
pantalla,
un
ejemplo
muy
simple
pero
muy
ilustrativo
de
todo
lo
que
se
podra
hacer
al
leer
uno
de
estos
cdigos.
171
Android
por
default
no
integra
en
su
api
un
lector
de
cdigos
QR,
para
lo
cul
ser
necesario
agregar
una
librera
que
nos
ayudar
y
facilitar
el
trabajo
de
lectura
e
interpretacin
del
cdigo.
Es
as
que
antes
de
empezar
tendremos
que
aclarar
dos
cosas:
Qu
son
los
cdigos
QR?,
y
segundo
dnde
obtenemos
la
librera,
y
cmo
la
instalamos
en
nuestro
proyecto?.
Librera
ZXing
El
proyecto
ZXing
es
una
librera
de
procesamiento
de
imagen
que
es
de
cdigo
abierto,
y
procesa
cdigos
de
barra
en
1D/2D
en
mltiples
formatos.
Para
descargarlo
lo
haremos
de
la
siguiente
URL
http://repo1.maven.org/maven2/com/google/zxing/core/3.0.0/core-3.0.0.jar,
y
la
instalacin
ser
muy
simple
ya
descargado,
habr
que
copiar
el
archivo
descargado
(core-3.0.0.jar)
en
la
carpeta
/ruta/workspace/ToDoSQLite/libs/
ya
con
esto
podemos
usar
la
librera
en
nuestro
proyecto.
Permisos
en
el
AndroidManifest
Cmo
lo
hemos
visto
y
hecho
en
secciones
anteriores
empezaremos
nuestro
ejemplo
con
la
declaracin
de
permisos
en
el
archivo
AndroidManifest.xml
de
nuestro
proyecto,
por
qu
es
necesario
ahora
declarar
permisos?,
en
nuestro
caso
como
vamos
a
usar
hardware
de
nuestro
dispositivo
mvil
(la
cmara),
es
necesario
hacerlo,
y
as
va
a
pasar
para
cualquier
otro
proyecto
que
hagamos
en
el
futuro,
hay
que
definir
los
permisos
para
poder
hacer
uso
del
hardware
o
servicios
que
tenga
nuestro
mvil,
tambin
nuestro
proyecto
har
una
pequea
vibracin
en
el
momento
de
detectar
un
cdigo
para
avisarle
al
usuario,
bueno
tambin
tenemos
que
declarar
permisos
para
poder
usar
la
vibracin,
e
incluso
el
permiso
para
solicitar
el
autofocus
de
la
cmara,
y
he
aqu
lo
que
habra
que
colocar
en
nuestro
AndroidManifest
para
este
ejemplo:
<!-- Permisos para utilizar la cmara, para que vibre y para que la
cmara haga autofocus -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature
android:name="android.hardware.camera.autofocus"
172
android:required="false" />
<uses-feature
android:name="android.hardware.touchscreen"
android:required="false" />
Y
para
nuestro
proyecto
vamos
a
dar
permisos
a
nuestras
actividades
que
usaremos,
que
slo
sern
dos:
<activity
android:name="com.android.utm.todosqlite.QRDetailActivity"
android:screenOrientation="portrait" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.android.utm.todosqlite.MainActivity" />
</activity>
<activity
android:name="com.android.utm.todosqlite.ZXingActivity"
android:configChanges="keyboard|keyboardHidden|orientation"
android:screenOrientation="landscape" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
173
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<SurfaceView
android:id="@+id/preview_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<View
android:id="@+id/center_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_centerInParent="true"
android:background="#00000000" />
</RelativeLayout>
</FrameLayout>
En
el
momento
en
que
ya
se
est
ejecutando
la
aplicacin
y
estemos
leyendo
algn
cdigo
QR
veremos
algo
como
lo
siguiente:
174
Ya
terminada
la
creacin
del
layout
de
la
cmara
para
el
lector
es
momento
de
proceder
a
la
creacin
del
layout
que
mostrar
la
vista
de
resultado,
en
este
layout
lo
que
veremos
ser
el
resultado
de
una
consulta
a
la
base
de
datos
y
en
la
cual
utilizaremos
lo
que
lemos
del
cdigo
QR,
pues
en
el
cdigo
tendremos
el
id
del
registro
que
queremos
leer.
El
diseo
de
la
interfz
es
demasiado
simple
pues
no
es
el
caso
de
este
ejemplo
ver
como
disear
o
construir
las
interfaces,
y
bueno
he
aqu
el
cdigo
del
layout
que
llevar
por
nombre
activity_qr_detail.xml.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@android:color/darker_gray"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/LinearLayout01"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="@+id/category"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Categora" />
<TextView
android:id="@+id/category_result"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Categora" />
</LinearLayout>
<LinearLayout
android:id="@+id/LinearLayout01"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="@+id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Resumen" />
<TextView
175
android:id="@+id/summary_result"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />
</LinearLayout>
<TextView
android:id="@+id/description_result"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="top" />
</LinearLayout>
La
interfaz
que
acabamos
de
crear
al
momento
de
ya
haber
ledo
un
cdigo
vlido
veremos
algo
como
lo
que
se
muestra
a
continuacin
(la
verdad
una
interfaz
muy
simple):
Clases
para
el
lector
de
QR
En
este
ejemplo
se
tiene
una
nueva
clase
en
el
paquete
com.android.utm.todosqlite.util
(recordemos
que
estos
paquetes
son
los
de
mi
proyecto,
aqu
deberan
de
tener
de
acuerdo
a
los
suyos)
esta
clase,
de
qu
se
encargar
o
para
qu
nos
servir?,
pues
para
algo
muy
simple
como
hacer
que
el
mvil
vibre
y
produzca
un
beep,
en
el
momento
que
decodifique
un
cdigo
QR.
Primero
para
esto
ya
tenemos
los
permisos
en
establecidos
en
el
AndroidManifes.xml
de
nuestro
proyecto,
segundo
lo
que
hace
falta
antes
de
continuar
ser
poner
un
archivo
de
audio
en
nuestro
proyecto
que
ser
el
que
haga
el
beep.
Es
necesario
crear
una
nueva
carpeta
dentro
de
la
carpeta
res
de
nuestro
proyecto
a
la
que
176
llamaremos
raw,
quedando
de
esta
manera
/res/raw/beep.ogg,
y
como
vemos
el
archivo
se
llamar
beep.ogg,
en
caso
de
no
contar
con
ninguno
se
puede
descargar
desde
esta
direccin
http://soundbible.com/1251-Beep.html,
esta
pgina
es
una
biblioteca
de
sonidos,
si
no
les
agrada
ese
pueden
colocar
el
que
deseen
slo
que
deben
de
recordar
de
cambiar
el
nombre
del
archivo
en
el
cdigo
por
el
del
nuevo
archivo
de
audio
seleccionado
para
que
funcione
de
la
manera
adecuada,
estos
son
todos
los
preparativos
que
habra
que
hacer
respecto
a
esta
clase
cuyo
nombre
ser
BeepManager.java
(recuerda
de
poner
la
clase
en
el
paquete
com.android.utm.todosqlite.util),
esta
clase
la
podemos
utilizar
as
como
est
en
cualquier
otro
proyecto
as
sin
modificaciones,
salvo
el
nombre
del
archivo
de
audio
que
usemos,
si
es
otro
al
que
se
especifica
en
el
cdigo
ser
necesario
cambiarlo.
Este
es
el
cdigo:
package com.android.utm.todosqlite.util;
import
import
import
import
import
import
import
import
import
android.app.Activity;
android.content.Context;
android.content.SharedPreferences;
android.content.res.AssetFileDescriptor;
android.media.AudioManager;
android.media.MediaPlayer;
android.os.Vibrator;
android.preference.PreferenceManager;
android.util.Log;
import java.io.IOException;
import com.android.utm.todosqlite.R;
import com.android.utm.todosqlite.ZXingActivity;
/**
* Manages beeps and vibrations for {@link ZXingActivity}.
*/
public final class BeepManager {
private static final String TAG =
BeepManager.class.getSimpleName();
private static final float BEEP_VOLUME = 0.10f;
private static final long VIBRATE_DURATION = 200L;
private
private
private
private
/*
* Constructor de la clase que inicia
* variables y pone las condiciones de
177
178
179
mediaPlayer = null;
}
return mediaPlayer;
}
}
Ahora
es
el
turno
para
la
clase
de
la
activity
que
mostrar
el
resultado
y
llamar
a
la
consulta
dicha
clase
la
llamaremos
QRDetailActivity.java,
esta
clase
tiene
una
funcionalidad
muy
similar
a
la
de
DetailsActivity.java,
salvo
que
en
esta
solo
tiene
la
funcionalidad
de
mostrar
resultados
no
hace
modificaciones
de
datos.
Algo
en
lo
que
me
detendr
a
explicar
es
la
forma
en
la
que
recuperamos
el
dato
del
id
que
es
envado
desde
la
clase
ZxingActivity.java
(en
este
punto
an
no
la
hemos
hecho),
dicho
parmetro
se
manda
en
un
objeto
Bundle,
y
es
de
esta
manera
en
la
que
se
mandan
parmetros
entre
actividades,
el
cdigo
que
se
encarga
de
hacer
esto
es
colocado
dentro
de
mtodo
onCreate(),
y
es
el
siguiente:
/*
* Recuperamos los parmetros que enviamos a esta
* activity
* */
mRowId = null;
Bundle extras = getIntent().getExtras();
mRowId = (bundle == null) ? null : (Long)
bundle.getSerializable(DBAdapter.KEY_ROWID);
if (extras != null) {
mRowId = extras.getLong(DBAdapter.KEY_ROWID);
}
Todo
el
dems
cdigo
est
comentado
para
su
comprensin
por
esto
es
que
a
continuacin
se
los
muestro:
package com.android.utm.todosqlite;
import
import
import
import
import
import
import
import
import
import
android.app.ActionBar;
android.content.Intent;
android.database.Cursor;
android.os.Bundle;
android.support.v4.app.FragmentActivity;
android.view.Menu;
android.view.MenuItem;
android.view.View;
android.view.View.OnClickListener;
android.widget.TextView;
import com.android.utm.todosqlite.database.DBAdapter;
public class QRDetailActivity extends FragmentActivity implements
OnClickListener {
180
private
private
private
private
private
DBAdapter mDbHelper;
TextView categoryResult;
TextView summaryResult;
TextView descriptionResult;
Long mRowId;
@Override
public void onBackPressed() {
// TODO Auto-generated method stub
super.onBackPressed();
}
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
/**
* Se crea una instancia de la clase DBAdapter,
* el constructor de la clase mandar a crear la BD si no
existe,
* en caso de ya existir solo crear la conexin a la BD
* */
mDbHelper = new DBAdapter(this);
// Abre la conexin a la BD
mDbHelper.open();
// Cargamos el layout de nuestro fragment
setContentView(R.layout.activity_qr_detail);
/*
* Inicializamos los objetos y los enlazamos con
* los elementos (views) del layout
* */
categoryResult = (TextView)
findViewById(R.id.category_result);
summaryResult = (TextView)
findViewById(R.id.summary_result);
descriptionResult = (TextView)
findViewById(R.id.description_result);
/*
* Recuperamos los parmetros que enviamos a esta
* activity
* */
mRowId = null;
Bundle extras = getIntent().getExtras();
mRowId = (bundle == null) ? null : (Long)
bundle.getSerializable(DBAdapter.KEY_ROWID);
if (extras != null) {
mRowId = extras.getLong(DBAdapter.KEY_ROWID);
}
181
182
descriptionResult.setText(todo.getString(todo.getColumnIndexOrThr
ow(DBAdapter.KEY_DESCRIPTION)));
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// TODO Auto-generated method stub
return super.onCreateOptionsMenu(menu);
}
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
}
/*
* Reacciona al evento del botn
* Up/Home y nos regresa a la
* activity indicada
* */
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
break;
// Something else
}
return super.onOptionsItemSelected(item);
}
}
Por
ltmo
es
turno
de
la
creacin
de
la
clase
que
se
encargar
de
leer
e
interpretar
el
cdigo
QR
dicha
clase
llevar
por
nombre
ZxingActivity.java
en
esta
clase
no
explicar
todo
lo
que
hace,
pero
son
mtodos
que
deben
de
ir
y
a
los
cuales
no
sera
conveniente
modificarles
o
moverles
algo,
pero
si
debemos
de
poner
atencin
al
mtodo
onPreviewFram(),
aqu
muestro
el
cdigo
de
este
mtodo:
/** Camera.PreviewCallback */
/*
* En este motodo se hace la captura de la imagen
* del cdigo QR y la decodifica, a su vez manda
* llamar a la activity QRDetailActivity para que
* se muestre el detalle de la consulta
* */
183
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
View centerView = (View)findViewById(R.id.center_view);
int left = centerView.getLeft() * previewPoint.x /
screenPoint.x;
int top = centerView.getTop() * previewPoint.y /
screenPoint.y;
int width = centerView.getWidth() * previewPoint.x /
screenPoint.x;
int height = centerView.getHeight() * previewPoint.y /
screenPoint.y;
PlanarYUVLuminanceSource source
PlanarYUVLuminanceSource(
= new
data,
previewPoint.x,
previewPoint.y,
left,
top,
width,
height,
false);
/*
* Se crea un objeto BinaryBitmap que contiene la imagen del
cdigo QR
* que se acaba de leer
* */
BinaryBitmap bitmap = new BinaryBitmap(new
HybridBinarizer(source));
/*
* Creamos el objeto que se encarga de leer el cdigo QR
* */
MultiFormatReader reader = new MultiFormatReader();
try {
/*
* Se decodifica la imagen que capt el lector
* con la cmara y se guarda en un objeto Result
* */
Result result = reader.decode(bitmap);
// Ejecutamos el mtodo que ejecuta el beep y hace vibrar
el telfono
beepManager.playBeepSoundAndVibrate();
/*
* Si el objeto Result no est vaco creamos un
* intent y mandamos ejecutar la activity
QRDetailActivity*/
if(result.getText()!=null){
/*
184
} finally {
if(continua){
Camera.Parameters parameters =
myCamera.getParameters();
if
(!parameters.getFocusMode().equals(Camera.Parameters.FOCUS_MODE_FIXED)
) {
myCamera.autoFocus(this);
}
}
}
}
Pues
es
aqu
donde
se
lee
el
cdigo
QR
y
tambin
en
donde
se
descifra,
es
por
eso
que
aqu
si
pueden
existir
modificaciones
al
cdigo,
esto
va
de
la
mano
de
lo
que
quieren
que
haga
si
aplicacin,
en
el
caso
de
este
ejemplo
slo
leemos
el
QR
y
lo
interpretamos
para
luego
mandar
el
dato
ledo
como
un
parmetro
a
la
siguiente
actividad,
a
continuacin
viene
el
cdigo
de
esta
clase
completo:
package com.android.utm.todosqlite;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
185
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
android.annotation.TargetApi;
android.app.Activity;
android.app.AlertDialog;
android.content.Context;
android.content.DialogInterface;
android.content.Intent;
android.content.res.Configuration;
android.graphics.Point;
android.hardware.Camera;
android.os.Build;
android.os.Bundle;
android.util.Log;
android.view.Display;
android.view.MotionEvent;
android.view.SurfaceHolder;
android.view.SurfaceView;
android.view.View;
android.view.Window;
android.view.WindowManager;
import
import
import
import
import
import
com.android.utm.todosqlite.util.BeepManager;
com.google.zxing.BinaryBitmap;
com.google.zxing.MultiFormatReader;
com.google.zxing.PlanarYUVLuminanceSource;
com.google.zxing.Result;
com.google.zxing.common.HybridBinarizer;
186
@Override
protected void onPause() {
closeCamera();
if (!hasSurface) {
SurfaceHolder holder = surfaceView.getHolder();
holder.removeCallback(this);
}
super.onPause();
}
/** SurfaceHolder.Callback */
@Override
public void surfaceCreated(SurfaceHolder holder) {
187
if (!hasSurface) {
hasSurface = true;
initCamera(holder);
Camera.Parameters parameters = myCamera.getParameters();
if(parameters.getFocusMode()!=null)
if
(!parameters.getFocusMode().equals(Camera.Parameters.FOCUS_MODE_FIXED)
) {
myCamera.autoFocus(this);
}
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
hasSurface = false;
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int
width, int height) {
}
/** Camera.AutoFocusCallback */
@Override
public void onAutoFocus(boolean success, Camera camera) {
//if (success)
try {
camera.setOneShotPreviewCallback(this);
} catch (RuntimeException e) {
e.printStackTrace();
}
}
/** devices */
@Override
public boolean onTouchEvent(MotionEvent event) {
if (myCamera != null) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
Camera.Parameters parameters =
myCamera.getParameters();
if(parameters.getFocusMode()!=null)
if
(!parameters.getFocusMode().equals(Camera.Parameters.FOCUS_MODE_FIXED)
) {
myCamera.autoFocus(this);
}
}
}
188
return true;
}
/** Camera.PreviewCallback */
/*
* En este motodo se hace la captura de la imagen
* del cdigo QR y la decodifica, a su vez manda
* llamar a la activity QRDetailActivity para que
* se muestre el detalle de la consulta
* */
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
View centerView = (View)findViewById(R.id.center_view);
int left = centerView.getLeft() * previewPoint.x /
screenPoint.x;
int top = centerView.getTop() * previewPoint.y /
screenPoint.y;
int width = centerView.getWidth() * previewPoint.x /
screenPoint.x;
int height = centerView.getHeight() * previewPoint.y /
screenPoint.y;
PlanarYUVLuminanceSource source
PlanarYUVLuminanceSource(
= new
data,
previewPoint.x,
previewPoint.y,
left,
top,
width,
height,
false);
/*
* Se crea un objeto BinaryBitmap que contiene la imagen del
cdigo QR
* que se acaba de leer
* */
BinaryBitmap bitmap = new BinaryBitmap(new
HybridBinarizer(source));
/*
* Creamos el objeto que se encarga de leer el cdigo QR
* */
MultiFormatReader reader = new MultiFormatReader();
try {
/*
* Se decodifica la imagen que capt el lector
* con la cmara y se guarda en un objeto Result
* */
Result result = reader.decode(bitmap);
189
} finally {
if(continua){
Camera.Parameters parameters =
myCamera.getParameters();
if
(!parameters.getFocusMode().equals(Camera.Parameters.FOCUS_MODE_FIXED)
) {
myCamera.autoFocus(this);
}
}
}
}
public boolean checkCode(String str_codigo){
190
return true;
}
public AlertDialog crearDialogo(String mensaje) {
AlertDialog.Builder builder = new AlertDialog.Builder(
ZXingActivity.this);
builder.setMessage(mensaje).setCancelable(false)
.setNeutralButton("OK", new
DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
continua=true;
Camera.Parameters parameters =
myCamera.getParameters();
if(!parameters.getFocusMode().equals(Camera.Parameters.FOCUS_MODE
_FIXED)) {
myCamera.autoFocus(ZXingActivity.this);
}
dialog.cancel();
}
});
return builder.create();
}
/**
*
* @param holder
*/
private void initCamera(SurfaceHolder holder) {
try {
openCamera(holder);
} catch (Exception e) {
Log.w(TAG, e);
}
}
private void openCamera(SurfaceHolder holder) throws IOException {
if (myCamera == null) {
myCamera = Camera.open();
if (myCamera == null) {
throw new IOException();
}
}
myCamera.setPreviewDisplay(holder);
if (!initialized) {
initialized = true;
191
initFromCameraParameters(myCamera);
}
setCameraParameters(myCamera);
//myCamera.setDisplayOrientation(90);
myCamera.startPreview();
}
/**
* ????????????????????????
*/
private void closeCamera() {
if (myCamera != null) {
myCamera.stopPreview();
myCamera.release();
myCamera = null;
}
}
/**
* ????????????????????????
* @param camera
*/
private void setCameraParameters(Camera camera) {
Camera.Parameters parameters = camera.getParameters();
parameters.setPreviewSize(previewPoint.x, previewPoint.y);
List<String> focusModes = parameters.getSupportedFocusModes();
if(parameters.getFocusMode()!=null)
if
(focusModes.contains(Camera.Parameters.FOCUS_MODE_MACRO)){
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_MACRO);
} else if
(focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
}
camera.setParameters(parameters);
}
/**
*
* @param camera
*/
private void initFromCameraParameters(Camera camera) {
Camera.Parameters parameters = camera.getParameters();
WindowManager manager =
(WindowManager)getApplication().getSystemService(Context.WINDOW_SERVIC
E);
Display display = manager.getDefaultDisplay();
int width = display.getWidth();
192
193
supportedHeight);
diff = newDiff;
}
}
if (previewPoint == null) {
Camera.Size defaultPreviewSize =
parameters.getPreviewSize();
previewPoint = new Point(defaultPreviewSize.width,
defaultPreviewSize.height);
}
return previewPoint;
}
}
Por
ltimo
es
necesario
tener
una
forma
de
donde
mandar
ejecutar
todo
el
proceso
para
abrir
el
lector
esto
lo
haremos
desde
el
men
del
MainActivity.java
(NavigationDrawer),
para
lo
cual
habr
que
agregar
unas
lneas
de
cdigo
en
el
switch
del
mtodo
MostrarFragment(),
dicho
cdigo
extra
es
el
siguiente:
case 4:
startActivity(new Intent(this, ZXingActivity.class));
break;
Con
esto
damos
por
terminado
el
ejemplo
de
lectura
de
cdigos
QR
Adapters
Los
Adapters
de
Android
son
un
puente
entre
el
Adapter
View
(por
ejemplo
ListView)
y
los
datos
subyacentes
para
esa
vista.
Imagnese
lo
que
hubiera
sido
el
mundo
sin
necesidad
de
adaptadores!
Sin
Adapters,
para
implementar
la
funcionalidad
del
ListView,
se
habra
necesitado
de:
A
continuacin
se
muestra
un
diagrama
conceptual
de
alto
nivel
que
muestra
el
trabajo
del
adaptador
de
Android:
194
En
la
figura
anterior,
asumimos
que
estamos
viendo
los
meses
en
un
ao
en
un
ListView.
Para
empezar,
los
meses
de
enero
a
mayo
se
muestran
en
la
pantalla.
Al
desplazarse
por
la
vista,
el
mes
de
enero
se
sale
de
la
zona
de
visualizacin
de
la
pantalla
del
mvil.
Tan
pronto
como
la
vista
de
enero
sale
de
la
pantalla,
el
Adapter
View
(ListView
en
este
caso)
enva
la
vista
a
algo
que
se
llama
un
reciclador.
As
que
cuando
se
desplaza
hacia
arriba,
el
mtodo
getView()
se
llama
para
obtener
el
siguiente
punto
de
vista
(que
es
de
junio).
Este
mtodo
getView()
tiene
un
parmetro
llamado
convertview
que
apunta
a
la
vista
sin
utilizar
en
el
reciclador.
A
travs
del
convertview,
el
adaptador
intenta
controlar
la
vista
sin
usar
y
reutilizarla
para
mostrar
la
nueva
vista
(que
es
de
junio,
en
este
caso).
195
Integracin
con
los
Servicios
de
Google
Play
(Google
Play
Services)
y
la
Consola
de
APIs.
Utilizacin
a
travs
de
un
nuevo
tipo
especfico
de
fragment
(MapFragment),
una
mejora
muy
esperada
por
muchos.
Utilizacin
de
mapas
vectoriales,
lo
que
repercute
en
una
mayor
velocidad
de
carga
y
una
mayor
eficiencia
en
cuanto
a
uso
de
ancho
de
banda.
Mejoras
en
el
sistema
de
cach,
lo
que
reducir
en
gran
medida
las
famosas
reas
en
blanco
que
tardan
en
cargar.
Los
mapas
son
ahora
3D,
es
decir,
podremos
mover
nuestro
punto
de
vista
de
forma
que
lo
veamos
en
perspectiva.
Imagen
33
196
Tras
pulsar
el
botn
de
Install
y
aceptar
la
licencia
correspondiente
el
paquete
quedar
instalado
en
nuestro
sistema,
concretamente
en
la
ruta:
<carpeta-sdkandroid>/extras/google/google_play_services/.
Recordemos
esto
porque
nos
har
falta
ms
adelante.
2. El
siguiente
paso
ser
obtener
una
API
Key
para
poder
utilizar
el
servicio
de
mapas
de
Google
en
nuestra
aplicacin.
3. La
nueva
API
de
mapas
de
Android
se
ha
integrado
por
fin
en
la
Consola
de
APIs
de
Google,
por
lo
que
el
primer
paso
ser
acceder
a
ella.
4. Es
probable
que
si
nunca
hemos
entrado
a
la
consola
de
APIS
de
Google
nos
pida
que
una
pantalla
como
la
que
se
muestra
a
continuacin,
por
lo
que
hacemos
click
en
el
botn
Create
Proyect,
en
caso
de
no
ser
as
continuamos
con
el
punto
5
directamente.
Imagen
34
5. Una
vez
hemos
accedido,
tendremos
que
crear
un
nuevo
proyecto
desplegando
el
men
superior
izquierdo
y
seleccionando
la
opcin
Create.
Imagen
35
197
6. Aparecer
entonces
una
ventana
que
nos
solicitar
el
nombre
del
proyecto.
Introducimos
algn
nombre
descriptivo
y
aceptamos
sin
ms.
Imagen
36
7. Una
vez
creado
el
proyecto,
accederemos
a
la
opcin
Services
del
men
izquierdo.
Desde
esta
ventana
podemos
activar
o
desactivar
cada
uno
de
los
servicios
de
Google
que
queremos
utilizar.
En
este
caso
slo
activaremos
el
servicio
llamado
Google
Maps
Android
API
v2
pulsando
sobre
el
botn
ON/OFF
situado
justo
a
su
derecha.
Imagen
37
Imagen
38
9. Una
vez
activado
aparecer
una
nueva
opcin
en
el
men
izquierdo
llamada
API
Access.
Accediendo
a
dicha
opcin
tendremos
la
posibilidad
de
obtener
nuestra
nueva
API
Key
que
nos
permita
utilizar
el
servicio
de
mapas
desde
nuestra
aplicacin
particular.
198
Imagen
39
10. Para
ello,
pulsaremos
el
botn
Create
new
Android
key.
Esto
nos
llevar
a
un
cuadro
de
dilogo
donde
tendremos
que
introducir
algunos
datos
identificativos
de
nuestra
aplicacin.
En
concreto
necesitaremos
dos:
la
huella
digital
(SHA1)
del
certificado
con
el
que
firmamos
la
aplicacin,
y
el
paquete
java
utilizado.
El
segundo
no
tiene
misterio,
pero
el
primero
requiere
alguna
explicacin.
Toda
aplicacin
Android
debe
ir
firmada
para
poder
ejecutarse
en
un
dispositivo,
tanto
fsico
como
emulado.
Este
proceso
de
firma
es
uno
de
los
pasos
que
tenemos
que
hacer
siempre
antes
de
distribuir
pblicamente
una
aplicacin.
Adicionalmente,
durante
el
desarrollo
de
la
misma,
para
realizar
pruebas
y
la
depuracin
del
cdigo,
aunque
no
seamos
conscientes
de
ello
tambin
estamos
firmado
la
aplicacin
con
un
certificado
de
pruebas.
Podemos
saber
en
qu
carpeta
de
nuestro
sistema
est
almacenado
este
certificado
accediendo
desde
Eclipse
al
men
Window/Preferences y accediendo
a la seccin Android/Build.
199
Imagen
40
12. Suponiendo
que
tu
200
Imagen
41
13. Pues
bien,
nos
copiamos
este
dato
y
lo
aadimos
a
la
ventana
de
obtencin
de
la
API
Key
donde
nos
habamos
quedado
antes,
y
a
continuacin
separado
por
un
punto
y
coma
aadimos
el
paquete
java
que
vayamos
a
utilizar
en
nuestra
aplicacin,
que
en
mi
caso
ser
com.demo.proyectodemo.
Imagen
42
14. Pulsamos
el
botn
Create
y
ya
deberamos
tener
nuestra
API
Key
generada,
podremos
verla
en
la
pantalla
siguiente
dentro
del
apartado
Key
for
Android
Apps
(with
certificates).
Apuntaremos
tambin
este
dato
para
utilizarlo
ms
tarde.
201
Imagen
43
15. Con
esto
ya
habramos
concluido
los
preparativos
iniciales
necesarios
para
utilizar
el
servicio
de
mapas
de
Android
en
nuestras
propias
aplicaciones,
por
lo
que
modificaremos
nuestro
proyecto
de
ejemplo
en
Eclipse.
16. lo
primero
que
haremos
ser
aadir
al
fichero
AndroidManifest.xml
la
API
Key
que
acabamos
de
generar.
Para
ello
aadiremos
al
fichero,
dentro
de
la
etiqueta
<application>,
un
nuevo
elemento
<meta-data>
con
los
siguientes
datos:
Imagen
44
17. Como
valor
del
parmetro
android:value
tendremos
que
poner
nuestra
API
Key
recin
generada.
En
mi
caso
mi
API
Key
generada
es:
AIzaSyDmw0rDncgMS1TbUkaXavswHdZRdMbyw6w (recuerda
este
valor
es
para
el
caso
mo,
aqu
debe
de
ir
valor
que
a
ustedes
les
genera).
18. Siguiendo
con
el
AndroidManifest,
tambin
tendremos
que
incluir
una
serie
de
permisos
que
nos
permitan
hacer
uso
de
los
mapas.
En
primer
lugar
tendremos
que
definir
y
utilizar
un
permiso
llamado
tu.paquete.java.permission.MAPS_RECEIVE,
estas
etiquetas
deben
de
ser
colocadas
antes
de
la
etiqueta
<application,
en
mi
caso
quedara
de
la
siguiente
forma
(recordemos
y
tengamos
mucho
cuidado
de
usar
el
nombre
del
paquete
principal
de
su
proyect:
<permission
android:name="com.android.utm.todosqlite.java.permission.MAPS_RECEIVE"
android:protectionLevel="signature" />
<uses-permission
android:name="com.android.utm.todosqlite.java.permission.MAPS_RECEIVE"
/>
202
Imagen
45
19. Adems,
tendremos
que
aadir
permisos
adicionales
que
nos
permitan
acceder
a
los
servicios
web
de
Google,
a
Internet,
y
al
almacenamiento
externo
del
dispositivo
(utilizado
para
la
cach
de
los
mapas),
estos
permisos
son
colocados
inmediatamente
despus
de
los
anteriores:
<uses-permission
android:name="com.google.android.providers.gsf.permission.READ_GSERVIC
ES" />
<!-- permitimos abrir conexiones de red. -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Imagen
46
20. Por
ltimo,
dado
que
la
API
v2
de
Google
Maps
Android
utiliza
OpenGL
ES
versin
2,
deberemos
especificar
tambin
dicho
requisito
en
nuestro
AndroidManifest
aadiendo
un
nuevo
elemento
<uses-feature> inmediatamente
despus
de
los
permisos
anteriores:
Imagen
47
21. Una
vez
hemos
configurado
todo
lo
necesario
en
el
AndroidManifest,
y
antes
de
escribir
nuestro
cdigo,
tenemos
que
seguir
aadiendo
elementos
externos
a
nuestro
proyecto.
El
primero
de
ellos
ser
referenciar
desde
nuestro
proyecto
la
librera
con
el
SDK
de
Google
Play
Services
que
nos
descargamos
al
principio
de
este
tutorial.
Para
ello,
desde
Eclipse
podemos
importar
la
librera
a
nuestro
conjunto
de
proyectos
mediante
la
opcin
de
men
File / Import /
Existing Android Code Into Workspace.
Como
ya
dijimos
este
paquete
se
localiza
en
la
ruta
<carpeta-sdkandroid>/extras/google/google_play_services/libproject/googleplay-services_lib.
203
Imagen
48
22. Tras
seleccionar
la
ruta
correcta
dejaremos
el
resto
de
opciones
con
sus
valores
por
defecto
y
pulsaremos
Finish
para
que
Eclipse
importe
esta
librera
a
nuestro
conjunto
de
proyectos.
23. El
siguiente
paso
ser
referenciar
esta
librera
desde
nuestro
proyecto
de
ejemplo.
Para
ello
iremos
a
sus
propiedades
pulsando
botn
derecho
/
Properties
sobre
nuestro
proyecto
y
accediendo
a
la
seccin
Android
de
las
preferencias.
En
dicha
ventana
podemos
aadir
una
nueva
librera
en
la
seccin
inferior
llamada
Library.
Cuando
pulsamos
el
botn
Add
nos
aparecer
la
librera
recin
importada
y
podremos
seleccionarla
directamente,
aadindose
a
nuestra
lista
de
libreras
referenciadas
por
nuestro
proyecto.
204
Imagen
49
24. Como
ltimo
paso
de
configuracin
de
nuestro
proyecto,
si
queremos
que
nuestra
aplicacin
se
pueda
ejecutar
desde
versiones
antiguas
de
Android
(concretamente
desde
la
versin
de
Android
2.2)
deberemos
asegurarnos
de
que
nuestro
proyecto
incluye
la
librera
android-
support-v4.jar,
que
debera
aparecer
si
desplegamos
las
seccin
Android
Dependencies
o
la
carpeta
lib
de
nuestro
proyecto.
Imagen
50
25. Las
versiones
ms
recientes
de
ADT
incluyen
por
defecto
esta
librera
en
nuestros
proyectos,
pero
si
no
est
incluida
podramos
hacerlo
mediante
la
opcin
del
men
contextual
Android
Tools
/
Add
Support
Library
sobre
el
proyecto,
o
bien
de
forma
manual.
205
Pasos
para
construir
una
aplicacin
bsica
usando
la
API
de
Google
Maps
Y
con
esto
hemos
terminado
de
configurar
todo
lo
necesario.
Ya
podemos
escribir
nuestro
cdigo.
Y
para
este
primer
ejemplo
sobre
el
tema
nos
vamos
a
limitar
a
mostrar
un
mapa
en
la
pantalla
principal
de
la
aplicacin.
Posteriormente
veremos
cmo
aadir
otras
opciones
o
elementos
al
mapa.
1. Para
esto
tendremos
simplemente
que
aadir
el
control
correspondiente
al
layout
de
nuestra
actividad
en
este
caso
es
activity_mapa.xml.
En
el
caso
de
la
nueva
API
v2
este
control
se
aadir
en
forma
de
fragment
(de
ah
que
hayamos
tenido
que
incluir
la
librera
android-
support
para
poder
utilizarlos
en
versiones
de
Android
anteriores
a
la
3.0)
de
un
determinado
tipo
(concretamente
de
la
nueva
clase
com.google.android.gms.maps.SupportMapFragment),
quedando
por
ejemplo
de
la
siguiente
forma
(ver
Imagen
132):
Imagen
51
Grficamente
el
diseo
de
la
interfaz
se
vera
como
se
muestra
en
la
Imagen
53.
Imagen
52
206
2. Por
supuesto,
dado
que
estamos
utilizando
fragments,
la
actividad
MapasActivity.java
tambin
tendr
que
extender
a
FragmentActivity
(en
vez
de
simplemente
Activity
como
es
lo
normal).
Usaremos
tambin
la
versin
de
FragmentActivity
incluida
en
la
librera
android-support
para
ser
compatibles
con
la
mayora
de
las
versiones
Android
actuales.
Veamos
la
Imagen
54
para
ver
cmo
queda
el
cdigo
de
nuestra
activity.
Imagen
53
Con
esto,
ya
podramos
ejecutar
y
probar
nuestra
aplicacin.
En
mi
caso
las
pruebas
las
he
realizado
sobre
un
dispositivo
fsico
con
Android
2.3.5
ya
que
por
el
momento
parece
haber
algunos
problemas
para
hacerlo
sobre
el
emulador.
Por
tanto
tendremos
que
conectar
nuestro
dispositivo
a
la
PC
mediante
el
cable
de
datos
e
indicar
a
Eclipse
que
lo
utilice
para
la
ejecucin
de
la
aplicacin.
En
la
Imagen
55
podemos
ver
una
captura
en
pantalla
de
la
ejecucin
del
cdigo
que
previamente
hemos
creado.
207
Imagen
54
En
el
ejemplo
anterior
todo
lo
que
hicimos
fue
lo
necesario
para
configurar
la
API
de
Google
y
poder
cargar
un
mapa
en
nuestra
pantalla,
pero
ahora
lo
que
se
pretende
hacer
es
ya
interactuar
con
el
mapa,
en
qu
consistir
esta
interaccin,
pues
lo
primero
ser
lograr
que
el
mapa
se
posicione
sobre
un
punto
en
especfico
y
a
este
punto
le
colocaremos
unos
markers
personalizado
junto
a
algn
tipo
de
mensaje.
1. Bueno
lo
primero
que
haremos
ser
abrir
el
archivo
MapasActivity.java
para
modificarlo,
de
ahora
en
adelante
en
este
ejemplo
todo
lo
que
hagamos
ser
en
esta
clase.
2. Como
en
este
ejemplo
ser
algo
demostrativa
y
simple
pondremos
las
coordenadas
de
dos
puntos
de
forma
manual
en
unas
variables
globales
del
tipo
LatLng,
en
posteriores
ejemplos
veremos
cmo
recuperar
la
posicin
actual
a
travs
del
GPS
del
celular
por
lo
pronto
veremos
la
Imagen
56
y
observamos
la
forma
de
declarar
las
coordenadas.
Imagen
55
3. Ahora
pasaremos
a
inicializar
la
variable
del
tipo
GoogleMap
declarada
y
el
elemento
respectivo
del
layout.
En
la
siguiente
Imagen
podemos
ver
cmo
se
hace
(recuerda
que
esto
se
hace
en
el
mtodo
onCreate):
208
Imagen
56
4. Posteriormente
agregaremos
los
markers
para
cada
uno
de
los
puntos
que
crearemos
en
el
mapa
y
tambin
pondremos
el
zoom
de
inicio
sobre
el
mapa
y
declararemos
un
efecto
al
momento
de
hacer
zoom
sobre
el
mapa,
ver
Imagen
58
para
el
cdigo.
Imagen
57
209
posteriormente
obtendremos
la
lista
de
proveedores
mediante
el
mtodo
citado
para
obtener
la
lista
de
nombres
de
los
proveedores:
Imagen
58
Una
vez
obtenida
la
lista
completa
de
proveedores
disponibles
podramos
acceder
a
las
propiedades
de
cualquiera
de
ellos
(precisin,
coste,
consumo
de
recursos,
o
si
es
capaz
de
obtener
la
altitud,
la
velocidad,
etc).
As,
podemos
obtener
una
referencia
al
provider
mediante
su
nombre
llamando
al
mtodo
getProvider(nombre)
y
posteriormente
utilizar
los
mtodos
disponibles
para
conocer
sus
propiedades,
por
ejemplo
getAccuracy()
para
saber
su
precisin
(tenemos
disponibles
las
constantes
Criteria.ACCURACY_FINE
para
precisin
alta,
y
Criteria.ACCURACY_COARSE
para
precisin
media),
supportsAltitude()
para
saber
si
obtiene
la
altitud,
o
getPowerRequirement()
para
obtener
el
nivel
de
consumo
de
recursos
del
proveedor.
La
lista
completa
de
mtodos
para
obtener
las
caractersticas
de
un
proveedor
se
puede
consultar
en
la
documentacin
oficial
de
la
clase
LocationProvider.
Imagen
59
Al
margen
de
esto,
hay
que
tener
en
cuenta
que
la
lista
de
proveedores
devuelta
por
el
mtodo
getAllProviders()
contendr
todos
los
proveedores
de
localizacin
conocidos
por
el
dispositivo,
incluso
si
stos
no
estn
permitidos
(segn
los
permisos
de
la
aplicacin)
o
no
estn
activados,
por
lo
que
esta
informacin
puede
que
no
nos
sea
de
mucha
ayuda.
Imagen
60
210
Tras
esto,
podremos
utilizar
los
mtodos
getProviders()
o
getBestProvider()
para
obtener
la
lista
de
proveedores
que
se
ajustan
mejor
al
criterio
definido
o
el
proveedor
que
mejor
se
ajusta
a
dicho
criterio,
respectivamente.
Adems,
ambos
mtodos
reciben
un
segundo
parmetro
que
indica
si
queremos
que
slo
nos
devuelvan
proveedores
que
estn
activados
actualmente.
Veamos
cmo
se
utilizaran
estos
mtodos:
Imagen
61
Con
esto,
ya
tenemos
una
forma
de
seleccionar
en
cada
dispositivo
aquel
proveedor
que
mejor
se
ajusta
a
nuestras
necesidades.
Imagen
62
En
el
cdigo
anterior,
verificamos
si
el
GPS
est
activado
y
en
caso
negativo
mostramos
al
usuario
un
mensaje
de
advertencia.
Este
mensaje
podramos
mostrarlo
sencillamente
en
forma
de
notificacin
de
tipo
toast,
211
menos
intuitivas.
Para
empezar,
en
Android
no
existe
ningn
mtodo
del
tipo
obtenerPosicinActual().
Obtener
la
posicin
a
travs
de
un
dispositivo
de
localizacin
como
por
ejemplo
el
GPS
no
es
una
tarea
inmediata,
sino
que
puede
requerir
de
un
cierto
tiempo
de
procesamiento
y
de
espera,
por
lo
que
no
tendra
sentido
proporcionar
un
mtodo
de
ese
tipo.
Si
buscamos
entre
los
mtodos
disponibles
en
la
clase
LocationManager,
lo
ms
parecido
que
encontramos
es
un
mtodo
llamado
getLastKnownLocation(String provider),
que
como
se
puede
suponer
por
su
nombre,
nos
devuelve
la
ltima
posicin
conocida
del
dispositivo
devuelta
por
un
provider
determinado.
Es
importante
entender
esto:
este
mtodo
NO
devuelve
la
posicin
actual,
este
mtodo
NO
solicita
una
nueva
posicin
al
proveedor
de
localizacin,
este
mtodo
se
limita
a
devolver
la
ltima
posicin
que
se
obtuvo
a
travs
del
proveedor
que
se
le
indique
como
parmetro.
Y
esta
posicin
se
pudo
obtener
hace
pocos
segundos,
hace
das,
hace
meses,
o
incluso
nunca
(si
el
dispositivo
ha
estado
apagado,
si
nunca
se
ha
activado
el
GPS,
etc.).
Por
tanto,
cuidado
cuando
se
haga
uso
de
la
posicin
devuelta
por
el
mtodo
getLastKnownLocation().
Entonces,
de
qu
forma
podemos
obtener
la
posicin
real
actualizada?
Pues
la
forma
correcta
de
proceder
va
a
consistir
en
algo
as
como
activar
el
proveedor
de
localizacin
y
suscribirnos
a
sus
notificaciones
de
cambio
de
posicin.
O
dicho
de
otra
forma,
vamos
a
suscribirnos
al
evento
que
se
lanza
cada
vez
que
un
proveedor
recibe
nuevos
datos
sobre
la
localizacin
actual.
Y
para
ello,
vamos
a
darle
previamente
unas
indicaciones
(que
no
son
ordenes)
sobre
cada
cuanto
tiempo
o
cada
cuanta
distancia
recorrida
necesitaramos
tener
una
actualizacin
de
la
posicin.
Todo
esto
lo
vamos
a
realizar
mediante
una
llamada
al
mtodo
requestLocationUpdates(),
al
que
deberemos
pasar
4
parmetros
distintos:
Tanto
el
tiempo
como
la
distancia
entre
actualizaciones
pueden
pasarse
con
valor
0,
lo
que
indicara
que
ese
criterio
no
se
tendr
en
cuenta
a
la
hora
de
decidir
la
frecuencia
de
actualizaciones.
Si
ambos
valores
van
a
cero,
las
actualizaciones
de
posicin
se
recibirn
tan
pronto
y
tan
frecuentemente
como
estn
disponibles.
Adems,
como
ya
hemos
indicado,
es
importante
comprender
que
tanto
el
tiempo
como
la
distancia
especificadas
se
entendern
como
simples
indicaciones
o
pistas
para
el
proveedor,
por
lo
que
puede
que
no
se
cumplan
de
forma
estricta.
En
cuanto
al
listener,
ste
ser
del
tipo
LocationListener
y
contendr
una
serie
de
mtodos
asociados
a
los
distintos
eventos
que
podemos
recibir
del
proveedor:
212
Por
nuestra
parte,
tendremos
que
implementar
cada
uno
de
estos
mtodos
para
responder
a
los
eventos
del
proveedor,
sobre
todo
al
ms
interesante,
onLocationChanged(),
que
se
ejecutar
cada
vez
que
se
recibe
una
nueva
localizacin
desde
el
proveedor.
Veamos
un
ejemplo
de
cmo
implementar
un
listener
de
este
tipo:
Imagen
63
Como
podemos
ver,
en
nuestro
caso
de
ejemplo
nos
limitamos
a
mostrar
al
usuario
la
informacin
recibida
en
el
evento,
bien
sea
un
simple
cambio
de
estado,
o
una
nueva
posicin,
en
cuyo
caso
llamamos
al
mtodo
auxiliar
mostrarPosicion().
En
el
mtodo
mostrarPosicion()
nos
vamos
a
limitar
a
mostrar
los
distintos
datos
de
la
posicin
pasada
como
parmetro
en
los
controles
correspondientes
de
la
interfaz,
utilizando
para
ello
los
mtodos
proporcionados
por
la
clase
Location.
En
nuestro
caso
utilizaremos
getLatitude(),
getAltitude()
y
getAccuracy()
para
obtener
la
latitud,
longitud
y
precisin
respectivamente.
Por
supuesto,
hay
otros
mtodos
disponibles
en
esta
clase
para
obtener
la
altura,
orientacin,
velocidad,
etc
que
se
pueden
consultar
en
la
documentacin
oficial
de
la
clase
Location.
Veamos
el
cdigo:
213
Imagen
64
214
Imagen
65
Como
se
puede
observar,
al
comenzar
la
recepcin
de
posiciones,
mostramos
en
primer
lugar
la
ltima
posicin
conocida,
y
posteriormente
solicitamos
al
GPS
actualizaciones
de
posicin
cada
30
segundos.
En
las
Imgenes
67
-
69
podemos
ver
la
el
diseo
grfico
y
el
archivo
xml
que
utilizaremos
para
la
pantalla
de
la
interfaz
grfica.
215
Imagen
66
Imagen
67
216
Imagen
68
En
las
siguientes
Imgenes
70
-
74
podemos
ver
el
cdigo
de
los
diferentes
mtodos
que
conforman
nuestra
activity
TrazarActivity.java.
Imagen
69.
Declaracin
de
variables
globales.
217
Imagen
70.
Mtodo
onCreate()
Imagen
71.
Mtodos
trazarRuta()
y
mostrarDestino()
218
Imagen
72.
Mtodo
comenzarLocalizacion()
Imagen
73.
Mtodos
mostrarAvisoGpsDeshabilitado()
y
mostrarPosicion()
219
AsyncTask
La
clase
AsyncTask
nos
ayuda
a
los
desarrolladores
a
darle
un
uso
adecuado
y
ms
fcil
al
UI
thread
de
nuestras
aplicaciones.
Permite
ejecutar
operaciones
en
segundo
plano
y
definir
los
resultados
en
el
UI
thread
sin
tener
que
quebrarnos
la
cabeza
manipulando
threads
y
handlers.
Para
utilizar
AsyncTask
debemos:
Crear
una
subclase
de
AsyncTask,
comnmente
como
una
clase
interna
privada
dentro
de
la
actividad
en
la
que
estemos
trabajando.
Sobreescribir
uno
o
ms
mtodos
de
AsyncTask
para
poder
realizar
el
trabajo
en
segundo
plano,
adems
de
cualquier
otra
tarea
asociada
para
poder
mostrar
alguna
actualizacin
en
el
UI
thread.
Cuando
sea
necesario,
crear
una
instancia
de
AsyncTask
y
llamar
al
mtodo
execute()
para
que
empiece
a
realizar
su
trabajo.
Tipos
genricos
AsyncTask
utiliza
tipos
genricos,
por
lo
que
resulta
necesario
definir
tres
tipos
de
datos
cada
vez
que
necesitemos
crear
una
instancia
de
esta
clase:
Hay
que
tener
en
cuenta
que
existen
casos
en
los
que
algn
tipo
genrico
no
es
utilizado
por
la
AsyncTask,
para
ello
utilizamos
el
tipo
Void
como
se
muestra
a
continuacin:
220
221
Google
AppScript
es
la
propuesta
de
la
empresa
por
hacer
que
las
apps
sean
mas
que
una
suite
de
oficina,
es
un
conjunto
de
cdigo
que
va
por
detrs
de
dichas
apps
escrito
en
Javascript
(aunque
la
interpretacin
del
mismo
corre
en
los
servidores
de
Google)
que
permite
extender
la
funcionalidad
de
aplicaciones
como
Google
Docs
o
Google
Spreadsheets
a
la
vez
que
permite
comunicarse
con
servicios
como
Gmail
o
Google
Calendar.
En
este
ejemplo
vamos
a
realizar
un
rest
API
con
Google
Spreadsheets,
si
suena
raro,
pero
nuestra
Base
de
datos
por
as
decirlo,
no
sra
mas
que
una
hoja
de
SpreadSheet,
vanlo
como
una
posibilidad
para
aplicaciones
ligeras
donde
cualquier
persona
puede
modificar
La
base
de
datos
como
una
hoja
de
Calculo
normal
y
ver
los
cambios
sin
problemas
en
la
aplicacin
Android.
La
siguiente
liga
contiene
la
hoja
con
la
que
estaremos
trabajando,
debemos
crear
una
copia
a
nuestra
cuenta
de
Drive
(es
necesario
tener
cuenta
de
Google,
y
acceder
a
ella
primeramente),
eso
se
realiza
de
la
siguiente
manera:
Concentremonos
en
la
hoja,
podemos
observar
que
se
conforma
de
3
partes:
Header,
Data
y
Footer.
El
motivo
es
resaltar
los
datos
vamos
a
utilizar,
como
el
app
solo
mostrara
a
cada
persona
en
la
nomina,
el
header
y
el
footer
no
nos
sirven,
as
mismo
nuestro
script
estar
preparado
para
solo
obtener
los
datos
importantes
sin
importar
el
tamao
de
cualquiera
de
las
secciones.
222
El
siguiente
paso
es
trabajar
con
el
script,
cuando
ustedes
crearon
una
copia
de
la
liga
anterior,
no
solo
copiaron
los
datos
de
la
hoja,
si
no
que
por
detrs,
copiamos
el
script
que
fue
escrito
previamente
en
ella,
para
crear
o
modificar
un
script
ingresamos
al
menu
Herramientas
y
debemos
acceder
a
la
opcin
Editor
de
secuencias
de
comando.
Al
hacer
lo
anterior
lo
que
veremos
ser
algo
muy
similar
a
lo
siguiente
223
Es
importante
que
verifiquemos
en
dnde
se
declara
la
variable
SPREADSHEET_ID
cuyo
valor
no
debe
de
conterner
la
siguiente
cadena
&usp
en
caso
de
contenerla
se
deber
de
quitar
Podemos
observar
que
el
Script
contiene
3
funciones:
myFunction
toObject
doGet
Al
inicio
tenemos
2
variables
con
el
tamao
del
header
y
del
footer,
no
olviden
actualizar
esos
valores
si
es
que
modificaron
el
numero
de
rows.
myFunction
es
el
encargado
de
obtener
todos
los
datos
del
SpreadSheet,
toObject
es
una
funcion
que
creamos
para
convertir
los
datos
obtenidos
como
arreglo
a
objeto,
esto
sera
de
gran
utilidad
ya
que
la
respuesta
JSON
sera
mas
agradable
de
manejar
y
por
ultimo
doGet
es
requerido
para
cuando
publiquemos
el
script
como
WebApp,
las
partes
mas
importantes
estan
comentadas.
Para
ver
funcionar
nuestro
Script,
debemos
publicarlo
como
WebApp,
esto
es
muy
facil,
tan
solo
con
acceder
al
menu
Publicar
->
Implementar
como
aplicacin
web
224
En
este
caso
es
necesario
establecer
una
versin
del
proyecto,
ponemos
1
como
la
versin
del
proyecto
y
hacemos
click
en
Guardar
nueva
versin
225
Para
comprobar
que
todo
funciona
correctametne
haremos
click
en
el
enlace
que
dice
ltimo
cdigo
que
aparece
en
la
imagen
anterior,
con
esto
abrimos
la
URL
generada
y
deber
crear
una
respuesta
como
la
de
la
siguiente
imagen:
Ahora
toca
el
turno
de
manejar
dicha
informacin
en
nuestra
app,
para
ello
no
utilizaremos
la
manera
tradicional
(Usando
Threads
con
AsyncTask),
en
su
remplazo
usaremos
un
Framework
HTTP
client
support
llamado
Volley,
el
uso
de
uno
o
de
otro
ya
depende
de
gustos.
Nota
Es
importante
hacer
notar
que
es
necesario
declarar
el
proyecto
completamente
pblico
y
abierto,
pues
es
necesario
que
desde
la
aplicacin
Android
pueda
acceder
a
este.
226
Agregando
la
Librera
El
primer
paso
necesario
es
conseguir
la
librera,
esto
lo
lograremos
clonando
el
proyecto
Volley
desde
un
repositorio
para
lo
cual
seleccionamos
File
Import
Git
Projects
from
Git,
como
se
muestra
en
la
siguiente
imagen
y
pulsamos
Next
Posteriormente
seleccionamos
la
opcin
URI
y
Next
227
En
la
siguiente
pantalla
se
deber
de
seleccionar
el
branche
que
se
se
desea,
por
default
estn
seleccionados
todos
pero
debemos
de
slo
seleccionar
la
que
se
llama
master
y
click
en
Next.
228
El
repositorio
comenzar
a
descargarse
automticamente.
Ya
por
ltimo
tenemos
que
elegir
la
forma
en
que
queremos
crear
el
proyecto,
en
la
siguiente
imagen
se
muestra
la
pantalla
que
aparece
para
este
fin
la
vamos
a
dejar
como
est
o
en
caso
de
que
no
aparezca
como
se
ve
en
la
imagen
se
deber
de
seleccionar
las
mismas
opciones.
Y
hacemos
click
en
Next
en
todas
las
pantallas
que
aparezcan.
Es
as
como
se
ha
creado
un
proyecto
pero
que
en
realidad
ser
una
librera
y
nos
auxiliar
en
el
desarrollo
y
correcto
funcionamiento
de
nuestro
proyecto,
dicha
librera
contiene
todas
las
clases
que
pertenecen
al
proyecto
Volley.
Ya
descargado
el
siguiente
paso
ser
el
de
asignar
como
librera
a
nuestro
proyecto:
click
derecho
en
nuestro
proyecto
->
Android
->
Library
add
->
volley,
y
ya
con
esto
debe
de
quedar
listo
el
entorno
para
comenzar
a
desarrollar
nuestro
proyecto
de
android.
Preparando
Volley
Para
empezar
a
trabajar
con
Volley
creamos
una
instancia
del
mismo
(RequestQueue),
solo
necesitamos
crearla
a
partir
del
mtodo
newRequestQueue
de
Volley
que
recibe
nuestro
contexto:
RequestQueue queue = Volley.newRequestQueue(this);
Como
se
menciona
anteriormente,
debemos
saber
que
tipo
de
respuesta
esperamos
recibir,
en
nuestro
caso
es
un
JSONArray.
Construiremos
una
instancia
de
ese
tipo
la
cual
podremos
usarla
en
cualquier
momento
que
lo
necesitamos
(es
como
un
singleton,
aqu
preparamos
el
request,
aun
no
es
ejecutado).
Para
construir
el
JsonArrayRequest
su
constructor
recibe
la
URL
a
la
que
queremos
acceder,
la
clase
anonima
Response.Listener
que
sobrecarga
el
metodo:
onResponse(),
ademas
de
la
clase
anonima
Response.ErrorListener()
que
sobrecarga
el
metodo
onErrorResponse().
Esto
quiere
decir
que
intuitivamente,
dependiendo
de
si
la
respuesta
fue
exitosa
o
no,
se
mandan
a
llamar
uno
u
el
otro:
229
String
URL="https://script.googleusercontent.com/macros/echo?user_content_key
=lFICbdS8JH7Qu5P8Zc-O8Obivcf58FTKcnLZcMCSlI2Nj6WhAZKVgz9Du2S6C5xmVaOSNBOdG5o85LRco60xiKXdElX244Rm5_BxDlH2jW0nuo2oDemN9CC
S2h10ox_1xSncGQajx_ryfhECjZEnEDsaoV-dQuTXwGeEegV2_Od5afzYas7yyPsvS7GrZOuKlOh3tRsmWDRy7wERKzg&lib=M5aD4PDtvLBAgJtbZlnaQMLGP5fZpIYsy";
JsonArrayRequest req = new JsonArrayRequest(URL, new
Response.Listener<JSONArray> () {
@Override
public void onResponse(JSONArray response) {
"Entraremos en este mtodo si el llamado fue exitoso"
"recibimos JSONArray response como respuesta"
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
"Entraremos en este mtodo si existi un error"
}
});
Ahora
solo
queda
ejecutar
nuestro
request,
recordamos
que
antes
hemos
creado
una
instancia
RequestQueue
llamada
queue,
queue
tiene
un
metodo
llamado
add
que
recibe
como
parametro
un
request
preparado
de
cualquier
tipo
(recordar
el
de
nosotros
es
JsonArrayRequest
llamado
req),
entonces
lo
pasamos
como
parametro
para
que
se
pueda
ejecutar:
queue.add(req);
En
nuestro
caso
solo
es
uno,
pero
RequestQueue
puede
ejecutar
n
llamados
como
instancias
de
respuesta
hemos
creado,
cool
no
es
cierto?.
String nombre;
230
private
private
private
String salarioDiario;
String diasLaborados;
String sueldo;
231
ViewHolder{
nombre;
salarioDiario;
diasLaborados;
sueldo;
232
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Nombre"
android:textColor="#FFFFFF"
android:textStyle="bold"
android:gravity="center_horizontal"
android:paddingTop="15dp"
android:paddingBottom="15dp"
android:id="@+id/nombre" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Sueldo"
android:textColor="#89d8fa"
android:layout_marginLeft="10dp"
android:layout_marginBottom="10dp"
android:id="@+id/sueldo" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Salario diario"
android:textStyle="italic"
android:textColor="#ffb900"
android:layout_marginLeft="10dp"
android:id="@+id/salario_diario" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Dias"
android:textStyle="italic"
android:layout_marginRight="10dp"
android:layout_marginBottom="15dp"
android:layout_gravity="right"
android:textColor="#00de72"
android:id="@+id/dias_laborados" />
</LinearLayout>
Finalmente
Nuestro
MainActivity
contiene
el
llamado
a
nuestro
API
(hecho
con
Volley),
el
cual
si
es
un
xito,
construira
nuestro
adapter
para
el
ListView
con
todos
los
objetos
recibidos,
no
es
tan
directo
ya
que
se
necesita
parsear
la
informacin,
y
de
la
cual
creamos
un
metodo
para
dicho
proposito,
a
continuacion
el
codigo
completo
de
nuestro
MainActivity:
public class MainActivity extends ActionBarActivity {
233
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//ActionBar de Color Negro, solo por esttica
ColorDrawable colorDrawable = new
ColorDrawable(Color.parseColor("#000000"));
ActionBar actionbar = getSupportActionBar();
actionbar.setBackgroundDrawable(colorDrawable);
//Creamos una instancia de RequestQueue que slo recibe el
contexto
RequestQueue queue = Volley.newRequestQueue(this);
//URL del SpreadSheet
String URL =
"https://script.googleusercontent.com/macros/echo?user_content_key=lFI
CbdS8JH7Qu5P8Zc-O8Obivcf58FTKcnLZcMCSlI2Nj6WhAZKVgz9Du2S6C5xmVaOSNBOdG5o85LRco60xiKXdElX244Rm5_BxDlH2jW0nuo2oDemN9CC
S2h10ox_1xSncGQajx_ryfhECjZEnEDsaoV-dQuTXwGeEegV2_Od5afzYas7yyPsvS7GrZOuKlOh3tRsmWDRy7wERKzg&lib=M5aD4PDtvLBAgJtbZlnaQMLGP5fZpIYsy";
//Creamos una instancia de un ProgressDialog para que el
usuario observe que los datos se estan obteniendo
final ProgressDialog progressDialog =
ProgressDialog.show(this, "Por favor espere ...", "Descargando Datos
...", true);
//Configuramos nuestro request, al intanciar JsonArrayRequest
recibe la URL y un Listener de JSON Array, el cual
//contiene una serie de mtodos a implelentar, prcticamente
si resulto bien o existio un error, ademas
// sirve como un singleton para mandarlo a llamar cuando sea
necesario hacer de nuevo el request.
// Recordar que este solo construye el llamado HTTP, se ejecuta
mas adelante cuando lo agregamos como parametro del metodo add
//de RequestQueue
JsonArrayRequest req = new JsonArrayRequest(URL, new
Response.Listener<JSONArray> () {
@Override
public void onResponse(JSONArray response) {
//Un textview antes de la vista nos permite ver los
datos crudos dentro de la misma app
TextView textView = (TextView)
findViewById(R.id.datos_crudos);
234
textView.setText(response.toString());
//dejamos en el Log un pequeo mensaje con el response
como string para ver un preview de lo que recibimos
Log.e("respeusta", response.toString());
//buscamos el listview de main_activity
ListView list = (ListView)
findViewById(R.id.list_view);
//Si vemos el CustomAdapter debemos pasar un contexto
y un ArrayList de objetos Personas
//dicho ArrayList es parseao de la respuesta por medio
de la funcion parser
CustomAdapter adapter = new
CustomAdapter(getApplicationContext(), parser(response));
//pasamos el adapter para que la lista se muestre en
el UI
list.setAdapter(adapter);
progressDialog.dismiss();
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
VolleyLog.e("Error: ", error.getMessage());
progressDialog.dismiss();
}
});
// Ejecutamos Volley, con el request preparado
queue.add(req);
}
// La funcin de abajo se encarga de parsear toda la informacin
public ArrayList<Persona> parser(JSONArray respuesta){
ArrayList<Persona> personasAux = new ArrayList<Persona>();
for(int i = 0; i < respuesta.length(); i++){
JSONObject jsonObject;
Persona persona = new Persona();
try {
jsonObject = (JSONObject) respuesta.get(i);
persona.setNombre(jsonObject.getString("nombre"));
persona.setSalarioDiario(jsonObject.getString("salario
Diario"));
235
persona.setDiasLaborados(jsonObject.getString("diasLab
orados"));
persona.setSueldo(jsonObject.getString("sueldo"));
personasAux.add(persona);
} catch (JSONException e) { Log.e("peticin", "Error al
parsear");}
}
return personasAux;
}
}
Layout
de
MainActivity
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.android.nomina.MainActivity">
<ScrollView
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:layout_weight="3" >
<TextView
android:layout_weight="1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/datos_crudos"
android:layout_gravity="center_horizontal" />
</ScrollView>
<ListView
android:layout_weight="1"
android:headerDividersEnabled="false"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/list_view"
android:footerDividersEnabled="false" />
</LinearLayout>
El
resultado
de
la
ejecucin
de
todo
esto
que
hemos
realizado
lo
podemos
ver
en
la
siguiente
imagen
236
Datos en crudo
Datos procesados
En
el
cual
se
puede
apreciar
en
la
parte
superior
la
seccin
en
dnde
se
muestran
los
datos
en
crudo
tal
como
los
obtenemos
desde
nuestro
proyecto
en
Google
Docs.
Y
la
segunda
parte
muestra
una
lista
con
la
misma
informacin
pero
ya
con
la
informacin
formateada
de
tal
manera
que
sea
entendible
para
el
usuario.
Otra
punto
a
destacar
es
que
en
cada
ocasin
en
la
que
cambiemos
la
informacin
en
nuestra
hoja
de
Google
los
datos
de
que
sean
modificados
se
reflejaran
en
nuestra
aplicacin
mvil,
pero
para
poder
ver
esto
es
necesario
cerrar
la
aplicacin
y
cargarla
de
nuevo
para
que
se
note
el
cambio.
Navegacin
Navegacin
con
Back
y
Up
La
navegacin
consistente
es
un
componente
esencial
de
la
experiencia
general
del
usuario.
Hay
pocas
cosas
que
frustran
ms
a
los
usuarios
de
navegacin
bsica
que
se
comporta
de
maneras
contradictorias
e
inesperadas.
Android
3.0
introdujo
cambios
significativos
en
el
comportamiento
global
de
navegacin.
Cuidadosamente
siguiendo
las
directrices
para
atrs
(back)
y
hacia
arriba
(up)
har
que
la
navegacin
de
sus
aplicaciones
sea
previsible
y
fiable
para
los
usuarios.
Android
2.3
y
anteriores
se
bas
en
el
sistema
de
botn
Atrs
para
apoyar
la
navegacin
dentro
de
una
aplicacin.
Con
la
introduccin
de
las
barras
de
accin
en
Android
3.0,
un
segundo
mecanismo
de
237
Up
vs.
Back
El
botn
Arriba
se
utiliza
para
navegar
dentro
de
una
aplicacin
basada
en
las
relaciones
jerrquicas
entre
pantallas.
Por
ejemplo,
si
la
pantalla
A
muestra
una
lista
de
elementos,
y
la
seleccin
de
un
elemento
conduce
a
la
pantalla
de
B
(que
presenta
ese
tema
con
ms
detalle),
a
continuacin,
la
pantalla
B
debe
ofrecer
un
botn
Arriba
que
devuelve
a
la
pantalla
A.
Si
una
pantalla
es
la
ms
alta
en
una
aplicacin
(es
decir,
el
hogar
de
la
aplicacin),
no
debe
presentar
un
botn
Arriba.
El
sistema
de
botn
Atrs
se
utiliza
para
navegar,
en
orden
cronolgico
inverso,
a
travs
de
la
historia
de
las
pantallas
que
el
usuario
ha
trabajado
recientemente.
Se
basa
generalmente
en
las
relaciones
temporales
entre
las
pantallas,
en
lugar
de
la
jerarqua
de
la
aplicacin.
Cuando
la
pantalla
vista
anteriormente
es
tambin
el
padre
jerarquico
de
la
pantalla
actual,
al
pulsar
el
botn
Atrs
tiene
el
mismo
resultado
que
al
pulsar
un
botn
Up
esto
ocurre
comunmente.
Sin
embargo,
al
contrario
el
botn
de
arriba,
lo
que
garantiza
es
que
el
usuario
permanezca
dentro
de
su
aplicacin,
el
botn
Atrs
puede
devolver
al
usuario
a
la
pantalla
de
inicio,
o
incluso
a
una
aplicacin
diferente.
238
El
botn
Back
tambin
es
compatible
con
algunos
comportamientos
que
no
estn
directamente
vinculados
a
la
navegacin
de
pantalla
a
la
pantalla:
3. Navegar
entre
pantallas
hermanas
Cuando
la
aplicacin
soporta
la
navegacin
entre
una
lista
de
elementos
hacia
una
vista
detallada
de
uno
de
esos
artculos,
a
menudo
es
conveniente
que
soporte
la
direccin
de
navegacin
a
partir
de
ese
punto
a
otro
que
le
precede
o
le
sigue
en
la
lista.
Por
ejemplo,
en
Gmail,
es
fcil
deslizar
hacia
la
izquierda
o
hacia
la
derecha
a
partir
de
una
conversacin
para
ver
una
ms
nueva
o
ms
antigua
en
la
misma
bandeja
de
entrada.
Del
mismo
modo
que
al
cambiar
la
vista
en
una
pantalla,
como
la
navegacin
no
cambia
el
comportamiento
de
Up
o
Back.
239
Sin
embargo,
una
notable
excepcin
a
esto
ocurre
cuando
se
navega
entre
las
vistas
de
detalle
relacionados
no
ligadas
a
a
referida
lista
-por
el
ejemplo,
cuando
se
navega
en
la
Play
Store
entre
aplicaciones
del
mismo
desarrollador,
o
lbumes
del
mismo
artista.
En
estos
casos,
despus
de
cada
enlace
crea
la
historia,
haciendo
que
el
botn
Back
se
desplase
por
cada
pantalla
que
visualizada
anteriormente.
Up
podra
continuar
para
eludir
esas
pantallas
relacionadas
y
vaya
a
la
pantalla
de
contenedores
utilizada
ms
recientemente.
240
Tambin
se
tiene
la
capacidad
de
hacer
el
comportamiento
Up
an
ms
inteligente
basado
en
el
conocimiento
de
la
vista
de
detalle.
Ampliando
el
ejemplo
de
arriba
de
Play
Store,
imagine
que
el
usuario
ha
navegado
desde
el
ltimo
libro
a
los
detalles
de
la
adaptacin
de
la
pelcula.
En
ese
caso,
Up
puede
volver
a
un
contenedor
(Pelculas),
que
el
usuario
no
ha
navegado
travs
de
el.
241
Si
la
pantalla
de
destino
suele
ser
accesible
desde
una
pantalla
en
particular
dentro
de
la
aplicacin,
Up
debera
navegar
a
esa
pantalla.
De
lo
contrario,
Up
debera
ir
a
la
pantalla
superior
("Home")
de
su
aplicacin.
En
el
caso
del
botn
Back,
se
debe
hacer
la
navegacin
ms
predecible
mediante
la
insercin
en
la
pila
de
retroceso
de
la
ruta
completa
de
navegacin
hacia
arriba
para
la
pantalla
superior
de
la
aplicacin.
Esto
permite
a
los
usuarios
que
han
olvidado
como
ellos
entraron
en
la
aplicacin
para
navegar
a
la
pantalla
superior
de
la
aplicacin
antes
de
salir.
242
A
modo
de
ejemplo,
el
widget
de
Gmail
en
la
pantalla
Inicio
tiene
un
botn
para
el
salto
directamente
a
la
ventana
de
redaccin.
O
la
vuelta
de
la
ventana
de
redaccin
podra
llevar
al
usuario
a
la
Bandeja
de
entrada,
y
desde
all
en
el
botn
Back
sigue
Home.
Notificaciones
Indirectas
Cuando
una
aplicacin
necesita
para
presentar
informacin
sobre
varios
eventos
a
la
vez,
se
puede
utilizar
una
sola
notificacin
que
dirige
al
usuario
a
una
pantalla
intersticial.
Esta
pantalla
resume
estos
eventos,
y
ofrece
caminos
para
que
el
usuario
sumergirse
profundamente
en
la
aplicacin.
Notificaciones
de
este
estilo
se
denominan
notificaciones
indirectas.
A
diferencia
de
las
notificaciones
estndar
(directas),
al
pulsar
Back
de
la
pantalla
intersticial
de
una
notificacin
indirecta
devuelve
al
usuario
al
punto
donde
la
notificacin
se
desencaden
-no
se
insertan
pantallas
adicionales
en
la
pila
de
retroceso.
Una
vez
que
el
usuario
procede
en
la
aplicacin
desde
la
pantalla
intersticial,
Up
y
Back
se
comportan
como
para
las
notificaciones
estndar,
tal
como
se
describe
ms
arriba:
navegando
dentro
de
la
aplicacin
en
lugar
de
volver
al
intersticial.
Por
ejemplo,
supongamos
que
un
usuario
de
Gmail
recibe
una
notificacin
indirecta
desde
Calendario.
Al
tocar
esta
notificacin
se
abre
la
pantalla
intersticial,
que
muestra
recordatorios
para
diferentes
eventos.
Tocando
Back
desde
la
intersticial
devuelve
al
usuario
a
Gmail.
Al
tocar
en
un
evento
en
particular
lleva
al
usuario
lejos
de
la
intersticial
e
ingresando
por
completo
a
la
aplicacin
Calendario
para
mostrar
los
detalles
del
evento.
A
partir
de
los
detalles
del
evento,
arriba
y
atrs
navegar
a
la
vista
de
nivel
superior
de
Calendario.
243
Notificaciones
pop-up
Las
notificaciones
pop-up
evitan
el
buzn
de
notificaciones,
en
lugar
de
eso
aparecen
directamente
en
frente
del
usuario.
Rara
vez
se
utilizan,
y
deben
reservarse
para
ocasiones
en
que
se
requiere
una
respuesta
oportuna
y
la
interrupcin
del
contexto
del
usuario
si
es
necesario.
Por
ejemplo,
Talk
utiliza
este
estilo
para
alertar
al
usuario
de
la
invitacin
de
un
amigo
a
unirse
a
un
chat
de
vdeo,
ya
que
esta
invitacin
caducar
automticamente
despus
de
unos
segundos.
En
trminos
de
comportamiento
de
navegacin,
las
notificaciones
emergentes
siguen
de
cerca
el
comportamiento
de
la
pantalla
intersticial
de
una
notificacin
indirecta.
Back
descarta
la
notificacin
emergente.
Si
el
usuario
se
desplaza
desde
el
pop-up
en
la
aplicacin
notifica,
Up
y
Back
siguen
las
reglas
para
las
notificaciones
estndar,
navegando
dentro
de
la
aplicacin.
244
En
Android,
una
actividad
es
un
componente
de
aplicacin
que
define
una
pantalla
de
informacin
y
todas
las
acciones
asociadas
que
el
usuario
puede
realizar.
Las
aplicaciones
son
una
coleccin
de
actividades,
que
constan
tanto
de
las
actividades
que
se
crean
y
las
que
se
reusan
de
otras
aplicaciones.
245
Una
tarea
es
la
secuencia
de
actividades
de
un
usuario
sigue
para
lograr
una
meta.
Una
sola
tarea
puede
hacer
uso
de
las
actividades
de
una
sola
aplicacin,
o
puede
basarse
en
las
actividades
de
un
nmero
de
diferentes
aplicaciones.
Un
intent
es
un
mecanismo
para
que
una
aplicacin
indique
que
le
gustara
la
ayuda
de
otra
aplicacin
en
la
realizacin
de
una
accin.
Las
actividades
de
una
aplicacin
pueden
indicar
a
cuales
intents
pueda
responder.
Para
los
intents
comunes
tales
como
"Compartir",
el
usuario
puede
tener
muchas
aplicaciones
instaladas
que
pueden
cumplir
esa
peticin.
Para
comprender
cmo
las
actividades,
tareas,
y
los
intents
trabajan
juntos,
considere
cmo
una
aplicacin
permite
a
los
usuarios
compartir
contenido
utilizando
otra
aplicacin.
Por
ejemplo,
el
lanzamiento
de
la
aplicacin
Play
Store
desde
Home
comienza
nueva
tarea
A
(ver
figura
siguiente).
Despus
de
navegar
a
travs
de
la
Play
Store
y
tocar
un
libro
promovido
para
ver
sus
detalles,
el
usuario
permanece
en
la
misma
tarea,
que
se
extiende
mediante
la
adicin
de
actividades.
Activando
la
accin
Compartir
pide
al
usuario
con
un
dilogo
donde
se
enumeran
cada
una
de
las
actividades
(de
diferentes
aplicaciones)
que
se
han
registrado
para
manejar
el
intent
Compartir.
246
Cuando
el
usuario
decide
compartir
a
travs
de
Gmail,
se
aade
la
actividad
de
redaccin
de
Gmail
como
una
continuacin
de
la
tarea
A-ninguna
nueva
tarea
se
crea.
Si
Gmail
tena
su
propia
tarea
en
funcionamiento
en
segundo
plano,
no
se
vera
afectada.
Desde
la
actividad
de
redaccin,
enviando
el
mensaje
o
tocando
el
botn
Back,
regresa
al
usuario
a
la
actividad
de
detalles
del
libro.
Toques
posteriores
de
Back
continuan
navegando
a
travs
de
la
Play
Store,
llegando
hasta
Home.
Sin
embargo,
al
tocar
Up
en
la
actividad
de
redaccin,
el
usuario
indica
un
deseo
de
permanecer
dentro
de
Gmail.
Aparece
la
actividad
lista
de
conversaciones
de
Gmail,
y
una
nueva
Tarea
B
se
crea
para
ello.
Nuevas
tareas
siempre
estn
arraigadas
a
la
portada,
por
lo
que
tocando
Back
desde
la
lista
de
conversacin
se
vuelve
all.
247
La
tarea
A
persiste
en
el
fondo,
y
el
usuario
puede
volver
a
ella
ms
tarde
(por
ejemplo,
a
travs
de
la
pantalla
Recientes).
Si
Gmail
ya
tena
su
propio
tarea
funcionando
en
segundo
plano,
sera
sustituida
por
la
tarea
B
-el
contexto
previo
se
abandona
en
favor
de
la
nueva
meta
del
usuario.
Cuando
la
aplicacin
registra
manejar
los
intentos
con
una
actividad
profunda
dentro
de
la
jerarqua
de
la
aplicacin,
consulte
Navegacin
en
su
aplicacin
a
travs
de
widgets
de
la
pantalla
principal
y
Notificaciones
para
obtener
orientacin
sobre
cmo
especificar
de
navegacin
hacia
arriba.
248
Estilos
en
Android
Dispositivos
y
Pantallas
Android
potencializa
a
millones
de
telfonos,
tabletas
y
otros
dispositivos
en
una
amplia
variedad
de
tamaos
de
pantalla
y
factores
de
forma.
Al
tomar
ventaja
del
sistema
de
diseo
flexible
de
Android,
se
pueden
crear
aplicaciones
que
se
adapten
a
la
escala
de
grandes
tabletas
as
como
tambin
de
telfonos
ms
pequeos.
Sea
flexible
Estirar
y
comprimir
sus
diseos
para
adaptarse
a
diferentes
alturas
y
anchuras.
Optimice
los
diseos
En
los
dispositivos
ms
grandes,
se
debe
aprovechar
el
espacio
adicional
en
pantalla.
Cree
vistas
compuestas
que
combinan
mltiples
vistas
para
revelar
ms
contenido
y
facilidad
de
navegacin.
249
Temas
Los
temas
son
el
mecanismo
de
Android
para
aplicar
un
estilo
coherente
con
una
aplicacin
o
actividad.
El
estilo
especifica
las
propiedades
visuales
de
los
elementos
que
componen
la
interfaz
de
usuario,
como
el
color,
la
altura,
el
relleno
y
el
tamao
de
la
fuente.
Para
promover
una
mayor
cohesin
entre
todas
las
aplicaciones
en
la
plataforma,
Android
proporciona
dos
temas
del
sistema
que
usted
puede
elegir
la
hora
de
la
creacin
de
aplicaciones:
Holo
Light
Holo
Black
La
aplicacin
de
estos
temas
recorren
un
largo
camino
para
ayudar
a
construir
aplicaciones
que
se
adapten
correctamente
en
el
lenguaje
visual
general
de
Android.
250
Gmail
en
Holo
Light.
Ajustes
en
Holo
Black.
Elija
el
tema
del
sistema
que
mejor
se
adapte
a
las
necesidades
y
la
esttica
de
diseo
para
su
aplicacin.
Si
su
deseo
es
tener
una
mirada
ms
clara
para
su
aplicacin,
utilizando
uno
de
los
temas
del
sistema
como
punto
de
partida
para
las
personalizaciones
es
una
buena
idea.
Los
temas
del
sistema
proporcionan
una
base
slida
sobre
la
que
se
puede
implementar
de
forma
selectiva
sus
propios
estilismos
visuales.
251
Retroalimentacin
al
Toque
Utilizar
iluminacin
y
oscurecimiento
al
responder
a
los
toques,
reforzar
los
comportamientos
resultantes
de
gestos,
e
indicar
qu
acciones
estn
activadas
y
desactivadas.
Sea
sensible
a
toques
de
una
manera
suave.
Cada
vez
que
un
usuario
toca
un
rea
procesable
en
su
aplicacin,
hacerles
saber
que
la
aplicacin
est
"escuchando",
proporcionando
una
respuesta
visual.
Que
sea
sutil
slo
un
poco
ms
claro
o
ms
oscuro
que
el
color
intacto.
Esto
proporciona
dos
beneficios:
252
Estados
La
mayor
parte
de
los
elementos
de
interfaz
de
usuario
de
Android
tienen
retroalimentacin
tctil
incorporada,
incluyendo
estados
que
indican
si
tocar
el
elemento
tendr
ningn
efecto.
Comunicacin
Cuando
los
objetos
reaccionan
a
los
gestos
ms
complejos,
ayudan
a
los
usuarios
a
entender
cul
ser
el
resultado.
253
En
Recientes,
cuando
un
usuario
inicia
a
deslizar
la
miniatura
hacia
la
izquierda
o
la
derecha,
comienza
a
oscurecerse.
Esto
ayuda
al
usuario
a
comprender
que
el
deslizamiento
har
que
el
elemento
ser
removido
Lmites
Cuando
los
usuarios
intentan
desplazarse
ms
all
del
principio
o
al
final
de
un
rea
de
desplazamiento,
se
comunica
el
lmite
con
una
seal
visual.
Muchos
de
los
widgets
de
interfaz
de
usuario
de
Android
desplazables,
como
listas
y
listas
de
la
red,
tienen
retroalimentacin
de
apoyo
para
el
lmite
integrado.
Si
usted
est
construyendo
widgets
personalizados,
tenga
retroalimentacin
del
lmite
en
mente
y
ofrezcala
en
su
aplicacin.
Mtricas
y
Rejillas
Los
dispositivos
varan
no
slo
en
tamao
fsico,
sino
tambin
en
la
densidad
de
la
pantalla
(DPI).
Para
simplificar
la
forma
de
disear
para
mltiples
pantallas,
pensar
en
cada
dispositivo
como
caer
en
un
cubo
de
tamao
y
densidad
cubo
especial:
Los cubos de tamao son el hanset (menor que 600 DP) y la tableta (mayor que o igual 600dp).
254
Los cubos de densidad son LDPI, MDPI, IPAP, XHDPI, XXHDPI, y XXXHDPI.
Consideraciones
sobre
el
espacio
Dispositivos
varan
en
la
cantidad
de
pxeles
independientes
de
la
densidad
(dp)
que
se
pueden
mostrar.
48dp
Rhythm
Los
Componentes
en
la
interfazque
el
usuario
puede
tocar
o
manejar
son
generalmente
dispuestas
a
lo
largo
de
48dp
unidades.
Por
qu
48dp?
En
promedio,
48dp
se
traducen
a
un
tamao
fsico
de
aproximadamente
de
9
mm
(con
cierta
variabilidad).
Esto
es
cmodo
en
la
gama
de
tamaos
recomendados
(7-10
mm)
para
los
objetos
de
la
pantalla
tctil
y
los
usuarios
sern
capaces
de
forma
fiable
y
precisa
apuntarlos
con
sus
dedos.
Si
el
diseo
de
los
elementos
son
de
al
menos
48dp
alto
y
ancho
usted
puede
garantizar
que:
sus
objetivos
nunca
ser
menor
que
el
tamao
mnimo
recomendado
de
7mm,
independientemente
de
lo
que
se
muestre
en
la
pantalla.
255
usted
tiene
un
buena
realcin
entre
la
densidad
de
informacin
general
por
un
lado,
y
la
seleccin
de
elementos
de
la
interfaz
en
el
otro.
Cuidado
con
el
hueco
El
espacio
entre
cada
elemento
de
la
interfaz
de
usuario
es
8dp.
Ejemplos:
256
Tipografa
257
El
actual
marco
TextView
ofrece
Roboto
en
variantes
delgadas,
ligeras,
regular
y
negrita,
junto
con
un
estilo
de
cursiva
para
cada
variante.
El
marco
tambin
ofrece
la
variante
Roboto
Condensada
en
pesos
regulares
y
audaces
,
junto
con
un
estilo
de
cursiva
para
cada
variante.
Colores
de
tipo
predeterminado
La
interfaz
de
usuario
de
Android
utiliza
los
siguientes
estilos
de
color
por
defecto:
textColorPrimary
y
textColorSecondary.
Para
los
temas
ligeros
utiliza
textColorPrimaryInverse
y
textColorSecondaryInverse.
Los
estilos
de
color
de
texto
de
framework
tambin
admiten
variantes
para
el
tacto
de
retroalimentacin
cuando
se
utiliza
dentro
de
los
elementos
de
interfaz
de
usuario.
Escala
Tipogrfica
El
contraste
en
tamaos
de
letra
puede
recorrer
un
largo
camino
para
crear
diseos
comprensibles.
Sin
embargo,
tambin
muchos
tamaos
diferentes
en
la
misma
interfaz
de
usuario
puede
ser
un
poco
incmodo.
El
framework
de
Android
utiliza
el
siguiente
conjunto
limitado
de
tamaos
de
letra:
Los usuarios pueden seleccionar un factor de escala de todo el sistema
para
el
texto
en
aplicacin
Ajustes.
Para
apoyar
estas
funciones
de
accesibilidad,
la
tipografa
debe
especificarse
en
pixeles
de
escala
independiente
(sp)
siempre
que
sea
posible.
Los
diseos
que
soporten
tipografas
escalables
deben
ser
probados
contra
estos
valores.
Color
Usar
colores
primarios
para
enfasis.
Escoja
los
colores
que
vayan
con
su
marca
y
proporcione
un
buen
contraste
entre
los
componentes
visuales.
Note
que
el
rojo
y
el
verde
pueden
ser
indistinguibles
para
los
daltonicos.
258
Paleta
El
azul
es
el
color
de
enfasis
estandar
en
la
paleta
de
colores
de
Android.
Cada
color
tiene
su
tono
ms
oscuro
correspondiente
que
puede
ser
usado
como
un
complemento
cuando
sea
necesario.
Iconografa
Un
icono
es
una
grfica
que
ocupa
una
pequea
parte
del
espacio
de
la
pantalla
y
proporciona
una
rpida
representacin
intuitiva
de
una
accin,
un
estado
o
una
aplicacin.
Al
disear
iconos
para
su
aplicacin,
es
importante
tener
en
cuenta
que
su
aplicacin
se
puede
instalar
en
una
variedad
de
dispositivos
que
ofrecen
una
amplia
gama
de
densidades
de
pxeles,
como
se
menciona
en
la
seccin
Dispositivos
y
Pantallas.
Pero
usted
puede
hacer
que
sus
iconos
se
vean
muy
bien
en
todos
los
dispositivos,
proporcionando
a
cada
icono
en
varios
tamaos.
Cuando
su
aplicacin
se
ejecuta,
Android
comprueba
las
caractersticas
de
la
pantalla
del
dispositivo
y
carga
los
assets
apropiados
para
la
densidad
especifica
para
su
aplicacin.
259
Dado
que
va
a
entregar
cada
icono
en
varios
tamaos
para
soportar
diferentes
densidades,
las
directrices
de
diseo
que
siguen
se
refieren
a
las
dimensiones
del
icono
en
las
unidades
dp,
que
se
basan
en
las
dimensiones
en
pxeles
de
una
pantalla
de
densidad
media
(MDPI).
Por
lo
tanto,
para
crear
un
icono
para
diferentes
densidades,
debe
seguir
la
relacin
de
escala
2:3:4:6:8
entre
los
cinco
densidades
primarios
(medio,
alto,
x-alta,
xx-alta
y
alta,
respectivamente-
xxx).
Por
ejemplo,
considere
la
posibilidad
de
que
se
especifica
el
tamao
de
un
icono
de
lanzador
para
ser
48x48
dp.
Esto
significa
que
la
lnea
de
base
(MDPI)
de
activos
es
de
48x48
pxeles,
y
el
asset
de
alta
densidad
(HDPI)
debe
ser
de
1,5
x
de
la
lnea
base
en
72x72
pxeles,
y
los
assets
de
x-high
densidad
(XHDPI)
deben
ser
2
veces
la
lnea
de
base
a
96x96
pxeles,
y
as
sucesivamente.
Nota:
Android
tambin
es
compatible
con
pantallas
de
baja
densidad
(LDPI),
pero
normalmente
no
es
necesario
crear
assets
personalizados
en
este
tamao
porque
Android
efectivamente
reduce
sus
assets
HDPI
a
la
mitad
para
que
coincida
con
el
tamao
esperado.
Lanzador
El
icono
de
lanzador
es
la
representacin
visual
de
su
aplicacin
en
la
pantalla
de
inicio
o
la
pantalla
All
Apps.
Dado
que
el
usuario
puede
cambiar
el
papel
tapiz
de
la
pantalla
de
inicio,
asegrese
de
que
el
icono
de
lanzador
es
claramente
visible
en
cualquier
tipo
de
fondo.
Dimensiones y escala
260
Dimensiones
Activo
completo,
dp
48x48
Estilo
261
Action
Bar
Iconos
de
la
barra
de
accin
son
los
botones
grficos
que
representan
las
acciones
ms
importantes
que
las
personas
pueden
tomar
dentro
de
su
aplicacin.
Cada
uno
debe
emplear
una
metfora
simple
que
representa
un
concepto
nico
que
la
mayora
de
la
gente
puede
entender
de
un
vistazo.
Glifos
pre-definidos
deberan
ser
utilizados
para
ciertas
acciones
comunes
tales
como
"actualizar"
y
"compartir".
Dimensiones
y
escala
rea
focal
y
proporciones
Activo
completo,
dp
32x32
Plaza
ptico,
dp
24x24
Estilo
Colores
Colores:
#
333333
Habilitado:
el
60%
de
opacidad
para
minusvlidos:
30%de
opacidad
Colores:
#
FFFFFF
Habilitado:
el
80%
de
opacidad
para
minusvlidos:
30%de
opacidad
262
Iconos
pequeos/contextuales
Dentro
del
cuerpo
de
su
aplicacin,
use
pequeos
iconos
para
acciones
superficiales
y/o
proporcionar
el
estado
de
elementos
especficos.
Por
ejemplo,
en
la
aplicacin
de
Gmail,
cada
mensaje
tiene
un
icono
de
estrella
que
marca
el
mensaje
como
importante.
Dimensiones y escala
263
Colores
Iconos
de
notificacin
Si
su
aplicacin
genera
notificaciones,
proporcionar
un
icono
que
el
sistema
puede
mostrar
en
la
barra
de
estado
cada
vez
que
una
nueva
notificacin
est
disponible.
Dimensiones
y
escala
Iconos
de
notificacin
deben
ser
24x24
dp
.
264
Estilo
Mantener
el
estilo
llano
y
simple,
utilizando
el
mismo
single,
metfora
visual
como
su
icono
de
lanzador.
Colores
Iconos
de
notificacin
deben
ser
totalmente
blanco.
Adems,
el
sistema
puede
escalar
hacia
abajo
y
/
u
oscurecer
los
iconos.
Consejos
de
Diseo
Estos
son
algunos
consejos
que
pueden
resultar
tiles
a
medida
que
crea
iconos
u
otros
drawables
assets
para
su
aplicacin.
Estos
consejos
se
presupone
que
est
utilizando
programa
Adobe
Photoshop
o
algn
similar
de
edicin
de
imgenes
raster
y
vector.
Utilice
formas
vectoriales
cuando
sea
posible
Muchos
programas
de
edicin
de
imgenes
como
Adobe
Photoshop
le
permiten
utilizar
una
combinacin
de
formas
vectoriales
y
capas
raster
y
efectos.
Cuando
sea
posible,
utilice
formas
vectoriales
para
que
en
caso
de
necesidad,
los
activos
pueden
ser
ampliadas
sin
prdida
de
detalle
y
nitidez
de
borde.
265
El
uso
de
vectores
tambin
hace
que
sea
fcil
para
alinear
los
bordes
y
esquinas
a
pxel
lmites
a
resoluciones
menores.
Comience
con
grandes
mesas
de
trabajo
Debido
a
que
usted
tendr
que
crear
assets
para
diferentes
densidades
de
pantalla,
lo
mejor
es
empezar
sus
diseos
de
iconos
en
grandes
mesas
de
trabajo
con
dimensiones
que
son
mltiplos
de
los
tamaos
de
los
iconos
objetivo.
Por
ejemplo,
los
iconos
del
lanzador
son
48,
72,
96,
o
144
pxeles
de
ancho,
dependiendo
de
la
densidad
de
la
pantalla
(mdpi,
hdpi,
xhdpi
y
xxhdpi,
respectivamente).
Si
dibuja
inicialmente
iconos
de
lanzadores
en
una
mesa
de
trabajo
864x864,
ser
ms
fcil
y
ms
limpio
para
ajustar
los
iconos
cuando
se
escala
la
mesa
de
trabajo
hasta
los
tamaos
de
destino
para
la
creacin
de
activos
final.
Al
escalar,
vuelva
a
dibujar
las
capas
de
mapa
de
bits,
segn
sea
necesario
Si
escalas
una
imagen
a
partir
de
una
capa
de
mapa
de
bits,
en
lugar
de
partir
de
una
capa
vectorial,
tendrn
que
volver
a
dibujar
manualmente
a
aparecer
ntidas
a
mayores
densidades
esas
capas.
Por
ejemplo,
si
un
crculo
60x60
fue
pintado
como
un
mapa
de
bits
para
MDPI
que
tendr
que
volver
a
pintar
como
un
crculo
90x90
para
HDPI.
Use
convenciones
de
nombres
comunes
para
los
activos
icono
Trate
de
nombrar
archivos
para
que
los
assets
relacionados
se
agrupan
dentro
de
un
directorio
al
que
estn
ordenados
alfabticamente.
En
particular,
ayuda
a
utilizar
un
prefijo
comn
para
cada
tipo
de
icono.
Por
ejemplo:
Tipo de activo
Prefijo
Ejemplo
Iconos
ic_
ic_star.png
ic_launcher
ic_launcher_calendar.png
ic_menu
ic_menu_archive.png
ic_stat_notify
ic_stat_notify_msg.png
Iconos Tab
ic_tab
ic_tab_recent.png
Iconos de dilogo
ic_dialog
ic_dialog_info.png
Tenga
en
cuenta
que
no
est
obligado
a
usar
un
prefijo
comn
de
cualquier
tipo-hacerlo
es
slo
para
su
conveniencia.
266
Debido
a
que
la
estructura
del
espacio
de
trabajo
es
similar
a
la
de
la
aplicacin,
se
puede
determinar
rpidamente
qu
assets
deben
copiarse
en
el
directorio
cada
recursos.
La
separacin
de
los
activos
por
la
densidad
tambin
le
ayuda
a
detectar
cualquier
variacin
en
los
nombres
de
archivos
a
travs
de
las
densidades,
lo
cual
es
importante
porque
los
activos
correspondientes
a
diferentes
densidades
debe
compartir
el
mismo
nombre
de
archivo.
267
Para
comparar,
aqu
est
la
estructura
de
directorio
de
recursos
de
una
aplicacin
tpica:
res/...
drawable- ldpi/...
finished_asset .
drawable- mdpi/...
finished_asset .
drawable- hdpi/...
finished_asset .
drawable- xhdpi/...
finished_asset .
png
png
png
png
Su
imagen
de
marca
Siguiendo
el
patrn
de
diseo
en
Android
no
significa
que
tu
aplicacin
tenga
la
misma
apariencia
que
la
de
las
aplicaciones
de
los
dems.
En
Android,
tu
aplicacin
puede
brillar
como
una
extensin
de
tu
marca.
Color
Usa
el
color
de
tu
marca
para
Acentuar,
sobrescribiendo
el
marco
azul
por
defecto
de
los
elementos
de
la
Interfaz
de
Usuario
(UI)
como,
barras
de
progreso,
botones
radio,
diapositivas,
pestaas
e
indicadores
de
scroll.
Busca
la
oportunidad
de
usar
colores
de
contraste-alto
para
enfatizar,
por
ejemplo,
el
color
de
fondo
de
la
barra
de
accin,
o
un
botn
primario.
Pero
no
te
excedas:
no
todas
las
acciones
son
las
mismas,
as
que
salo
solamente
para
una
o
dos
cosas
importantes.
Cuando
se
personalizan
los
colores,
la
retroalimentacin
tctil
debe
de
ser
sutil-
solo
ligeramente
mas
claro
u
obscuro
que
el
color
sin
tocar.
268
Logo
El
lanzador
del
icono
de
tu
aplicacin
es
la
llave
para
incorporar
tu
logo,
por
que
es
lo
que
los
usuarios
buscaran
y
tocaran
al
empezar
a
utilizar
tu
aplicacin.
Tu
puedes
mover
tu
icono
a
travs
de
todas
las
pantallas
en
tu
aplicacin,
mostrando
en
la
barra
de
accin
el
nombre
de
la
aplicacin.
Otra
consideracin
a
tomar
en
cuenta
es
colocar
el
logo
en
tu
icono,
as
como
el
nombre
de
la
aplicacin
en
la
barra
de
accin.
Google
+,
refuerza
su
marca
colocando
su
icono
a
travs
de
la
barra
de
accin.
269
Iconos
Si
cuentas
con
iconos
que
ya
estas
usando
para
tu
aplicacin
en
otras
plataformas
y
estos
a
su
vez
tienen
un
look
distintivo
de
acuerdo
a
tu
marca,
los
puedes
utilizar
tambin
en
tu
aplicacin
Android.
Si
se
toma
en
cuenta
esta
consideracin,
tiene
uno
que
estar
seguro
que
el
estilo
de
tu
marca
es
aplicado
a
cada
icono
en
tu
aplicacin.
Excepcin:
para
cualquier
icono
en
tu
juego
existente
de
iconos
donde
la
simbologa
es
manejada
diferente
a
como
se
maneja
en
Android,
usa
los
smbolos
de
Android
para
darle
estilo
a
tu
marca.
De
esa
forma,
el
usuario
entender
que
propsito
tiene
el
icono.
Aun
as,
el
icono
se
vera
como
si
perteneciera
a
tu
conjunto
de
iconos
como
parte
de
tu
marca.
Ejemplo:
El
icono
normal
para
compartir
con
otras
plataformas
es
la
flecha
hacia
la
derecha
Pero,
qu
pasara
si
no
tienes
aun
tus
propios
iconos-
por
ejemplo,
si
estas
creando
una
nueva
aplicacin
solo
para
Android?.
En
este
caso,
usa
los
iconos
estndar
de
Android.
270
Estilos
de
Escritura.
La
voz
de
Android.
Al
escribir
el
texto
que
aparece
en
su
aplicacin,
que
sea
concisa,
simple
y
amigable.
Conciso:
Eliminar la redundancia, como los ttulos que reiteran el cuerpo de un cuadro de informacin.
Accediendo ...
271
Poner
primero
lo
ms
importante.
"Carga
frontal"
los
primeros
11
caracteres
con
la
informacin
ms
relevante
en
la
cadena.
272
No
hacer
Toque
Siguiente
para
completar
la
configuracin
mediante
una
conexin
Wi-Fi
Hacer
Para
finalizar
la
configuracin
a
travs
de
Wi-Fi,
toque
Siguiente
Amistoso
Utilice contracciones.
Use
1,
2,
3,
4,
...
273
Aplicacin
app
okay, ok,
OK
yo, mi, mo
De
formato
al
texto
Capitalizacin
Utilice maysculas al estilo de oracin para todas las cadenas de la IU: "Palabras para vivir."
Sea
conservador.
No
utilice
maysculas
en
palabras
que
no
son
parte
de
un
nombre
rasgo
formal:
274
Puntuacin
Perodo.
No
utilice
un
perodo
despus
de
una
sola
oracin
o
frase
que
se
usa
de
manera
aislada,
como
en
un
brindis,
una
etiqueta
o
notificacin.
Dondequiera
que
dos
o
ms
oraciones
corren
juntas,
utilice
un
punto
para
cada
frase.
.
Elipsis
Utilice
el
carcter
de
puntos
suspensivos
(...)
(Opcin-;
en
MacOS
y
...
en
HTML)
para
indicar
o
Que
un
elemento
del
men
(como
impresin...
o
Compartir...)
conduce
a
una
mayor
UI
implica
decisiones
importantes.
Excepcin:
Los
comandos
cuya
redaccin
ya
implica
ms
(pero
limitado)
interfaz
de
usuario,
tales
como
Buscar
en
la
pgina
o
Elija
una
fecha,
no
requieren
275