Está en la página 1de 46

Formacin en Tecnologas Java

App Android: Desarrollo de aplicaciones en Android.


Tutorial: Lector RSS de CAMON
Material complementario (para hacer copy/paste del cdigo) proporcionado a los asistentes de la charla-taller impartida en CAMON Alicante el 11-12 de enero de 2011. Boyn Bonev, Pablo Suau, Miguel A. Lozano y el Dep. CCIA de la Universidad de Alicante

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-1

Formacin en Tecnologas Java

Puntos a tratar
Creacin del proyecto con Eclipse Manifest, actividad principal y recursos Vista de tabla, layout para las filas, adaptador Descarga y parsing de XML en segundo plano Descarga de imgenes en segundo plano Dilogo, men, cambios de orientacin Intents para sntesis del habla y navegador Generar paquete y firmarlo

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-2

Formacin en Tecnologas Java

Creacin del proyecto con Eclipse


Instalacin:
Descargar y descomprimir Android SDK Instalacin del plug-in para Eclipse:
Help > Install new software > Available software > Add: https://dl-ssl.google.com/android/eclipse/ Ok, seleccionar el software, Next, Finish. Reiniciar Eclipse.

Configuracin de Eclipse:
Windows > Preferences > Android > SDK Location: Indicamos la ruta donde hemos descomprimido el Android SDK

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-3

Formacin en Tecnologas Java

AVD Manager
Crear nuevo dispositivo virtual (AVD) Seleccionar la versin de Android

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-4

Formacin en Tecnologas Java

Emulador

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-5

Formacin en Tecnologas Java

Crear el proyecto
Asistente de Eclipse
Genera la estructura bsica del proyecto AndroidManifest.xml Actividad principal Layout Recursos

Conviene seleccionar la mnima versin posible


CAMON Alicante, 11-12 enero 2010 Depto. Ciencia de la Computacin e IA (Univ. Alicante) App Android-6

Formacin en Tecnologas Java

Aadir recursos
En values/strings.xml las cadenas de texto que vamos a mostrar en la interfaz En drawable, el icono de CAMON a alta, media y baja resolucin En layout/main.xml la disposicin de los componentes de la interfaz grfica

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-7

Formacin en Tecnologas Java

strings.xml
Introducimos (en la pestaa XML):
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">CAMON</string> <string name="url_base">http://www.tucamon.es</string> <string name="url_rss">http://www.tucamon.es/welcome/rss?format=rss</string> <string name="noitems">Lista vaca</string> <string name="errordered">Error en la descarga!</string> <string name="calla">Calla!</string> <string name="recargar">Recargar</string> <string name="acerca_de">Acerca de...</string> <string name="acerca_de_camon">Acerca de CAMON</string> <string name="licencia">Esta aplicacin descarga las noticias RSS de www.tucamon.es y las muestra. Fue desarrollada en el taller de Android llevado a cabo en el aula de CAMON de Alicante en enero de 2011, por los asistentes y por Boyn Bonev (Universidad de Alicante) Esta aplicacin no es \"oficial\" de CAMON, no se puede vender y su finalidad es didctica. La Universidad de Alicante y CAMON no se responsabilizan de su uso y modificaciones hechas por terceros.</string> <string <string <string <string <string <string <string <string <string name="aceptar">Aceptar</string> name="ok">OK</string> name="leemelo">Lemelo</string> name="web">Web</string> name="atras">Atrs</string> name="espere">Espere...</string> name="descargandonoticias">Descargando noticias</string> name="descargandonoticia">Descargando noticia</string> name="imagenes_descargadas">Imgenes descargadas</string>

</resources>

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-8

Formacin en Tecnologas Java

Drawable
En las carpetas drawable introducimos el icono de la CAMON, redimensionado a tres resoluciones diferentes:
drawable-hdpi/icon.png de 72x72 pxeles drawable-mdpi/icon.png de 48x48 pxeles drawable-ldpi/icon.png de 36x36 pxeles

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-9

Formacin en Tecnologas Java

