Android Master Class Introducción al desarrollo de aplicaciones en Android
Prefacio
Sobre nosotros
Sobre el curso
Sobre Catdroid
Temario
1. Introducción
2. Eclipse y el SDK
3. Hello World
4. El ciclo de vida
5. Recursos
6. Layouts y Views
7. Interacción con el usuario
8. Menús
9. Preferencias
10. Intents
11. Depuración
12. El Market
1. Introducción a Android
Introducción
Smartphones
Android en cifras
Historia de Android
Funcionamento interno
Smartphones
Teléfono
Rádio
MP3
GPS
Cámera
Internet
Apps
Android en cifras
#1 en activaciones (350.000 al día)
23% de la cuota de mercado (finales 2010)
250.000+ apps en el market
100+ modelos de teléfono
40+ modelos de tablet
Android en cifras (cont.)
Mòbils al món, segons Gartner (Abril 2011)
Android en cifras (cont.)
¿Qué es Android?
Conjunto de software para dispositivos móviles que incluye:
• Sistema operativo • Middleware • Aplicaciones
Open source
Impulsado por Google
Basado en Linux y Java
Historia
Julio 2005: Google compra Android Inc.
Noviembre 2007: Nace la OHA
Febrero 2009: Release de 1.1
Abril 2009: Release de 1.5 (Cupcake)
Octubre 2009: Release de 2.0 (Eclair)
Deciembre 2010: Release de 2.3 (Gingerbread)
Versiones
API level
• 3 (Cupcake) • 7 (Eclair) • 9 (Gingerbread)
Características
Sistema base es Linux
Máquina virtual Dalvik
Librerías de sistema
• WebKit • SQLite • Media codecs • Comunicaciones (GSM, bluetooth, wifi) • Cámara, GPS, sensores
Application framework
Arquitectura
Aplicaciones
Java (.apk)
Se ejecutan en un espacio aislado (instancia de Dalvik)
No hay jerarquía
Se comunican a través de Intents
El market no es imprescindible
Más información
Web oficial Android
• http://www.android.com/ • http://developer.android.com/index.html
Wikipedia
• http://es.wikipedia.org/wiki/Android CatDroid
• http://catdroid.org/
2. El entorno de desarrollo
Elementos necesarios
Eclipse
Android SDK
Eclipse ADT plugin + ADV Manager
Instalación
1. Preparar el equipo (Instalar Eclipse)
2. Descargar el SDK
3. Instalar el plugin ADT para Eclipse
4. Instalar plataformas y APIs
http://developer.android.com/sdk/installing.html
Catclipse
Descargar y abrir
Ultimo update: Bolets Barruers
Disponible para Windows y Mac, próximamente para Linux
3. Hola mundo
Creación de un nuevo proyecto
Elementos del proyecto nuevo
Activity
Manifest
Resources
Activities
Una Activity es una pantalla de la interfaz
Las aplicaciones constan de una o más Activity
Cada Activity es reponsable de guardar su estado
Una Activity se encarga de:
• Crear una ventana donde colocar la interfaz • Gestionar la interfaz • Responder a los eventos (onClick, onLongClick, etc).
Una Activity básica
Manifest
El Manifest es el archivo donde la aplicación le dice al sistema que elementos requiere para funcionar
Siempre debe llamarse AndroidManifest.xml y estar en la raíz del proyecto
Entre otras cosas contiene:
• Atributos de la aplicación y metadatos • La declaración de actividades y otros componentes • Librerías externas • Permisos
Se puede editar via GUI o editando el XML
Manifest inicial
Versión de la aplicación
VersionCode es importante para el Market
VersionName es importante para el usuario y/o nosotros
Definición de la actividad
Definimos las actividades y sus intent-filter
Versión del SDK
minSdkVersion, maxSdkVersion y targetSdkVersion
Permisos de la aplicación
Avisan al usuario de las acciones que realizará la aplicación
Listados en: http://developer.android.com/reference/android/Manifest.permission.html
Recursos
Un recurso es un elemento a utilizar durante la ejecución de la aplicación
Existen diferentes tipos de recursos:
• Layouts • Imágenes • Cadenas de texto • Sonidos • Colores • Temas • Animaciones • etc
Recursos
Se almacenan en la carpeta resources
Cada tipo de recurso tiene va en una carpeta específica
Utilizan sufijos para determinar que recursos utilizar según contexto (tamaño de pantalla, idioma, orientación, etc.)
Nombre en mínusculas
La extensión se ignora (mismo nombre, diferente extensión se considera duplicado)
La clase R
La clase R es generada y mantenida por el sistema y no debe ser modificada
Contiene un identificador (int) único por cada recurso
Podemos hacer referencia a un recurso en código por R.<tipo>.<nombre>. Ej.: R.layout.main
Nombrar recursos en XML
Para referirnos a un recurso utilizamos la siguiente sintaxis:
@<tipo de recurso>/<nombre del recurso>
Por ejemplo
@string/app_name
Para definir un nombre utilizamos:
@+<tipo de recurso>/<nombre de recurso>
Ejemplo
4. El ciclo de vida
Estados de una actividad
El sistema gestiona las actividades como una pila
Una actividad tiene cuatro estados:
• Activa: la actividad está en primer plano y tiene el focus (enfoque de usuario). Se encuentra en lo alto de la pila.
• En pausa: la actividad es visible, pero no tiene el focus. Ej: hay un diálogo sobre ella con el focus retenido.
• Detenida: La actividad está tapada por otra aplicación. Mantiene sus datos.
• Destruida: Una actividad detenida ha sido destruida para liberar memoria y ha perdido sus datos. Hay que recrearla completamente.
Ciclo de vida de una actividad
Métodos
Método Descripción Siguiente onCreate() Donde se crea la interfaz. Se le proporciona un bundle
con su estado anterior. onStart
onRestart() Justo antes de un onStart cuando venimos de onStop onStart onStart() La actividad se hace visible al usuario onResume
onStop onResume() La actividad está en primer plano interactuando con el
usuario onPause
onPause La actividad va a ser detenida. Se utiliza para guardar información
onResume onStop
onStop La actividad ya no es visible al usuario. onRestart onDestroy
onDestroy Última llamada antes de que la actividad sea destruida. El método isFinishing() nos ayuda a saber si es final o temporal
Otro grafo
Ejercicio (I)
Clase android.util.Log
Log.<método>(String tag, String message) Métodos:
• e – error • d – debug • i – info • v – verbose • w – warning
private static final String TAG = "MyActivity"; Log.v(TAG, "index=" + i);
Ejercicio(II)
@Override…
protected void onDestroy()
protected void onPause()
protected void onRestart()
protected void onResume()
protected void onStart()
protected void onStop()
5. Recursos
Imágenes
Carpeta drawables
Tres tamaños: ldpi, mdpi, hdpi
Tamaño ldpi mdpi hdpi Relación 0.75 1 1.5 Launcher 36x36 px 48x48 px 72x72 px Menu 36x36 px 48x48 px 72x72 px Status Bar (<=2.2) 19x19 px 25x25 px 38x38 px Status Bar (>=2.3) 12x19 px 16x25 px 24x38 px Tab 24x24 px 32x32 px 48x48 px
Iconos
Simplificados
Realísta pero no fotorealista
Imágen frontal
Iluminación superior
Formatos de imágen
Recomendación:
• PNG-24 para imágenes con transparencias • JPG para imágenes sin transparencias
Archivos de cadenas
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="resource name1">cadena</string>
<string name="resource name2">cadena</string>
<string name="resource name3">cadena</string>
….
</resources>
Arrays de cadenas
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="SearchTimeFrameArray">
<item>@string/SearchTimeFrameAll</item>
<item>@string/SearchTimeFrame24h</item>
<item>@string/SearchTimeFrame48h</item>
<item>@string/SearchTimeFrameWeek</item>
…
<Spinner android:entries="@array/ SearchTimeFrameArray " android:prompt="@string/ SearchTimeFrame " android:id="@+id/SearchTime"/>
Colores
Format: #rgb | #rrggbb | #rrggbbaa
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="background">#FFF</color>
<color name="text">#000</color>
<color name="hbackground">#eb5200</color>
<color name="htext">#fff</color>
<color name="dimtext">#444</color>
</resources>
Uso de recursos desde código
El objeto R.tipo.id siempre devuelve un entero
Para recuperar el recurso en cuestión utilizamos:
getResources().get<tipo>(Integer id)
O
getResources().getIdentifier(String nombre, String tipo)
7. Interacción con el usuario
Eventos
Los layouts generan eventos de tipo onAcción
Los eventos son acciones que interrumpen el flujo del código
Se generan a partir de acciones externas
Para implementar un método onAcción una clase debe implementar la interfaz onAcciónListener
Para adjudicar la clase que implmementa el «escuchador» utilizamos el método setOnAcciónListener de la vista
Ejemplo con dos clases
public class alHacerClick implements OnClickListener { @Override public void onClick(View v){ v.setText("Click aqui!"); } } ... public class Main extends Activity { ... boton.setOnClickListener(new alHacerClick()); ... }
Ejemplo con la actividad
public class Main extends Activity implements OnClickListener { @Override public void onClick(View v){ v.setText("Click aqui!"); } ... boton.setOnClickListener(this); ... }
Múltiples eventos en la misma clase
Si tenemos a nuestra clase escuchando más de un evento OnClick, el parametro v nos permite averiguar que view ha disparado el evento.
Podemos comparar v.getId() con un recurso R.id @Override public void onClick(View v){ switch(v) { case R.id.btnOk: … case R.id.btnCancel: … } }
Un brindis con el usuario
La clase toast permite lanzar mensajes rápidos
Toast.makeText(Context context, int resId, int duration)
Toast makeText(Context context, CharSequence text, int duration)
Duration: Toast. LENGTH_LONG | Toast.LENGTH_SHORT
Diálogos. setButtons
AlertDialog: puede gestionar entre 0 y 3 respuestas AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage("Are you sure you want to exit?") .setCancelable(false) .setPositiveButton("Yes", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { MyActivity.this.finish(); } }) .setNegativeButton("No", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); AlertDialog alert = builder.create();
Diálogos. Una lista.
final CharSequence[] items = {"Red", "Green", "Blue"}; AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("Pick a color"); builder.setItems(items, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int item) { Toast.makeText(getApplicationContext(), items[item], Toast.LENGTH_SHORT).show(); } }); AlertDialog alert = builder.create();
Diálogos. Checkboxes
final CharSequence[] items = {"Red", "Green", "Blue"}; AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("Pick a color"); builder.setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int item) { Toast.makeText(getApplicationContext(), items[item], Toast.LENGTH_SHORT).show(); } }); AlertDialog alert = builder.create();
Crear un diálogo personalizado
Hemos creado el layout custom_dialog Context mContext = getApplicationContext(); Dialog dialog = new Dialog(mContext); dialog.setContentView(R.layout.custom_dialog); dialog.setTitle("Custom Dialog"); TextView text = (TextView) dialog.findViewById(R.id.text); text.setText("Hello, this is a custom dialog!"); ImageView image = (ImageView) dialog.findViewById(R.id.image); image.setImageResource(R.drawable.android);
dialog.show();
Menús
Menús. Archivos de menú
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
…
<item android:id="@+id/settings" android:title="@string/settings_label"
android:alphabeticShortcut="@string/settings_shortcut" />
…
</menu>
Abrir el menú
Sobrecargamos el método onCreateOptionsMenu public boolean onCreateOptionsMenu(Menu menu)
Llamamos a GetMenuInflater
MenuInflater inflater = getMenuInflater();
Llamamos al método inflate del MenuInflater
MenuInflater inflater = getMenuInflater();
Procesar las opciones de menú
Sobrecargamos el método onOptionsItemSelected @Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.settings:
...
}
9. Preferencias
Archivos de preferencias
Layout especializado que permite crear pantallas de configuración de forma rápida. <?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference android:key="music"
android:title="@string/music_title" android:summary="@string/music_summary"
android:defaultValue="true" />
<CheckBoxPreference android:key="hints"
android:title="@string/hints_title" android:summary="@string/hints_summary"
android:defaultValue="true"/>
</PreferenceScreen>
Mostrar archivo de preferencias
public class Prefs extends PreferenceActivity {
protected void onCreate(Bundle savedInstanceState)
{ super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings);
}
}
En el manifest: <activity android:name=".Prefs" android:label="@string/settings_title" />
Leer y escribir preferencias
PreferenceManager.getDefaultSharedPreferences(context)….
getTipo(Nombre, Predeterminado);
setTipo(Nombre, Predeterminado);
Gestionar opciones @Override
public boolean onPreferenceClick(Preference preference){
if (preference.getKey() == "About"){
Dialog dialog = new Dialog(this);
dialog.setContentView(R.layout.about);
dialog.setTitle(getResources().getString(R.string.OptionAbout));
dialog.setCancelable(true);
dialog.show();
}
if (preference.getKey() == "DoLogin"){
findPreference("User").setEnabled(
PreferenceManager.getDefaultSharedPreferences(this).getBoolean("DoLogin", false));
indPreference("Password").setEnabled(
PreferenceManager.getDefaultSharedPreferences(this).getBoolean("DoLogin", false));
}
return false;
}
10. Intents
Intents
Android se basa en multitud de pequeños componentes
Estos componentes se comunican via Intents
Mensajes utilizados para notificar a las aplicaciones de eventos
• Cambios de Hardware. Ej: tarjeta SD insertada. • Recepción de datos. Ej: llegada de un sms • Eventos de la apliación. Ej: se ha lanzado la aplicación • Etc
Es posible crear nuestros propio intents
Partes de un Intent
Partes básicas • La acción: una constante que indica la acción que se lanza. Ej.:
VIEW_ACTION, EDIT_ACTION • Los datos: uri indicando el recurso asociado. Ej.:
content://contacts/people/1 Partes opcionales
• Una categoría: agrupa el tipo de Intent • Un tipo MIME: indica el tipo de recurso si no concemos una uri • Un componente: la clase que debe tener el receptor. Obvia las
otras propiedades, pero es más frágil. • Extras: un Bundle con información extra que el receptor va a
necesitar
Ejemplos de Intent
ANSWER_ACTION CALL_ACTION DELETE_ACTION DIAL_ACTION EDIT_ACTION FACTORY_TEST_ACTION GET_CONTENT_ACTION INSERT_ACTION MAIN_ACTION: Inicio de aplicación PICK_ACTION: permitir a otras apps elegir contenido de la tuya VIEW_CONTENT: para ver contenido EDIT_CONTENT: para editar contenido
Categorias de Intent
ALTERNATIVE_CATEGORY
BROWSABLE_CATEGORY
DEFAULT_CATEGORY
GADGET_CATEGORY
HOME_CATEGORY
LAUNCHER_CATEGORY
PREFERENCE_CATEGORY
SELECTED_ALTERNATIVE_CATEGORY
TAB_CATEGORY
TEST_CATEGORY
Llegando a la actividad adecuada
Una actividad debe cumplir tres reglas para responder un Intent
• La actividad debe soportar la acción especificada • La actividad debe soportar el tipo MIME si lo hay • La actividad debe soportar TODAS las categorias nombradas en el
Intent
Uso de Intent-Filter en el manifest
Ejemplo
Iniciar otra Activity
Uso del método startActivity(Intent) o startActivityForResult (Intent, int)
Podemos pasar parametros con Intent.putExtra(int, <type>)
Recibirlos con getIntent().getExtras().get<Type>(clave);
Devolver valores de una Activity
Establecemos el valor a devolver con setResult(int resultCode) o setResult (int resultCode, Intent data)
La actividad «llamadora» implementa el método onActivityResult(int requestCode, int resultCode, Intent data)
resultCode puede ser uno de estos valores:
• RESULT_CANCELED • RESULT_OK • RESULT_FIRST_USER