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 onStart con su estado anterior.
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â&#x20AC;Ś 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> â&#x20AC;Ś. </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> â&#x20AC;Ś <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)â&#x20AC;Ś. 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