layout/main.xml
Introducimos un ListView que ser la tabla donde iremos colocando las noticias de la web de CAMON. De momento no producir ningn resultado visible.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <ListView android:id="@+id/ListView01" android:layout_width="fill_parent" android:layout_height="fill_parent" android:scrollbars="vertical" /> </LinearLayout>

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-10

Formacin en Tecnologas Java

AndroidManifest.xml
Especificaremos que la aplicacin necesita permisos para acceder a Internet El XML quedara as:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="es.tucamon" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".Camon" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-sdk android:minSdkVersion="4" />

<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-11

Formacin en Tecnologas Java

Actividad principal
es.tucamon.Camon.java Aadimos dos cadenas que nos harn falta, recogindolas de los recursos string. Aadimos una variable Context porque accederemos a ella varias veces.
public class Camon extends Activity { private static String URL_BASE; private static String URL_RSS; Context context; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Context = getApplicationContext(); URL_BASE = getString(R.string.url_base); URL_RSS = getString(R.string.url_rss); } }

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-12

Formacin en Tecnologas Java

Acceso a componentes del layout


Obtenemos una referencia utilizando el identificador del elemento. Asignamos un Listener para clicks sobre los items de la tabla
public class Camon extends Activity { private static String URL_BASE; private static String URL_RSS; Context context;

ListView listView;
/** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Context = getApplicationContext(); URL_BASE = getString(R.string.url_base); URL_RSS = getString(R.string.url_rss);

listView = (ListView)findViewById(R.id.ListView01); listView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View arg1, int position, long id) {
// en "id" tenemos el nmero de fila seleccionada

} });
} }

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-13

Formacin en Tecnologas Java

Clase noticia
Creamos una nueva clase Noticia.java en el mismo paquete
public String getTitulo() { return titulo; } public void setTitulo(String titulo) { this.titulo = titulo; } public Spanned getDescripcion() { return descripcion; } public void setDescripcion(Spanned descripcion) { this.descripcion = descripcion; } public class Noticia { public String getLink() { private String titulo; return link; private Spanned descripcion; } private String link; public void setLink(String link) { private String fecha; this.link = link; private String linkImagen; } private Drawable imagen; public String getFecha() { return fecha; public Noticia(){ } titulo = ""; public void setFecha(String fecha) { descripcion = new SpannedString(""); this.fecha = fecha; link = ""; } fecha = ""; public String getLinkImagen() { linkImagen = ""; return linkImagen; } } public Noticia(String titulo, String fecha, Spanned descripcion, public void setLinkImagen(String linkImagen) { String link,String linkImagen){ this.linkImagen = linkImagen; this.titulo=titulo; } this.fecha=fecha; public void setImagen(Drawable imagen) { this.descripcion=descripcion; this.imagen = imagen; this.link=link; } this.linkImagen=linkImagen; public Drawable getImagen() { } return imagen; } }

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-14

Formacin en Tecnologas Java

Layout para las filas


En la carpeta res/layout creamos un nuevo xml llamado fila.xml Le aadimos una imagen con identificador @+id/FilaImagen y al lado de ella un Layout que disponga los componentes verticalmente, con dos campos de texto: @+id/FilaTexto1 y @+id/FilaTexto2
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <ImageView android:id="@+id/FilaImagen" android:layout_width="100px" android:layout_height="70px" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/FilaTexto1" android:textSize="12sp" android:textColor="#E1DEFF" android:textStyle="bold" android:layout_width="fill_parent" android:layout_height="wrap_content"/> <TextView android:id="@+id/FilaTexto2" android:textSize="10sp" android:layout_width="fill_parent" android:layout_height="wrap_content"/> </LinearLayout> </LinearLayout> App Android-15

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

Formacin en Tecnologas Java

Adaptador para la tabla


NoticiasAdapter colocar la informacin de los objetos Noticia en el layout fila.xml, para cada fila (para cada noticia)
public class NoticiasAdapter extends ArrayAdapter<Noticia> { ArrayList<Noticia> noticias; Context context; public NoticiasAdapter(Context context, int textViewResourceId, ArrayList<Noticia> noticias) { super(context, textViewResourceId, noticias); this.noticias = noticias; this.context = context; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.fila, null); } Noticia noticia = noticias.get(position); if (noticia != null) { TextView tv1 = (TextView) convertView.findViewById(R.id.FilaTexto1); TextView tv2 = (TextView) convertView.findViewById(R.id.FilaTexto2); ImageView iv = (ImageView) convertView.findViewById(R.id.FilaImagen); if (tv1 != null) { tv1.setText(noticia.getTitulo()); } if (tv2 != null) { tv2.setText(noticia.getFecha()); } if (iv != null) { iv.setImageDrawable(noticia.getImagen()); } } return convertView; } }

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-16

Formacin en Tecnologas Java

Adaptador para la table


Declaramos una lista de noticias y el adaptador Asignamos el adaptador a la tabla (listView) dentro del mtodo onCreate
public class Camon extends Activity { private static String URL_BASE; private static String URL_RSS; Context context; ListView listView;

ArrayList<Noticia> noticias; NoticiasAdapter noticiasAdapter;


@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Context = getApplicationContext(); URL_BASE = getString(R.string.url_base); URL_RSS = getString(R.string.url_rss); noticias = new ArrayList<Noticia>(); noticiasAdapter = new NoticiasAdapter(context, R.layout.fila, noticias); listView = (ListView)findViewById(R.id.ListView01);

listView.setAdapter(noticiasAdapter);
listView.setOnItemClickListener(new OnItemClickListener() {

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-17

Formacin en Tecnologas Java

Descarga y parsing de XML en segundo plano


Las operaciones lentas deben realizarse en segundo plano, de lo contrario la aplicacin dejar de responder y Android nos ofrecer matarla. Cualquier operacin de red se puede considerar una operacin lenta. Para crear procesos en segundo plano podemos utilizar Threads.
El problema: no podemos acceder a los componentes grficos desde otro hilo que no sea el principal. La solucin: Android nos ofrece las AsyncTask que facilitan el acceso a los componentes grficos
CAMON Alicante, 11-12 enero 2010 Depto. Ciencia de la Computacin e IA (Univ. Alicante) App Android-18

Formacin en Tecnologas Java

Declaracin de AsyncTask
La declaramos dentro de la clase Camon para poder acceder a sus campos (sus variables)
public class Camon extends Activity { private static String URL_BASE; private static String URL_RSS; Context context; ListView listView; ArrayList<Noticia> noticias; NoticiasAdapter noticiasAdapter; TareaDescarga tarea; @Override public void onCreate(Bundle savedInstanceState) { // ... lanzaDescargaDeNoticias(); } void lanzaDescargaDeNoticias(){ try { tarea = new TareaDescarga(); tarea.execute(new URL(URL_RSS)); } catch (MalformedURLException e) { e.printStackTrace(); } } private class TareaDescarga extends AsyncTask<URL, String, List<Noticia>>{ // ... } }

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-19

Formacin en Tecnologas Java

Mtodos de AsyncTask
private class TareaDescarga extends AsyncTask<URL, String, List<Noticia>>{ ArrayList<Noticia> noticiasDescargadas; ProgressDialog progressDialog; boolean error=false; @Override protected List<Noticia> doInBackground(URL... params) { return noticiasDescargadas; } @Override protected void onPreExecute() { } @Override protected void onCancelled() { } @Override protected void onProgressUpdate(String... values) { } @Override protected void onPostExecute(List<Noticia> result) { } }

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-20

Formacin en Tecnologas Java

Mtodos de AsyncTask
El mtodo doInBackground( ) realizar la descarga pero no podr acceder a la interfaz; lo har solicitando la ejecucin de onProgressUpdate( ) y onPostExecute( ) Tambin declaramos un ProgressDialog que debemos ir actualizando durante el progreso de la descarga (y parsing de XML).

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-21

Formacin en Tecnologas Java

AsyncTask acceso a interfaz


@Override protected void onPreExecute() { super.onPreExecute(); noticiasAdapter.clear(); progressDialog = ProgressDialog.show(Camon.this, getString(R.string.espere), getString(R.string.descargandonoticias),true,true); progressDialog.setOnCancelListener(new OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { tarea.cancel(true); } }); } @Override protected void onCancelled() { super.onCancelled(); noticiasAdapter.clear(); noticiasDescargadas = new ArrayList<Noticia>(); } @Override protected void onProgressUpdate(String... progreso) { super.onProgressUpdate(progreso); progressDialog.setMessage(progreso[0]); noticiasAdapter.notifyDataSetChanged(); } @Override protected void onPostExecute(List<Noticia> result) { super.onPostExecute(result); for(Noticia n:noticiasDescargadas){ noticiasAdapter.add(n); } noticiasAdapter.notifyDataSetChanged(); progressDialog.dismiss(); if(error){ Toast.makeText(context, R.string.errordered, Toast.LENGTH_LONG).show(); } }

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-22

Formacin en Tecnologas Java

AsyncTask doInBackground( )
Utilizaremos XmlPullParser para trocear el documento XML.
@Override protected List<Noticia> doInBackground(URL... params) { try { URL url = params[0]; noticiasDescargadas = new ArrayList<Noticia>(); XmlPullParserFactory parserCreator = XmlPullParserFactory.newInstance(); XmlPullParser parser = parserCreator.newPullParser(); parser.setInput(url.openStream(), null); int parserEvent = parser.getEventType(); int nItems = 0; while (parserEvent != XmlPullParser.END_DOCUMENT) { switch (parserEvent) { // Examinar la informacin parseada // ... } parserEvent = parser.next(); } } catch (Exception e) { Log.e("Net", "Error in network call", e); error = true; } return noticiasDescargadas; }

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-23

Formacin en Tecnologas Java

Informacin a parsear
Cdigo fuente descargado de http://www.tucamon.es/welcome/rss?format=rss
<?xml version="1.0" encoding="UTF-8"?> <rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"> <channel> <atom:link type="application/rss+xml" rel="self" href="http://www.tucamon.es/contenido/rss"/> <title>Feed de art&#237;culos</title> <link>http://www.tucamon.es/</link> <description>Feed de art&#237;culos</description> <language>es-ES</language> <item> <title>Presentaci&#243;n de Los zapatos de tac&#243;n rojos</title> <description>&lt;p&gt;El &lt;strong&gt; ... &lt;img alt=&quot;Zapatos&quot; src=&quot;/photo_posts/0000/8463/zapatos.jpg?1293014230&quot; /&gt;</description> <author>(Chivone)</author> <pubDate>Wed, 22 Dec 2010 11:46:57 +0100</pubDate> <link>/contenido/presentacion-de-los-zapatos-de-tacon-rojos</link> <guid>/contenido/presentacion-de-los-zapatos-de-tacon-rojos</guid> </item> <item> <title>D-FORMA inaugura su exposici&#243;n en CAMON Madrid</title> <description>&lt;p&gt;El colectivo D-Forma present&amp;oacute; en CAMON&amp; ... </description> <author>(Silvia Mu&#241;oz Garc&#237;a)</author> <pubDate>Tue, 21 Dec 2010 19:56:47 +0100</pubDate> <link>/contenido/d-forma-emulo-exposicion-paisaje-terro</link> <guid>/contenido/d-forma-emulo-exposicion-paisaje-terro</guid> </item> ...

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-24

Formacin en Tecnologas Java

El bucle del XmlPullParser


while (parserEvent != XmlPullParser.END_DOCUMENT) { switch (parserEvent) { case XmlPullParser.START_TAG: String tag = parser.getName(); if (tag.equalsIgnoreCase("item")) { publishProgress(getString(R.string.descargandonoticia)+" "+(++nItems)); Noticia noticia = new Noticia(); parserEvent = parser.next(); boolean itemClosed = false; while (parserEvent != XmlPullParser.END_DOCUMENT && !itemClosed) { switch (parserEvent) { case XmlPullParser.START_TAG: tag = parser.getName(); if (tag.equalsIgnoreCase("title")) { noticia.setTitulo(parser.nextText()); } if (tag.toLowerCase().contains("pubdate")) { noticia.setFecha(parser.nextText()); } if (tag.equalsIgnoreCase("link")) { noticia.setLink(URL_BASE+parser.nextText()); } if (tag.equalsIgnoreCase("description")) { String textoHtml = parser.nextText(); Spanned texto = Html.fromHtml(textoHtml, new ImageGetter(), null); noticia.setDescripcion(texto); String linkImagen = URL_BASE+imageSource; noticia.setLinkImagen(linkImagen); } break; case XmlPullParser.END_TAG: tag = parser.getName(); if(tag.equalsIgnoreCase("item")){ itemClosed = true; noticiasDescargadas.add(noticia); } break; } parserEvent = parser.next(); } } break; } parserEvent = parser.next(); }

String imageSource=null; class ImageGetter implements Html.ImageGetter { public Drawable getDrawable(String source) { imageSource = source; return new BitmapDrawable(); } };

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-25

Formacin en Tecnologas Java

Primer prototipo
Tras descargar las noticias debe mostrarlas en la tabla El formato es el indicado por fila.xml y el adaptador que hemos implementado.
CAMON Alicante, 11-12 enero 2010 Depto. Ciencia de la Computacin e IA (Univ. Alicante) App Android-26

Formacin en Tecnologas Java

Descarga de imgenes
Aadimos a Noticia un mtodo que descarga la imagen de la noticia, dada una URL
public class Noticia { private String titulo; private Spanned descripcion; private String link; private String fecha; private String linkImagen; private Drawable imagen; //... public void loadImagen(String url) throws MalformedURLException, IOException{ InputStream is = (InputStream) new URL(url).getContent(); imagen = Drawable.createFromStream(is, "src"); } }

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-27

Formacin en Tecnologas Java

Descarga de imgenes en segundo plano

private class TareaDescargaImagen extends AsyncTask<List<Noticia>, String, Drawable>{ @Override protected Drawable doInBackground(List<Noticia>... arg0) { List<Noticia> noticias = arg0[0]; int imagenesSinCargar = noticias.size(); while(imagenesSinCargar > 0){ imagenesSinCargar = noticias.size(); for(Noticia n:noticias){ if(n.getImagen()==null || n.getImagen().getIntrinsicHeight() <= 0){ // Reintento necesario? try{ n.loadImagen(n.getLinkImagen()); publishProgress(""); }catch(Exception e){ n.setImagen(getResources().getDrawable(R.drawable.icon)); } }else{ imagenesSinCargar --; } } try { Thread.sleep(1000); } catch (InterruptedException e) { } } return null; } @Override protected void onPostExecute(Drawable result) { super.onPostExecute(result); Toast.makeText(context, getString(R.string.imagenes_descargadas), Toast.LENGTH_SHORT).show(); noticiasAdapter.notifyDataSetChanged(); } @Override protected void onProgressUpdate(String... values) { super.onProgressUpdate(values); noticiasAdapter.notifyDataSetChanged(); } }

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-28

Formacin en Tecnologas Java

Iniciar la descarga
Podemos iniciar la descarga de imgenes una vez que las noticias se hayan cargado.
private class TareaDescarga extends AsyncTask<URL, String, List<Noticia>>{ // ... @Override protected void onPostExecute(List<Noticia> result) { super.onPostExecute(result); for(Noticia n:noticiasDescargadas){ noticiasAdapter.add(n); } noticiasAdapter.notifyDataSetChanged(); progressDialog.dismiss(); if(error){ Toast.makeText(context, R.string.errordered, Toast.LENGTH_LONG).show(); } lanzaDescargaDeImagenes(); } } void lanzaDescargaDeImagenes(){ TareaDescargaImagen tdi = new TareaDescargaImagen(); tdi.execute(noticias); }

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-29

Formacin en Tecnologas Java

Men el recurso XML


Creamos un New Android XML File, de tipo men y lo llamamos menu.xml. El asistente lo coloca en res/menu/menu.xml Lo editamos e introducimos tres items:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/item01" android:title="@string/calla"></item> <item android:id="@+id/item02" android:title="@string/recargar"></item> <item android:id="@+id/item03" android:title="@string/acerca_de"></item> </menu>

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-30

Formacin en Tecnologas Java

Men creacin en la Activity principal


@Override public boolean onCreateOptionsMenu(Menu m) { getMenuInflater().inflate(R.menu.menu, m); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch(item.getItemId()){ case R.id.item01: break; case R.id.item02: lanzaDescargaDeNoticias(); break; case R.id.item03: break; } return true; }

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-31

Formacin en Tecnologas Java

Dilogo Acerca de
case R.id.item03: AlertDialog.Builder ab=new AlertDialog.Builder(Camon.this); ab.setTitle(R.string.acerca_de_camon); ab.setIcon(getResources().getDrawable(R.drawable.icon)); ab.setMessage(R.string.licencia); ab.setPositiveButton(R.string.aceptar,null); ab.show(); break;

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-32

Formacin en Tecnologas Java

Dilogo con la noticia


Creamos una clase en un fichero NoticiaAlertDialog.java, en el mismo paquete.
public class NoticiaAlertDialog extends AlertDialog.Builder { private Noticia n; private Context c; /** * After creating the NoticiaAlertDialog, don't forget to call .show(); * @param context The main Activity context. * @param noticia Noticia object with information on Noticia */ protected NoticiaAlertDialog(Context context, Noticia noticia) { super(context); n = noticia; c = context; this.setTitle(n.getTitulo()); this.setIcon(context.getResources().getDrawable(R.drawable.icon)); this.setMessage(n.getDescripcion()); this.setNegativeButton(context.getString(R.string.atras), null); this.setPositiveButton(context.getString(R.string.leemelo), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }); this.setNeutralButton(context.getString(R.string.web), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }); }

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-33

