4 Fundamentos de Aplicaciones
4 Fundamentos de Aplicaciones
4 Fundamentos de Aplicaciones
Fundamentos de
aplicaciones
●
Permite controlar las aplicaciones
distribuidas.
●
Establece los permisos de usuario.
●
Define las bibliotecas a utilizar.
●
Especifica todos los componentes del
paquete.
●
Registra los componentes que se ejecutan.
2. Activity
2.1. Definición
●
Es el controlador principal de la ejecución.
●
Permite controlar lo que se va a visualizar en la pantalla.
●
Hay distintos tipos de controladores específicos.
●
Todos heredan de AppCompatActivity y está relacionados
con los distintos tipos de pantallas que maneja Android.
import android.support.v7.app.AppCompatActivity;
Proceso automát. de
liberación de
memoria de Android,
NO perdemos datos
Proceso automát. de
liberación de
memoria de Android,
perdemos datos
Cuando pulsamos La Activity ya no está
atrás o lanzamos el visible en ningún
método finish() momento
2.2. Ciclo de vida (II)
public class MyApplication extends Application {
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onLowMemory() {
super.onLowMemory();
}
@Override
public void onTerminate() {
super.onTerminate();
}
}
2.3. Métodos principales
●
setContentView: permite cargar una vista.
– setContentView(R.layout.activity_main);
●
findViewById: permite capturar un objeto de la vista.
– private EditText et1 = (EditText) findViewById(R.id.et1);
●
startActivity: permite arrancar otra activity.
– startActivity(intent);
●
onCreateOptionMenu: carga un menú de opciones.
●
onOptionsItemSelected: permite realizar acciones
dependiendo del elemento del menú seleccionado.
4. Intent
4.1. Definición
●
Es el componente que nos permite realizar saltos entre actividades (de
una pantalla a otra).
●
Permite la comunicación entre aplicaciones de Android.
●
El Sistema puede generar Intents para notificar acciones que hayan
pasado a las aplicaciones.
– Por ejemplo cuando tenemos una llamada entrante.
●
El arranque de una aplicación se realiza a través de una Intent que
genera el sistema.
4.2. Tipos de Intent
●
Implícita:
– Realiza un salto conforme a la configuración del dispositivos.
– Permite realizar saltos a Activities que desconocemos o que son de sistema.
●
Ejemplo: se especifica la funcionalidad requerida a través de una acción (por ejemplo
marcar) y un dato (por exemplo el número que se desea marcar), y Android debe
determinar el mejor componente para su utilización.
●
Explícita:
– Nosotros le indicamos el destino de la Intent porque conocemos la clase
destino declarado previamente en AndroidManifest.xml con intent-filters.
– Indicamos qué es lo que queremos y será el sistema el responsable de
identificar la Activity correspondiente para manejar esa acción.
●
Ejemplo: Al hacer el una fotografía el sistema nos lleva automáticamente a la Intend
que captura una foto.
4.3. Campos de Intent
●
ACTION: un String que representa o nombra la operación que va a ser realizada.
– ACTION_DIAL: queremos que alguien marque un número de teléfono.
– ACTION_EDIT: queremos que se muestren algunos datos para editar por el usuario.
– ACTION_SYNC: nos gustaría sincronizar algunos datos en nuestro dispositivo con los datos de un servidor.
– ACTION_MAIN: queremos iniciar una actividad como la actividad inicial de una aplicación.
●
DATA: representa los datos que son asociados con el Intent. El formato de los datos es una URI
(Uniform Resource Identifier).
●
CATEGORY: representa información adicional sobre los tipos de componentes que puede
manipular o debe manipular este Intent.
– CATEGORY_BROWSABLE: la actividad de destino permite ser iniciado por un navegador web para mostrar
datos referenciados por un enlace URI, como una imagen o un mensaje de correo electrónico.
– CATEGORY_LAUNCHER: la actividad es la actividad inicial de una tarea y aparece en la aplicación de inicio
del sistema.
●
TYPE: especifica los tipos MIME (Multipurpose Internet Mail Extensions) de los Intents de datos.
●
COMPONENT: especifica la Actividad de destino del Intent.
●
EXTRAS: añaden información adicional al Intent.
4.4. Iniciar Actividades
startActivity(Inten intent): éste método es utilizado para
empezar una nueva actividad.
Intent iniciarNuevaActividadIntent = new Intent(
ActividadActual.this, SiguienteActividad.class);
startActivity(iniciarNuevaActividadIntent);
●
Etiqueta de AndroidManifest.xml.
●
Especifica características de Intents que recibe el componente.
– Si no se indica solamente se podrá iniciar otra Actividad con explicit
Intent.
Acción a realizar por
el Intent
<activity android:name="ShareActivity">
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"/>
</intent-filter> Categorías aceptadas
Datos aceptados por el por el Intent
Intent
4.6. Ejemplos
●
Permiten adjuntar información que pasamos con la
Intent.
●
Funciona de manera muy parecida a un Map de Java
– tiene un id y un valor.
●
Hay que pasar los mínimos datos posibles mediante
la Intent, es un proceso muy costoso para el sistema
– Intent.putExtra: método para pasar el conjunto de datos.
– Clase Bundle
●
getExtras: método para recoger los datos enviado por putExtra.
4.8. Ejemplo
//EN LA ACTIVIDAD PRINCIPAL
Intent intent = new Intent();
intent.setClass(this, Other_Activity.class);
intent.putExtra("EXTRA_ID", "SOME DATAS");
StartActivity(intent);
●
Cuando muestra el diálogo
de selección de aplicación
a ejecutar el Intent
externamente a nuestra
aplicación.
– Por ejemplo, cuando
queremos compartir un
archivo con la acción
ACTION_SEND.
4.10. Ejemplo
●
El mismo crea y gestiona un hilo de ejecución.
●
Se detiene automáticamente una vez concluida la tarea.
●
Extiende de la clase IntentService y añade su
constructor de dicha clase
●
Se implementa a través de su método onHandleIntent().
●
Utilizado mayormente cuando el segundo hilo no tiene
relación con el hilo principal.
●
Se suelen utilizar más los Hilos y Tareas.
6.3. Ciclo de vida
Cuando los
Cuando finalice
clientes se
su estado o un
desconectan
cliente lo indique
se destruirá
6.3.2. Ejemplo (I)
Extiende de la clase
padre
bcIntent.putExtra("progreso", i*10);
sendBroadcast(bcIntent); Enviamos en forma de
} broadcast
Intent bcIntent = new Intent();
Broadcast que indica que la
bcIntent.setAction(ACTION_FIN);
aplicación ha terminado
sendBroadcast(bcIntent);
}
7. Hilos y Tareas
7.1. Definición
●
Permiten la ejecución de tareas en segundo plano.
●
Modelo de un solo hilo principal por app (conocido como
hilo de interfaz de usuario).
●
Se independizan del hilo principal de ejecución (conocidos
como hilos de fondo o hilos trabajadores).
●
Existen dos tipos de implementación.
– ASyncTask: mediante un sistema de definición de tipo de datos.
– Threads.
7.2. Threads (I)
●
Declaración.
Recibe Objeto
//Constructor de la Clase Thread
new Thread(new Runnable() {
Construcción del
public void run() {
thread a través del
//Aquí ejecutamos nuestras tareas costosas
método run
}
}).start();
7.2. Threads (II)
●
¿Sería correcto?
●
No. Dos reglas fundamentales:
– No bloquee el hilo de interfaz de usuario.
– No acceder al kit de herramientas de interfaz de usuario
desde fuera del hilo de interfaz del usuario.
●
¿Cual regla no cumple?
7.2. Threads (III)
●
No acceder al kit de herramientas de interfaz de usuario desde
fuera del hilo de interfaz del usuario.
– Modifica el ImageView desde el hilo de trabajo en vez de modificarla
desde el hilo de interfaz de usuario.
●
Solución: acceso al hilos desde otros hilos. Métodos:
– Activity.runOnUiThread(Runnable): para “enviar” operaciones al hilo
principal desde el hilo secundario.
– View.post(Runnable): para actuar sobre cada control de la interfaz.
– View.postDelayed(Runnable, long): igual que post pero con un lapso de
tiempo.
7.2. Threads (IV)
●
¿Y ahora es correcto?
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
final Bitmap mBitmap = loadImageFromNetwork(
"http://example.com/image.png");
mImageView.post(new Runnable() {
public void run() {
mImageView.setImageBitmap(mBitmap);
}
});
}
}).start();
}
7.2. Threads (V)
●
Si.
– el funcionamiento de la red se realiza desde un
hilo separado, mientras que el imageView se
manipula desde el subproceso de la interfaz de
usuario.
7.2. Threads (VI)
new Thread(new Runnable() {
public void run() { Invocación principal
pbarProgreso.post(new Runnable() {
public void run() {
pbarProgreso.setProgress(0);
}
}); Método post para actuar
sobre el control de
for(int i=1; i<=10; i++) {
tareaLarga(); ProgressBar
pbarProgreso.post(new Runnable() {
public void run() {
pbarProgreso.incrementProgressBy(10);
}
});
} Método runOnUiThread()
para mostrar el mensaje
runOnUiThread(new Runnable() {
public void run() { TOAST cuando acabe el
Toast.makeText(MainHilos.this, "Tarea finalizada!",
Toast.LENGTH_SHORT).show();
progreso
}
});
}
}).start();
7. Handler Class
8.1. Handler Class (I)
●
Clase que nos permite mover datos de un subproceso
de fondo al hilo de interfaz de usuario.
●
Definir un controlador en el hilo de interfaz de usuario.
●
Pasos para la creación
– Definir el controlador en el hilo de interfaz de usuario.
– Mover datos de una tarea al hilo de interfaz de usuario.
– Enviar el estado a la jerarquía de objetos.
– Mover los datos al hilo interfaz de usuario.
8.2. Definir un controlador
en el hilo principal
●
Recibe mensajes y ejecuta código para manejarlos.
●
Controlador nuevo para cada nuevo hilo.
●
Crear una instancia Handler en el constructor de
la clase que creará sus grupos de subprocesos y
almacenará el objeto en una variable global.
●
Conectamos al hilo principal con el constructor
Handler(Looper) que es parte del framework de
gestión de hilos en Android.
8.2. Definir un controlador
en el hilo principal
private PhotoManager() {
// Definimos un objeto Handler que se une al hilo de interfaz de usuario.
mHandler = new Handler(Looper.getMainLooper()) {
...
/*
* Dentro del Handler, sobrescribimos el método handleMessage(). El sistema Android invoca
* a éste método cuando recibe un nuevo mensaje de un hilo; todos los objetos Handler de
* un hilo reciben el mismo mensaje.
*/
/*
* handleMessage() define las operaciones a realizar cuando
* el Handler recibe un nuevo mensaje para porcesar.
*/
@Override
public void handleMessage(Message inputMessage) {
// Obtenemos la imagen del objeto del mensaje entrante.
PhotoTask mPhotoTask = (PhotoTask) inputMessage.obj;
...
}
...
}
}
8.3. Mover datos de una
tarea al hilo principal
●
Comenzar con el almacenamiento a las referencias
de los datos y el objeto.
●
Luego pasar el objeto de la latera y un código de
estado al objeto que crea la instancia del Handler.
●
En el ejemplo:
– Un Runnable se ejecuta en un subproceso de fondo y
éste decodifica un mapa de bits y lo almacena en el
objeto padre PhotoTask. El Runnable también almacena
el código de estado DECODE_STATE_COMPLETED.
8.3. Definir un controlador
en el hilo principal
// Una clase que decodifica archivos de fotos en mapas de bits.
class PhotoDecodeRunnable implements Runnable {
...
PhotoDecodeRunnable(PhotoTask downloadTask) {
mPhotoTask = downloadTask;
}
...
// Obtenemos el array de bytes descargados.
byte[] mImageBuffer = mPhotoTask.getByteBuffer();
...
// Ejecutamos el código para esta tarea.
public void run() {
// Intentamos descodificar el búfer de la imágen.
mReturnBitmap = BitmapFactory.decodeByteArray(
imageBuffer, 0, imageBuffer.length, bitmapOptions);
...
// Establecemos el Bitmap de la imágen.
mPhotoTask.setImage(returnBitmap);
// Informamos del estado "completado".
mPhotoTask.handleDecodeState(DECODE_STATE_COMPLETED);
...
}
...
}
9. AsyncTask (I)
9.1. Métodos
●
OnPreExecute: inicialización de la tarea. Este método se invoca desde el Thread
principal y puede, por tanto, modificar la interfaz de usuario.
– protected void onPreExecute()
●
doInBackground: se encarga de realizar el procesamiento de la tarea y se invoca
desde el Thread secundario. Este método devuelve el resultado del procesamiento.
– protected abstract Result doInBackground (Params... params)
●
publishProgress: puede ser invocado en cualquier momento por doInBackgroud para
actualizar la interfaz de usuario según el avance actual del procesamiento. Esta
llamada provocará que se invoque el método onProgressUpdate desde el Thread
principal.
– protected void onProgressUpdate (Progress... values)
●
onPostExecute: método invocado para procesar el resultado. Este método se invoca
desde el Thread principal y puede, por tanto, modificar la interfaz de usuario.
– protected void onPostExecute (Result result)
9.2. Peculiaridades
●
Fijarse que separa la parte trabajo que hace un
subproceso (doInBackground()) con la parte de interfaz
de usuario (onPostExecute()).
●
Tipos genéricos de AsyncTask
– Params: son el tipo de parámetros enviados a la tarea de
ejecución.
– Progress: es el progreso de las unidades de progreso
publicados durante las tareas realizadas en segundo plano.
– Result: es el resultado de las obtenido por las tareas de que
se realizan en segundo plano.
9.2. Ejemplo
public void onClick(View v) {
new DownloadImageTask().execute(
"http://example.com/image.png");
}
private class DownloadImageTask extends AsyncTask<string, void="" ,="" bitmap=""> {
/** El sistema llama a éste método para realizar el trabajo
* en un subproceso de trabajo
* y realiza la entrega los parámetros dados a AsyncTask.execute() */
protected Bitmap doInBackground(String... urls) {
return loadImageFromNetwork(urls[0]);
}
@Override
Antes de lanzar el hilo
protected void onPreExecute() {
pbarProgreso.setMax(100); secundario
pbarProgreso.setProgress(0);
Cuando acaba el hilo
}
@Override
secundario
protected void onPostExecute(Boolean result) {
if(result)
Toast.makeText(MainHilos.this, "Tarea finalizada!",
Toast.LENGTH_SHORT).show();
} En caso de no finalización
@Override de la tarea
protected void onCancelled() {
Toast.makeText(MainHilos.this, "Tarea cancelada!",
Toast.LENGTH_SHORT).show();
}
}
10. Notificaciones
(Notify)
10.1. Definición
●
Permite generar alertas para que el usuario sepa que es lo que
está pasando en el sistema o en una aplicación.
●
Las notificaciones son visibles desde la barra de notificaciones o
desde dispositivos que estén enganchados contra ellas (Android
Wear)
●
Se pueden generar desde cualquier parte de la aplicación.
●
Pueden contener imágenes y ser personalizadas.
●
1. Hay varios tipos de notificaciones: En Toast, Barra de
notificaciones, Diálogos y Snack Bar.
●
NO ABUSAR.
10.2. Tipos
Barra de estado Diálogos
Toast
SnackBar
10.3.1. Toast por defecto
btnToast.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Toast toast =
Toast.makeText(getApplicationContext(),
"Toast ejemplo", Toast.LENGTH_SHORT);
toast.show();
}
});
btnToast.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Toast toast =
Toast.makeText(getApplicationContext(),
"Toast con gravedad", Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER|Gravity.LEFT,0,0);
toast.show();
}
Zona en la que se quiere que
});
aparezca: CENTER/ LEFT/ RIGHT/
BOTTOM
10.4.1. Barra de estado.
Declaración
Creamos el objeto pasándo
el objeto de la aplicación
mNotificationManager.notify(NOTIF_ALERTA_ID, mBuilder.build());
btnAlerta.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
FragmentManager fragmentManager = getSupportFragmentManager();
DialogoAlerta dialogo = new DialogoAlerta();
dialogo.show(fragmentManager, "tagAlerta"); Creamos el objeto tipo
} DialogAlerta mediante
}); la clase
Método show que muestra el FragmentManager
diáologo
10.5.2. Diálogo de
confirmación. Construcción (I)
Igual que el anterior
public class DialogoConfirmacion extends DialogFragment {
Que muestra el
@Override
Diálogo
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage("¿Confirma la acción seleccionada?")
.setTitle("Confirmacion")
.setPositiveButton("Aceptar", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Log.i("Dialogos", "Confirmacion Aceptada.");
dialog.cancel();
Evento en el caso de que pulse en
}
el Button de Confirmar
})
10.5.2. Diálogo de
confirmación. Construcción (II)
.setNegativeButton("Cancelar", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Log.i("Dialogos", "Confirmacion Cancelada.");
dialog.cancel();
} En caso de cancelar
});
return builder.create();
}
}
btnSnackbarSimple.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Esto es una prueba", Snackbar.LENGTH_LONG)
.show();
}
}); Contenedor tipo view donde se
visualizará Tiempo en el que está en pantalla
10.6.2. Snackbar con
acción
Snackbar.make(view, "Esto es otra prueba", Snackbar.LENGTH_LONG)
.setActionTextColor(getResources().getColor(R.color.snackbar_action))
.setAction("Acción", new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.i("Snackbar", "Pulsada acción snackbar!");
}
})
.show(); Al pulsar en “ACCIÓN”
¿Que Significa el método
setActionTextColor? ¿De dónde
obtiene el color y cómo se definiría?
10.6.2. Snackbar con
acción
<resources>
<color name="snackbar_action">#ff7663</color>
</resources>
11. Receptores de anuncios
(BroadcastReceiver)
11.1. Definición
●
Permite registrar ante eventos de sistema operativo y de las aplicaciones.
●
Se pueden registrar con el Android Manifest o mediante el método
onReceive().
●
El método principal es onReceive, ejecutado por el hilo principal y solo
existe durante esta llamada.
●
Utilizado principalmente para notificaciones internas de Android:
– Controlar distintos estados de la Batería baja, llamada entrante, arranque, etc..
●
Pueden ser nativos (de sistema) o propios.
●
Utilizar para operaciones cortas. Operaciones largas en hilos secundarios.
– Hay que tener en cuenta que se ejecuta en el hilo principal.
11.2. Formas de registro
●
Estáticamente en AndoridManifest.xml. Añadiendo las etiquetas:
– <receiver>: indica el nombre del receptor
– <intent-filter>: especifica acciones, datos y categorías.
●
Dinámicamente llamando al método onReceiver().
– Creamos un IntentFilter.
– Creamos un BroadcastReceiver.
– Registramos el BroadcastReceiver usando el método registerReceiver().
●
Usamos la clase LocalBroadcastManager. Es solo para el uso de la aplicación que
estemos desarrollando.
●
Usamos la clase Context. Puede ser recibida por otra aplicación de nuestro
dispositivo.
●
Llamamos al método un RegisterReceiver() para anular el registro.
11.2. Declaración
//EN MANIFEST
<receiver android:narne= ".ReceptorAnuncio”>
<intent-filter>
<action android:name="android.intent, BATTERY_ LOW " / >
</intent-f i1ter>
</receiver>
//CLASE JAVA
public class ReceptorAnuncio extends BroadcastReceiver{
@Override
public void onReceive{Context context, Intent intent)
{
//CODIGO OMITIDO
}
}
12. Proveedores de contendio
(Content Provider)
12.1. Definición
●
Permite la comunicación entre aplicaciones en Android.
●
Normalmente funciona como un acceso a base de datos remoto.
●
Tenemos dos componentes:
– La aplicación que tiene los datos.
– La aplicación que accede a los datos.
●
Un ejemplo es la agenda de contactos.
●
Cualquier aplicación puede acceder a ella si se tienen los permisos oportunos.
●
Se debe acceder mediante una URI (ver standard RFC 3296).
– <standard_pref ix>://<authority>/<data_path>/<id>
●
Para comenzar, debemos obtener una referencia a un ContentResolver, objeto
a través del que realizaremos todas las acciones necesarias sobre el content
provider. Esto es tan fácil como utilizar el método getContentResolver()
12.2. Más importantes
Clase Información almacenada Ejemplos de URIs
Browser Enlaces favoritos, historial de browser/bookmarks
navegación, historial de búsquedas
CallLog Llamadas entrantes, salientes y content://call_log/calls
pérdidas.
ContactsContract Lista de contactos del usuario. content://contacts/people
MediaStore Ficheros de audio, vídeo e content://media/internal/images
imágenes, almacenados en content://media/external/video
dispositivos de almacenamiento content://media/*/audio
internos y externos.
Setting Preferencias del sistema. content://settings/system/ringtone
content://settings/system/notification_sound
UserDictionary Palabras definidas por el usuario, content://user_dictionary/words
(a partir de 1.5) utilizadas en los métodos de entrada
predictivos.
Telephony Mensajes SMS y MMS content://sms
(a partir de 1.5) mandados o recibidos desde content://sms/inbox
el teléfono. content://sms/sent
content://mms
Calendar Permite consultar y editar los content://com.android.calendar/time
(a partir de 4.0) eventos content://com.android.calendar/events
12.3. Introducción a
SQLite
●
Para comenzar, debemos obtener una referencia a un Content Resolver, objeto a través del que
realizaremos todas las acciones necesarias sobre el content provider.
– Método getContentResolver()
●
Para hacer la consulta
– Cursor cur = cr.query(clientesUri,
null, //Columnas a devolver
null, //Condición de la query
null, //Argumentos variables de la query
null); //Orden de los resultadosCursor
●
Extraer de la BBDD:
– String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
●
Insertar en la BBDD: cr.insert(ClientesProvider.CONTENT_URI, values);
●
Eliminar de la BBDD:
– cr.delete(ClientesProvider.CONTENT_URI,Clientes.COL_NOMBRE + " = 'ClienteN'", null);
●
Cerrar nuestro cursos: pCur.close();