Manual de Prácticas Programación Móvil
Manual de Prácticas Programación Móvil
Manual de Prácticas Programación Móvil
MATERIA
Elaborado por
OBJETIVO DE LA MATERIA
El principal objetivo de esta asignatura es que al final del curso los estudiantes sean
capaces de diseñar y construir aplicaciones para dispositivos móviles. Para alcanzar este
objetivo, los estudiantes tienen que desarrollar paso a paso una aplicación Android
completa.
Competencias específicas:
Competencias previas:
Introducción.
i
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Contenido
Unidad 1. Introducción a las Tecnologías de Móviles ................................................................................... 1
Practica 1. Instalación de Android Studio.................................................................................................. 2
Unidad 2. Arquitecturas y Entorno de Desarrollo ......................................................................................... 6
Práctica 2. Estructura de un Proyecto ....................................................................................................... 7
Práctica 3. Lenguaje de Programación Kotlin .......................................................................................... 15
Unidad 3. Desarrollo de Aplicaciones Móviles ............................................................................................ 42
Práctica 4. Uso de Layouts ...................................................................................................................... 43
Unidad 4. Administración de datos en dispositivos móviles ....................................................................... 62
Práctica 5. Bases de Datos en SQLite y Llenado de Controles ................................................................. 63
Práctica 6. Servicios Web ........................................................................................................................ 89
Práctica 7. Generación de PDF en Android ........................................................................................... 128
Práctica 8. Generación de una Gráficas en Android .............................................................................. 139
Práctica 9. Mapas y Marcas en Android ................................................................................................ 148
Práctica 10. Geolocalización en Tiempo Real Android .......................................................................... 158
Bibliografía ................................................................................................................................................ 168
ii
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Conoce la evolución de los dispositivos móviles y de las tecnologías de conectividad móviles para
identificar los ambientes de desarrollo en esta área.
Subtema
Sugerencias Didácticas
1
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
PRACTICAS PROPUESTAS
Objetivo
Introducción
El estudiante deberá descargar el instalador del IDE de Android Studio para poder practicar el
desarrollar aplicaciones móviles en Kotlin.
La práctica apoya al tema 1.2. Introducción a las tecnologías y herramientas móviles, para que el
estudiante conozca las herramientas que proporciona el Entorno de Desarrollo Integrado “IDE”
para aplicaciones móviles de Android.
Metodología
2
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
El primer paso es, obviamente, descargar el instalador. Está disponible oficialmente para Windows,
Mac y Linux, y encontrarás el enlace de descarga en su web oficial. La instalación será para la
versión de Windows, aunque muchas indicaciones te servirán para los otros sistemas operativos.
2. Inicia la instalación
Android Studio es una herramienta enormemente compleja, pero por suerte su instalación no lo
es. Aunque está disponible únicamente en inglés, lo cierto es que no hay mucha dificultad pues
en la mayoría de pantallas solo necesitas pulsar Next, o siguiente.
3. Configuración inicial
Lo primero que verás al abrir Android Studio por primera vez es una pantalla como la siguiente.
En ella simplemente se te pregunta si quieres importar la configuración de una versión anterior.
Generalmente Android Studio detectará la configuración por sí mismo, y si no tienes ninguna
configuración anterior guardada se marcará Do not import settings, o no importar configuración.
¿Anteriormente instalar Android Studio era un lío? Parte de la culpa la tenía Java y el SDK de
Android, pero ahora el proceso es automático. Si elegiste la instalación estándar, Android Studio
elige por ti los componentes que necesita descargar.
NOTA: Se deberá instalar la API de acuerdo a la versión del sistema operativo en que se ejecutará
la App.
Que API instalo e indique el porcentaje de dispositivos en los que se podrá ejecutar la App.
3
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
a.) Reporte escrito: El estudiante deberá presentar un reporte escrito explicando las ventanas del
proceso de instalación de Android Studio. Este deberá incluir portada e índice, así como
referencias bibliográficas.
b.) Rubrica de evaluación
Todos los párrafos La mayor parte de Los párrafos incluyen La estructura del
incluyen una los párrafos incluye información párrafo no estaba
Construcción de introducción, una introducción, relacionada pero no clara y las oraciones
Párrafos explicaciones o explicaciones o fueron generalmente no estaban
detalles y una detalles y una bien organizados. generalmente
conclusión. conclusión. relacionadas.
No hay errores de Casi no hay errores Unos pocos errores Muchos errores de
gramática, ortografía o de gramática, de gramática, gramática, ortografía o
puntuación. ortografía o ortografía o puntuación.
Redacción puntuación. puntuación.
Todos los temas Todos los temas Todos los temas Uno o más temas no
tratados y todas las tratados y la mayor tratados y la mayor están tratados.
Cantidad de preguntas fueron parte de las parte de las
Información contestadas en al preguntas fueron preguntas fueron
menos 2 oraciones. contestadas en al contestadas en 1
menos 2 oraciones. oración.
4
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
5
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Subtema
Sugerencias Didácticas
6
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Objetivo
El estudiante conocerá la estructura de un proyecto creado en el Entorno de Desarrollo Integrado
de Android Studio.
Introducción
Esta práctica tiene como fin comprender la estructura de archivos de un proyecto en Android
Studio. Esto nos permitirá investigar a fondo la lógica de construcción de una aplicación.
7
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Metodología
Crear un proyecto nuevo en Android Studio y revisar su estructura de acuerdo a la siguiente
información:
Cada proyecto en Android Studio contiene uno o más módulos con archivos de código fuente y
archivos de recursos. Entre los tipos de módulos se incluyen los siguientes:
Figura 1
Estructura de proyecto
8
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Todos los archivos de compilación son visibles en el nivel superior de Secuencias de comando de
Gradle y cada módulo de la aplicación contiene las siguientes carpetas (Developers, 2023):
• java: en este directorio encontraremos los ficheros.java con el código fuente. Ubicación:
“/src/main/java/”.
• res:
9
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Ø raw: en esta carpeta ubicamos los archivos multimedia descomprimidos, de esta manera
Android sabe que no debe procesarlos más tarde. Se encuentra en el directorio
“/src/main/res/raw”.
Ø values: archivos XML que definen valores constantes. Ya hemos detallado qué es y para qué
sirve la carpeta Values, así que solo haremos un pequeño resumen. Se encuentra en:
“src/main/res/values”.
§ strings.xml: este XML contiene las cadenas de texto de nuestra aplicación. Más adelante
veremos cómo nos facilita la tarea de traducir nuestra aplicación a otros idiomas
cómodamente.Ubicación “/src/main/res/values/strings.xml”.
§ styles.xml: en este fichero XML se definen los estilos de nuestro proyecto. Ubicación
“/src/main/res/values/styles.xml”.
§ color.xml: aquí se definen los colores que usaremos en el diseño de nuestra aplicación.
Ubicación “/src/main/res/values/color.xml”.
Ø gradle: por último, encontramos los ficheros gradle de Android Studio. En el módulo de
gradle agregamos las dependencias a librerías que deseamos manejar en nuestro proyecto.
La estructura del proyecto para Android en el disco difiere de esta representación plana. Para ver
la estructura de archivos real del proyecto, selecciona Project en la lista desplegable Project.
También puedes personalizar la vista de los archivos del proyecto para concentrarte en aspectos
específicos del desarrollo de tu app.
10
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Interfaz de usuario
La ventana principal de Android Studio consta de varias áreas lógicas que se muestran en la figura
2 (Developers, 2023).
Figura 2
11
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
3. La ventana del editor es el área donde puedes crear y modificar código. Según el tipo de
archivo actual, el editor puede cambiar. Por ejemplo, cuando se visualiza un archivo de
diseño, el editor muestra el editor de diseño.
4. La barra de la ventana de herramientas se extiende alrededor de la parte externa de la
ventana del IDE y contiene los botones que te permiten expandir o contraer ventanas de
herramientas individuales.
5. Las ventanas de herramientas te permiten acceder a tareas específicas, como la
administración de proyectos, las búsquedas, los controles de versión, etc. Puedes
expandirlas y contraerlas.
6. En la barra de estado, se muestra el estado de tu proyecto y del IDE en sí, como también
cualquier advertencia o mensaje.
Clase R.java
El archivo R.java es un archivo que se autogenera dentro de la carpeta build, para linkear todos los
recursos que tenemos en nuestro proyecto al código Java o Kotlin.
package com.TUPAQUETE.test;
12
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Como ves, la clase R contiene clases anidadas que representan todos los recursos de nuestro
proyecto. Cada atributo tiene una dirección de memoria asociada referenciada a un recurso en
específico. Por ejemplo, la clase string posee el atributo hello_world, el cual representa nuestro
TextView en la actividad principal. Este recurso está ubicado en la posición0x7f050002.
a.) Reporte escrito: El estudiante deberá presentar un reporte escrito en forma de resumen
explicando la funcionalidad de las diferentes opciones que se encuentra en la estructura de un
13
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
proyecto en Android Studio. Este deberá incluir portada e índice, así como referencias
bibliográficas.
b.) Rubrica de evaluación
Categoría 5 Excelente 4 Bueno 3 Regular 2 Deficiente 1 Malo
Demasiado
Demasiado
Se ajustó a la cantidad Se sobrepaso uno o Tres o más extenso, no
Resume según lo corto o
de páginas o palabras dos párrafos más párrafos de supo eliminar
solicitado. extenso el
descritas. de lo solicitado. más o menos. párrafos o
resumen.
frases.
La mayoría de
Varios títulos
Justificación del párrafo, Algún párrafo no los párrafos sin No agregó
sin resaltar,
Estilo, formato. espaciado, separación justificado, título justificar, no ningún estilo,
párrafos sin
de textos, etc. sin resaltar, etc. agrega color, justificación.
justificar.
espacio.
Muestra la
Faltó pequeños
El resumen está idea principal,
detalles para Muy corto o Falta mucha
Completo completo en la cantidad aunque
comprender más lo extenso. información.
de palabras indicadas. faltaron
detallado.
detalles.
14
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Objetivo
El estudiante conocerá la sintaxis del lenguaje de programación Kotlin.
Introducción
Esta práctica tiene como fin comprender el lenguaje de programación Kotlin.
Metodología
Revisar la siguiente documentación y al final realizar el ejercicio propuesto:
15
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Sentencias
Bloques
• Agrupan instrucciones.
• Definen el ámbito de las variables.
• En kotlin las llaves {y} para delimitarlos.
Comentarios en Kotlin
• De una línea, //
• De multiples líneas, /* comentario */
• Se pueden anidar, así están balanceados /*/**/*/
• Los comentarios en kotlin se pueden anidar.
Operador de Asignación
X=X+1
ó
x += 1
16
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Operadores aritméticos
Figura 4
17
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Figura 5
Nota:
== estamos comparando contenido de los objetos
=== Triple igual compara si las referencias son las mismas es decir si se trata del mismo
objeto.
Operadores lógicos
Figura 6
18
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
19
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Nota: Kotlin no hace conversiones automáticas entre tipos esto ayuda a evitar errores.
Tenemos que expresar la expresión de forma explícita.
Ejemplos:
val b : Byte = 1 //ok
val i : Int = b //error
---------------------------------------------
val i :Int = b.toInt() // Ok: expresada explícitamente
Valores Opcionales
typesafe null
Una característica importante de Kotlin es que maneja seguridad en nulos. Esto es algo que varios
lenguajes han estado implementando últimamente.
Normalmente, una variable de cualquier tipo que sea objeto, acepta null. En Kotlin no es así; para
que una variable acepte null, se necesita especificar de esa forma. Esto no compila:
20
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Porque x ha sido definida como de tipo String, y no acepta nulos. Para que acepte nulos, se tiene
que definir así:
Los tipos opcionales se pueden usar en parámetros de funciones, tipos de retorno y declaraciones
locales. Cuando se tiene un valor que puede ser null, no se puede usar de manera directa. Hay que
verificar que el objeto exista; esto se puede lograr de varias formas:
Esto nos evita dolores de cabeza porque en vez de tener que lidiar con NullPointerException en
tiempo de ejecución, estos errores se detectan en tiempo de compilación. Sin embargo, Kotlin
tiene un gran problema con esto: integrado con la seguridad de nulos, viene un mecanismo para
desactivarla por completo: Si se agrega una doble admiración al final de una variable opcional, el
compilador deshabilita las verificaciones de nulos y se porta como lo haría el compilador de Java,
permitiendo que sea nulo donde sea:
21
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Conversiones
Para todos los tipos de datos se tienen tipos de conversiones, solo es necesario poner la variable
con punto y el tipo de dato al que la queremos convertir:
toByte() : Byte
toShort(): Short
toInt() : Int
toLong() : Long
toFloat(): Float
toDouble(): Double
toChar(): Char
toString(): String
por ejemplo:
22
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Val c: Int
c=3
var hora = 9
23
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
println(“, A cenar”)
• En Kotlin, el sistema de tipos distingue entre referencias que pueden almacenar null y a las
que no.
• Este mecanismo hace explicito el hecho de que una variable puede ser nula.
• Permite al compilador detectar el uso de referencias nulas.
• ¿Se declaran poniendo? Detrás del nombre del tipo
Figura 8
Variables anulables
24
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Clases en Kotlin
Para crear una clase en Kotlin, tienes que usar la palabra reservada class. Por ejemplo, una clase
llamada Person:
class Person {
Agregando Propiedades
Una clase generalmente tiene propiedades y función miembro (también llamados métodos).
Agreguemos dos propiedades a la clase Person, name de tipo String y age de tipo Int.
Debemos usar la palabra reservada var. Sin embargo, si quieres que tu variable sea una variable de
solo lectura/una única asignación, mejor utiliza la palabra reservada val.
25
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Variables NULL
Por el bien de la seguridad null, Kotlin también hace una distinción entre variables que pueden ser
null y variables que nunca pueden ser null. En nuestro ejemplo previo, ambas variables name y age
nunca pueden ser null. Si son null, el compilador emitirá un error.
Para crear una variable que puede contener null, se necesita añadir un ? después del tipo de la
variable. Por ejemplo:
Para crear una instancia es bastante sencillo, solo le asignamos a una variable una clase y listo
var jake = Person()
No, Kotlin no tiene la palabra reservada new. Una vez que la instancia ha sido creada, puedes
accesar a sus propiedades de la misma forma que lo harías en Java:
26
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Constructores
class Person(var name: String, var age: Int, var college: String?) {
}
Nota: si no se tiene nada que agregar a tu clase, no necesitas las llaves. El siguiente
código funciona bien:
class Person(var name: String, var age: Int, var college: String?)
Estructuras de control
Evalúa una variable contra distintos valores y ejecuta las sentencias correspondientes, su
funcionamiento po puede observar en la figura 9:
Características de when
27
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Figura 9
Instrucción when
Nota: Instrucción when para evaluar varias alternativas, esta instrucción es similar al switch de otros lenguajes, (Jaureguialzo,
2017)
Ejemplo
when (x){
Else ->print(“otherwise)
Los valores contra los que evaluamos una constante puede ser cualquier expresión
when (x){
28
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
when (x){
Ejemplo
Sentencia 1 y 2 se ejecutan si la
condición se evalúa a true
También se puede incluir el else
cuando la condición se evalué a
false.
29
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
30
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Figura 10
Repetitivas
En kotlin tenemos tres tipos repetitivas, las cuales las puede observar en la figura11:
31
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Figura 11
Estructuras Repetitivas
For es una repetitiva distinta en kotlin no se maneja de la misma manera que en Java pues recorre
los intervalos por colecciones, While y do-While tienen el mismo funcionamiento que en Java.
Declaración de While
Ejemplo:
while(x>0){
x---
}
Declaración de do-While
32
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Ejemplo:
Do{
Val y = retrieveData()
}while(y ¡= null)
Se ejecutará mientras la condición sea cierta, pero en este caso la condición se evalúa al final, pero
al menos en el cuerpo del bucle se habrá ejecutado una vez.
Declaración de for
Sintaxis
for(ítem in colección) sentencia
Recorre la colección y a cada vuelta del bucle proporciona acceso a cada uno de los
elementos en la variable ítem.
Ejemplo:
for (ítem: Int in ints){
Println (item)
}
Recorrido de un array con índices
Si queremos hacer un recorrido dependiendo a la posición del elemento podmeos recurrir
a la propiedad índices del elemento.
33
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
for(i in array.indices){
Printl(array[i])
}
Transferencia de control
• Se puede poner break dentro de un bucle para cortar la repetición actual y forzar a que el
bucle termine.
• Se puede utilizar continue dentro de un bucle para terminar la repetición actual y pasar a
la siguiente.
• Se pueden utilizar etiquetas para definir a quien afecta un posible break o continue.
(Jaureguialzo, 2017)
Existe una regla de oro en el mundo de la programación: en los programas ocurren errores. Esto
es sabido, pero ¿Qué sucede realmente después de que ha ocurrido el error?
“Una excepción es un evento que ocurre durante la ejecución del programa que interrumpe el
flujo normal de las sentencias”
La captura de errores se realiza incluyendo el código que puede potencialmente contener un
error (o provocar una excepción) entre las llaves de la sentencia try, como en el siguiente código:
try
34
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
{
// Se ejecuta algo que puede producir una excepción
}
catch (Exception e)
{
// Manejo de una excepción
}
finally
{
// Código a ejecutar haya o no excepción
}
Para ejemplificar los temas tratados de esta práctica, vamos a crear un nuevo proyecto de nombre
MyAppErrores, en este vamos a utilizar el try para atrapar un error de división por cero.
En este proyecto se va a crear una actividad vacía de nombre MainActivity. Un proyecto de Android
contiene un programa de Kotlin y otros datos en una serie de archivos, que son utilizados por el
programa o por el sistema. Un programa de Kotlin es una colección de clases, contenidas en uno
o varios archivos file1.kt, file2.kt. En Android estos archivos Kotlin se almacenan en Android->app-
>java->com.example.myapperrores. Para nuestro proyecto se crea MainActivity.kt, y un layout con
el nombre activity_main.xml ubicado en app->res->layout, la figura 12 muestra la ubicación de
estos archivos:
35
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Figura 12
Existe una clase de nombre R que contiene las definiciones de todos los recursos de un paquete
de aplicación. Y es a través de este que vamos a poder declarar variables que referencien a los
controles de nuestras actividades, utilizando la instrucción findViewById.
36
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
<TextView
android:id="@+id/ tvTexto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Como puede observar se agregó el id al TextView con el nombre tvTexto, con la finalidad de
poder referenciar este control desde Kotlin.
package com.example.myapperror
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
37
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Este es el modelo que utilizaremos como punto de partida en todos nuestros programas Kotlin.
Examinaremos su estructura:
\MyAppCurso\app\src\main\java\com\example\myapperror
• Las dos líneas siguientes precedidas por import indican que este programa utiliza dos
clases predefinidas en dos paquetes del sistema Android.
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
En este caso, el programa importa la clase Activity del paquete android.app y la clase Bundle
del paquete del paquete android.os. Android contiene numerosos paquetes con miles de
clases. En el editor de Android Studio, cuando escribimos el nombre de una clase, ésta se
subraya en rojo si se requiere añadir un import, por lo que no necesitamos recordar el
nombre del paquete. Basta pulsar Alt-Enter, para que se agregue la importación faltante.
38
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
• El programa contiene una clase llamada MainActivity cuya definición abarca el bloque
de código comprendido entre la llave inicial y final:
}
}
La declaración finaliza con AppCompatActivity. Esto significa que nuestra clase es una
subclase AppCompatActivity, definida en el paquete android.app y hereda todas sus
propiedades, además de las que nosotros le queramos añadir. Por tanto, myappcurso es
una extensión o una generalización de la clase AppCompatActivity. Se dice que
AppCompatActivity es una superclase de myapperror.
Este método es una función con un parámetro llamado savedInstanceState de tipo Bundle. La
declaración comienza con la clave override, lo que indica que se está redefiniendo o sobre
escribiendo el método onCreate de la super-clase.
• Finalmente, entre dos llaves, tenemos la definición del método, que consiste en dos
instrucciones:
39
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
super.onCreate(savedInstanceState)
A nivel de la clase declaramos un variable tvTex de tipo TextView que se inicializará más tarde,
esto lo hacemos para poder referenciar al TextView de la interfaz.
tvTex = findViewById<TextView>(R.id.tvTexto)
asigna a la variable tvTex la referencia del TextView ubicado en la clase R. La clase R que contiene
las definiciones de todos los recursos de un paquete de aplicación, para nuestro ejemplo hacemos
referencia al tvTexto colocado en la interfaz activity_mail.xml.
40
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
La operación de división por 0 generara un error, el cual será atrapado por el catch, evitando que
la app se interrumpa su ejecución.
Figura 13
41
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Desarrolla aplicaciones móviles nativas, web e híbridas para atender las necesidades del entorno.
Subtema
Sugerencias Didácticas
1. El estudiante utilizará los Constraint Layout y Linear Layout para diseñar interfaces de
usuario.
2. Implementara formularios para el ingreso de información validada.
3. Creará un menú para una interfaz de una aplicación móvil, respondiendo al clic del
usuario.
42
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Objetivo
El estudiante aprenderá a usar el Constraint Layout y el Liner Layout en el diseño de una app.
Introducción
Esta práctica tiene como fin comprender el uso de los Layouts, en el diseño de una aplicación
móvil.
Metodología
El estudiante deberá leer el siguiente material previo a la elaboración de la práctica:
43
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Layouts
Son un conjunto de contenedores en donde podemos colocar muchos elementos según el diseño
de nuestra aplicación, por ejemplo, dentro de un Layout puedes colocar, botones, imágenes,
formularios, textos, etc. todos estos deben tener un orden y armonía entre si dentro del diseño,
para esto debemos haber elegido un Layout primero para luego colocar dentro de este los
elementos que necesitemos. (Colectiva, 2018)
Figura 14
ConstraintLayout
Este nuevo layout ha sido añadido en una librería de compatibilidad, por lo que se nos anima a
usarlo de forma predeterminada. Nos permite crear complejos diseños sin la necesidad de usar
layout anidados, ver figura 14. El hecho de realizar diseños donde un layout se introduce dentro
de otro y así repetidas veces, ocasionaba problemas de memoria y eficiencia en dispositivos de
pocas prestaciones.
44
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Es muy parecido a RelativeLayout, pero más flexible y fácil de usar desde el editor visual de Android
Studio (disponible desde la versión 2.3). De hecho, se recomienda crear tu layout con las
herramientas drag-and-drop, en lugar de editar el fichero XML. El resto de layouts, son más fáciles
de crear desde XML.
Las posiciones de las diferentes vistas dentro de este layout se definen usando constraint (en
castellano restricciones). Un constraint puede definirse en relación al contenedor (parent), a otra
vista o respecto a una línea de guía (guideline). Es necesario definir para cada vista al menos un
constraint horizontal y uno vertical. Pero también podemos definir más de un constraint en el
mismo eje. La figura 15 ilustra el manejo:
Figura 15
Layout constraint
Observa como la vista A está posicionada con respecto al contenedor. La vista B está posicionada
verticalmente con respecto a la vista A, aunque se ha definido un segundo constraint con respecto
al lado derecho del contenedor.
LinearLayout es el Layout más utilizado en la práctica, distribuye los elementos uno detrás de otro,
de forma horizontal o vertical.
45
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Linear layout permite acomodar los componentes de tu UI, de manera lineal. Es decir, acomodara
los componentes uno enseguida de otro, así que es muy fácil saber que componente va enseguida
de otro, a diferencia que el en Relative layout, en el cual tienes que especificar en donde irá cada
componente. Aunque esto último es más difícil en el Relative layout, es una ventaja en cuanto a
más maneras de acomodar todo.
Orientación
Uno de los aspectos fundamentales del linear layout es la orientación. Por default usa orientación
horizontal. Y solo puedes alternar entre Horizontal y Vertical.
Figura 16
Linearlayout vertical
Figura 17
Linearlayout horizontal
46
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
En el siguiente ejemplo se crea una interfaz para calcular el índice de masa corporal, para lo cual
se pide que se ingrese el peso en Kg y la estatura en Mt, de acuerdo a la siguiente formula:
Se deberán implementar los siguientes rangos, como salida dependiendo del IMC:
0 a 18 Desnutrición
18 a 25 Normal
25 a 30 Sobrepeso
30 a 40 Obesidad
47
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Figura 18
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
48
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
android:layout_marginTop="76dp"
android:gravity="center"
android:text="Calculo del IMC"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/textInputLayout"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_marginTop="80dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/txtPeso"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:hint="Ingresa tu Peso en Kg" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/textInputLayout2"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_marginTop="79dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textInputLayout">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/txtEstatura"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Ingresa tu Estatura en Mt"
android:padding="30dp" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/btnCalcular"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="51dp"
android:clickable="true"
android:onClick="btnCalcularIMC"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
49
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
app:layout_constraintTop_toBottomOf="@+id/textInputLayout2"
app:srcCompat="@android:drawable/ic_menu_send"
tools:ignore="SpeakableTextPresentCheck" />
</androidx.constraintlayout.widget.ConstraintLayout>
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Toast
import
com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.textfield.TextInputEditText
findViewById<FloatingActionButton>(R.id.btnCalcular).setOnClickListener
{
Calcular()
}
}
50
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
51
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Figura 19
En el siguiente ejemplo creamos la interfaz de una aplicación para calcular el índice de masa
corporal, como el ejercicio anterior, para lo cual se pide que se ingrese el peso en Kg y la estatura
en Mt, en la figura 20 se observa el diseño usando el Linearlayout:
52
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Figura 20
Como se puede observar en el recuadro rojo (component Tree), se muestran los elementos que
tiene nuestra interfaz y como están anidados. En primer lugar, tenemos un Linear layout vertical
como contenedor principal, y enseguida colocamos un linear layout horizontal por cada control
que vaya a tener nuestra interfaz.
53
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="15dp"
tools:context=".MainActivity" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="40dp"
android:orientation="horizontal">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:padding="30dp"
android:text="Calculo del IMC"
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/txtPeso"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="30dp"
android:hint="Ingresa tu Peso en Kg" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="40dp"
android:orientation="horizontal">
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/txtEstatura"
android:layout_width="match_parent"
54
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
android:layout_height="wrap_content"
android:hint="Ingresa tu Estatura en Mt"
android:padding="30dp" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingTop="50dp">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/btnCalcular"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:onClick="btnCalcularIMC"
app:srcCompat="@android:drawable/ic_menu_send"
tools:ignore="SpeakableTextPresentCheck" />
</LinearLayout>
</LinearLayout>
package com.example.myapplication
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_main.*
55
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
}
else{
if (txtEstatura.text.toString().isEmpty()){
txtEstatura.setError("Error falta de ingresar la
estatura en Mt")
txtEstatura.requestFocus()
}
else{
peso = txtPeso.text.toString().toDouble()
estatura = txtEstatura.text.toString().toDouble()
res = peso / (estatura * estatura)
when (res){
in 0.0 .. 18.0 ->{ // Enviar a la actividad en Rojo
Toast.makeText(this, "Tu IMC es: $res y es
Desnutrición ", Toast.LENGTH_LONG).show();
}
in 18.01 .. 25.0->{ // Enviar a la actividad en
Verde
Toast.makeText(this, "Tu IMC es: $res y es
Normal", Toast.LENGTH_LONG).show();
}
in 25.01 .. 30.0 ->{ // Enviar a la actividad en
Amarillo
Toast.makeText(this, "Tu IMC es: $res y es de
Sobre Peso", Toast.LENGTH_LONG).show();
}
in 30.01 .. 40.0 ->{ // Enviar a la actividad en
Amarillo
Toast.makeText(this, "Tu IMC es: $res y es de
Obesidad", Toast.LENGTH_LONG).show();
}
else ->{ // Enviar a la actividad en
Rojo
Toast.makeText(this, "Tu IMC esta fuera de
rango checar datos de entrada", Toast.LENGTH_LONG).show();
}
}
}
}
}
}
56
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Figura 21
57
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Esto genera que se agregue a la carpeta res la carpeta menu con el archivo menu1.xml
que se agregó, quedando como se muestra en la figura 23:
58
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Figura 23
</menu>
59
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Figura 24
package com.example.myapplicationmenu
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.widget.Toast
60
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
El estudiante presentará las diferencias de las App con Constraint y Linear Layout.
El estudiante deberá usar el conocimiento de estas prácticas en su proyecto, y mostrar evidencias.
61
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Subtema
4.1 Introducción.
4.2 Modelo de objetos de acceso a datos.
4.3 Manipulación de datos.
4.4 XML.
4.5 JSON.
Sugerencias Didácticas
62
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Objetivo
El estudiante aprenderá a usar la librería de base de datos SQLite de Android y el llenado de
controles Spinner y RecyclerView.
Introducción
Esta práctica tiene como fin comprender el uso de la librería SQLite, para almacenar información
persistente en los dispositivos móviles.
Metodología
El estudiante deberá leer el siguiente material previo a la elaboración de la práctica:
63
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
¿Qué es SQLite?
Es un motor ligero de bases de datos de código abierto, que se caracteriza por mantener el
almacenamiento de información persistente de forma sencilla (Revelo, 2014).
Dentro de los distintos sistemas de bases de datos tanto privativos como libres/open source
(Oracle, SQLServer, MySQL, etc) existe uno que se adapta perfectamente a las aplicaciones
móviles: SQLite. El principal motivo es que SQLite no requiere más que un simple fichero para
almacenar los datos, ya que la lógica de funcionamiento debe ser implementada por la plataforma
que desee interactuar con los datos.
En nuestro caso concreto el SDK Android incluye soporte completo para SQLite. La mayoría de las
aplicaciones móviles (tanto en Android como en otros sistemas) incluyen bases de datos SQLite,
bien sea para la gestión total de los datos, o bien para al menos gestionar los datos almacenados
localmente cuando las aplicaciones son parte de infraestructuras mayores que incluyen bases de
datos centralizadas online o servicios Web para la obtención de los datos.
El procedimiento recomendado para crear una nueva base de datos SQLite es, de forma
esquemática:
64
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Tabla: Producto
idProd Integer Auto incrementable
NomProd Text
Existencia integer
Precio double
Enseguida agregaremos una clase de Kotlin de nombre AdminBD, a través de la cual gestionaremos
la estructura de la base de datos y los accesos, a la cual llamaremos BDInventario. A continuación,
se muestra el código de la clase:
package com.example.appsqlite
import android.content.Context
import android.database.Cursor
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
import android.util.Log
// En este método se crean las tablas de la base de datos la primera vez que se
// ejecuta el proyecto, si se hacen cambios deberá desinstalar la App del dispositivo
// para eliminar la base de datos y que vuelva a crear las tablas con los nuevos cambios
override fun onCreate(bd: SQLiteDatabase?) {
if (bd != null) {
bd.execSQL("Create Table Producto(idProd integer primary key AUTOINCREMENT," +
"NomProd text, Existencia integer, Precio double)")
}
}
65
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
try {
val bd = this.writableDatabase
bd.execSQL(sentencia)
bd.close()
return true
}
catch (ex : Exception){
// La siguiente instrucción manda el mensaje a la pestaña de Log,
// cuando estamos depurando
Log.d("Zazu", ex.message.toString() + "-->" + sentencia)
return false
}
}
66
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Figura 25
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Catálogo de Productos"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.473"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.087" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/textInputLayout"
67
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_marginTop="44dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/txtidProd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Cve Producto"
android:inputType="number" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/textInputLayout2"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textInputLayout">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/txtNomProd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Nombre del Producto" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/textInputLayout3"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_marginTop="22dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textInputLayout2">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/txtExistencia"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
android:hint="Existencia" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/textInputLayout4"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_marginTop="31dp"
app:layout_constraintEnd_toEndOf="parent"
68
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textInputLayout3">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/txtPrecio"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="numberDecimal"
android:hint="Precio" />
</com.google.android.material.textfield.TextInputLayout>
<Button
android:id="@+id/btnInsertar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginTop="107dp"
android:layout_marginEnd="285dp"
android:onClick="btnInsertar"
android:text="Insert"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textInputLayout4" />
<Button
android:id="@+id/btnActualizar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginTop="108dp"
android:layout_marginEnd="150dp"
android:onClick="btnActualizar"
android:text="Update"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/btnInsertar"
app:layout_constraintTop_toBottomOf="@+id/textInputLayout4" />
<Button
android:id="@+id/btnEliminar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="38dp"
android:layout_marginTop="111dp"
android:layout_marginEnd="45dp"
android:onClick="btnEliminar"
android:text="Delete"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/btnActualizar"
app:layout_constraintTop_toBottomOf="@+id/textInputLayout4" />
<Button
android:id="@+id/btnConsultar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
69
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
android:layout_marginTop="30dp"
android:onClick="btnConsultar"
android:text="Select"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.482"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btnActualizar" />
</androidx.constraintlayout.widget.ConstraintLayout>
El código de Kotlin asociado a la interfaz con los eventos programados, se muestra a continuación:
package com.example.appsqlite
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Toast
import com.google.android.material.textfield.TextInputEditText
70
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
71
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
producto", Toast.LENGTH_SHORT).show()
}
txtid.requestFocus()
}
}
fun btnConsultar(view: View) {
if (txtid.text.toString().isEmpty()){
txtid.setError("Error para buscar ingresa la clave del
producto")
txtid.requestFocus()
}
else{
val idp = txtid.text.toString()
// 0 1 2 3
val query = "Select idProd,NomProd,existencia,precio from
Producto where idProd=$idp"
val tuplas = admin.Consultar(query)
if (tuplas == null){
Toast.makeText(this, "Producto no encontrado",
Toast.LENGTH_LONG).show();
txtid.requestFocus()
}
else{
if (tuplas.moveToFirst()){
txtNomP.setText(tuplas.getString(1).toString())
txtExis.setText(tuplas.getInt(2).toString())
txtPrec.setText(tuplas.getDouble(3).toString())
txtNomP.requestFocus()
tuplas.close()
}
else
{
Toast.makeText(this, "Producto no encontrado",
Toast.LENGTH_LONG).show();
txtid.requestFocus()
}
}
}
}
fun Limpiar(){
txtid.setText("")
txtNomP.setText("")
txtExis.setText("")
txtPrec.setText("")
txtid.requestFocus()
}
}
En este punto puede probar ejecutar la aplicación de dar de alta algunos productos y buscarlos,
para comprobar su funcionalidad.
72
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Spinner
Un spinner es un elemento de la Interfaz de usuario, el cual es como una lista expandible. Se
pueden colocar varios elementos para que el usuario elija uno (Tutoriales, 2020).
El spinner solo mostrará una de las opciones, pero al momento en que el usuario de clic en el
spinner, éste mostrará todas las opciones y el usuario podrá elegir la que desee, ver figura 26. En
otros lenguajes este control es conocido con otro nombre, por ejemplo, en aplicaciones Windows
con C# es un ComboBox, en programación web HTML es un select, etc.
Figura 26
Control Spinner
Para llenar el Spinner con las opciones del usuario, estas deberán provenir de cualquier fuente,
pero deben proporcionarse a través de un SpinnerAdapter, como un ArrayAdapter si las opciones
están disponibles en una matriz o un CursorAdapter si las opciones están disponibles en una
consulta de base de datos.
73
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Llenar un Spinner
Para llenar un Spinner vamos a utilizar el Ejercicio de Base de Datos SQLite (anterior), al cual se
agregará una nueva actividad de nombre MainActivity2 y en esta vamos agregar un control spinner
de nombre spProducto, el cual lo llenaremos con los productos que se dieron de alta en la base de
datos, como se muestra en la figura 27:
Figura 27
Spinner de Productos
<Spinner
android:id="@+id/spProducto"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_marginTop="132dp"
74
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.756"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="36dp"
android:layout_marginTop="132dp"
android:layout_marginEnd="8dp"
android:text="Producto:"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintEnd_toStartOf="@+id/spProducto"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
package com.example.appsqlite
init {
this.idp = idProd
this.nomp = NomProd
this.exist = Existencia
this.pre = Precio
}
}
75
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
package com.example.appsqlite
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.Spinner
import android.widget.Toast
76
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
while (tuplas!!.moveToNext())
{
val idp = tuplas.getInt(0) // idProd
val nomp = tuplas.getString(1) //NomProd
val exi = tuplas.getInt(2) //Existencia
val pre = tuplas.getDouble(3) //Precio
arregloProducto.add(Producto(idp,nomp,exi,pre))
arregloNomProd.add(nomp)
}
}
}
Figura 28
77
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Figura 29
78
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Recyclerview
¿Qué es RecyclerView?
La clase RecyclerView nos permite mostrar un listado (o bien una grilla) de elementos (PYM, 2017).
Lleva este nombre porque a medida que se renderizan los elementos de la lista, los elementos que
dejan de observarse se reciclan para mostrar los elementos siguientes (PyM, 2023).
Es posible personalizar un ListView para lograr lo mismo, pero implicaría considerar varios detalles,
a fin de conseguir el mismo rendimiento.
¿Qué es CardView?
Si bien un RecyclerView representa una lista de elementos, cada elemento debe tener una UI
definida.
Al usar Material Design se suele usar la clase CardView para definir la apariencia de cada
elemento de un listado, en la mayoría de los casos.
79
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Es posible usar CardViews directamente sobre un Activity o Fragment, sin situarlos al interior de
un RecyclerView.
Cuando no se requiere usar tarjetas con bordes y elevaciones, entonces se puede prescindir de la
clase CardView.
Es posible usar cualquier otro componente visual para representar al layout de cada elemento del
RecyclerView.
Figura 30
Funcionamiento de Recyclerview
80
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Llenar un Recyclerview
Para llenar un Recyclerview vamos a utilizar el ejercicio la Ejercicio 6, al cual se agregará una nueva
actividad de nombre MainActivityRecycler la cual contendrá un Recyclerview con los productos
que están almacenados en la base de datos. La figura 31 ilustra como quedara la interfaz:
Figura 31
81
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
activity_main_recycler.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:padding="20dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivityRecycler">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvProductosList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
tools:layout_editor_absoluteX="1dp"
tools:layout_editor_absoluteY="1dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
En seguida agregamos un archivo dando clic derecho en la carpeta Layout y seleccionamos “Layout
Resource File” y le ponemos el nombre celda_prototipo.xml, en este agregamos una CardView y
un LinearLayout(vertical), dentro de este último agregamos los 2 textview que vamos a desplegar
en cada elemento del RecyclerView, el código se muestra a continuación:
celda_prototipo.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_margin="10dp"
app:cardCornerRadius="40dp">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="30dp">
<TextView
android:id="@+id/tvnomProd"
82
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:layout_width="match_parent"
android:text="Alex Lora"
android:textSize="18sp"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/tvPrecio"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:text="Ing. Sistemas Computacionales"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</androidx.cardview.widget.CardView>
A continuación, agregamos una clase de kotlin de nombre Producto.kt, en esta agregamos las
propiedades y su constructor. Esta clase nos va a servir para crear una Lista de Productos y poder
llenar el RecyclerView, en seguida se muestra el código de la clase (esta clase ya la creamos en el
ejercicio anterior Llenar un Spinner):
Producto.kt
package com.example.appsqlite
init {
this.idprod = idProd
this.nomprod = NomProd
this.existencia = Existencia
this.precio = Precio
}
}
En seguida agregamos el adapter del Recyclerview. Un adapter es la clase que hace de puente
entre la vista (el recyclerview) y los datos.
Un adapter:
83
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
ProductoAdapter.kt
package com.example.appsqlite
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
//-----------------------------------------------------------
// Adaptador del RecyclerView
// Es la clase que hace de puente entre la vista
// (el recyclerview) y los datos
//
//-----------------------------------------------------------
class ProductoAdapter(private var mLista:List<Producto>,
private val mContext: Context, private val
clickListener: (Producto) -> Unit)
: RecyclerView.Adapter<ProductoAdapter.ProductoViewHolder>() {
/**
* El layout manager invoca este método para renderizar cada
elemento
*/
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int):
ProductoViewHolder {
val layoutInflater = LayoutInflater.from(mContext)
return
ProductoViewHolder(layoutInflater.inflate(R.layout.celda_prototipo,
84
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
parent, false))
}
/**
* Este método asigna valores para cada elemento de la lista
*
* @param holder Vincular los datos del cursor al ViewHolder
* @param position La posición de los datos en la lista
*/
override fun onBindViewHolder(holder: ProductoViewHolder, position:
Int) {
holder.bind(mLista[position], mContext, clickListener)
}
/**
* El método getItemCount() Cantidad de elementos del RecyclerView
*/
override fun getItemCount(): Int = mLista.size
/**
* Cuando los datos cambian, este metodo actualiza la lista de
Productos
* y notifica al adaptador a usar estos nuevos valores
*/
fun setTask(lista: List<Producto>){
mLista = lista
notifyDataSetChanged()
}
/*
* Clase interna para asignar los valores a los textView definidos
en la celda_prototipo
*/
class ProductoViewHolder (itemView: View)
:RecyclerView.ViewHolder(itemView) {
val titulo: TextView = itemView.findViewById(R.id.tvnomProd)
val subTitulo: TextView = itemView.findViewById(R.id.tvPrecio)
itemView.setOnClickListener{ clickListener(prod)}
}
}
}
85
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Por último, vamos a agregar el código del MainActivityRecycler.kt, en este propiamente manda
ejecutar la consulta a la base de datos y en seguida se llena una Lista de estudiantes y esta se le da
al adaptador para llenar el RecyclerView:
MainActivityRecycler.kt
package com.example.appsqlite
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
rvProdList.apply {
setHasFixedSize(true)
layoutManager = viewManager
adapter = viewAdapter
addItemDecoration(DividerItemDecoration(this@MainActivityRecycler,
DividerItemDecoration.VERTICAL))
}
86
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
// 0 1 2
3
val tupla = admin.Consultar("SELECT
idProd,NomProd,Existencia,Precio FROM Producto ORDER BY nomProd")
while (tupla!!.moveToNext()) {
val idp = tupla.getString(0).toInt()
val nomp = tupla.getString(1)
val exi = tupla.getString(2).toInt()
val pre = tupla.getInt(3).toDouble()
ListaProductos.add(Producto(idp,nomp,exi,pre))
}
tupla.close()
admin.close()
return ListaProductos
}
}
87
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
La figura 32 ilustra como se ve la aplicación una vez que presionamos clic en el botón de llenar
recyclerview:
Figura 32
88
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Objetivo
El estudiante aprenderá a usar servicios web para que intercambiar información entre las
aplicaciones móviles y servidores web.
Introducción
Esta práctica tiene como fin comprender el uso de los servicios web para el intercambio de
información entre aplicaciones.
Metodología
El estudiante deberá leer el siguiente material previo a la elaboración de la práctica:
89
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Servicios Web
Figura 33
Un Web Service o Servicio Web es una aplicación que facilita la comunicación entre varios sistemas
independientemente del lenguaje de programación o plataforma en que fueron desarrollados,
como se observa en la figura 33. Este debe tener una interfaz basada en un formato estándar
entendible por las maquinas como lo es XML o JSON.
Dos alternativas para programar los servicios web SOAP(XML) o REST(Json) (Naeem, 2020).
90
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
creado por Dave Winer en 1998, llamado XML-RPC. SOAP fue creado por Microsoft, IBM y otros.
Está actualmente bajo el auspicio de la W3C.
REST es una interfaz para conectar varios sistemas basados en el protocolo HTTP (uno de los
protocolos más antiguos) y nos sirve para obtener y generar datos y operaciones, devolviendo esos
datos en formatos muy específicos, como XML y JSON.
El formato más usado en la actualidad es el formato JSON, ya que es más ligero y legible en
comparación al formato XML. Elegir uno será cuestión de la lógica y necesidades de cada proyecto.
REST se apoya en HTTP, los verbos que utiliza son exactamente los mismos, con ellos se puede
hacer GET, POST, PUT y DELETE. De aquí surge una alternativa a SOAP.
Cuando hablamos de SOAP hablamos de una arquitectura divididas por niveles que se utilizaba
para hacer un servicio, es más complejo de montar como de gestionar y solo trabajaba con XML.
Ahora bien, REST llega a solucionar esa complejidad que añadía SOAP, haciendo mucho más fácil
el desarrollo de una API REST, en este caso de un servicio en el cual nosotros vamos a almacenar
nuestra lógica de negocio y vamos servir los datos con una serie de recursos URL y una serie de
datos que nosotros los limitaremos, es decir, será nuestro BACKEND nuestra lógica pura de
negocios que nosotros vamos a utilizar.
JSON (JavaScript Object Notation) es un formato para el intercambio de datos, básicamente JSON
describe los datos con una sintaxis dedicada que se usa para identificar y gestionar los datos. JSON
91
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
nació como una alternativa a XML, el fácil uso en javascript ha generado un gran número de
seguidores de esta alternativa. Una de las mayores ventajas que tiene el uso de JSON es que puede
ser leído por cualquier lenguaje de programación. Por lo tanto, puede ser usado para el
intercambio de información entre distintas tecnologías.
Imaginemos que tenemos una frutería y que queremos obtener el nombre y la cantidad de fruta y
verdura que tenemos. En un principio vamos a suponer que tenemos lo siguiente:
Ø Fruta:
• 10 manzanas
• 20 peras
• 30 naranjas
Ø Verduras
• 80 lechugas
• 15 tomates
• 50 pepinos
Para asignar a un nombre un valor debemos usar los dos puntos ':' este separador es el
equivalente al igual ('=') de cualquier lenguaje.
Los tipos de valores que podemos encontrar en Json son los siguientes:
92
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Objetos JSON
Los objetos JSON se identifican entre llaves, un objeto puede ser en nuestro caso una fruta
o una verdura.
{ "NombreFruta":"Manzana" , "Cantidad":20 }
Arrays JSON
En un JSON puedes incluir arrays, para ellos el contenido del array debe ir entre corchetes
[ ]:
"Frutas": [
{ "NombreFruta":"Manzana" , "cantidad":10 },
{ "NombreFruta":"Pera" , "cantidad":20 },
{ "NombreFruta":"Naranja" , "cantidad":30 }
93
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Una vez explicado el funcionamiento de la sintaxis JSON, vamos a aplicar nuestro ejemplo
de la frutería:
{"Fruteria":
[
{"Fruta":
[
{"Nombre":"Manzana","Cantidad":10},
{"Nombre":"Pera","Cantidad":20},
{"Nombre":"Naranja","Cantidad":30}
},
{"Verdura":
{"Nombre":"Lechuga","Cantidad":80},
{"Nombre":"Tomate","Cantidad":15},
{"Nombre":"Pepino","Cantidad":50}
Como podemos observar, hemos creado un objeto llamado frutería y, dentro de ese objeto
hemos almacenado un array de dos elementos. El primer elemento del array contiene un
94
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
objeto llamado fruta y el segundo elemento del array contiene otro objeto llamado
verdura. Estos objetos a su vez contienen un array cuyo contenido es el nombre y la
cantidad de cada fruta o verdura.
Existen herramientas online que ayudan a visualizar mejor un JSON. Una de las mejores
herramientas es la página JSON Viewer, como se observa en la figura 34. Si introducimos
nuestro ejemplo observamos lo siguiente:
Figura 34
Visor de JSON
REST no es solo una moda, y es por las siguientes razones que esta interfaz está teniendo
tanto protagonismo en los últimos años:
• Crea una petición HTTP que contiene toda la información necesaria, es decir, un
REQUEST a un servidor tiene toda la información necesaria y solo espera una
RESPONSE, ósea una respuesta en concreto.
95
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
• Se apoya sobre un protocolo que es el que se utiliza para las páginas web, que es
HTTP, es un protocolo que existe hace muchos años y que ya está consolidado, no
se tiene que inventar ni realizar cosas nuevas.
• Todos los objetos se manipulan mediante URI, por ejemplo, si tenemos un recurso usuario
y queremos acceder a un usuario en concreto nuestra URI seria
/user/identificadordelobjeto, con eso ya tendríamos un servicio USER preparado para
obtener la información de un usuario, dado un ID.
Ventajas de REST
• Nos permite separar el cliente del servidor. Esto quiere decir que nuestro servidor se puede
desarrollar en Node y Express, y nuestra API REST con Vue por ejemplo, no tiene por qué
estar todos dentro de un mismo.
• En la actualidad tiene una gran comunidad como proyecto en Github.
• Podemos crear un diseño de un microservicio orientado a un dominio (DDD)
• Es totalmente independiente de la plataforma, así que podemos hacer uso de REST tanto
en Windows, Linux, Mac o el sistema operativo que nosotros queramos.
• Podemos hacer nuestra API pública, permitiendo darnos visibilidad si la hacemos pública.
• Nos da escalabilidad, porque tenemos la separación de conceptos de CLIENTE y SERVIDOR,
por tanto, podemos dedicarnos exclusivamente a la parte del servidor.
96
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Muchas empresas como Twitter, Facebook, Google, Netflix, LinkedIn y miles de startups y
empresas usan REST. Todos estas empresas y servicios tienen su API REST por un lado con su lógica
de negocio y por otro lado su parte front-end, con lo cual nos permite centrarnos también un poco
más en lo que es nuestra lógica de negocio haciendo una API REST potente.
Los servicios web responden con códigos de estado de respuesta HTTP, los cuales indican si se ha
completado satisfactoriamente una solicitud HTTP específica. Las respuestas se agrupan en cinco
clases:
200 OK. La solicitud ha tenido éxito. El significado de un éxito varía dependiendo del
método HTTP:
201 Created. La solicitud ha tenido éxito y se ha creado un nuevo recurso como resultado
de ello. Ésta es típicamente la respuesta enviada después de una petición PUT.
Redirecciones (300–399)
400 Bad Request. Esta respuesta significa que el servidor no pudo interpretar la solicitud
dada una sintaxis inválida.
97
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
404 Not Found. El servidor no pudo encontrar el contenido solicitado. Este código de
respuesta es uno de los más famosos dada su alta ocurrencia en la web.
500 Internal Server Error. El servidor ha encontrado una situación que no sabe cómo
manejarla.
501 Not Implemented. El método solicitado no está soportado por el servidor y no puede
ser manejado. Los únicos métodos que los servidores requieren soporte (y por lo tanto no
deben retornar este código) son GET y HEAD.
98
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Figura 35
Tabla de Producto
Una vez creada la tabla vamos a insertar unos 8 productos, como a continuación se muestra:
A continuación, creamos dentro de la carpeta de htdocs una carpeta de nombre WSAndroid, con
los siguientes servicios web:
99
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Figura 36
{“idprod”: “2”} {
getProducto.php "success": 200,
"message": "Registro encontrado",
"productos": [
{
"idp": "4",
"nom": "Moto Bomba",
"exi": "5",
"pre": "450.00"
}
]
}
getProducto.php
<?php
/*
* El siguiente código localiza un producto
* AGZ Junio 2023
*/
$Cn = mysqli_connect("localhost","root","","android")or die ("server no
encontrado");
mysqli_set_charset($Cn,"utf8");
if ($_SERVER['REQUEST_METHOD']== "POST"){
$objson = json_decode(file_get_contents("php://input"), true);
$idp = $objson["idprod"];
$sentencia = "Select idProd idp,nomProd nom,existencia exi,Precio pre
From Producto Where idProd =$idp";
$res = mysqli_query($Cn,$sentencia);
100
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
if (mysqli_num_rows($res)>0){
$respuesta["success"] = 200;
$respuesta["message"] = "Registro encontrado";
$respuesta["productos"] = array();
$tupla = mysqli_fetch_array($res,MYSQLI_ASSOC);
$respuesta["productos"] = $tupla;
}
else{
$respuesta["success"] = 404;
$respuesta["message"] = "No hay registros";
}
}
else{
$respuesta["success"] = 400;
$respuesta["message"] = "Método incorrecto";
}
echo json_encode($respuesta);
mysqli_close($Cn);
?>
Para probar el servicio web, vamos a usar el software Insomnia, como se muestra en la figura 37:
Figura 37
101
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Servicio web getProductos.php, este se encarga de regresar todos los productos que hay en la base
de datos en formato JSON, la figura 38 ilustra las salidas en formato JSON:
Figura 38
getProductos.php {
"success": 200,
"message": "Registros encontrados",
"productos": [
{
"idp": "2",
"nom": "Desarmador Plano",
"exi": "12",
"pre": "50.00"
},
{
"idp": "1",
"nom": "Taladro",
"exi": "7",
"pre": "850.00"
}
]
}
getProductos.php
<?php
/*
* El siguiente código consulta todos los productos
* AGZ Junio 2023
*/
$Cn = mysqli_connect("localhost","root","","android")or die ("server no
encontrado");
mysqli_set_charset($Cn,"utf8");
if ($_SERVER['REQUEST_METHOD']== "POST"){
$sentencia = "Select idProd idp,nomProd nom,existencia exi,Precio pre
From Producto Order by nomProd";
$res = mysqli_query($Cn,$sentencia);
if (mysqli_num_rows($res)>0){
$respuesta["success"] = 200;
102
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Figura 39
103
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Servicio web insertProducto.php. este servicio web recibe los datos de unproducto en formato
JSON y los inserta en la base de datos, regresando el estado de la ejecución del servicio. La figura
40 ilustra las entradas y salidas del servicio web:
Figura 40
"exi": "12", }
"pre": "150.00"
}
Nota: Representación de las entradas y salidas del servicio web insertProducto.php
insertProducto.php
<?php
/*
* El siguiente código Inserta un producto
* AGZ Junio 2023
*/
$Cn = mysqli_connect("localhost","root","","android")or die ("server no
encontrado");
mysqli_set_charset($Cn,"utf8");
if ($_SERVER['REQUEST_METHOD']== "POST"){
$objson = json_decode(file_get_contents("php://input"), true);
$nom = $objson["nom"];
$exi = $objson["exi"];
$pre = $objson["pre"];
$sentencia = "Insert into Producto(nomProd,existencia,Precio)
values ('$nom',$exi,$pre)";
$res = mysqli_query($Cn,$sentencia);
if ($res){
$respuesta["success"] = 200;
$respuesta["message"] = "Registro Insertado";
$respuesta["id"]=$Cn->insert_id;
} else {
104
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
$respuesta["success"] = 404;
$respuesta["message"] = "No se inserto el Producto";
}
}
else{
$respuesta["success"] = 400;
$respuesta["message"] = "Método incorrecto";
}
echo json_encode($respuesta);
mysqli_close($Cn);
?>
Figura 41
105
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Servicio web updateProducto.php, que recibe los datos de un producto en formato JSON y lo
actualiza en la base de datos, regresando el estado de la ejecución. La figura 42 ilustra lasentradas
y salidas del servicio web:
Figura 42
"exi": "12", }
"pre": "150.00"
}
Nota: Representación de las entradas y salidas del servicio web updateProducto.php
updateProducto.php
<?php
/*
* El siguiente código Actualiza un producto
* AGZ Junio 2023
*/
$Cn = mysqli_connect("localhost","root","","android")or die ("server no
encontrado");
mysqli_set_charset($Cn,"utf8");
if ($_SERVER['REQUEST_METHOD']== "POST"){
$objson = json_decode(file_get_contents("php://input"), true);
$idp = $objson["idp"];
$nom = $objson["nom"];
$exi = $objson["exi"];
$pre = $objson["pre"];
$sentencia = "Update Producto set
nomProd='$nom',existencia=$exi,Precio=$pre Where idProd=$idp";
$res = mysqli_query($Cn,$sentencia);
if ($res){
if (mysqli_affected_rows($Cn) > 0){
$respuesta["success"] = 200;
$respuesta["message"] = "Registro Actualizado";
106
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
}
else{
$respuesta["success"] = 404;
$respuesta["message"] = "No se actualizo el Producto";
}
} else {
$respuesta["success"] = 404;
$respuesta["message"] = "No se actualizo el Producto";
}
}
else{
$respuesta["success"] = 400;
$respuesta["message"] = "Método incorrecto";
}
echo json_encode($respuesta);
mysqli_close($Cn);
?>
Figura 43
107
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Figura 44
{“idp”: “8”} {
"success": 200,
deleteProducto.php "message": "Registro Eliminado",
deleteProducto.php
<?php
/*
* El siguiente código Elimina un producto
* AGZ Junio 2023
*/
$Cn = mysqli_connect("localhost","root","","android")or die ("server no
encontrado");
mysqli_set_charset($Cn,"utf8");
if ($_SERVER['REQUEST_METHOD']== "POST"){
$objson = json_decode(file_get_contents("php://input"), true);
$idp = $objson["idp"];
108
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
}
else{
$respuesta["success"] = 400;
$respuesta["message"] = "Método incorrecto";
}
echo json_encode($respuesta);
mysqli_close($Cn);
?>
Figura 45
109
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Servicio web resProductos.php, este recibe un JSON con los productos y los inserta en la base de
datos. La figura 46 ilustra las entradas y salidas del servicio web:
Figura 46
{ {
"correo": "agz@gmail.com", resProductos.php "success": 200,
"contra": "hola", "message": "Se Respaldaron Correctamente"
"productos": [ }
{
"idp": "2",
"nom": "Desarmador Plano ",
"exi": "12",
"pre": "50.00"
},
{
"idp": "3",
"nom": "Martillo",
"exi": "8",
"pre": "45.00"
}
}
Nota: Representación de las entradas y salidas del servicio web resProductos.php
resProductos.php
<?php
/*
* El siguiente recibe un Json con los productos del dispositivo
* y los inserta en mysql con la finalidad de respaldarlos
* AGZ Junio 2023
*/
$Cn = mysqli_connect("localhost","root","","android")or die ("server no
encontrado");
mysqli_set_charset($Cn,"utf8");
header('Content-type: application/json; charset=utf-8');
if ($_SERVER['REQUEST_METHOD']== "POST"){
$response = array();
$obj = json_decode( file_get_contents('php://input'),true );
$objArr = (array)$obj;
if (empty($objArr))
{
$response["success"] = 422; //No encontro información
$response["message"] = "Error: checar json de entrada";
}
else
110
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
{
$Productos = array();
$corr= $objArr['correo'];
$cont= $objArr['contra'];
$Productos= $objArr['productos'];
Figura 47
En este punto podemos confiar en que nuestros servicios web están funcionando, ahora solo falta
probarlos desde Android.
112
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Aplicación en Android
implementation 'com.android.volley:volley:1.2.0'
Ahora vamos a editar el archivo de AndroidManifest.xml y agregamos los permisos para que
nuestra aplicación pueda acceder a internet, el archivo se muestra a continuación:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myproducts">
<uses-permission android:name="android.permission.INTERNET">
</uses-permission>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
113
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
</manifest>
A continuación, nos ubicamos en la carpeta de los archivos de Kotlin de nuestro proyecto(ver figura
48) y agregaremos una clase de kotlin de nombre VolleySingleton:
Figura 48
VolleySingleton.kt
package com.example.myapplicationws
import android.content.Context
import com.android.volley.Request
import com.android.volley.RequestQueue
import com.android.volley.toolbox.Volley
114
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
@Volatile
private var INSTANCE: VolleySingleton? = null
fun getInstance(context: Context) =
INSTANCE ?: synchronized(this) {
INSTANCE ?: VolleySingleton(context).also {
INSTANCE = it
}
}
}
Esta clase implementa el patrón de diseño singleton, el cual nos permite generar una sola instancia
de la clase volley, siendo más eficiente de esta manera.
El código del layout del activity_main.xml se muestra a continuación:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Catálogo de Productos"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintVertical_bias="0.06"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
/>
<EditText
android:id="@+id/etIdProd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
115
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
android:layout_marginTop="24dp"
android:ems="10"
android:hint="Clave Producto"
android:inputType="numberSigned"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.858"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
<EditText
android:id="@+id/etPrecio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="56dp"
android:ems="10"
android:hint="Precio"
android:inputType="numberDecimal"
android:text="0"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.858"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/etNomProd" />
<EditText
android:id="@+id/etExistencia"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:hint="Existencia"
android:inputType="numberSigned"
android:text="0"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.853"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/etPrecio"
app:layout_constraintVertical_bias="0.129" />
<EditText
android:id="@+id/etNomProd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="44dp"
android:ems="10"
android:hint="Nombre Producto"
android:inputType="textPersonName"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.858"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/etIdProd" />
<Button
android:id="@+id/btnBorrar"
android:layout_width="wrap_content"
116
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="8dp"
android:text="Borrar"
android:onClick="Borrar"
app:layout_constraintEnd_toStartOf="@+id/btnActualizar"
app:layout_constraintHorizontal_bias="0.485"
app:layout_constraintStart_toEndOf="@+id/btnAgregar"
app:layout_constraintTop_toBottomOf="@+id/etExistencia" />
<Button
android:id="@+id/btnAgregar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="48dp"
android:layout_marginTop="20dp"
android:onClick="Agregar"
android:text="Agregar"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/etExistencia" />
<Button
android:id="@+id/btnLimpiar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginEnd="100dp"
android:text="Limpiar"
android:onClick="Limpiar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btnBorrar" />
<Button
android:id="@+id/btnActualizar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginEnd="28dp"
android:onClick="Actualiza"
android:text="Actualizar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/etExistencia" />
<Button
android:id="@+id/btnConsultar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="100dp"
android:layout_marginTop="20dp"
android:onClick="Consultar"
android:text="Consultar"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btnBorrar" />
117
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
<Button
android:id="@+id/btnCarga"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="8dp"
android:onClick="getAllProductos"
android:text="Carga Productos"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.476"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btnConsultar" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="112dp"
android:text="Clave Producto:"
app:layout_constraintEnd_toStartOf="@+id/etIdProd"
app:layout_constraintHorizontal_bias="0.328"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="72dp"
android:text="Nombre Producto:"
app:layout_constraintEnd_toStartOf="@+id/etNomProd"
app:layout_constraintHorizontal_bias="0.432"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView2" />
<TextView
android:id="@+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="64dp"
android:text="Precio:"
app:layout_constraintEnd_toStartOf="@+id/etPrecio"
app:layout_constraintHorizontal_bias="0.253"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView3" />
<TextView
android:id="@+id/textView5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="60dp"
android:text="Existencia:"
118
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
app:layout_constraintEnd_toStartOf="@+id/etExistencia"
app:layout_constraintHorizontal_bias="0.316"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView4" />
<Button
android:id="@+id/btnRespaldar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="163dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="154dp"
android:onClick="btnRespaldar"
android:text="Respaldar Productos"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btnCarga" />
</androidx.constraintlayout.widget.ConstraintLayout>
Figura 49
Interfaz de la aplicación
119
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Ahora agregamos una clase de Kotlin de nombre AdminBD, para gestionar la base de datos del
dispositivo, el código se muestra a continuación:
AdminBD.kt
package com.example.myapplicationws
import android.content.Context
import android.database.Cursor
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
import java.lang.Exception
120
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
MainActivity.kt
package com.example.myapplicationws
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.TextView
import android.widget.Toast
import com.android.volley.Request
import com.android.volley.Response
import com.android.volley.toolbox.JsonObjectRequest
import com.google.android.material.textfield.TextInputEditText
import org.json.JSONArray
import org.json.JSONObject
121
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
val idprod =
sensadoJson.getJSONObject(i).getString("idp")
val nomprod =
sensadoJson.getJSONObject(i).getString("nom")
val existencia =
sensadoJson.getJSONObject(i).getString("exi")
val precio =
sensadoJson.getJSONObject(i).getString("pre")
VolleySingleton.getInstance(this).addToRequestQueue(jsonObjectRequest)
}
122
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
123
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
}
}
sendRequest(IP + "/Android/deleteProducto.php",jsonEntrada)
}
}
VolleySingleton.getInstance(this).addToRequestQueue(jsonObjectRequest)
}
124
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
while (tuplas!!.moveToNext())
{
var productoJson = JSONObject()
productoJson.put("idp", tuplas.getInt(0))
productoJson.put("nom", tuplas.getString(1))
productoJson.put("exi", tuplas.getInt(2))
productoJson.put("pre", tuplas.getDouble(3))
jsonArray.put(productoJson)
}
jsonParam.put("productos", jsonArray)
putProductos(jsonParam)
}
VolleySingleton.getInstance(this).addToRequestQueue(jsonObjectRequest)
}
}
125
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Nota: Si no corre, cheque la dirección del servidor web y actualice en el Mainactivity.kt, de igual
manera asegúrese que el dispositivo en donde se corre la app este en la misma red que el servidor
web.
a.) Reporte escrito: El estudiante deberá presentar un reporte escrito con el avance de su
proyecto, aplicando los servicios web.
b.) Rubrica de evaluación:
Todos los párrafos La mayor parte de Los párrafos incluyen La estructura del
incluyen una los párrafos incluye información párrafo no estaba
Construcción de introducción, una introducción, relacionada pero no clara y las oraciones
Párrafos explicaciones o explicaciones o fueron generalmente no estaban
detalles y una detalles y una bien organizados. generalmente
conclusión. conclusión. relacionadas.
No hay errores de Casi no hay errores Unos pocos errores Muchos errores de
gramática, ortografía o de gramática, de gramática, gramática, ortografía o
puntuación. ortografía o ortografía o puntuación.
Redacción puntuación. puntuación.
126
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Todos los temas Todos los temas Todos los temas Uno o más temas no
tratados y todas las tratados y la mayor tratados y la mayor están tratados.
Cantidad de preguntas fueron parte de las parte de las
Información contestadas en al preguntas fueron preguntas fueron
menos 2 oraciones. contestadas en al contestadas en 1
menos 2 oraciones. oración.
127
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Objetivo
El estudiante aprenderá a generar informes pdf en Android.
Introducción
Esta práctica es opcional y deberá usarla si su proyecto final requiere la generación de informes
en pdf.
Metodología
El estudiante deberá leer el siguiente material y enseguida implementarla en Android Estudio:
128
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
En este ejemplo vamos a abordar como crear un archivo PDF, que incluya títulos, subtitulos, tablas,
marcas de agua, imágenes, fecha de creación y demás objetos característicos de estos
documentos. Para su creación, este ejemplo se apoya en la librería droidText.0.4. jar
implementada en Android Studio. iText. Creamos un nuevo Proyecto de nombre MyApplicationPDF
y agregamos los permisos al AndroidManifest, para leer y escribir en el dispositivo:
Enseguida se va a crear nuestra interface el cual consistirá en una caja de texto de nombre etTexto
y un botón al que llamaremos btnGenerar, la figura 50 la ilustra:
Figura 50
129
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<EditText
android:id="@+id/etTexto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="8dp"
android:ems="10"
android:hint="TEXTO"
android:inputType="textMultiLine"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btnGenerar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="8dp"
android:text="Generar pdf"
android:onClick="btnGenerar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/etTexto" />
</androidx.constraintlayout.widget.ConstraintLayout>
Ahora antes de empezar con el código, tendremos que utilizar una librería de tipo .jar el cual nos
permitirá utilizar colores tipo de letras y demás herramientas para crear nuestro archivo pdf.
Descarga la siguiente librería: droidText0.4.jar, dando clic en este vínculo.
Esta librería debe estar dentro de la carpeta lib, para ello en el paso 1 seleccionemos Project,
enseguida entra a la carpeta app, después copia la librería droidText.0.4.jar dentro de la carpeta
libs, como se ilustra en la figura 51:
130
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Figura 51
Después tenemos que agregar la siguiente línea a nuestro Modulo de build.gradle al final de las
dependencies.
implementation files('libs/droidText.0.4.jar')
Debes agregar una imagen pequeña con el nombre logo.png dentro de tu carpeta Drawable como
lo muestra la figura 52:
131
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Figura 52
Ubicación de la imagen
132
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
setContentView(R.layout.activity_main)
etText = findViewById<EditText>(R.id.etTexto)
fun crearPDF() {
// Creamos el documento.
val documento = Document()
try {
// Creamos el flujo de datos de salida para el fichero donde
// guardaremos el pdf.
val file: File? = crearFichero(NOMBRE_DOCUMENTO)
val ficheroPDF = FileOutputStream(file!!.absoluteFile)
val writer = PdfWriter.getInstance(documento, ficheroPDF)
documento.setHeader(cabecera)
documento.setFooter(pie)
documento.open()
133
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
documento.add(Paragraph("TABLA \n\n"))
documento.add(
Paragraph(
"""
${etText.text}
""".trimIndent()
)
)
ColumnText.showTextAligned(writer.directContentUnder,Element.ALIGN_CENTER,
Paragraph("www.tecnm.mx",font2), 297.5f, 421f, if (writer.pageNumber % 2
=== 1) 45.0f else -45.0f)
134
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
/**
* Obtenemos la ruta donde vamos a almacenar el fichero.
*
* @return
*/
fun getRuta(): File? {
var ruta: File? = null
if
(Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()))
{
ruta = File(getExternalFilesDir(null), NOMBRE_DIRECTORIO)
if (ruta != null) {
if (!ruta.mkdirs()) {
if (!ruta.exists()) {
return null
}
}
}
}
return ruta
}
}
Para localizar el reporte hay que abrir el Device File Explorer como se muestra en la figura 53:
Figura 53
Nota: Ubicación del archivo pdf en el Device File Explorer de Android Estudio
135
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
En la ruta: /storage/emulated/0/Android/data/com.example.myapplicationpdf/files/MisPDFs
La figura 54 ilustra el reporte que se genero:
Figura 54
A continuación, con la finalidad de abrir directamente el archivo pdf, agregaremos los siguientes
cambios:
Agregamos un archivo a la carpeta XML de res, dando clic derecho – new – XML Resource File,
como se muestra en la figura 55:
136
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Figura 55
El texto en rojo debe ser cambiado por que es el nombre del proyecto en minúsculas.
137
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
<provider
android:authorities="${applicationId}.provider"
android:name="androidx.core.content.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>
</manifest>
138
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Objetivo
El estudiante aprenderá a generar gráficas en Android.
Introducción
Esta práctica es opcional y deberá usarla si su proyecto final requiere la generación de una
gráfica.
Metodología
El estudiante deberá leer el siguiente material y enseguida implementarla en Android Estudio:
139
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Figura 56
En primer lugar, vamos a crear un nuevo proyecto de nombre AppGrafica, con una actividad vacía.
Enseguida vamos a importar las librerías al archivo build.gradle(Module:app), para es esto vamos
agregar el siguiente(líneas resaltadas en amarillo), en la sección de dependencias:
dependencies {
implementation fileTree(dir:"libs", include:["*.jar"])
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.5.1'
implementation 'com.google.android.material:material:1.7.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.4'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0'
implementation 'com.github.PhilJay:MPAndroidChart:v2.2.4'
140
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Y le damos sincronizar en la esquina superior derecha, para proceder a descargarlas las librerías de
internet.
141
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="numberDecimal"
android:ems="10"
android:id="@+id/etVtas" app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="8dp" app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="8dp" app:layout_constraintTop_toBottomOf="@+id/etNom"
android:layout_marginTop="80dp" tools:text="0" android:hint="Importe Ventas"/>
<Button
android:text="Guardar"
android:layout_width="wrap_content"
android:layout_height="wrap_content" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:id="@+id/gtnGuardar" app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="8dp"
app:layout_constraintEnd_toStartOf="@+id/btnGraficar" android:layout_marginEnd="8dp"
android:onClick="guardarClic" tools:text="Guardar"/>
<Button
android:text="Graficar"
android:layout_width="wrap_content"
android:layout_height="wrap_content" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:id="@+id/btnGraficar" app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="60dp"
app:layout_constraintVertical_bias="0.499" android:onClick="graficaClic"/>
</androidx.constraintlayout.widget.ConstraintLayout>
Agregamos una nueva actividad vacía de nombre MainActivityGrafica y una clase de Kotlin de
nombre AdminBD.
142
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
143
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
La llave primaria es _id y el guion bajo indica que ese campo es auto numérico.
En seguida mostramos el código del MainActivity.kt:
package com.example.myapplicationgrafica
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.EditText
import android.widget.Toast
fun graficaClic(v:View){
val intGraf = Intent(this, MainActivityGrafica::class.java)
startActivity(intGraf)
}
144
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Es importante agregar unos empleados con sus Ventas, para tener información que graficar, de lo
contrario el botón de Graficar no mostrara nada.
<com.github.mikephil.charting.charts.BarChart
android:id="@+id/barChart"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
145
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
import com.github.mikephil.charting.data.BarEntry
import com.github.mikephil.charting.utils.ColorTemplate
barChart = findViewById<BarChart>(R.id.barChart)
cargarDatos()
setBarChart()
}
fun cargarDatos(){
val admin = AdminBD(this)
cursor = admin.Consulta("Select * from Empleado Order by
Ventas")
}
fun setBarChart() {
var i: Int = 0
if (cursor!!.moveToFirst()){
do {
val nom = cursor!!.getString(1)
val vtas = cursor!!.getFloat(2)
entries.add(BarEntry(vtas,i )) // Agregamos Ventas
labels.add(nom) // Agregamos nomEmp
i++
} while (cursor!!.moveToNext())
val barDataSet = BarDataSet(entries, "Datos")
val data = BarData(labels,barDataSet)
barChart.data = data
barDataSet.setColors(ColorTemplate.JOYFUL_COLORS,250)
barDataSet.valueTextColor = Color.BLACK
barDataSet.valueTextSize = 15f
barChart.animateY(5000)
}
}
}
146
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Figura 58
147
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Objetivo
El estudiante aprenderá a usar los mapas en Android y colocar marcas.
Introducción
Esta práctica es opcional y deberá usarla si su proyecto final requiere el uso de mapas.
Metodología
El estudiante deberá leer el siguiente material y enseguida implementarla en Android Estudio:
148
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Google Maps, es una herramienta que es capaz de hacer muchas más cosas que se ven simples a
la vista. En este tema vamos a crear nuestro primer mapa en Android y añadiremos un marcador.
Debemos crear un proyecto en Google Cloud, para entrar da clic a este vínculo. Si es
necesario entra con una cuenta de Google y su respectiva contraseña. Una vez accedas a este,
verás que en la esquina superior derecha podemos crear un nuevo proyecto. Haremos clic y
seleccionaremos un nombre. No es necesario seleccionar Ubicación, como se muestra en la figura
59:
Figura 59
Ya creado el proyecto, en el menú lateral seleccionaremos APIs y servicios y una vez dentro en la
parte superior pulsamos HABILITAR APIS Y SERVICIOS. Apareceremos en un buscador donde están
todas las APIs de Google, en nuestro caso tenemos que buscar Maps SDK for Android, como se
observa en la figura 60:
149
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Figura 60
Seleccionamos el API y dentro nos saldrá un botón azul para habilitarla, pulsamos en HABILITAR.
Ya tenemos habilitado los mapas en Android en nuestro proyecto, el siguiente paso será generar
una API KEY que deberemos añadir en nuestro proyecto. Para ello volvemos al panel de control de
nuestro proyecto de Google Cloud y esta vez hacemos clic en el menú lateral APIs y servicios >
Credenciales, como se observa en la figura 61.
Figura 61
150
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Figura 62
Creamos un nuevo proyecto, con el nombre My Project Android. Como siempre seleccionaremos
empty activity (Guimerá, Google Maps en Android con Kotlin, 2020).
Para poder utilizar Google Maps dentro de nuestro proyecto tenemos que añadir una librería, así
que iremos a Build.Gradle y dentro de la sección dependencies añadimos la siguiente línea.
implementation 'com.google.android.gms:play-services-maps:18.0.0'
A continuación damos clic en Sync Now (esquina superior derecha), para iniciar la descarga de las
librerías, ya que termino la sincronización, vamos a proceder a añadir el api key que creamos. En
seguida vamos agregar un archivo de tipo Values Resource File, en la carpeta res>values, de
nombre google_maps_api.xml.
151
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Figura 63
Una vez creado el recurso, debemos indicarle a nuestro proyecto android que ya tenemos una api
key válida, es por ello que iremos al fichero AndroidManifest.xml y dentro de la etiqueta
<application> añadiremos nuestra la referencia al archivo gogle_maps_api, como se indica en el
siguiente código resaltado en amarillo:
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.MyProjectAndroid"
tools:targetApi="31">
152
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="@string/google_maps_key" />
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
En seguida trabajaremos con el diseño de la aplicación para ello entremos al código del
activity_main.xml y sustituiremos el contenido del layout que nos viene por defecto por un
componente fragment, el siguiente código muestra cómo debe quedar:
A continuación vamos a crear un fragment desde el layout, pero le estamos diciendo que sea de
tipo com.google.android.gms.maps.SupportMapFragment, que es un fragment que viene dentro
de la librería que instalamos anteriormente.
En seguida trabajaremos con el código de Kotlin “MainActivity.kt”. en primer lugar vamos a crear
una función llamada createMapFragment() que será la encargada de inicializar el fragment que
hemos creado en el layout. Esta función la llamaremos desde el método onCreate().
153
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
createMapFragment()
}
Creamos una variable y le decimos a supportFragmentManager que busque un fragment que tenga
una id llamada fragmentMap, que será la id del fragment que añadimos en activity_main.xml, luego
a nuestra variable que contiene un SupportMapFragment (fragment de tipo mapa) la inicializamos
con la función getMapAsync(this).
Hay un error en la última línea de la función. Esto es porque getMapAsync(this) necesita que
nuestra activity implemente la función onMapReady() y para ello tenemos que añadir la interfaz
OnMapReadyCallback en la declaración de la clase.
Esta interfaz que hemos implementado nos obliga a sobrescribir la función onMapReady(), que se
llamará automáticamente cuando el mapa haya cargado. Es por eso que nuestra activity nos marca
un error, pues no hemos sobrescrito el método todavía.
Esta función nos devolverá un objeto GoogleMap que será muy útil, es por ello que debemos
guardarlo en una variable. Para ello creamos una variable en la parte superior de la clase y le
asignaremos el objeto GoogleMap cuando lo recibamos.
154
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Google nos permite añadir markers, pequeñas etiquetas para marcar un lugar a través
de sus coordenadas. Para ello crearemos una nueva función de nombre createMarker()
que la llamaremos cuando el método onMapReady() se ejecute.
Los markers se crean de una forma muy sencilla, basta con crear una instancia de un objeto
LatLng() que recibirá dos parámetros, la latitud y la longitud. Para este ejemplo se han colocado las
coordenadas del TecNm en Roque.
Una vez creado el objeto con las coordenadas, llamaremos a nuestro mapa y con la función
addMarker() le añadiremos:
MarkerOptions().position(favoritePlace).title(“TecNm en Roque”)
simplemente le hemos puesto las coordenadas anteriormente creadas y hemos asignado un title
que se mostrará cuando el usuario pulse el marker. El title es opcional.
Terminaremos añadiendo una animación para que el mapa haga zoom donde creamos el marker.
map.animateCamera(CameraUpdateFactory.newLatLngZoom(coordenadas,18f),
4000,
null
)
155
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Un CameraUpdateFactory que a su vez llevará otros dos parámetros, el primero las coordenadas
donde queremos hacer zoom y el segundo valor (es un float) será la cantidad de zoom que
queremos hacer en dichas coordenadas.
package com.example.myprojectandroid
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.google.android.gms.maps.CameraUpdateFactory
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.OnMapReadyCallback
import com.google.android.gms.maps.SupportMapFragment
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.MarkerOptions
map.animateCamera(CameraUpdateFactory.newLatLngZoom(coordenadas,18f),
4000,
156
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
null
)
}
}
Figura 64
157
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Objetivo
El estudiante aprenderá a usar obtener la geolocalización del dispositivo móvil en tiempo real.
Introducción
Esta práctica es opcional y deberá usarla si su proyecto final requiere el uso de mapas.
Metodología
El estudiante deberá leer el siguiente material y enseguida implementarla en Android Estudio:
Para este ejercicio utilizaremos el código del ejercicio “12. Mapas y marcas” (Guimerá, Google
Maps en Android con Kotlin [Parte 2] – Localización en tiempo real, 2021).
158
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Al proyecto anterior le vamos a agregar 3 nuevos permisos, ya que obviamente si queremos saber
la localización en tiempo real tendremos que tener acceso a dicha localización a través del permiso.
Iremos al AndroidManifest.xml y añadiremos los permisos resaltados en amarillo:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission
android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.MyProjectAndroid"
tools:targetApi="31">
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="@string/google_maps_key" />
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Una vez añadidos los permisos, nos cambiamos al código del MainActivity.kt y crearemos una
función de nombre isPermissionsGranted que usaremos a lo largo de nuestra app para comprobar
si el permiso ha sido aceptado o no.
159
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
A través de esta función el programa sabrá si los permisos están activados o no, en seguida
creamos una nueva función de nombre enableMyLocation que compruebe si el mapa ha sido
inicializado, si no es así saldrá de la función con el return, si por el contrario map ya ha sido
inicializada, es decir que el mapa ya ha cargado, se comprobaran los permisos.
private fun enableMyLocation() {
if (!::map.isInitialized) return
if (isPermissionsGranted()) {
map.isMyLocationEnabled = true
} else {
requestLocationPermission()
}
}
160
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Se crea el companion object con una variable constante, que será el código de respuesta para
saber si al aceptarse permisos ha sido el nuestro.
Si entra en el if significa que ya había rechazado los permisos antes y por ello le mostramos un
toast avisándole de que vaya a los ajustes de la app y modifique los permisos. Si por el contrario
entra por el else significará que nunca le hemos pedido los permisos y lo haremos a través de la
función ActivityCompat.requestPermissions, pasándole la activity (this), el permiso o los permisos
que queremos que acepte (en este caso uno) y el código de localización que creamos en el
companion object.
El siguiente paso será crear el método que nos avise si al pedirle los permisos los ha aceptado. Para
ello tendremos que sobre escribir el método onRequestPermissionsResult().
La instrucción map.isMyLocationEnabled = true la subraya en rojo, pero no es error.
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray)
{
when(requestCode){
REQUEST_CODE_LOCATION -> if(grantResults.isNotEmpty() &&
grantResults[0]==PackageManager.PERMISSION_GRANTED){
map.isMyLocationEnabled = true
}else{
Toast.makeText(this, "Para activar la localización ve a
ajustes y acepta los permisos", Toast.LENGTH_SHORT).show()
}
else -> {}
}
}
161
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Sin embargo ¿Qué pasaría si ahora salgo de la app, voy a ajustes y desactivo los permisos?
Obviamente nuestra app los necesita y eso provocaría que la aplicación falle y es por eso que
tenemos que añadir un último método onResumeFragments.
override fun onResumeFragments() {
super.onResumeFragments()
if (!::map.isInitialized) return
if(!isPermissionsGranted()){
map.isMyLocationEnabled = false
Toast.makeText(this, "Para activar la localización ve a ajustes
y acepta los permisos", Toast.LENGTH_SHORT).show()
}
Este código se ejecuta cuando regresamos a la app, después de hacer alguna otra cosa en el
dispositivo y lo primero que debemos hacer es comprobar si el mapa ha cargado, si no es así
salimos del método. Luego volvemos a comprobar si los permisos siguen activos, si no siguen
activos, desactivamos la localización en tiempo real y le mostramos un toast.
162
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Figura 65
Con lo que hemos programado de la app hasta aquí ya podríamos decir que tenemos la localización
en tiempo real completa.
Para empezar ¿Recuerdas el botón que apareció en el mapa? (ver figura 65) ¿El que te lleva a tu
posición (señalado con flecha roja)? pues podemos modificar su comportamiento, para que nos
lleve a la localización de nuestro dispositivo y si el usuario da clic no mande un mensaje con la
localización en función de Latitud y Longitud. Para ello iremos a la parte superior de nuestra activity
y añadiremos las implementaciónes OnMyLocationButtonClickListener y
OnMyLocationClickListener.
class MainActivity : AppCompatActivity(), OnMapReadyCallback,
OnMyLocationButtonClickListener,OnMyLocationClickListener {
Al añadir las implementaciones nos saldrá un error en el nombre de nuestra clase, porque hemos
implementado una función, pero no la hemos añadido en el código así que añadimos los siguientes
métodos.
163
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
import android.content.pm.PackageManager
import android.location.Location
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import androidx.core.app.ActivityCompat
164
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
import androidx.core.content.ContextCompat
import com.google.android.gms.maps.CameraUpdateFactory
import com.google.android.gms.maps.GoogleMap
import
com.google.android.gms.maps.GoogleMap.OnMyLocationButtonClickListener
import com.google.android.gms.maps.GoogleMap.OnMyLocationClickListener
import com.google.android.gms.maps.OnMapReadyCallback
import com.google.android.gms.maps.SupportMapFragment
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.MarkerOptions
map.animateCamera(CameraUpdateFactory.newLatLngZoom(coordenadas,18f),
4000,
null
)
}
165
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
) == PackageManager.PERMISSION_GRANTED
arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION),
REQUEST_CODE_LOCATION)
}
}
166
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
return false
}
Al ejecutar la aplicación damos clic en el punto de la esquina superior derecha, para que nos lleve
a nuestra ubicación y si damos clic en ella, nos mostrara las coordenadas, como se muestra en la
siguiente figura:
Figura 66
167
MANUAL DE PRÁCTICAS DE LA MATERIA “DESARROLLO DE APLICACIONES
PARA DISPOSITIVOS MÓVILES”
Carrera Ingeniería en Tecnologías de la Información y Comunicaciones
Elaborado por: Alejandro Guzmán Zazueta
Bibliografía
Ardións, A. (19 de Abril de 2015). AS.com. Obtenido de AS.com:
https://androidstudiofaqs.com/conceptos/cual-es-la-estructura-de-un-proyecto-en-android-
studio
Colectiva, N. (15 de 08 de 2018). Que son los Layouts y cuales existen en Android Studio. Obtenido de
https://blog.nubecolectiva.com/que-son-los-layouts-y-cuales-existen-en-android-studio/
Guimerá, A. (28 de 01 de 2021). Google Maps en Android con Kotlin [Parte 2] – Localización en tiempo
real. Obtenido de https://cursokotlin.com/capitulo-30-google-maps-en-android-con-kotlin-
parte-2-localizacion-en-tiempo-real-kotlin/
Naeem, T. (20 de 01 de 2020). Comprender los conceptos básicos de las API REST. Obtenido de
https://www.astera.com/es/type/blog/rest-api-definition/
Perez, M. (03 de 01 de 2016). Geeky Theory JSON I - ¿Qué es y para qué sirve JSON? Obtenido de
https://geekytheory.com/json-i-que-es-y-para-que-sirve-json/
PYM. (17 de 03 de 2017). Programación y Más "Android: Listas dinámicas usando RecyclerView".
Obtenido de https://programacionymas.com/blog/listas-dinamicas-android-usando-recycler-
view-card-view
Revelo, J. (13 de 11 de 2014). Tutorial de Bases de datos SQLite en Aplicaciones Android. Obtenido de
https://es.paperblog.com/tutorial-de-bases-de-datos-sqlite-en-aplicaciones-android-2926645/
168