Formacin en Tecnologas Java

Mostrar dilogo con la noticia


Lo mostraremos al hacer click sobre un item de la lista. Introducimos el cdigo en el listener que ya tenamos asignado a la lista:
listView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View arg1, int position, long id) { Noticia n = noticias.get((int)id); NoticiaAlertDialog nad = new NoticiaAlertDialog(Camon.this, n); nad.show(); } });

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-34

Formacin en Tecnologas Java

Cambios de orientacin
Cuando cambia la orientacin del mvil de vertical a horizontal, Android la reinicia para que todos los componentes se coloquen de nuevo en la nueva configuracin de pantalla. En consecuencia las noticias se empiezan a cargar de nuevo. Hay 3 maneras de evitarlo:
Deshabilitarlo: <activity android:name="Camon"
android:configChanges="keyboardHidden|orientation">

Ocuparnos de recolocar los componentes (complicado). Guardarnos las noticias para no volver a bajarlas.
CAMON Alicante, 11-12 enero 2010 Depto. Ciencia de la Computacin e IA (Univ. Alicante) App Android-35

Formacin en Tecnologas Java

Cambios de orientacin
public void onCreate(Bundle savedInstanceState) { // ... final ArrayList<Noticia> data = (ArrayList<Noticia>) getLastNonConfigurationInstance(); if (data == null) { noticias = new ArrayList<Noticia>(); noticiasAdapter = new NoticiasAdapter(context, R.layout.fila, noticias); lanzaDescargaDeNoticias(); }else{ noticias = data; noticiasAdapter = new NoticiasAdapter(context, R.layout.fila, noticias); } // ... } @Override public Object onRetainNonConfigurationInstance() { final ArrayList<Noticia> data = noticias; return data; }

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-36

Formacin en Tecnologas Java

Abrir el navegador web con un intent


Hay actividades que nos proporciona el sistema operativo, y que pueden ser ejecutadas por medio de un Intent. Abrimos el navegador web al pulsar el botn correspondiente:
public class NoticiaAlertDialog extends AlertDialog.Builder { // ... protected NoticiaAlertDialog(Context context, Noticia noticia) { // ... this.setNeutralButton(context.getString(R.string.web), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(n.getLink())); c.startActivity( intent ); } }); } }

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-37

Formacin en Tecnologas Java

Sntesis del habla


Se utiliza la clase TextToSpeech Slo se puede utilizar su mtodo .speak( ) una vez que ha terminado su inicializacin (implementar mtodo onInit). Adems es necesario tener instalado el TextToSpeech en el sistema operativo. Se puede hacer una comprobacin y si no est instalado, lanzar la actividad que ofrece su instalacin. Una vez terminado, hay que llamar al mtodo .shutdown( ) del objeto de clase TextToSpeech, para que se liberen los recursos nativos involucrados.
CAMON Alicante, 11-12 enero 2010 Depto. Ciencia de la Computacin e IA (Univ. Alicante) App Android-38

Formacin en Tecnologas Java

Speech
Creamos, en un fichero aparte, una clase que encapsule toda la lgica necesaria para utilizar la sntesis del habla: Speech.java
package es.tucamon; import java.util.Locale; import android.app.Activity; import android.content.Intent; import android.speech.tts.TextToSpeech; import android.speech.tts.TextToSpeech.Engine; import android.speech.tts.TextToSpeech.OnInitListener; /** * Encapsulates some methods for using TextToSpeech from an Activity. * @author Boyan Bonev, Universidad de Alicante * @date December 20th, 2010 */ public class Speech { private Activity activity; private TextToSpeech tts; private static final int TTS_DATA_CHECK = 1; private String text; private boolean isTTSinstalled = false; private boolean isTTSinitialized = false;

/** * Gets the reference to the Activity for being able to call Intents. * @param activity */ public Speech(Activity activity){ this.activity = activity; } // ... }

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-39

Formacin en Tecnologas Java

Mtodos de Speech
/** * Does not assume that TextToSpeech is installed but starts an intent * for checking whether it is or not. The Activity which calls this * function should implement: * protected void onActivityResult(int requestCode, int resultCode, Intent data) { * speech.installOrSpeak(requestCode,resultCode); * } * @param txt Text to speak */ public void speakAfterCheckingForTTS(String txt){ this.text = txt; if(isTTSinitialized){ tts.speak(txt, TextToSpeech.QUEUE_ADD, null); }else{ Intent intent = new Intent(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA); activity.startActivityForResult(intent, TTS_DATA_CHECK); } } /** * Assumes that TextToSpeech is installed * @param txt Text to speak */ public void speakWithoutCheckingForTTS(String txt){ tts = new TextToSpeech(activity, new OnInitListener() { public void onInit(int status) { if (status == TextToSpeech.SUCCESS) { Locale loc = new Locale("es","",""); if (tts.isLanguageAvailable(loc) >= TextToSpeech.LANG_AVAILABLE) tts.setLanguage(loc); tts.setPitch(0.8f); tts.setSpeechRate(1.1f); isTTSinitialized = true; //Speak this: tts.speak(text, TextToSpeech.QUEUE_ADD, null); } } }); } /** * Called after checking for the installation of TTS * @param requestCode * @param resultCode */ public void installOrSpeak(int requestCode, int resultCode){ if(requestCode == TTS_DATA_CHECK){ if (resultCode == Engine.CHECK_VOICE_DATA_PASS) { isTTSinstalled = true; speakWithoutCheckingForTTS(text); } else { Intent installVoice = new Intent(Engine.ACTION_INSTALL_TTS_DATA); activity.startActivity(installVoice); } } } /** * Should be called in the onPause() or onStop() method of the Activity. */ public void stop(){ if (tts != null) { tts.stop(); tts.shutdown(); isTTSinitialized = false; } } public boolean isTTSinstalled() { return isTTSinstalled; }

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-40

Formacin en Tecnologas Java


public class Camon extends Activity { Speech speech; public void onCreate(Bundle savedInstanceState) { // ...

Uso de la clase Speech


La declaramos en nuestra actividad Camon y la inicializamos en onCreate( ). Aadimos el mtodo onActivityResult( ) e invocamos Speech.stop( ) cuando Camon termine su ejecucin, en onStop( ), as como cuando se pulse el botn Calla del men. Ya tenemos cundo callar, ahora falta decidir cundo hablar.
}

speech = new Speech(this); // ... } protected void onActivityResult(int requestCode, int resultCode, Intent data) { speech.installOrSpeak(requestCode,resultCode); } @Override public void onStop() { speech.stop(); super.onStop(); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch(item.getItemId()){ case R.id.item01: speech.stop(); break; case R.id.item02: lanzaDescargaDeNoticias(); break; case R.id.item03: // ... break; } return true; }

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-41

Formacin en Tecnologas Java

Speech en NoticiaAlertDialog
Para pronunciar la descripcin de la noticia al pulsar leer del NoticiaAlertDialog, le pasaremos por el constructor el objeto speech ya inicializado .
public class NoticiaAlertDialog extends AlertDialog.Builder { private Noticia n; private Context c; private Speech s; protected NoticiaAlertDialog(Context context, Speech speech, Noticia noticia) { super(context); n = noticia; c = context; s = speech; this.setTitle(n.getTitulo()); this.setIcon(context.getResources().getDrawable(R.drawable.icon)); this.setMessage(n.getDescripcion()); this.setNegativeButton(context.getString(R.string.atras), null); this.setPositiveButton(context.getString(R.string.leemelo), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { s.speakAfterCheckingForTTS(n.getTitulo()+". "+n.getDescripcion()); } }); this.setNeutralButton(context.getString(R.string.web), new DialogInterface.OnClickListener() { // ... }); } }

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-42

Formacin en Tecnologas Java

Pasar Speech por el constructor


No olvidemos pasar el objeto speech como parmetro del constructor de NoticiaAlertDialog
listView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View arg1, int position, long id){ Noticia n = noticias.get((int)id); NoticiaAlertDialog nad = new NoticiaAlertDialog(Camon.this, speech, n); nad.show(); } });

La aplicacin ya permite escuchar una descripcin mientras seguimos examinando la lista.


CAMON Alicante, 11-12 enero 2010 Depto. Ciencia de la Computacin e IA (Univ. Alicante) App Android-43

Formacin en Tecnologas Java

Paquete
Podemos generar un paquete instalable de prueba, firmndolo con un certificado self-signed (no firmado por ninguna autoridad certificadora).
keytool -genkey -v -keystore mialmacen.keystore -alias aliasname -keyalg RSA -validity 10000 Introducimos una contrasea para el almacn y otra para el certificado (puede ser la misma). Eclipse: sobre el proyecto, Android tools > Export signed package. Nos pedir abrir el almacn, y su contrasea.

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-44

Formacin en Tecnologas Java

Probar el paquete
Debemos guardarlo en el dispositivo mvil, copindolo por cable o envindolo por e-mail.
Si al enviar el .apk a gmail, y al intentar abrirlo da un error, se puede probar renombrndolo a .zip; entonces el cliente de gmail nos permite guardarlo; le cambiamos el nombre a .apk (con un gestor de archivos) y lo ejecutamos.

Al ejecutarlo se inicia el instalador que nos advierte que la aplicacin necesita acceso a Internet.
CAMON Alicante, 11-12 enero 2010 Depto. Ciencia de la Computacin e IA (Univ. Alicante) App Android-45

Formacin en Tecnologas Java

Preguntas...?

CAMON Alicante, 11-12 enero 2010

Depto. Ciencia de la Computacin e IA (Univ. Alicante)

App Android-46

También podría gustarte