Práctica 2
Sistemas Operativos Multimedia
Introducción a Android
1. ¿Qué es Android?
1.1. El sistema operativo Android
Android es un sistema operativo basado en Linux con una interfaz de programación (API) en
Java. El sistema nos ofrece una serie de herramientas: compilador, depurador, emuladores de
dispositivos así como su propia máquina virtual de Java, conocida como Dalvik Virtual Machine
– DVM. Esta máquina virtual implementa el modelo de concurrencia de Java, utilizando
objetos compartidos y monitores. Para la implementación de hilos, sigue el modelo definido en
el estándar POSIX de pthreads, dónde los hilos se encuentran separados en grupos y las
aplicaciones pueden lanzar múltiples hilos. Como veremos a continuación, la planificación y el
manejo de interrupciones se delegan al Kernel de Linux.
Ilustración 1. Componentes sistema operativo Android
Android ofrece soporte para gráficos 2D y 3D utilizando librerías OpenGL y además nos ofrece
soporte de almacenamiento a través de una base de datos SQLite.
Cada aplicación desarrollada en Android se ejecuta sobre su propio proceso y sobre su propio
usuario, el cual es generado por el sistema operativo durante el despliegue de la aplicación.
Además la aplicación se encuentra aislada de otras aplicaciones que se encuentren en
ejecución de forma que las aplicaciones no puedan fácilmente perjudicarse entre ellas.
1.2. Principales componentes de una aplicación Android
Una aplicación en Android está compuesta en parte por los siguientes elementos:
Activities: representan la capa de presentación de una aplicación en Android, por
ejemplo, la pantalla que el usuario ve. Una aplicación Android puede tener varias
actividades y se puede cambiar entre ellas durante la ejecución de la aplicación.
Views: Las interfaces de usuario de las actividades son construidas con clases de
widgets, las cuales heredan de “android.view.View”. El diseño de las vistas es
gestionado por “android.view.ViewGroups”. Las vistas a su vez poseen una serie de
atributos, los cuales pueden ser usados para cambiar su apariencia y comportamiento.
Services: ejecutan tareas en segundo plano. Utilizan el framework de notificaciones de
Android.
Content Providers: capa de datos para las aplicaciones. A través del proveedor de
contenidos tu aplicación puede compartir información con otras aplicaciones. Los
dispositivos Android incluyen de serie un conjunto de proveedores de contenidos
nativos que permiten acceder a datos del terminal, como por ejemplo los contactos o
el contenido multimedia.
Intents: mensajes asíncronos, los cuales permiten a la aplicación solicitar
funcionalidades de otros servicios o aplicaciones. Una aplicación puede llamar
directamente a un servicio o actividad, o incluso preguntar al sistema Android sobre
los servicios registrados y aplicaciones. Las aplicaciones se registran a sí mismas a
través del IntentFilter.
Receivers: recibe mensajes del sistema e Intents implícitos, puede ser utilizado para
reaccionar ante ciertas condiciones del sistema. Una aplicación puede registrarse como
receptor de broadcast para algunos eventos y puede comenzar ciertas tareas en caso
de que algún evento predefinido ocurra.
Widgets: Componentes interactivos usados principalmente en la pantalla principal o
“escritorio” Android para mostrar datos sin necesidad de lanzar la aplicación
correspondiente
1.3. Seguridad y permisos
Una aplicación en Android utiliza el fichero “AndroidManifest.xml” para definirse a sí misma,
especificando en este fichero atributos para su configuración y ejecución. Este fichero debe
especificar también los permisos requeridos para la aplicación. Por ejemplo, si la aplicación
requiere acceso a la red debe ser especificado en el fichero. El fichero “AndroidManifest.xml”
puede ser visto como un descriptor de despliegue para una aplicación Android.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.eps.myapplication">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
El atributo “package” del AndroidManifest.xml define el paquete base para los siguientes
elementos. Este además debe ser único ya que el Market de Android solo permite definir una
aplicación bajo el mismo paquete. Es un buen hábito usar el nombre de tu dominio al revés
para evitar colisiones con otros desarrolladores, por ejemplo:
es.ua.multimedia.android.nombreApp
“android:versionName” y “android:versionCode” especifican la versión de tu aplicación.
“versionName” es lo que el usuario ve y puede ser cualquier tipo de String. “versionCode”
debe ser un entero y el Market de Android lo utiliza para determinar si hay una nueva versión
de la aplicación y en ese caso solicitar la actualización en los dispositivos donde la aplicación se
encuentre instalada. Normalmente se empieza con un valor “1” y conforme se van sacando
nuevas versiones se incrementa este valor.
“activity” define una actividad en nuestra aplicación, esta se encuentra asociada a una clase
Java. En el caso de nuestro AndroidManifest.xml, apunta a la clase:
es.ua.multimedia.so.android.calculadoraActivity
Un “filter intent” es registrado también para la clase anterior, de forma que especifica que la
clase se ejecuta una vez que la aplicación ha sido ejecutada. (action
android:name=”android.intent.action.MAIN”). La definición de “category” especifica que la
aplicación se añade al directorio de aplicaciones del dispositivo (category
android:name=”android.intent.category.LAUNCHER”).
El “uses-sdk” define la versión mínima del sdk para el cual tu aplicación es válida. Esto
previene que la aplicación sea instalada en dispositivos con versiones antiguas del sdk.
1.4. R.Java, Resources y Assets
El directorio “gen” en un proyecto Android contiene valores generados. “R.java” es una clase
generada la cual contiene referencias hacia recursos de la carpeta del proyecto
“res”. Estos recursos son definidos en el directorio “res” y pueden ser valores, iconos,
imágenes, animaciones, diseños, etcétera. Por ejemplo un recurso puede ser una imagen o un
fichero Xml donde se definen mensajes para la aplicación.
Si creamos un nuevo recurso, la correspondiente referencia es automáticamente creada en
“R.java”. Estas referencias son valores int estáticos, el sistema operativo Android provee
métodos para acceder al recurso necesario. Por ejemplo para acceder a un String con el id de
referencia “R.string.tuString” utilizamos el método getString(R.string.tuString); Es
recomendable no modificar manualmente la clase R.java.
1.5. Activities y Layouts
Las interfaces de usuario para una “Activity” son definidas a través de layouts. En tiempo de
ejecución los layout son instancias de “android.view.ViewGroups”. El layout define los
elementos de la UI, sus propiedades y su disposición.
Los elementos de la UI están basados en la clase “android.view.View”. ViewGroup es una
subclase de la clase “View” y un layout puede contener componentes UI (Views) u otros
layouts (ViewGroups). No se deben anidar demasiados ViewGroups ya que esto tiene un
impacto negativo sobre el rendimiento de la aplicación.
Un layout puede ser definido a través de código Java o vía XML. Los layout definidos usando
XML son definidos a través de un fichero recurso en la carpeta “/res/layout”.
Este fichero especifica los ViewGroup, Views, sus relaciones y sus atributos. En el código Java
estos elementos de la UI son accesibles a través del método findViewById(R.id.tuvalor);
La definición de los layout en ficheros XML es la opción más recomendable debido a que nos
permite desacoplar la lógica de programación de la definición del diseño de la aplicación.
2. Entorno de desarrollo.
El entorno de desarrollo utilizado en dicha práctica será Android Studio 4.1. En esta sección,
describiremos paso a paso como realizar nuestra primera aplicación Android y para ello
arrancamos Android Studio que nos mostrará la siguiente pantalla.
Seleccionaremos Create New Project y pasamos a la siguiente pantalla en la que
seleccionaremos la plantilla Empty Activity.
La siguiente pantalla nos va a permitir dar nombre a nuestra aplicación, el Package name, la
ubicación donde se almacenará, el lenguaje de programación utilizado y la API de Android.
Seleccionamos Finish.
Llegados a este punto ya tenemos nuestro entorno de trabajo preparado para ir desarrollando
nuestra aplicación.
Trabajaremos con las dos pestañas remarcadas en la siguiente imagen de modo que en
MainActivity.java (azul) escribiremos el código java que determina el funcionamiento de
nuestra aplicación y en activity_main.xml (rojo) escribiremos el código xml que determina el
aspecto visual de la aplicación con la que vamos a trabajar.
l siguiente paso es comprobar el funcionamiento de nuestra aplicación y para ello podemos
optar por utilizar el AVD Manager que nos gestiona un dispositivo virtual similar a un móvil o
utilizar nuestro propio móvil android conectado al puerto USB del ordenador.
Para comprobar el correcto funcionamiento de la aplicación utilizaremos los emuladores
disponibles en la herramienta AVD Manager que nos solicitara que elijamos cuando vayamos a
ejecutar nuestra aplicación. Dicha herramienta nos permite crear nuestros propios dispositivos
virtuales. Icono del AVD Manager.
Nos aparecerá una pantalla similar a la siguiente imagen:
Seleccionaremos el dispositivo móvil sobre el que deseamos lanzar la actividad. En la siguiente
imagen aparece el emulador del móvil donde se ejecutará la aplicación creada.
A continuación comprobamos el funcionamiento de la aplicación y para ello y desde Android
Studio seleccionamos el icono que nos permite ejecutar la aplicación que instala y lanza la
aplicación en el dispositivo apareciendo en la pantalla del móvil.
En la pantalla del emulador aparece la misma información que en la ventana de diseño de
Android Studio.
Desarrollo de la práctica.
Para llevar a cabo la práctica se deja el código necesario para realizar una sencilla aplicación
que lleva a cabo la suma de dos números y muestra su resultado. Este será el código de partida
que nos permitirá ir avanzando en los diferentes puntos de la práctica.
En MainActivity.java escribiremos el siguiente código:
package com.example.eps.myapplication;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
public class MainActivity extends AppCompatActivity {
private EditText numA,numB,sumaNumeros;
private Button botonSuma;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Obtenemos una referencia a los controles de la interfaz gráfica
numA = (EditText)findViewById(R.id.numA);
numB = (EditText) findViewById(R.id.numB);
sumaNumeros =(EditText)findViewById(R.id.sumaNumeros);
botonSuma = (Button) findViewById(R.id.botonSuma);
//Implementamos el evento click del botón
botonSuma.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//Realizamos la suma
String valor1=numA.getText().toString();
String valor2=numB.getText().toString();
int numero1=Integer.parseInt(valor1);
int numero2=Integer.parseInt(valor2);
int suma=numero1+numero2;
String resultado=String.valueOf(suma);
sumaNumeros.setText(resultado);
}
});
}
}
Y en activity_main.xml escribiremos el siguiente código:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/teal_200"
tools:context="MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="NUM A"
android:id="@+id/textView1" />
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/numA"
android:textColor="#FF0"
android:layout_below="@+id/textView1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="NUM B"
android:id="@+id/textView2"
android:layout_below="@+id/numA" />
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/numB"
android:textColor="#FF0"
android:layout_below="@+id/textView2" />
<Button android:id="@+id/botonSuma"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="SUMA"
android:layout_below="@+id/numB" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Resultado "
android:id="@+id/Resultado"
android:singleLine="false"
android:textColor="#000"
android:textSize="25sp"
android:layout_below="@+id/botonSuma"/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/sumaNumeros"
android:textSize="16sp"
android:textColor="#000"
android:layout_below="@+id/botonSuma"
android:layout_toRightOf="@+id/Resultado"/>
</RelativeLayout>
Si seleccionamos la opción Split veremos en la parte izquierda el código xml y en la parte
derecha el efecto de dicho código sobre la vista de la aplicación en la pantalla del móvil.
El último paso consiste en comprobar el correcto funcionamiento de la aplicación y para ello
utilizaremos el procedimiento descrito anteriormente. El resultado que veríamos en el
dispositivo virtual es el siguiente:
EVALUACIÓN PRÁCTICA 2
Ejercicio 1 (5 puntos). Aplicación básica guiada denominada “Circuitos Integrados” que
muestra el comportamiento de dos circuitos integrados y sus posibles aplicaciones. En este
caso se trata de los circuitos NE555 funcionando como oscilador y uA741 haciendo labores de
amplificador de tensión.
Para empezar ejecuta el código de ejemplo que realiza la suma de los datos introducidos y
comprueba su correcto funcionamiento.
o Verifica que sucede si nos situamos en el EditText que muestra el resultado y
escribimos un valor después de realizar un cálculo.
o Realiza las modificaciones oportunas para solucionar el problema detectado.
Realiza las modificaciones en la interfaz grafica para obtener un menú inicial que nos permita
elegir el tipo de circuito integrado con el que debemos de trabajar.
Modifica el código java de la aplicación para que mediante el uso de intents podamos acceder
a nuevas actividades y navegar entre ellas. Por ejemplo, si pulsamos sobre el NE555 debería
abrirse una nueva actividad con el siguiente aspecto visual.
En la parte superior hay una imagen que muestra el circuito realizado con el circuito integrado
cuya frecuencia de oscilación estará determinada por los valores de R1, R2 y C, mientras que
en la parte inferior podremos introducir los valores de R1, R2, C y Frecuencia y al pulsar sobre
el botón CALCULA obtener el resultado de la única variable que no hayamos introducido. El
valor de la frecuencia de oscilación está determinado por la siguiente fórmula:
Nota: R1 debe ser mayor que R2 y su valor debe estar comprendido entre 1 KΩ y 10 MΩ.
En la parte inferior y de color azul derecha hay otro botón que permite regresar a la actividad
principal que nos permite seleccionar el circuito integrado con el que deseamos trabajar.
La parte fraccionaria de los resultados obtenidos tendrá una longitud máxima de 6 dígitos. En
la siguiente figura se muestra un ejemplo de los cálculos realizados con para valores de R1= 2
KΩ , R2= 1 KΩ y C= 0.1 µF.
Si desde la actividad principal pulsamos sobre el ua741 debería abrirse una nueva actividad
con el siguiente aspecto visual.
Ejercicio 2 (3 puntos). Realiza las modificaciones necesarias en el programa que el programa
realice las siguientes acciones:
2.1.- Mostrar notificaciones en caso de que no se introduzcan todos los datos necesarios o no
sean correctos con ayuda del método Toast.
2.2.- Realiza las modificaciones oportunas para que ante un eventual giro de móvil la
aplicación siga viéndose correctamente.
2.3.- Realiza las modificaciones oportunas para evitar que el programa finalice
inesperadamente mostrando la correspondiente notificación.
Ejercicio 3 (2 puntos). Aspectos de mejora
Durante las sesiones en clase se plantearán modificaciones con mejoras y nuevas
funcionalidades.
NORMAS DE ENTREGA
• Se establecerá un control de entrega de prácticas en el CV para la práctica P2. Dicha entrega
será individual e incluirá código fuente comentado, memoria descriptiva en la que se explica
diseño e implementación de la solución de manera detallada. La corrección de la práctica en
laboratorio se realizará el día 21 Diciembre de 2022 para los grupos 1 y 3 de prácticas y el día
22 de Diciembre para los grupos 2 y 4 de prácticas.