You are on page 1of 61

[Manual] [SDK v1.

0] Creacin de base de datos


Despus de ver que han cambiado cosas durante todas las versiones que han sido saliendo de la SDK de Android voy a intentar explicar como crear y usar una base de datos en Android. Es nicamente una manera porque hay ms, y si al uien ve otras maneras estar!a muy bien que las "uera poniendo. #. $o me%or es que creemos una nueva clase donde tendremos los mtodos que van a crear la base de datos y van a hacer las peticiones que nos devolvern los datos que uardamos, as! como para insertarlos c&modamente. A re amos lo primero una variable lobal que apunte a la base de datos que vamos a crear y a'adiremos la librer!a de S($iteDatabase que necesitaremos. Es importante que a'adamos el contexto en el constructor ya que lo necesitaremos para crear la base de datos.
Cdigo : import android.database.sqlite.SQLiteDatabase; public class BD{ SQLiteDatabase db; public BD(Context ctx){ //constructor //apertura de base de datos //creacin de tablas } }

). A'adimos la creaci&n o apertura de la base de datos. $o hacemos mediante el contexto, para ello, el primer ar umento del mtodo *open+r,reateDatabase* es el nombre que tendr la base de datos, el se undo indicar si es de lectura, escritura o ambas, por de"ecto se pone - para ambas, y el tercer ar umento no ten o muy claro que es, pero se n las A./s se tiene que a'adir la clase que ser llamadapara instanciar un cursor 0clase ,ursor supon o1 cuando se hace al una petici&n. .or ahora lo de%amos en null.
Cdigo : db = ctx.openOrCreateDatabase( bdpr!eba " #" null);

2. 3a tenemos la base de datos abierta y si no estuviera creada la crea y la abre. El si uiente paso ser crear las tablas. .ara ello lo ms "cil es crear Strin s con la sentencia de creaci&n de las tablas, las podis poner en un archivo separado o como variable lobal, es indi"erente.
Cdigo : String C$%&'%('&BL% = C$%&'% '&BL% )* +O' %,)S'S tablita ( id )+'%.%$ /$)0&$1 2%1 &3'O)+C$%0%+'" dato text +O' +3LL); ; -

Despus habr que e%cutar ese comando para la creaci&n de la tabla, por eso, %usto despus de la creaci&n o apertura de la base de datos a'adiremos la e%ecuci&n de ese Strin .

Cdigo : db.execSQL(C$%&'%('&BL%);

4. Es importante que a'adamos capturas de excepciones porque si la base de datos est creada e intenta crear la tabla saltar la excepci&n y se saldr, de esa manera la capturaremos y podemos verla en los $o s. 5ecuerdo que para poder ver lue o los lo s bien hay que "iltrar y habr que a'adir una re"erencia.
Cdigo : try{ }catch(Exception e){ Lo4.d( B&S%D%D&'OS " } %xception initDB5 - e.toStrin4());

6. Ahora vamos a a'adir al n valor a la tabla, para ello crearemos un mtodo para poderlos meter automticamente. Se puede hacer "cilmente con la misma sentencia que se ha utili7ado para la creaci&n de las tablas, pero ahora usaremos uno de los mtodos que Android nos da. .ara ello le daremos el dato que queremos introducir 0s&lo tenemos ese campo, si no habr!a que poner el resto1 y creamos un ,ontent8alues, esta clase contendr el nombre del campo de la tabla que queremos a'adir el valor y el valor que tendr mediante *put*. 9na ve7 introducidos todos, se a'aden mediante *insert*, indicando el nombre de la tabla, el se undo ar umento no ten o claro qu es porque la explicaci&n que dan las A./s es que se utilice para no peritir introducir una l!nea completamente vac!a, pero por de"ecto lo ponemos a null y en el tercer ar umento introduciremos los ,ontent8alues antes uardados. $a "unci&n devolver un lon ya que eso devuelve el insert, devolviendo el /D de la l!nea insertada o :# en caso de error.
Cdigo : public lon4 addDato(String dato){ Content6al!es c6 = new Content6al!es(); c6.p!t( dato " dato); return db.insert( tablita " null" c6); }

;. Si queremos reco er datos podemos crear otro mtodo para "acilitar el proceso. Al i ual que en el paso anterior, se podr!a hacer mediante un simple exe, pero vamos a utili7ar otro mtodo que nos da Android para hacer peticiones. Sin duda si se utili7a bien se pueden conse uir mtodos sencillos y bastante automticos para todas las peticiones que necesitemos. $o primero que debemos crear es un array de Strin con el nombre de todas las columnas que queremos conse uir. Despus creamos el cursor donde se nos devolvern los datos de la petici&n. $a petici&n se hace mediante el mtodo *query* y contiene muchos campos< : nombre de la tabla : lista de columnas 0array de Strin creado antes1 : la selecci&n, lo que s epondr!a en la clusula =>E5E

: : : : :

ar umentos de la selecci&n roup by havin order by limit

Si sabes hacer sentencias S($ ser muy sencillo porque es i ual, pero no hay que armarlas en Strin s enormes, por lo que es bastante ms c&modo al menos a mi parecer. 3 como siempre que hacemos al o en S($ hay que reco er cualquier excepci&n que pudiera salir. Despus habr que leer el cursor devuelto, para ello hay que ir pasando al si uiente en todo momento, con un simple bucle *?hile* conse uiremos pasar por todos de manera sencilla e introducir los datos donde queramos. @ambin podemos enviar el cursor y lue o ya evaluarlo donde queramos, pero en mi caso he querido devolver un *Array$ist* de Strin s, por lo que va leyendo todos los datos sacados y los devuelve despus en el *Array$ist*. ,uando hace el * etStrin * hay que indicarle qu columna quieres co er, que ser el entero que va entre parntesis.
Cdigo : public &rra7List8Strin49 4etDatos(String txt){ String:; col!mns = { dato }; Cursor c = null; try{ c = db.q!er7( dato " col!mns" n!ll " null" null" null" dato ); }catch(Exception e){ Lo4.d( B&S%D%D&'OS " %xception 4et0a<es5 - e.toStrin4()); } &rra7List8Strin49 aL = new &rra7List8Strin49(); =>ile(c.mo?e'o+ext()) aL.add(c.4etStrin4(#)); return aL; }

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: $a clase quedar!a al o as!<


Cdigo : .....package..... import android.database.sqlite.SQLiteDatabase; .....otros imports q!e se necesiten..... public class BD{ SQLiteDatabase db; String C$%&'%('&BL% = C$%&'% '&BL% )* +O' %,)S'S tablita ( id )+'%.%$ /$)0&$1 2%1 &3'O)+C$%0%+'" dato text +O' +3LL); ; public BD(Context ctx){ try{ //apertura de base de datos db = ctx.openOrCreateDatabase( bdpr!eba " #" null); //creacin de tablas db.execSQL(C$%&'%('&BL%); }catch(Exception e){ -

Lo4.d( B&S%D%D&'OS " } }

%xception initDB5

- e.toStrin4());

public lon4 addDato(String dato){ Content6al!es c6 = new Content6al!es(); c6.p!t( dato " dato); return db.insert( tablita " null" c6); public &rra7List8Strin49 4etDatos(String txt){ String:; col!mns = { dato }; Cursor c = null; try{ c = db.q!er7( dato " col!mns" n!ll " null" null" null" dato ); }catch(Exception e){ Lo4.d( B&S%D%D&'OS " %xception 4et0a<es5 - e.toStrin4()); } &rra7List8Strin49 aL = new &rra7List8Strin49(); =>ile(c.mo?e'o+ext()) aL.add(c.4etStrin4(#)); return aL;

} }

A. .ara llamar a la clase lo podemos hacer desde la clase principal, la *Activity*, crearemos una variable lobal de la clase que hemos creado, y despus en el mtodo que primero se e%ecuta *on,reate* crearemos una instancia de la base de datos, que despus ya podremos utili7ar libremente.
Cdigo : BD db; /** Called when the activity is first created. */ @O?erride public ?oid onCreate(B!ndle sa?ed)nstanceState) { super.onCreate(sa?ed)nstanceState); setContent6ie=($.la7o!t.main); db = new BD(this); }

Bo descarto que haya al o mal sobretodo si se copia directamente el ltimo c&di o dado, lo he explicado para que se entienda todo ms o menos y puedas continuar creando cosas, si tienes al una duda o crees que hay al o mal o quieres ampliarlo no dudes en decirlo. Espero que sirva de ayuda. Saludos.

[Manual] Crear mens.


>ola a todos< 8isto que al uno si ue teniendo dudas de como implementar nuestro propio men en las aplicaciones, voy a poneros un tro7o de c&di o que es bastante explicativo.

A la primera parte se le llama una ve7 dentro de nuestra aplicaci&n y es la encar ada de montar el men. Aqu! deberemos ir a'adiendo las di"erentes opciones. @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); menu.add(0, 0, !oom ); menu.add(0, ", #ettings ); menu.add(0, $, Ot%er ); return true; &

$o se undo es crear el mtodo que entienda que hay que hacer cuando se pulsa en cada una de las acciones de nuestro men. @Override public boolean onOptions'tem#elected(Menu.'tem item){ s(itc% (item.get'd()) { case 0: s%o()lert( Menu 'tem Clic*ed , !oom , o* , null, +alse, null); return true; case ": s%o()lert( Menu 'tem Clic*ed , #ettings , o* , null, +alse, null); return true; case $: s%o()lert( Menu 'tem Clic*ed , Ot%er , o* , null, +alse, null); return true; & return +alse; & El e%emplo es muy sencillito, y lo nico que hace es ense'arnos ventanas de alerta al presionar sobre las opciones del men. El men tiene muchos parmetros con"i urables, al unos intentar ir ponindolos aqu! por si no se entienden bien, os animo a que investi uis y vayis probando cosas.

[Manual] Notificaciones en la barra de estado


>ola a todos< Aqu! os de%o un sencillo tutorial para aprender a lan7ar noti"icaciones en la barra de estado. A petici&n popular he creado un sencillo pro rama que coloca la bandera de t pa!s en la barra de noti"icaciones. Cdiv ali nD*center*ECbrECim srcD*http<FFs4.subirima enes.comFima enF24)-62Gdevice.pn *ECFdivE
Cdigo android:

package indra.android.taller; import import import import import import import android.app.&cti?it7; android.app.+otiAication; android.app.+otiAication0ana4er; android.app./endin4)ntent; android.content.Context; android.content.)ntent; android.os.B!ndle;

public class +otiAicaciones extends &cti?it7 { /** Called when the activity is first created. */ @O?erride public ?oid onCreate(B!ndle sa?ed)nstanceState) { super.onCreate(sa?ed)nstanceState); setContent6ie=($.la7o!t.main); //Recuperamos el administrador de notificaciones +otiAication0ana4er m+otiAication0ana4er = (+otiAication0ana4er)4etS7stemSer?ice(Context.+O')*)C&')O+(S%$6)C%); //Nos creamos una nueva notificacin, con el icono de la bandera que nosotros queramos, sin texto y lista para lan arse +otiAication notiAication = new +otiAication($.dra=able.spain" "System.c!rrent'ime0illis()); //!efinimos la interfa de la notificacin Context context = 4et&pplicationContext(); C>arSeq!ence content'itle = ; C>arSeq!ence content'ext = ; //"specificamos que accin reali ar si pulsamos sobre la notificacin )ntent notiAication)ntent = new )ntent(this" +otiAicaciones.class); /endin4)ntent content)ntent = /endin4)ntent.4et&cti?it7(this" #" notiAication)ntent" #); notiAication.setLatest%?ent)nAo(context" content'itle" content'ext" content)ntent); //#an amos la notificacin m+otiAication0ana4er.notiA7(#" notiAication); //Cerramos la aplicacin Ainis>(); } }

[Manual] List ie! "#rinci#iantes$


>ola a todos. Ah! os de%os este manual para iniciarse con los $ist8ie?. Est escrito para #.6, qui7as para versiones anteriores no "uncione correctamente. El $ist8ie? de Android es un ob%eto simple para la representaci&n de una lista en texto plano. Este es la primera parte de una serie de tutoriales, si dios quiere, en los que veremos como crear un $ist8ie? con poco traba%o. En este articulo veremos dos tcnicas para crear una $ist8ie? cuyas "ilas contienen iconos y texto. Si quiere que las "ilas ten an un aspecto distinto, una "orma de lo rarlo es proporcionar su propio $ayout que usara para cada "ila, esto dir a Android que use su layout en lu ar de uno propio. Esto le proporciona un control sobre lo que sucede en la "ila y la "orma en que se representa. .or e%emplo, supon amos que usted quiere un $ist8ie? cuyas entradas se componen de un icono, se uido de un texto. @u debes construir un layout para las "ilas como el si uiente xml<

Hichero 0main.xml1
Cdigo ,M-: <?xml ?ersion= B.# <LinearLayout android5id= @-idELinearLa7o!t#B android5la7o!t(=idt>= Aill(parent android5la7o!t(>ei4>t= Aill(parent android5orientation= ?ertical xmlns5android= >ttp5EEsc>emas.android.comEap<EresEandroid > <ListView android5id= @-idEandroid5list android5la7o!t(=idt>= Aill(parent android5la7o!t(>ei4>t= FG#px > </ListView> <TextView android5id= @-idEseleccion android5la7o!t(=idt>= F##px android5la7o!t(>ei4>t= H#px > </TextView> </LinearLayout> encodin4= !tACD ?>

Hichero 0"ila.xml1
Cdigo ,M-: <?xml ?ersion= B.# <LinearLayout android5id= @-idElistado(Ailas android5la7o!t(=idt>= Aill(parent android5la7o!t(>ei4>t= Aill(parent android5orientation= ?ertical xmlns5android= >ttp5EEsc>emas.android.comEap<EresEandroid > encodin4= !tACD ?>

< mageView android5id= @-idEicono android5la7o!t(=idt>= G#px android5la7o!t(>ei4>t= G#px android5src= @dra=ableEsi > </ mageView> <TextView android5id= @-idEtexto android5la7o!t(=idt>= F##px android5la7o!t(>ei4>t= H#px > </TextView> </LinearLayout>

Este dise'o 0"ila.xml1usa un $inear$ayout para la creaci&n de una "ila, con el icono a la i7quierda y el texto a la derecha. .or de"ecto, sin embar o, Android no tiene ni idea de que tu quieras usar este dise'o con el $ist8ie?, por lo tanto necesitamos asociar nuestro layout al Adapter a travs del /D< Hichero< Demo.%ava
Cdigo android: import android.app.&cti?it7; import android.app.List&cti?it7; import android.os.B!ndle; import android.?ie=.6ie=; import android.?ie=.6ie=.ro!p; import android.=id4et.&rra7&dapter; import android.=id4et.)ma4e6ie=; import android.=id4et.List6ie=; import android.=id4et.'ext6ie=; public class Demo extends List&cti?it7 { 'ext6ie= selection; String:; items={ lorem " consectet!er " li4!la " etiam " ips!m " dolor " sit " amet "

adipiscin4 " arc! "

elit "

morbi " mollis " ante "

?el "

?itae " ?el "

aliq!et "

erat "

placerat "

porttitor " p!r!s }; @O?erride

sodales "

pellentesq!e "

a!4!e "

public ?oid onCreate(B!ndle icicle) { super.onCreate(icicle); setContent6ie=($.la7o!t.main); setList&dapter(new )conic&dapter(this)); selection=('ext6ie=)Aind6ie=B7)d($.id.selection); } }

Este e%emplo, muestra una lista aleatoria de palabras, y establece la palabra selecciona sobre el @ext8ie?. $a clave de este e%emplo es usar un ArrayAdapter, pudiendo usar as! una apariencia personali7ada 05.$ayout."ila1 y establecer la lista de palabras sobre el @ext8ie? llamado en este caso 5.id.texto dentro de su apariencia personali7ada. El resultado es un $ist8ie? con iconos en el mar en i7quierdo. Si bien es cierto que todos los iconos son los mismo. Esta tcnica, que proporciona un dise'o alternativo para el uso de "ilas, estiona casos simples de "orma muy e"ectiva. Sin embar o, esto no es valido si los dise'os de las "ilas se complican, con son< I Bo todas las "ilas usan el mismo dise'o 0E%< 9nas "ilas tienen una linea de texto, otras dos1. I Es necesario con"i urar los iconos dependiendo de la "ila. 0E%., di"erentes iconos para di"erentes casos1. En estos casos, la me%or opci&n es crear tus propias subclases del adaptador que deseemos, sobrescribiendo el mtodo et8ie?01, y construyndolo tu mismo. El mtodo et8ie?01 es responsable de retornar un 8ie?, representando la posici&n en "ila proporcionada por el adaptador. .or e%emplo, vamos a modi"icar el c&di o anterior para utili7ar et8ie? 01, para que pueda tener iconos di"erentes para di"erentes "ilas,en este caso, un icono de palabras cortas y otro para las palabras lar as< Hichero< DemoDinamica.
Cdigo android: import android.app.&cti?it7; import android.app.List&cti?it7; import android.os.B!ndle; import android.?ie=.6ie=; import android.?ie=.6ie=.ro!p; import android.=id4et.&rra7&dapter; import android.=id4et.)ma4e6ie=;

import android.=id4et.List6ie=; import android.=id4et.'ext6ie=; public class DemoDinamica extends List&cti?it7 { 'ext6ie= selection; String:; items={ lorem " consectet!er " li4!la " etiam " ips!m " dolor " sit " amet "

adipiscin4 " arc! "

elit "

morbi " mollis " ante " a!4!e "

?el "

?itae " ?el "

aliq!et "

erat "

placerat "

porttitor " p!r!s }; @O?erride

sodales "

pellentesq!e "

public ?oid onCreate(B!ndle icicle) { super.onCreate(icicle); setContent6ie=($.la7o!t.main); setList&dapter(new )conic&dapter(this)); selection=('ext6ie=)Aind6ie=B7)d($.id.seleccion); } public ?oid onList)temClic<(ListView parent" View ?" int position" lon4 id) { selection.set'ext(items:position;); } class )conic&dapter extends &rra7&dapter { &cti?it7 context; )conic&dapter(&cti?it7 context) { super(context" $.la7o!t.Aila" items); this.context=context; } public View 4et6ie=(int position" View con?ert6ie=" 6ie=.ro!p parent) { View ro= = View.inAlate(this.4etContext()" $.la7o!t.Aila" null); 'ext6ie= label=('ext6ie=)ro=.Aind6ie=B7)d($.id.texto); label.set'ext(items:position;); iA (items:position;.len4t>()9I) { )ma4e6ie= icon=()ma4e6ie=)ro=.Aind6ie=B7)d($.id.icono); icon.set)ma4e$eso!rce($.dra=able.no); }

return(ro=); } } }

En nuestra implementaci&n de et8ie?01, primero usaremos el mtodo 8ie?.in"late. Este mtodo permite representar una serie de datos sobre una apariencia JK$ especi"ica 0nuestro $ayout1. Sin que ten amos que reali7ar el tedioso traba%o deL tomar un elemento, crear las instancias de las clase especi"ica 8ie?, recuperar los atributos, convertir y llamar a los setters, recorrer todos los elementos hi%os, etc, hasta ver representados los datos. As! que usaremos in"late con nuestro layout para representar la "ila. Entonces, modi"icaremos nuestro 8ie? dependiendo de nuestras necesidades< I ,ar aremos el texto de nuestro label, usando la palabra proporcionada por la posici&n del array. I 8emos si la palabra es mas lar a de cuatro caracteres y, si es as!, recuperamos nuestro /ma e8ie? y modi"icamos el icono por el adecuado. Ahora, tenemos un $ist8ie? con di"erentes iconos en base los datos de la lista. @an solo es un e%emplo, pero nos sirve para poder ver como se usa est tcnica y poder ponerla en marcha para cualquier tipo de adaptaci&n de las "ilas dependiendo de un criterio. Mueno, pues aqu! os trai o la )N, 2N y 4N parte de los manuales de $ist8ie?, al i ual que el primero, est actuali7ado para su "uncionamiento en #.6. Espero que os ayude a entender un poco mas el "uncionamiento de los $ist8ie?. Entendiendo estos ob%etos podemos lle ar a representar cualquier listado de ob%etos que queramos. 9n saludo. Bota. Si hay cualquier error o necesitis que se aclare al o, no dudis en dec!rmelo, todos estos modelos los ten o implementados y "uncionando. -'#. /'01 (#egunda parte) En nuestro ultimo manual, vimos como crear un $ist8ie? en android que conten!a mas que una simple lista de strin . En particular, vimos la "orma de modi"icar los ob%etos para adaptarlos a nuestras necesidades, en concretoL una subclase de Adapter, sobrescribiendo el mtodo et8ie?01, y retornando un 8ie? para cada una de las "ilas, basado en nuestro propio layout JK$. $os tel"onos actuales no son la cosas mas rpida que hay. En android, crear ?id et08ie?s1 es un proceso relativamente pesado, por no mencionar la esti&n que ha de hacer el recolector de basura para deshacerse de ellos una ve7 "inali7ado. .or lo que, no es conveniente crear mas ?id et de los que ya tenemos. Ahora, vamos a ima inarnos que tenemos un $ist8ie? que, visualmente en pantalla, puede mostrar A re istros, pero la propia lista contiene 6- re istros, tal ve7 procedentes de una base de datos o al unos contenido parseados de internet. ,rear un ?id et para A re istros es mucho menos costoso en recursos que hacerlo para 6- re istros. Sin embar o, nuestro et8ie?01, nuestra implementaci&n crea ?id ets cada ve7 que se pide. Si tu a'ades salidas $o podrs ver que ocurre, tu veras que si mueves el scroll a travs de toda la lista, est ser llamada 6- veces. Android tiene una "orma de me%orar la esti&n de su et8ie?01L esto es a travs del parmetro content8ie? pasado como ar umento a et8ie?01.

Al unas veces, convert8ie? ser nulo. En estos casos, tu tienes que crear una "ila 0vie?1 desde cero 0a travs de /n"late1, tal y como se hi7o en el primer manual. Sin embar o, si el convert8ie? no es nulo, entonces lo que visuali7amos es en realidad un 8ie? previamente creado. Esto ocurrir inicialmente cuando el usuario desplace el scroll del $ist8ie?, cuando aparecen nuevas "ilas. Android intentar reciclar las vie?s de las "ilas que han salido "uera del rea visual, de esta "orma ahorra tener que reconstruirlas. Asumiendo que cada una de las "ilas tiene la misma estructura bsica, tu puedes usar "ind8ie?Myid01 para lle ar a los ?id ets individuales que con"orman sus "ilas y modi"icar su contenido, entonces devolver content8ie? desde et8ie?01, en lu ar de crear una nueva "ila< .or e%emplo, aqu! tenemos el et8ie?01 implementado en el primer manual, ahora optimi7ado con content8ie?<
Cdigo android: public View 4et6ie=(int position" View con?ert6ie=" 6ie=.ro!p parent) { View ro==con?ert6ie=; iA (ro===null) { ro= = View.inAlate(this.4etContext()" $.la7o!t.Aila" null); } 'ext6ie= label=('ext6ie=)ro=.Aind6ie=B7)d($.id.texto); label.set'ext(items:position;); iA (items:position;.len4t>()9I) { )ma4e6ie= icon=()ma4e6ie=)ro=.Aind6ie=B7)d($.id.icono); icon.set)ma4e$eso!rce($.dra=able.no); } return(ro=); }

,omprobamos si el content8ie? es nulo, si es as!, car amos nuestra "ila, pero sino lo es la reusamos. En ambos casos debemos rellenar el contenido del texto y la ima en, pero podemos evitarnos el paso de in"late que es el paso mas costoso. En modelo de OrecicladoP, se hace complicado en dise'os de varias "ilas y este caso pueden variar si ni"icativamente. .or e%emplo, si es necesario crear una 8ie? que requiere dos l!neas de texto, no podemos utili7ar un e%emplo como el actual, con una l!nea de texto. .or supuesto, hay "ormas de hacer esto, como crear una se unda l!nea de texto visible o invisible, dependiendo de si es necesario. En un tel"ono, cada milise undo de tiempo de ,.9 es precioso, simplemente por la vida de la bater!a. Dicho esto, sobre todo si eres un novato a Android, recomiendo centrarse en conse uir primero que la aplicaci&n sea totalmente "uncional, despus me%orar el rendimiento revisando el c&di o una ve7 el pro rama "uncione correctamente. Huente< http<FF???.android uys.comF)--QF-AF#AF"ancy:listvie?s:part:t?oF -'#. /'01 (.ercera parte) En nuestro ltimo manual, vimos como pod!amos ahorrar tiempo de procesamiento, y por lo tanto, vida de la bater!a, usando el reciclado de "ilas de nuestra lista, simplemente validando y reusando el parmetro convert8ie? en nuestro mtodo et8ie?01. El ob%etivo, una ve7 mas es reducir el tiempo de traba%o que se necesita para reali7ar una lista, tanto para los usuarios, haciendo mas il la respuesta y reduciendo el consumo de bater!a. +tra operaci&n costosa es el uso de las llamadas a "ind8ie?My/d01. Esto ha de buscar dentro de la lista de ob%etos de la app los indicadores de cada uno hasta encontrar el requerido. Desde "ind8ie?My/d01 puede encontrar ob%etos en cualquier lu ar del rbol comen7ando desde el ra!7. Esto conlleva un buen nmero de instrucciones, sobre todo si tenemos tener que volver a encontrar ob%etos que hab!a buscado antes. En al unas herramientas de desarrollo este problema se evita creando las "ilas internamente en c&di o 0en este caso Rava1. 3 ciertamente esto se puede hacer en Android pero el c&di o es al o mas comple%o. Ah! es donde entra 8ie?=rapper. ,on esta clase reali7aremos est proceso mas simple y con la posibilidad de usar JK$ para nuestras "ilas @odos los ob%etos 8ie? contienen los mtodos et@a 01 y set@a s01. Estos mtodos permiten asociar arbitrariamente un ob%eto con la aplicaci&n. Si a'adimos al >andler 0mane%ador1 de

nuestra "ila 08ie?1 , cada ve7 que la usamos, nos evitaremos tener que hacer la llamada al "ind8ie?My/d01 de nuevo. ,on el consi uiente ahorro de memoria y por lo tanto de bater!a, al reducir el numero de ciclos de relo% de la ,.9. 8eamos como quedar!a la clase con este cambio<
Cdigo android: public class 6ie=Jrapper { View base; 'ext6ie= label = null; )ma4e6ie= icon = null; 6ie=Jrapper(View base) { this.base = base; } 'ext6ie= 4etLabel() { iA ( label == null) { label = ('ext6ie=) base.Aind6ie=B7)d($.id.texto); } return (label); } )ma4e6ie= 4et)con() { iA (icon == null) { icon = ()ma4e6ie=) base.Aind6ie=B7)d($.id.icono); } return (icon); }

$a principal di"erencia entre 8ie?=rapper y 8ie?>older 0al "inal del manual1 es que el 8ie?=rapper que crear un ?rapper 0envoltorio1 que nunca necesita un hi%o especi"ico hace que no necesites llamar continuamente al "ind8ie?My/d01 reduciendo as! los ciclos de ,.9 usados para este proceso. .or otro lado, 8ie?>older tiene los 8ie?s 0/ma e8ie? y @ext8ie? 1 como variables publicas y el 8ie?=rapper con mtodos etter, as! que habr situaciones en las que el 8ie?>older ser mas e"iciente que la clase 8ie?=rapper. 9sando la clase 8ie?=rapper el mtodo et8ie?01 quedar!a as!<
Cdigo android: public View 4et6ie=(int position" View con?ert6ie=" 6ie=.ro!p parent) { View ro= = con?ert6ie=; 6ie=Jrapper =rapper = null; //*$ iA (ro= == null) { //*% ro= = View.inAlate(this.4etContext()" $.la7o!t.Aila" null); =rapper = new 6ie=Jrapper(ro=); ro=.set'a4(=rapper); } else { //*& =rapper = (6ie=Jrapper) ro=.4et'a4(); } //*' =rapper.4etLabel().set'ext(items:position;); iA (items:position;.len4t>() 9 I) { //*' =rapper.4et)con().set)ma4e$eso!rce($.dra=able.no); } return (ro=); }

,omprobaremos si convert8ie? es nulo 0I#1 con el "in de crear las "ilas0I)1 , se n sea necesarios. Sacar o crear el 8ie?=rapper correspondiente a cada "ila 0I21 . ,on lo que reco er los vie?s hi%os de nuestra "ila, son tan solo cuesti&n de llamar a los mtodos asociados al =rapper 0I41. 8ie?>andler.class public class 8ie?>older S /ma e8ie? ima eL @ext8ie? textL T Huente< http<FF???.android uys.comF)--QF-AF))F"ancy:listvie?s:part:threeF -'#. /'01 (Cuarta parte) En la tercera parte del manual, vimos como pod!amos hacer nuestra $ist8ie? mucho mas e"iciente a la hora de renderi7arse. >oy echaremos un vista7o a como crear elementos interactivos por "ila en nuestro $ist8ie?. En concreto, veremos una implementaci&n en crudo de una lista de control< un $ist8ie? que contiene ,hecUbox. El $ist8ie? contendr ,hecUMox, pero muchos de los conceptos que estbamos usando son validos si usamos "ilas del $ist8ie? que conten an botones, checU o Edit8ie?. 9na lista de ,hecUMox esta principalmente dise'ada para permitir al usuario de una "orma sencilla la multiselecci&n, en particular en los casos en que varias selecciones son la norma. $a lista contiene un checU por linea y puede marcar los que le interesan. .ara esta demo usaremos las mismas clase que en anteriores partes de los manuales. A di"erencia de los anteriores en este e%emplo se mostrar una lista de checU que contendrn cada una de las palabras de la lista aleatoria. Si seleccionamos una de ellas est se pondr en mayscula. Bo es el e%emplo mas so"isticado del planeta, pero nos servir para centrar la l& ica del tratamiento, pudiendo a partir de ah! expandirla para nuestro uso particular. V(ue necesitamos hacerW @enemos que almacenar y veri"icar el checU seleccionado en al n lu ar, ya que nuestros ,hecUMoxs sern reciclados cuando el usuario se mueva por el scroll. @enemos que ser capaces de establecer el estado del ,hecUbox basado en la palabra real que contiene el ,hecUMox, y uardar el estado a medida que se mueve por el scroll no olvidemos que al mover el scroll el ob%eto se recicla. $o que hace esta interesante es que, por de"ecto, el ,hecUbox no tiene absolutamente nin una idea del ob%eto en el que est el ArrayAdapter. Despus de todo el ,hecUMox es un ?id et, usado en una "ila de un $ist8ie?. @enemos que ense'ar a las "ilas del modelo que estn mostrando actualmente, as! cuando se revisa su casilla de veri"icaci&n, que sepan el estado del modelo a modi"icar. Entonces, con todo esto en mente, echemos un vista7o a al o de c&di o. Esta es la clase Activity, con los cambios<
Cdigo android: public class List6ie=DemoI extends List&cti?it7 { 'ext6ie= selection; String:; items = { lorem " ips!m " dolor " sit " amet " consectet!er " adipiscin4 " elit " morbi " ?el " li4!la " ?itae " arc! " aliq!et " mollis " etiam " ?el " erat " placerat " ante " porttitor " sodales " pellentesq!e " a!4!e " p!r!s }; @O?erride public ?oid onCreate(B!ndle icicle) { super.onCreate(icicle); setContent6ie=($.la7o!t.main); !rrayList list = new !rrayList(); Aor (String s 5 items) { list.add(new $o=0odel(s));

} setList&dapter(new C>ec<&dapter(this" list)); selection = ('ext6ie=) Aind6ie=B7)d($.id.seleccion);

pri"ate $o=0odel 4et0odel(int position) { //return (((Chec)*dapter+ this.,et#ist*dapter(++.,et-tem(position++. return ($o=0odel) ((C>ec<&dapter)this.4etList&dapter()).4et)tem(position); } public ?oid onList)temClic<(ListView parent" View ?" int position" lon4 id) { selection.set'ext(4et0odel(position).toStrin4()); } class C>ec<&dapter extends &rra7&dapter { &cti?it7 context; C>ec<&dapter(&cti?it7 context" !rrayList list) { super(context" $.la7o!t.Aila" list); } this.context = context;

public View 4et6ie=(int position" View con?ert6ie=" 6ie=.ro!p parent) { View Aila = con?ert6ie=; 6ie=Jrapper =rapper; C>ec<Box cb; iA (Aila == null) { Aila = View.inAlate(this.4etContext()" $.la7o!t.Aila" null); =rapper = new 6ie=Jrapper(Aila); Aila.set'a4(=rapper); cb = =rapper.4etC>ec<Box(); Compo!ndB!tton.OnC>ec<edC>an4eListener l = newCompo!ndB!tton.OnC>ec<edC>an4eListener() { public ?oid onC>ec<edC>an4ed(Compo!ndB!tton b!tton6ie=" boolean isC>ec<ed) { nteger m7/osition = ( nteger) b!tton6ie=.4et'a4(); $o=0odel model = 4et0odel(m7/osition); model.isC>ec<ed = isC>ec<ed; b!tton6ie=.set'ext(model.toStrin4()); } }; cb.setOnC>ec<edC>an4eListener(l); } else { =rapper = (6ie=Jrapper) Aila.4et'a4(); cb = =rapper.4etC>ec<Box(); } $o=0odel model = 4et0odel(position); cb.set'a4(new nteger(position)); cb.set'ext(model.toStrin4()); cb.setC>ec<ed(model.isC>ec<ed); return (Aila);

} } class $o=0odel { String label; boolean isC>ec<ed = #alse; $o=0odel(String label) { this.label = label; } public String toStrin4() {

iA (isC>ec<ed) { return (label.to3pperCase()); } return (label); } } }

En concreto esto es lo que se ha hecho nuevo< #. Aunque aun estamos utili7ando elementos de un array de Strin , como la lista de palabras, en lu ar de a'adir nuestro array de texto directamente en un ArrayAdapter, lo convertimos en una lista de ob%etos 5o?Kodel. 9sar 5o?Kodel en esta demo es un excusa muy pobre para usar modelos mutables< usando un texto y el estado del checU. En un e%emplo real, estos podr!an ser ob%etos mas comple%os como un ,ursor, y propiedades adaptadas a nuestro ne ocio. ). 9samos metodos como on$ist/tem,licU01 para actuali7ar el cambio re"re%ado en el modelo de strin que usa el 5o?Kodel. 2. $a subclase ArrayAdapter 0,hecUAdapter1, en el metodo et8ie? 01, comprueba si el convert8ie? es nulo. Si es as!, crear una nueva "ila con el metodo in"late y tambin a'ade la "ila sobre el 8ie?=rapper. .ara cada checU de la "ila a'ade un evento on,hecUed,han ed01 que comprueba la "ila 0 etta 011 y que se convierte en un /nte er, lo que representa la posici&n dentro de la ArrayAdapter de la "ila que se muestra. Esando esto el checUboxpuede obtener el 5o?Kodel actual de la "ila y actuali7ar el modelo basado en el nuevo estado del checUbox. Adems, actuali7a el texto del cUecUbox en caso que su estado0checUFunchecUed1 coincida con el estado del cUecUbox. 4. Siempre ase rese de que el checUbox tiene el contenido adecuado y tiene una etiqueta 0a travs de set@a 011 apuntando a la posici&n en el adapter de la "ila que se muestra. El dise'o de la "ila es muy simple< s&lo un ,hecUMox dentro de un $inear$ayout. "ila.xml
Cdigo : 8Kxml ?ersion= B.# encodin4= !tACD K9 8LinearLa7o!t android5id= @-idElistado(Ailas android5la7o!t(=idt>= Aill(parent android5la7o!t(>ei4>t= Aill(parent android5orientation= ?ertical xmlns5android= >ttp5EEsc>emas.android.comEap<EresEandroid 9 8C>ec<Box android5id= @-idEc>ec< android5text= android5la7o!t(=idt>= =rap(content android5la7o!t(>ei4>t= =rap(content 9 8EC>ec<Box9 8ELinearLa7o!t9

.osiblemente, nuestro $inear$ayout es sencillo, pero puede que se desee complicar mas las "ilas que con un simple ,hecUMox, puede que quiera a'adir al unos /ma e8ie?s con iconos que representan varios tipos de in"ormaci&n para cada "ila, por e%emplo. El 8ie?=rapper es i ualmente sencillo, basta con extraer el checUbox "uera de la "ila<
Cdigo android: class 6ie=Jrapper { View base; C>ec<Box cb=null; 6ie=Jrapper(View base) { this.base=base; }

C>ec<Box 4etC>ec<Box() { iA (cb==null) { cb=(C>ec<Box)base.Aind6ie=B7)d($.id.c>ec<); } return(cb); }

Este c&di o es un poco en orroso. .ero sin duda, se puede simpli"icar, con el uso del 5o?Kodel en la etiqueta contra un /nte er, indicandolo como el indice dentro del ArrayAdapter. Adems, en un capitulo posterior, vamos a ver c&mo se puede envolver la mayor parte de la comple%idad hasta en un ?id et personali7ado.

[Manual] %sar &ilos ' a la ve( mostrar una barra de #ro)reso


El e%emplo es muy sencillo pero resulta muy til as! como un recurso bastante bueno. $a idea es reali7ar cierto traba%o en un hilo, mientras mostramos al usuario una barra de pro reso, es decir le indicamos que se estn reali7ando acciones y que debe esperar. $o primero es tener una clase que implemente runnable para as! poder lan7ar hilos. Esto se podr!a hacer con var!as clases 0 es solo un e%emplo1. $a idea es que al e%ecutar la clase se va a reali7ar lo que pon amos dentro del mtodo run, en nuestro caso est con"i urado al presionar una tecla. Kientras tanto mostramos la barra de pro reso, una ve7 termine de reali7ar las tareas en run, entonces podemos parar la barra y se uir con lo que queramos.

El c&di o del e%emplo es el si uiente<


Cdigo : public class /ro4ressDialo4%xample extends &cti?it7 implements $unnable { pri"ate String pr!eba; pri"ate 'ext6ie= t?; pri"ate /ro4ressDialo4 pd; @O?erride public ?oid onCreate(B!ndle icicle) { super.onCreate(icicle); setContent6ie=($.la7o!t.main); t? = ('ext6ie=) this.Aind6ie=B7)d($.id.main); t?.set'ext( /ress an7 <e7 to start calc!lation );

@O?erride public boolean on2e7Do=n(int <e7Code" %eyE"ent e?ent) { pd = /ro4ressDialo4.s>o=(this" #alse); Jor<in4.. " Calc!latin4 /i " true"

Thread t>read = new Thread(this); t>read.start(); } return super.on2e7Do=n(<e7Code" e?ent);

public ?oid r!n() { //Reali ar una operacin que requiera tiempo pr!eba = >olaaa ; int a!x=#; Aor(int i = # ; i8B#####; i--){ a!x = a!x - B; a!x = (a!x L I###) E H; } } >andler.send%mpt70essa4e(#);

pri"ate Mandler >andler = new Mandler() { @O?erride public ?oid >andle0essa4e(0essa4e ms4) { pd.dismiss(); t?.set'ext(pr!eba); } }; }

[Manual] *nviar SMS ' controlar avisos


.on o aqu! un mtodo que se puede? utili7ar para enviar mensa%es de texto 0SKS1, nicamente habr que darle el nmero de tel"ono en un Strin y el mensa%e que le quieras enviar, el mismo mtodo lo cortar y lo enviar. Adems puedes controlar los avisos, est comentado en los huecos para que cada uno pon a la acci&n que quiera reali7ar se n le conven a.
Cdigo android:

pri"ate ?oid sendS0S(String p>one+!mber" String messa4e) { String S%+' = S0S(S%+' ; String D%L)6%$%D = S0S(D%L)6%$%D ; /////cuando el 010 ha sido enviado/// re4ister$ecei?er(new Broadcast$ecei?er(){ @O?erride public ?oid on$ecei?e(Context ar4#" )ntent ar4B) { s=itc> (4et$es!ltCode()) { case &cti?it7.$%S3L'(O25 //enviado break; case Sms0ana4er.$%S3L'(%$$O$(.%+%$)C(*&)L3$%5 //fallo break; case Sms0ana4er.$%S3L'(%$$O$(+O(S%$6)C%5 //no funciona el servicio break; case Sms0ana4er.$%S3L'(%$$O$(+3LL(/D35 //no 2!3 break; case Sms0ana4er.$%S3L'(%$$O$($&D)O(O**5 //No hay cobertura break; } } }" new )ntent*ilter(S%+')); /////cuando el 010 ha sido recibido///

re4ister$ecei?er(new Broadcast$ecei?er(){ @O?erride public ?oid on$ecei?e(Context ar4#" )ntent ar4B) { s=itc> (4et$es!ltCode()) { case &cti?it7.$%S3L'(O25 //bien recibido break; case &cti?it7.$%S3L'(C&+C%L%D5 //cancelado break; } } }" new )ntent*ilter(D%L)6%$%D)); Sms0ana4er sms = Sms0ana4er.4etDeAa!lt(); //cortamos el mensa4e en tro os pr si fuera m5s ,rande de $67 &rra7List8Strin49 smsC!t = sms.di?ide0essa4e(messa4e); //creamos avisos para cada mensa4e enviado &rra7List8/endin4)ntent9 sent/)s = new &rra7List8/endin4)ntent9(); &rra7List8/endin4)ntent9 deli?ered/)s = new &rra7List8/endin4)ntent9(); Aor(int i=#; i8smsC!t.siNe(); i--){ sent/)s.add(/endin4)ntent.4etBroadcast(this" i-B" new )ntent(S%+')" #)); deli?ered/)s.add(/endin4)ntent.4etBroadcast(this" i-B" new )ntent(D%L)6%$%D)" #)); } sms.send0!ltipart'ext0essa4e(p>one+!mber" null" smsC!t" sent/)s" deli?ered/)s); }

[Manual] Cambiar el locale #or codi)o #ara cambio de idioma


>ola, despues de buscar por el "oro y no encontrar la manera de cambiar el idioma de la aplicacion por codi o, decidi oo lear un poco y encontre un tro7o de codi o que espero les sea util a mucha ente del "oro, a lo me%or ya estaba por el "oro, pero no lo encontre. Mueno la manera es crear como siempre dos carpetas *values*, una quedaria asi< *values* que seria la que contendria el xml de strin s por de"ecto, en nuestro caso en espa'ol, y las demas carpetas serian por e%emplo para el in les < *values:en*, y para demas idiomas bastaria con cambiar el *:en* por otro codi o de idioma, que se pueden encontrar en la ?iUipedia, por e%emplo. 9na ve7 ten amos las carpetas nombradas es hora de cambiar el $ocale por codi o, por e%emplo, si tenemos en nuestro pro rama un boton de cambio de idioma y este nos lleva a una nueva activity que conten a una vista con botones para di"erentes idiomas, o que simplemente el boton nos muestre una vista nueva a parte y en esa vista ten amos los botones, eso ya quedaria a usto del pro ramador xD. .ues en los botones de idioma iria el codi o este<
Cdigo : Locale l = new Locale( en ); $eso!rces reso!rce = this.4et$eso!rces(); ConAi4!ration cA = reso!rce.4etConAi4!ration(); Displa70etrics dm = reso!rce.4etDispla70etrics(); cA.locale = l; reso!rce.!pdateConAi4!ration(cA" dm);

Esto seria para un boton que cambiara el idioma a in les. .ara cambiar a otro idioma basta con crear un locale que conten a el codi o del idioma que queramos.

[Manual] +asar de una actividad a otra ' enviar informacin


Este c&di o seXia la llamada desde la primera actividad dYY, donde A,@/8/DAD A,@9A$ es la clase desde donde se llama 0BombreDe$a,lase.class, o this, o el contexto1, A,@/8/DAD S/Z9/EB@E ser!a el nombre de la si uiente clase 0BombreDe$a,lase.class1 e /DEB@/H/,AD+5 ser!a un e%emplo de lo que le podr!as pasar, pero puedes ponerle el nombre que quieras y a'adir cualquier dato seriali7able.
Cdigo : )ntent intent = new )ntent(&C')6)D&D &C'3&L"&C')6)D&D S).3)%+'% ); intent.p!t%xtra( id " )D%+')*)C&DO$); start&cti?it7(intent);

Este c&di o habr!a que e%ecutarlo al inicio de la se unda actividad, en on,reate01 por e%emplo, y reco e los datos que le has enviado anteriormente, en este caso al haber a'adido un entero hay que poner et/nt.
Cdigo : B!ndle b!ndle = 4et)ntent().4et%xtras(); iA(b!ndleO=null){ id = extras.4et)nt( id ); }

Kodi"icaciones< Si queremos despus recibir datos de la actividad secundaria a la principal haremos llamada de di"erente manera 3 para reco erla en la actividad principal a'adiremos el mtodo onActivity5esult que ser el que se e%ecute al volver a la actividad, donde al recibir el intent anterior podremos reco er en data los datos pasados. El /DEB@/H/,AD+5 es un entero que se pone es para indicarle que los datos los querrs recibir en el mtodo onActivity5esult y que llevar ese /D que lue o se recibir en request,ode. 0El ,+D/Z+ 5E@+5B+ ser el devuelto por la actividad secundaria que enera el resultado, es lo si uiente1
Cdigo : start&cti?it7*or$es!lt(intent" )D%+')*)C&DO$);

Cdigo : protected ?oid on&cti?it7$es!lt(int req!estCode" int res!ltCode" )ntent data) { iA (res!ltCode == COD).O $%'O$+O PP req!estCode == )D%+')*)C&DO$) { '3 CQD).O

En la actividad secundaria hay que indicarle antes de cerrar que vas a enviar los datos por lo que se hace un set@esult. Adems podemos indicar di"erente tipo de retorno mediante el ,+D/Z+ 5E@+5B+, un entero que se le enviar a la otra actividad.
Cdigo : set$es!lt(COD).O $%'O$+O" intent);

[M,N%,L] Como crear #referencias en tu #ro)rama


>e creado una entrada en mi blo , pero la copia y pe o aqu! por si a al uien le interesa 9na de las cosas que ms me usta de Android es que te "acilita crear muchas de las cosas comunes que necesita una aplicaci&n y para ello suele usar archivos JK$. En el caso de las pre"erencias no iba a ser distinto y en pocos minutos te puedes crear tus pre"erencias. Esto tiene dos venta%as< #. En poco minutos puedes hacer al o que tardar!as horas en dise'ar ). $as pre"erencias tienen un aspecto comn en todas las aplicaciones de Android. As! un usuario que est acostumbrado a usar el sistema estar "amiliari7ado con la pantalla Ahora vamos a por el c&di o. .ara reali7ar una pantalla de pre"erencias simplemente tienes que crear una nueva Actividad que herede de .re"erenceActivity. Desde el mtodo on,reate vamos a invocar un archivo JK$ que se encuentra en resFxml y que contiene la estructura, claves y ob%etos de nuestra pantalla de pre"erencias. El c&di o ser!a el si uiente<
Cdigo : public class /reAerences*rom,ml extends /reAerence&cti?it7 { @O?erride protected ?oid onCreate(B!ndle sa?ed)nstanceState) { super.onCreate(sa?ed)nstanceState); // #oad the preferences from an 81# resource add/reAerences*rom$eso!rce($.xml.preAerences); } }

Este c&di o es uno de los e%emplos que viene con el SDK de Zoo le y se encuentra aqu! 9na ve7 hecho esto simplemente tendremos que rellenar nuestro archivo JK$. .ara ello lo me%or es "i%arse en este e%emplo de Zoo le donde se pueden ver como crear rupos de pre"erencias, listas, checUbox, etc. 9na ve7 hecho esto nos queda acceder a los contenidos de las pre"erencias. $o me%or es que no nos tenemos que preocupar en nin n momento de almacenar la in"ormaci&n en nin n lado, de esto se encar a Android.

$o primero es poner bien todos los *Uey* en el JK$. ,ada ob%eto tiene un atributo llamado *android<Uey* que nos servir para poder acceder a l cuando sea necesario. .ara poder traba%ar con las pre"erencias necesitamos un ob%eto de tipo Shared.re"erences que podemos obtener en nuestra actividad de la si uiente "orma<
Cdigo : /reAerence0ana4er.setDeAa!lt6al!es(this" $.xml.preAer" #alse); S>ared/reAerences p = /reAerence0ana4er.4etDeAa!ltS>ared/reAerences(this); p.4etStrin4( <e7 " ?al!e(deAa!lt )

$o primero que tenemos que poner es como *pre"erencias por de"ecto* de nuestra actividad el archivo JK$ que contiene las pre"erencias. $ue o podremos acceder a las pre"erencias mediante el *Uey* y los mtodos que nos o"rece el ob%eto Shared.re"erences. 9na "orma muy c&mda de traba%ar y "cil de usar. A continuaci&n una ima en de como estn quedando las pre"erencias de mi pro rama<

[M,N%,L] ,#licacin sencilla-.or!ardin) editada


>ola, ya he terminado esta aplicaci&n....y pues a pesar de todo lo que hay en el "oro se eneraron ciertos errores , debido a esto pon o el c&di o "uncional completo ... disclpenme por no montarlo en un tutorial.....haber si al uien me ayuda y lo sube en pd".... sino ms tarde lo ha o yo.... Cdigo en . 2ava(prueba.3ava)
Cdigo android: package android.pr!eba; import import import import import import android.app.&cti?it7; android.content.)ntent; android.os.B!ndle; android.?ie=.6ie=; android.?ie=.6ie=.OnClic<Listener; android.=id4et.B!tton;

public class pr!eba extends &cti?it7 { /** Called when the activity is first created. */ @O?erride public ?oid onCreate(B!ndle sa?ed)nstanceState) { super.onCreate(sa?ed)nstanceState); setContent6ie=($.la7o!t.pr!eba#B); &utton Boton=(&utton)Aind6ie=B7)d($.id.B!tton#B); Boton.setOnClic<Listener(botonp!lsar); } pri"ate OnClic<Listener botonp!lsar = new OnClic<Listener() { public ?oid onClic<(View ?) { )ntent intent = new )ntent(); intent.setClass(pr!eba.this" pr!ebaF.class); start&cti?it7(intent); Ainis>(); } }; }

Cdigo en ,M- (prueba.,M-)


Cdigo ,M-: <?xml ?ersion= B.# encodin4= !tACD ?> <LinearLayout xmlns5android= >ttp5EEsc>emas.android.comEap<EresEandroid android5orientation= ?ertical android5la7o!t(=idt>= Aill(parent android5la7o!t(>ei4>t= Aill(parent > <TextView android5la7o!t(=idt>= Aill(parent android5la7o!t(>ei4>t= =rap(content android5text= @strin4E>ello /> <&utton android5text= p!lsar android5id= @-idEB!tton#B android5la7o!t(=idt>= =rap(content android5la7o!t(>ei4>t= =rap(content > </&utton> </LinearLayout>

Cdigo en . 2ava(prueba$.3ava)
Cdigo android: package android.pr!eba; import android.app.&cti?it7; import android.os.B!ndle; public class pr!ebaF extends &cti?it7 { /** Called when the activity is first created. */ @O?erride public ?oid onCreate(B!ndle sa?ed)nstanceState) { super.onCreate(sa?ed)nstanceState); setContent6ie=($.la7o!t.pr!ebaF); } }

Cdigo en ,M- (prueba$.,M-)


Cdigo ,M-: <?xml ?ersion= B.# encodin4= !tACD ?> <LinearLayout xmlns5android= >ttp5EEsc>emas.android.comEap<EresEandroid android5orientation= ?ertical android5la7o!t(=idt>= Aill(parent android5la7o!t(>ei4>t= Aill(parent > <TextView android5la7o!t(=idt>= Aill(parent android5la7o!t(>ei4>t= =rap(content android5text= @strin4En!e?a /> </LinearLayout>

Cdigo )ndroidMani+est.,MCdigo ,M-: <?xml ?ersion= B.# encodin4= !tACD ?> <mani#est xmlns5android= >ttp5EEsc>emas.android.comEap<EresEandroid pac<a4e= android.pr!eba android5?ersionCode= B android5?ersion+ame= B.# > <application android5icon= @dra=ableEicon android5label= @strin4Eapp(name > <acti"ity android5name= .pr!eba android5label= @strin4Eapp(name > <intent'#ilter> <action android5name= android.intent.action.0&)+ /> <category android5name= android.intent.cate4or7.L&3+CM%$ /> </intent'#ilter> </acti"ity> <acti"ity android5name= .pr!ebaF android5label= @strin4Eapp(name > <intent'#ilter> <action android5name= android.intent.action.0&)+

/>

<category android5name= android.intent.cate4or7.L&3+CM%$ </intent'#ilter> </acti"ity> </application> <uses'sdk android5minSd<6ersion= H </mani#est> />

/>

[M,N%,L] ,brir confi)uracin /+S


.ublicado< $un Kay )6, )--G G<#G am con"i uraci&n Z.S .4tulo del mensa3e< [KAB9A$\ Abrir

,on el si uiente c&di o podremos abrir la ventana de con"i uraci&n desde donde activar o desactivar el Z.S entre otras cosas. 5ecordar que desde la versi&n #.6 esta es la "orma correcta de cambiar la con"i uraci&n del dispositivo.
Cdigo : )ntent settin4s)ntent = new )ntent(android.pro?ider.Settin4s.&C')O+(LOC&')O+(SO3$C%(S%'')+.S); settin4s)ntent.set*la4s()ntent.*L&.(&C')6)'1(+%J('&S2 R )ntent.*L&.(&C')6)'1($%S%'('&S2()*(+%%D%D); this.start&cti?it7*or$es!lt(settin4s)ntent" #);

[Manual] *nviar un *-Mail desde ,ndroid


Aqu! os de%o un c&di o muy sencillo que sirva para enviar e:mails desde nuestro tel"ono.
Cdigo : )ntent send)ntent = new )ntent()ntent.&C')O+(S%+D); send)ntent.p!t%xtra()ntent.%,'$&('%,'" email text ); send)ntent.p!t%xtra()ntent.%,'$&(S3BS%C'" S!bTect ); send)ntent.set'7pe( messa4eErAcDFF ); start&cti?it7()ntent.createC>ooser(send)ntent" 'itle5 ));

Se uramente ten is problemas para probarlo desde el emulador puesto que no viene con nin n cliente de correo electr&nico instalado. $o ms se uro es que os d el si uiente mensa%e<
Cita: Bo Applications can per"orm this action

Es necesario tener un Z# para probarlo bien, si al uno es a"ortunado y tiene uno que nos di a si de verdad "unciona. Aqu! os de%o la lista de constantes que podemos utili7ar<

0,.5)60M)'-, 0,.5)6CC, 0,.5)67CC, 0,.5)6#8720C. http<FFcode. oo le.comFandroidFre"erenceFandroidFcontentF/ntent.html Saludos.

[Manual] Crear una a#licacin con ma#as +arte 1


>ola a todos< Mueno lo que vamos a ver aqu! es como empe7ar a crear una aplicaci&n que muestre los mapas de oo le, parecido al que viene con el emulador pero de momento mucho ms simple. En el primer capitulo y para no aburriros simplemente vamos a ver lo sencillo que es mostrar un mapa. public class M9)pp e:tends Map)ctivit9 { @Override public void onCreate(7undle icicle) { super.onCreate(icicle); ;;creamos una vista de mapa Map/ie( M/ < ne( Map/ie((t%is); ;;creamos un controlador de ese mapa MapController MC < M/.getController(); ;;0speci+icamos el =oom con el >ue lo vamos a mostrar MC.=oom.o("?); ;;8nas coordenadas, latitud longitud en gratos @ "0AB Coint point < ne( Coint(DEE"""00, $F$E000); ;;centramos la vista del mapa en este punto MC.centerMap.o(point, true); ;;le decimos >ue lo muestre setContent/ie((M/); &

& Mueno como veis es muy "cil empe7ar. Esto es s&lo el principio de lo que ser nuestra aplicaci&n, de momento empe7ar a trastear con esto.

[Manual] #ara crear una a#licacin con ma#as +arte 0


>ola a todos de nuevo< >oy vamos a se uir con el manual para crear aplicaciones con mapas. En el capitulo # vimos lo que hac!a "alta para mostrar el mapa por pantalla, as! como poder asi narle un controlador a ese mapa y reali7ar distintas acciones sobre l. En la se unda parte lo que vamos a ver es como asi nar ciertas acciones a distintas teclas,

as! cuando pulsemos una tecla en nuestro dispositivo deber!a reali7ar acciones sobre el mapa. $o primero es crearnos un nuevo mtodo que se llame public boolean onGe9Ho(n(int *e9Code, Ge90vent event) $o "undamental del mtodo es saber que tecla se ha pulsado, para ello usaremos lo si uiente< i+ (*e9Code << Ge90vent.G0ICOH06') ,on esto casi ya lo tenemos, "alta poco. 8oy a explicar que habria que poner para que al pulsar la tecla / que es a la que corresponde el c&di o que hemos puesto, hicieramos 7oom en el mapa. int level < mMap/ie(.get!oom-evel(); M/.getController().=oom.o(level J "); return true; $o primero que hacemos es conse uir el nivel de 7oom actual para poder sumarle o restarle un nivel, depende di si queremos ale%ar o acercar la vista en el mapa. K8 se corresponde con la vista del mapa que creamos en el capitulo #. A continuaci&n os de%o el c&di o completo por si habis perdido. $as acciones que estn asi nadas son, las dos del 7oom, activar la vista del satlite y activar la vista de la capa de tr"ico. Espero que os sirva de ayuda. En el si uiente capitulo veremos como dibu%ar marcas de sitios en el mapa, as! como conse uir mostrar in"ormaci&n sobre los mismos. Bos vemos en el si ueinte capitulo.

;@ Controlamos las acciones >ue se llevan a cabo, segKn >ue @ tecla %emos pulsado. @; public boolean onGe9Ho(n(int *e9Code, Ge90vent event) { ;; !oom 'n i+ (*e9Code << Ge90vent.G0ICOH06') { ;; miramos >ue =oom %a9, 9 le sumamos uno. int level < mMap/ie(.get!oom-evel(); M/.getController().=oom.o(level J "); return true; & ;;!oom Out else i+ (*e9Code << Ge90vent.G0ICOH06O) { int level < mMap/ie(.get!oom-evel(); M/.getController().=oom.o(level L "); return true; & ;;)ctivar;Hesactivar la vista de satelite

else i+ (*e9Code << Ge90vent.G0ICOH06#) { M/.toggle#atellite(); return true; & ;;)ctivar la capa de tra+ico else i+ (*e9Code << Ge90vent.G0ICOH06.) { M/.toggle.ra++ic(); return true; & return +alse; &

[Manual] ,ndroid en netbeans


"M Caso. Debemos ba%ar el si uiente archivo< : or :netbeans:modules:android:plat"orm.nbm, 02G.6AUM1

$M Caso.

FM Caso.

DM Caso.

?M Caso.

BM Caso.

NM Caso.

Zracias a Apache.

Guia Android: Avanzando con la base de datos


En el primer tutorial sobre Android hicimos el tpico Hello World, explicando la estructura de Android, cmo funcionaba ese bsico ejemplo. En este segundo tutorial vamos a meternos en muchos ms detalles. amos a construir un bloc de notas para nuestro tel!fono Android. "ebido a #ue son ms archivos $ ms lneas de cdigo #ue en el primer ejercicio os he comprimido los archivos iniciales $ finales en un archivo %ip &"escargar'. Asi siempre ten!is cdigo dnde comparar por si no os funciona algo. (ero como siempre, es mejor #ue va$is siguiendo el tutorial $ veis la evolucin del cdigo en ve% de mirar directamente la solucin.

Conexin a la base de datos


)na ve% #ue hab!is creado el pro$ecto Android seleccionando un pro$ecto existente &*otas', pod!is ver la estructura de archivos. Ha$ $a algunos archivos creados pero el +nico #ue he dejado con informacin es /src/com.android.demo.notepad1/NotasDbAdapter.java. Este archivo se va a encargar de conectarse a la base de datos para #ue no tengamos #ue estar lidiando con esto en otras partes del cdigo. ,ecordad #ue estamos en un es#uema - .. Este va a ser nuestro primer modelo. -iremos el cdigo en general/
#B p!blic class +otasDb&dapter { #F #H #I #G #U #V #D #W B# BB BF BH BI BG BU @O?erride @O?erride p!blic ?oid onCreate(SQLiteDatabase db) {...} DatabaseMelper(Context context) { s!per(context" D&'&B&S%(+&0%" n!ll" D&'&B&S%(6%$S)O+); } pri?ate static class DatabaseMelper extends SQLiteOpenMelper { EE ?ariables ?arias ...

p!blic ?oid on3p4rade(SQLiteDatabase db" int old6ersion"int ne=6ersion) {...} BV } BD BW F# FB FF FH FI ELL L &bre la base de datos de notas. Si no p!ede abrirla" la crea. FG Si no se p!ede FU L lanNa !na excepcion ELL L Constr!ctor C pasa el contexto para poder abrir o crear la DB LE p!blic +otasDb&dapter(Context ctx) {...}

FV FD FW H# HB HF

LE p!blic +otasDb&dapter open() t>ro=s SQL%xception {...}

p!blic ?oid close() {...}

ELL L )nserta !na n!e?a nota con el tXt!lo 7 el texto dados. Si se HH crea correctamente L de?!el?e el ro=)d" en caso contrario" de?!el?e CB para HI indicar q!e >a >abido HG L !n error.. HU HV HD HW I# IB IF IH II IG IU IV ID IW G# GB GF GH GI GG GU GV ELL L &ct!aliNa la nota con los detalles dados. LE p!blic boolean !pdate+ote(lon4 ro=)d" Strin4 title" Strin4 bod7) {...} ELL L De?!el?e !n C!rsor ap!ntando a la nota con el ro=)d dado LE p!blic C!rsor Aetc>+ote(lon4 ro=)d) t>ro=s SQL%xception {...} ELL L De?!el?e !n C!rsor ap!ntando a la lista de todas las notas LE p!blic C!rsor Aetc>&ll+otes() {...} ELL L Borra la nota con el ro=)d dado LE p!blic boolean delete+ote(lon4 ro=)d) {...} LE p!blic lon4 create+ote(Strin4 title" Strin4 bod7) {...}

GD }

0enemos m!todos para crear, actuali%ar, abrir $ cerrar la base de datos. 1 luego los m!todos .,)" para crear una nueva nota, devolver su informacin &o la de varias notas', actuali%arla $ borrarla. Esta clase es mu$ importante $a #ue

estar en todas vuestras apps de una forma u otra asi #ue miremos m!todo a m!todo.
#B pri?ate static class DatabaseMelper extends SQLiteOpenMelper { #F #H #I #G #U #V #D #W B# BB BF BH BI BG BU BV BD BW } } @O?erride p!blic ?oid on3p4rade(SQLiteDatabase db" int old6ersion" intne=6ersion) { Lo4.=('&." to - ne=6ersion EE sentencia drop onCreate(db); " =>ic> =ill destro7 all old data ); 3p4radin4 database Arom ?ersion - old6ersion @O?erride p!blic ?oid onCreate(SQLiteDatabase db) { db.execSQL(D&'&B&S%(C$%&'%); } DatabaseMelper(Context context) { s!per(context" D&'&B&S%(+&0%" n!ll" D&'&B&S%(6%$S)O+); }

Esta clase auxiliar nos permitir abrir la base de datos, crearla si no existe $ actuali%arla al lan%ar una nueva versin. 2a sentencia 342 para crear es/ 55 sentencia create
pri?ate static Ainal Strin4 D&'&B&S%(C$%&'% = create table notes ((id B inte4er primar7 <e7 a!toincrement" - title text not n!ll" bod7 text not n!ll); ;

.mo pod!is haber observado $a antes, estamos utili%ando la base de datos 342ite, es parecida a -$342 pero tiene pe#ue6os detalles diferentes. .on esto $a tenemos creada la base de datos. eamos el m!todo para insertar notas/
B p!blic lon4 create+ote(Strin4 title" Strin4 bod7) { F H Content6al!es initial6al!es = ne= Content6al!es(); initial6al!es.p!t(2%1(')'L%" title);

I G U V }

initial6al!es.p!t(2%1(BOD1" bod7);

ret!rn mDb.insert(D&'&B&S%('&BL%" n!ll" initial6al!es);

A trav!s de la clase .ontent alues guardamos la informacin con el m!todo put $ la insertamos. (ara actuali%ar es casi igual pero usamos el m!todo update en ve% de insert. Ha$ #ue acordarse de indicar el ro78d/
B p!blic boolean !pdate+ote(lon4 ro=)d" Strin4 title" Strin4 bod7) { F H I G ret!rn mDb.!pdate(D&'&B&S%('&BL%" ar4s" 2%1($OJ)D ro=)d" n!ll) P4t; #; V } U = Content6al!es ar4s = ne= Content6al!es(); ar4s.p!t(2%1(')'L%" title); ar4s.p!t(2%1(BOD1" bod7);

El m!todo borrar es mu$ obvio asi #ue pasamos a recuperar una nota de la base de datos/
#B p!blic C!rsor Aetc>+ote(lon4 ro=)d) t>ro=s SQL%xception { #F #H #I #G #U #V #D #W B# BB BF BH } } ret!rn mC!rsor; ro=)d"n!ll" mDb.q!er7(tr!e" D&'&B&S%('&BL%" ne= Strin4:; {2%1($OJ)D" 2%1(')'L%" 2%1(BOD1}" 2%1($OJ)D n!ll" n!ll" n!ll" n!ll); iA (mC!rsor O= n!ll) { mC!rsor.mo?e'o*irst(); = C!rsor mC!rsor =

Hacemos una #uer$ indicando #ue #ueremos un arra$ de tres strings con los tres campos #ue #ueremos, $ con la condicin de ro78d. El resto de los parmetros se usan si #ueremos hacer group9$, having u order9$. "espu!s

comprobamos #ue no est vaco $ si es as movemos el cursor a la primera posicin #ue apunta a la nota #ue #ueremos.

Insertando notas
amos a modificar el la$out de la actividad inicial /res/layout/notepad_list.xml
#B Plt;Kxml ?ersion= B.# #F #H #I #G #U #V #D #W B# BB BF BH BI Plt;ELinearLa7o!tP4t; Plt;List6ie= android5id= @android5idElist android5la7o!t(=idt>= =rap(content android5la7o!t(>ei4>t= =rap(content EP4t; Plt;'ext6ie= android5id= @android5idEempt7 android5la7o!t(=idt>= =rap(content android5la7o!t(>ei4>t= =rap(content android5text= @strin4Eno(notes EP4t; encodin4= !tACD KP4t; Plt;LinearLa7o!t xmlns5android= http/55schemas.android.com5ap:5res5android android5la7o!t(=idt>= =rap(content android5la7o!t(>ei4>t= =rap(content P4t;

0enemos dos elementos/ una lista $ un campo de texto. El 0ext ie7 slo se muestra si la lista est vaca. Android sabe esto gracias a empt$, #ue est unido al valor de list. A trav!s deandroid/id;<=android/id5list< indicamos #ue #ueremos #ue esa lista se rellene con los valores de la variable list de la actividad. (ara mostrar la informacin #ue aparece en cada fila de la lista necesitamos
B Plt;Kxml ?ersion= B.#

crear un nuevo template. .reamos un nuevo archivo /src/layout/notes_row.xml encodin4= !tACD KP4t;
xmlns5android= http/55schemas.android.com5ap:5res 5android android5la7o!t(=idt>= =rap(content android5la7o!t(>ei4>t= =rap(content EP4t;

F Plt;'ext6ie= android5id= @-idEtextB H I G

En el campo de texto &0ext ie7' vamos a mostrar solo el contenido de la variable text1 de la actividad. Antes de ir a la actividad mirad la clase ,.java #ue os dije en el anterior tutorial #ue Android la manejaba automticamente. (od!is ver cmo ha a6adido el archivo nuevo $ la variable text>. a$amos ahora con Notas.java, miremos su estructura/
B p!blic class +otas extends &cti?it7 {

F H I G U V D} p!blic boolean onOptions)temSelected(0en!)tem item) {...} p!blic boolean onCreateOptions0en!(0en! men!) {...} p!blic ?oid onCreate(B!ndle sa?ed)nstanceState) {...}

onCreate() es el m!todo principal de la actividad donde ejecutaremos todo nuestro cdigo.onCreateOptions enu() crear el men+ de opciones $ onOptions!tem"elected() estar atento a #u! botn del men+ presionamos para ejecutar la accin correspondiente. ,epito #ue es slo sobre acciones sobre el men+, las acciones de otros botones o enlaces van en otros m!todos, exactamente con 2isteners, pero eso $a lo veremos ms adelante. 2o primero #ue vamos a hacer es convertir a *otas en una actividad de lista, para ellos hacemos #ue extienda a 2istActivit$/
B p!blic class +otas extends List&cti?it7

)na combinacin de teclas mu$ +til para arreglar los imports de los pa#uetes es ctrl?shift?@ en Windo7s o 2inux, o cmd?shift?@ en el -ac. 4ueremos #ue en la pantalla principal de *otas muestre la lista de notas, para ello tiene #ue conectarse a la base de datos, coger la informacin $ mostrarla en el la$out #ue hemos hecho antes/
#B pri?ate +otasDb&dapter mDbMelper; #F #H @O?erride #I p!blic ?oid onCreate(B!ndle sa?ed)nstanceState) { #G #U #V #D #W B# } s!per.onCreate(sa?ed)nstanceState); setContent6ie=($.la7o!t.notepad(list); EE ne= notas mDbMelper.open(); AillData();

"eclaramos el objeto fuera para #ue est! disponible a todos los m!todos, fijamos #ue el la$out sea notepadAlist &fijaros como referenciamos a#u al la$out, no usamos urls o directorios, si no referencia mediante la clase ,.java'. amos a coger la informacin en un m!todo privado para #ue #uede todo ms ordenado/
#B pri?ate ?oid AillData() { EE $ec!peramos todas las notas de la DB 7 creamos !na lista C!rsor #H c = mDbMelper.Aetc>&ll+otes(); #F #I #G #U #V #D #W B# BB BF BH } to); E 1 creamos !n adaptador arra7 para q!e ?a7a mostrando las Ailas SimpleC!rsor&dapter notes = ne= SimpleC!rsor&dapter(t>is" $.la7o!t.notes(ro=" c" Arom" setList&dapter(notes); Strin4:; Arom = ne= Strin4:; { +otasDb&dapter.2%1(')'L% }; int:; to = ne= int:; { $.id.textB }; start0ana4in4C!rsor(c);

1a empe%amos a ver ms m!todos internos de Android, os animo a entrar a la A(8 de Android e ir viendo lo #ue hacen exactamente, es la mejor forma de aprender. En #illData()recuperamos todas las notas de la "9 con el m!todo fetchAll*otes #ue hicimos al principio, $ luego creamos un adaptador #ue relaciona el campo del objeto #ue #ueremos &BE1A0802E' con la variable text1 &otra ve% referenciada por $.java' e indica #ue #ueremos #ue use el la$out notes_row.xml #ue hemos creado antes. (or +ltimo avisa a %istActivity #ue notes va a ser la lista #ue #ueremos mostrar. .on estas modificaciones $a podramos ver las notas pero no tenemos ninguna asi #ue vamos a crear la actividad en un momento para #ue podamos probarlo ms a fondo. EnNotas.java a6adamos el botn de a6adir nota. 9asta con llamar a la clase superior para crear el menu $ a6adir el botn de Add 8tem en la primera posicin.
B p!blic static Ainal int )+S%$'()D = 0en!.*)$S'; F H @O?erride I p!blic boolean onCreateOptions0en!(0en! men!) {

G U V D}

boolean res!lt = s!per.onCreateOptions0en!(men!); men!.add(#" )+S%$'()D" #" $.strin4.men!(insert); ret!rn res!lt;

1 a6adimos otra variable de texto a strings.xml


B Plt;strin4 name= men!(insert P4t;&dd )temPlt;Estrin4P4t;

(erfecto, ahora hagamos #ue al hacer clic: en este nuevo botn ejecute la nueva actividad para mostrar el formulario. (ara eso modificamos el m!todo onOptions!tem"elected() tambi!n de Notas.java
#B @O?erride #F p!blic boolean onOptions)temSelected(0en!)tem item) { #H s=itc> (item.4et)tem)d()) { #I #G #U #V #D #W B# } ret!rn s!per.onOptions)temSelected(item); } case )+S%$'()D5 create+ote(); ret!rn tr!e;

.apturamos el 8d de la opcin del men+ $ si es la primera ejecutamos el m!todo createNote(). En un primer paso vamos a hacer #ue inserte una nota con un ttulo $ texto fijos. En el siguiente paso $a crearemos el formulario/
B pri?ate ?oid create+ote() { F H I G} Strin4 note+ame = +ote - m+ote+!mber--; mDbMelper.create+ote(note+ame" ); AillData();

2a ra%n de llamar a #illData() de nuevo es para #ue recargue la lista una ve% #ue se ha terminado de ejecutar el evento de hacer clic: en la opcin del men+ Add 8tem. Es hora de ver en accin lo #ue estamos viendo. .omprueba #ue no ha$ errores en ning+n archivo, arregla los imports $ ejecuta como un pro$ecto de Android. 3i das a menu podrs a6adir una nota e irs viendo como se crea una nota nueva cada ve% #ue le das. Enhorabuena, hemos conseguido comunicarnos correctamente con la base de datos.

Creando la nota con el formulario


2o #ue #ueremos ahora es #ue cuando hacemos clic: en Add 8tem va$amos a otra pantalla donde podamos escribir el ttulo $ el texto de la nota. "emos a guardar $ apare%ca en la lista de notas. (ara eso vamos a tener #ue crear otra actividad &pantalla?controlador'. (ensad #ue por cada pantalla #ue #ueramos tener vamos a tener #ue tener una nueva actividad. Antes de eso vamos a permitir borrar notas, para ello vamos a Notas.java. A6adimos la siguiente lnea al final del m!todo onCreate()
B re4ister*orContext0en!(4etList6ie=());

4ueremos #ue al hacer clic: en un elemento de lista nos salga un men+ desde donde podamos borrarlo. A6adimos un nuevo m!todo #ue sobreescribe a uno de Android/
B @O?erride F p!blic ?oid onCreateContext0en!(Context0en! men!" 6ie= ?" Context0en!)nAo men!)nAo) { H I G} s!per.onCreateContext0en!(men!" ?" men!)nAo); men!.add(#" D%L%'%()D" #" $.strin4.men!(delete);

Hace falta insertar ms variables en Notas.java


B pri?ate static Ainal int &C')6)'1(C$%&'%=#; F pri?ate static Ainal int &C')6)'1(%D)'=B; H I pri?ate static Ainal int )+S%$'()D = 0en!.*)$S'; G pri?ate static Ainal int D%L%'%()D = 0en!.*)$S' - B;

$ en strin&s.xml
B Plt;strin4 name= men!(delete P4t;Delete +otePlt;Estrin4P4t; F Plt;strin4 name= title P4t;'itlePlt;Estrin4P4t; H Plt;strin4 name= bod7 P4t;Bod7Plt;Estrin4P4t; I Plt;strin4 name= conAirm P4t;ConAirmPlt;Estrin4P4t; G Plt;strin4 name= edit(note P4t;%dit +otePlt;Estrin4P4t;

Ahora #ue $a podemos seleccionar la nota a borrar, vamos a crear el m!todo #ue efectivamente lo borra/
#B @O?erride

#F p!blic boolean onContext)temSelected(0en!)tem item) { #H s=itc>(item.4et)tem)d()) { #I #G #U #V #D #W B# BB } } ret!rn s!per.onContext)temSelected(item); case D%L%'%()D5 &dapterContext0en!)nAo inAo = (&dapterContext0en!)nAo) item.4et0en!)nAo(); mDbMelper.delete+ote(inAo.id); AillData(); ret!rn tr!e;

olvemos a hacer un s7itch para comprobar la posicin del botn del men+ $ si es la segunda borramos la nota $ recargamos la lista. .onseguimos el 8" de la nota gracias a &et enu!n#o()$ al m!todo re&ister'orContext enu() #ue hemos insertado antes al final de onCreate(). olvamos ahora al m!todo auxiliar para crear nuevas notas, borramos lo #ue tenamos $ vamos a cargar una nueva actividad/
B pri?ate ?oid create+ote() { F H I} )ntent i = ne= )ntent(t>is" +ote%dit.class); start&cti?it7*or$es!lt(i" &C')6)'1(C$%&'%);

2o #ue hacemos es crear un nuevo 8ntent, una nueva actividad, en este caso *oteEdit #ue todava no hemos creado. Ejecuta su comien%o $ espera el resultado. .on el resultado luego llamar a la funcin onActivity$esult() #ue implementaremos ms tarde. 3i no nos interesa saber el resultado basta con llamar a la funcin startActivity() amos a hacer algo parecido para editar las notas #ue $a tenemos. (ero antes de nada vamos a permitir utili%ar el .ursor en toda la clase, para eso a6adimos la variable de clase/
B pri?ate C!rsor m+otesC!rsor;

refactori%amos onCreate() #ue #uedara ahora as/


B @O?erride F p!blic ?oid onCreate(B!ndle sa?ed)nstanceState) { H s!per.onCreate(sa?ed)nstanceState);

I G U V D W}

setContent6ie=($.la7o!t.notepad(list); mDbMelper = ne= +otasDb&dapter(t>is); mDbMelper.open(); AillData(); re4ister*orContext0en!(4etList6ie=());

$ nuestro m!todo privado #illData()


#B pri?ate ?oid AillData() { #F #H #I #G #U #V #D #W B# BB BF BH BI BG } SimpleC!rsor&dapter notes = ne= SimpleC!rsor&dapter(t>is" $.la7o!t.notes(ro=" m+otesC!rsor" Arom" to); setList&dapter(notes); EE arra7 con las ?ariables asociadas para esos campos int:; to = ne= int:;{$.id.textB}; EE &rra7 con los campos q!e q!eremos mostrar en la lista Strin4:; Arom = ne= Strin4:;{+otasDb&dapter.2%1(')'L%}; EE $ec!pera todas las notas de la DB 7 las 4!arda en el c!rsor m+otesC!rsor = mDbMelper.Aetc>&ll+otes(); start0ana4in4C!rsor(m+otesC!rsor);

Ahora $a podemos fijarnos en el m!todo #ue se ejecute al hacer clic: sobre un elemento de la lista. 3e llama on%ist!temClic(() $ lo sobreescribimos/
#B @O?erride protected ?oid onList)temClic<(List6ie= l" 6ie= ?" int position"lon4 id) { #H s!per.onList)temClic<(l" ?" position" id); #F #I #G #U #V #D #W B# BB BF BH } C!rsor c = m+otesC!rsor; c.mo?e'o/osition(position); )ntent i = ne= )ntent(t>is" +ote%dit.class); i.p!t%xtra(+otasDb&dapter.2%1($OJ)D" id); i.p!t%xtra(+otasDb&dapter.2%1(')'L%" c.4etStrin4( c.4etCol!mn)ndexOr'>ro=(+otasDb&dapter.2%1(')'L%))); i.p!t%xtra(+otasDb&dapter.2%1(BOD1" c.4etStrin4( c.4etCol!mn)ndexOr'>ro=(+otasDb&dapter.2%1(BOD1))); start&cti?it7*or$es!lt(i" &C')6)'1(%D)');

2o #ue estamos haciendo es mover el .ursor a la posicin en la #ue estamos, crear el 8ntent $ pasarle como argumentos el 8d, ttulo $ texto. (ara pasar como argumentos utili%amos la funcin put)xtra(). @tra funcin mu$ +til. (or +ltimo lo ejecutamos esperando el resultado. a siendo hora de implementar el m!todo onActivity$esult() #ue es el #ue se ejecuta cuando recibimos el resultado de haber creado o editado una nota con startActivity'or$esult()
#B @O?erride #F protected ?oid on&cti?it7$es!lt(int req!estCode" int res!ltCode" )ntent intent) { #H s!per.on&cti?it7$es!lt(req!estCode" res!ltCode" intent); #I #G #U #V #D #W B# BB BF BH BI BG BU s=itc>(req!estCode) { case &C')6)'1(C$%&'%5 Strin4 title = extras.4etStrin4(+otasDb&dapter.2%1(')'L%); Strin4 bod7 = extras.4etStrin4(+otasDb&dapter.2%1(BOD1); mDbMelper.create+ote(title" bod7); AillData(); brea<; case &C')6)'1(%D)'5 Lon4 m$o=)d = extras.4etLon4(+otasDb&dapter.2%1($OJ)D); iA (m$o=)d O= n!ll) { B!ndle extras = intent.4et%xtras();

Strin4 edit'itle = extras.4etStrin4(+otasDb&dapter.2%1(')'L%); Strin4 editBod7 = BV extras.4etStrin4(+otasDb&dapter.2%1(BOD1); BD BW F# FB FF FH } } } AillData(); brea<; mDbMelper.!pdate+ote(m$o=)d" edit'itle" editBod7);

3i estamos creando la nota, la guarda en la base de datos. 3i la estamos editando, la actuali%a $ en ambos casos recarga la lista de notas.

1a tenemos la lgica ms o menos, vamos ahora a crear el la$out del formulario. (ara eso creamos el archivo /res/layout/note_edit.xml $ lo rellenamos con/
#B Plt;Kxml ?ersion= B.# #F Plt;LinearLa7o!t xmlns5android= http/55schemas.android.com5ap:5res5android android5orientation= ?ertical #I android5la7o!t(=idt>= Aill(parent #G android5la7o!t(>ei4>t= Aill(parent P4t; #H #U #V #D #W B# BB BF BH BI BG BU BV BD BW F# FB FF FH FI FG FU FV FD FW H# HB HF HH Plt;ELinearLa7o!tP4t; Plt;B!tton android5id= @-idEconAirm android5text= @strin4EconAirm android5la7o!t(=idt>= =rap(content android5la7o!t(>ei4>t= =rap(content EP4t; Plt;'ext6ie= android5la7o!t(=idt>= =rap(content android5la7o!t(>ei4>t= =rap(content android5text= @strin4Ebod7 EP4t; Plt;%dit'ext android5id= @-idEbod7 android5la7o!t(=idt>= Aill(parent android5la7o!t(>ei4>t= =rap(content android5la7o!t(=ei4>t= B android5scrollbars= ?ertical EP4t; Plt;'ext6ie= android5la7o!t(=idt>= =rap(content android5la7o!t(>ei4>t= =rap(content android5text= @strin4Etitle EP4t; Plt;%dit'ext android5id= @-idEtitle android5la7o!t(=idt>= =rap(content android5la7o!t(>ei4>t= =rap(content android5la7o!t(=ei4>t= B EP4t; Plt;ELinearLa7o!tP4t; Plt;LinearLa7o!t android5orientation= >oriNontal android5la7o!t(=idt>= Aill(parent android5la7o!t(>ei4>t= =rap(content P4t; encodin4= !tACD KP4t;

Este es un la$out $a ms complicado. 2o #ue hace es crear dos campos de texto, uno para el ttulo $ otro para el textoC $ el botn #ue guarda lo #ue hemos escrito. )tili%ando una me%cla de configuraciones de alturas conseguimos la apariencia #ue #ueremos. En el prximo tutorial entraremos ms en detalle en los la$outs. amos a crear la clase Note)dit.java ahora #ue $a tenemos su la$out. copiar el cdigo final comentado $ explico detalles al final/
#B EL #F L Cop7ri4>t (C) F##D .oo4le )nc. #H LE #I #G pac<a4e com.android.demo.notepadB; #U #V import android.app.&cti?it7; #D import android.content.)ntent; #W import android.os.B!ndle; B# import android.?ie=.6ie=; BB import android.=id4et.B!tton; BF import android.=id4et.%dit'ext; BH BI p!blic class +ote%dit extends &cti?it7 { BG BU BV BD BW F# FB FF FH FI FG FU FV FD FW EE ObTetos q!e reAerencian a los campos editables del la7o!t m'itle'ext = (%dit'ext) Aind6ie=B7)d($.id.title); mBod7'ext = (%dit'ext) Aind6ie=B7)d($.id.bod7); EE *iTamos el la7o!t de esta acti?idad setContent6ie=($.la7o!t.note(edit); @O?erride protected ?oid onCreate(B!ndle sa?ed)nstanceState) { s!per.onCreate(sa?ed)nstanceState); pri?ate %dit'ext m'itle'ext; pri?ate %dit'ext mBod7'ext; pri?ate Lon4 m$o=)d;

o$ a

H# HB HF HH HI HG HU

B!tton conAirmB!tton = (B!tton) Aind6ie=B7)d($.id.conAirm); EE Si >a7 ar4!mentos" los co4emos m$o=)d = n!ll; B!ndle extras = 4et)ntent().4et%xtras(); iA (extras O= n!ll) {

Strin4 title = extras.4etStrin4(+otasDb&dapter.2%1(')'L%); HV Strin4 bod7 = extras.4etStrin4(+otasDb&dapter.2%1(BOD1); HD HW I# IB IF IH II IG IU IV ID IW G# GB GF GH GI GG GU EE .!ardamos los n!e?os ?alores en !n B!ndle p!blic ?oid onClic<(6ie= ?ie=) { B!ndle b!ndle = ne= B!ndle(); EE Listener para el botYn de conAirmar conAirmB!tton.setOnClic<Listener(ne= 6ie=.OnClic<Listener() { } } iA (bod7 O= n!ll) { mBod7'ext.set'ext(bod7); } EE )nsertamos los ?alores act!ales de la nota en los campos iA (title O= n!ll) { m'itle'ext.set'ext(title); m$o=)d = extras.4etLon4(+otasDb&dapter.2%1($OJ)D);

b!ndle.p!tStrin4(+otasDb&dapter.2%1(')'L%" m'itle'ext.4et'ext().toStrin4()); b!ndle.p!tStrin4(+otasDb&dapter.2%1(BOD1" GV mBod7'ext.4et'ext().toStrin4()); GD GW U# UB UF UH EE 7 los mandamos de ?!elta al mZtodo q!e los est[ esperando )ntent m)ntent = ne= )ntent(); m$o=)d); } iA (m$o=)d O= n!ll) { b!ndle.p!tLon4(+otasDb&dapter.2%1($OJ)D"

UI UG UU UV UD UW V# VB } } }); }

m)ntent.p!t%xtras(b!ndle); set$es!lt($%S3L'(O2" m)ntent); Ainis>();

Ha$ #ue fijarse en cmo cogemos la referencia al campo de texto &mediante la clase ,.java por supuesto' m0itle0ext ; &Edit0ext' find ie79$8d&,.id.title'C En cmo cogemos los argumentos #ue hemos pasado antes con el m!todo put)xtra() $ cmo asignamos los valores actuales m0itle0ext.set0ext&title'C El +ltimo paso tras crear una nueva actividad es declararla en el archivo Android ani#est.xml. ,ecordarlo bien por#ue es un tpico fallo #ue nos hace perder muchas horas.
B Plt;acti?it7 android5name= .+ote%dit P4t;Plt;Eacti?it7P4t;

0ambi!n se puede introducir la nueva actividad con los paneles de control en ve% de directamente sobre el cdigo &Application ?D Add Application *ode ?D Activit$ $ rellenamos el nombre' Es hora de ejecutar el programa de nuevo para ir viendo cmo evoluciona. 1a podemos editar las notas #ue creamos antes $ crear nuevas con la opcin Add 8tem del men+. (robad a dar hacia atrs cuando est!is en el formulario. cmo salta una excepcin. er!is

Resumen
Ho$ hemos tocado muchos temas $ mu$ variados/

Hemos creado nuestro primer modelo con su conexin a la base de datos

&adaptador de por medio para facilitarnos la vida'.


Hemos visto ms la$outs para mostrar listas $ formularios. Hemos creado una actividad de lista #ue os puede servir de modelo para

vuestras apps. (ermite crear nuevas notas, editarlas $ borrarlas. Aun#ue mejor esperad a la semana #ue viene para tomarla como modelo $a #ue haremos algunos cambios importantes.
Hemos creado una segunda actividad por lo #ue $a podemos decir #ue

nuestra app es medianamente compleja, al menos tiene E pantallasF

Gua Android: Descubrindolo con el Hello World


amos a empe%ar en -aestros del Web una serie de artculos ms t!cnicos sobre cmo hacer aplicaciones para Android, el sistema operativo mvil de Google. .omo sab!is es de cdigo abierto $ gratuito por lo #ue cual#uier persona o empresa pueda cogerlo, modificarlo $ usarlo en sus productos. Esta apertura va a provocar #ue ha$a ms de EH mviles con Android a finales de a6o. 8ncluso recientemente hemos visto #ue Acer va a lan%ar un netboo: con una versin modificada de Android. (or si faltan excusas para aprender tambi!n deciros #ue )buntu ha financiado un pro$ecto #ue permitir ejecutar programas de Android en este famoso sistema operativo.

Requisitos
Android est hecho en IavaJK-2, siguiendo el patrn - . &-odel? ie7?

.ontroller'.
9jate el 3"B El mejor 8"E para programar para Android es Eclipse &multiplataforma',

pero puedes usar el #ue #uieras, solo #ue tendrs menos facilidades. En los artculos usaremos Eclipse.
9jate el plugin de Android para Eclipse &A"0'.

En estas fciles instrucciones podrs completar los pasos previos.

Creando un nuevo proyecto

2a mejor forma de conocer un sistema es probndolo asi #ue vamos a crear el pro$ecto $ por el camino vamos explicando cmo funciona Android.

)na ve% instalado el plugin, creamos el nuevo pro$ecto de Android &Lile D *e7 D (roject D Android (roject'. "amos a siguiente/

*roject+name, Hola-undo *ac(a&e+name, com.example.holamundo Create+Activity, Hola-undo Application+name, Hola -undo

Aun#ue he puesto los mismos nombres en los M sitios no tiene por #u! coincidir, como sabr!is. El nombre de la aplicacin es lo #ue ver!is en el mvil, las actividades son los controladores de Android, el nombre del pa#uete es algo interno $ el pro$ecto es lo #ue ver!is en Eclipse. Linali%amos $ podremos ver el siguiente rbol de archivos

o$ a explicar la estructura/
/src N A#u se encuentran las actividades &controladores recuerdo', clases

$ un archivo #ue se llama ,.java. Este archivo no se debe tocar nunca, Android lo actuali%a automticamente pero si lo veis os encontrar!is con variables $ posiciones.
/Android+%ibrary N Eclipse referencia al sd: de Android. *o movis nunca

el sd: de sitio o si lo hac!is recordad cambiar la direccin


/assets N A#u se puede incluir archivos varios &m+sica, pdfs, %ips, rars' /res/drawable N 0odas las imgenes van en este directorio /res/layout N 0odas las vistas van a#u

/res/values N En el archivo strings.xml podemos poner variables #ue

luego sustituiremos en las vistas


Android ani#est.xml N Este archivo es mu$ importante por#ue recoge

todas las actividades $ algunas configuraciones del pro$ecto.

Antes de seguir vamos a ejecutar el pro$ecto, $ para eso damos a ,un As $ elegimos Android Application. 3i instalasteis todo bien saldr el emulador, cargando iniciando Android &tarda un po#uito'. 2o desblo#ueamos dando a -en+, $ $a puedes ver la aplicacin ms bsica #ue se hace en todos los lenguajes, nuestro Hola -undo.

3i #uieres puedes investigar los programas #ue trae el emulador, est bastante bien conseguidoC aun#ue para mi gusto faltan varios detalles como girar el tel!fono en posicin hori%ontal. A continuacin veremos cmo ha funcionado el programa.

Entendiendo el Hola Mundo


Gracias al plugin de Android, no hemos programado nada $ $a tenemos el programa bsico. (ero como hemos visto antes en la estructura, se han creado unos cuantos archivos. amos a ir paso a paso por cada uno de ellos.

#B EE &ndroid0aniAest.xml #F Plt;Kxml ?ersion= B.# encodin4= !tACD KP4t; Plt;maniAest #H xmlns5android= http/55schemas.android.com5ap:5res5android #I #G #U pac<a4e= com.example.>olam!ndo android5?ersionCode= B

android5?ersion+ame= B.#.# P4t; Plt;application android5icon= @dra=ableEicon #V android5label= @strin4Eapp(name P4t; #D #W B# BB BF EP4t; Plt;acti?it7 android5name= .Mola0!ndo android5label= @strin4Eapp(name P4t; Plt;intentCAilterP4t; Plt;action android5name= android.intent.action.0&)+ EP4t;

Plt;cate4or7 android5name= android.intent.cate4or7.L&3+CM%$ BH Plt;EintentCAilterP4t; BI BG Plt;Eacti?it7P4t; Plt;EapplicationP4t;

BU Plt;EmaniAestP4t;

3upongo #ue estar!is familiari%ados con xml, si no, no os preocup!is, es mu$ fcil de entender. (odemos ver como crea un manifesto con el pa#uete $ la versin de Android. .ontiene la aplicacin #ue hemos creado. android/icon;<=dra7able5icon< coge la imagen llamada icon.png del directorio /res/drawables $ la asigna como icono. Esto es lo #ue v!is en el men+ de aplicaciones. 2o mismo sucede conandroid/label;<=string5appAname<, sustitu$e la variable app_name por su valor en el archivo/
B EE resE?al!esEstrin4s.xml F Plt;Kxml ?ersion= B.# encodin4= !tACD KP4t;

H Plt;reso!rcesP4t; I G Plt;strin4 name= >ello P4t;Mello Jorld" Mola0!ndoPlt;Estrin4P4t; Plt;strin4 name= app(name P4t;Mola 0!ndoPlt;Estrin4P4t;

U Plt;Ereso!rcesP4t;

olviendo a Android ani#est.xml, vemos #ue dentro de application se encuentra la actividad principal android/name;<.Hola-undo<, #ue corresponde con un punto ms el nombre de la clase java en src/com.example.-olamundo. El resto son detalles ms profundos. Asi #ue Android ejecuta esa clase, vamos a verla/
#B EE srcEcom.example.>olam!ndoEMola0!ndo.Ta?a #F pac<a4e com.example.>olam!ndo; #H #I import android.app.&cti?it7; #G import android.os.B!ndle; #U #V p!blic class Mola0!ndo extends &cti?it7 { #D #W B# BB BF BH BI BG BU } } ELL Called =>en t>e acti?it7 is Airst created. LE @O?erride p!blic ?oid onCreate(B!ndle sa?ed)nstanceState) { EE )nicialiNa la acti?idad s!per.onCreate(sa?ed)nstanceState); EE &si4namos la ?ista setContent6ie=($.la7o!t.main);

.rea una actividad llamada .ola undo con un +nico m!todo #ue sobreescribe al de la clase #ue extiende. emos como set.ontent ie7 pasa como parmetro $.layout.main #ue representa a /res/layout/main.xml. (ero como dije antes, todo las referencias a archivos $ variables pasan por la clase $.java #ue Android se encarga de ajustar automticamente. eamos la vista
#B EE resEla7o!tEmain.xml #F Plt;Kxml ?ersion= B.# encodin4= !tACD KP4t; Plt;LinearLa7o!t #H xmlns5android= http/55schemas.android.com5ap:5res5android #I #G #U #V android5orientation= ?ertical android5la7o!t(=idt>= Aill(parent android5la7o!t(>ei4>t= Aill(parent P4t;

#D Plt;'ext6ie= #W B# BB BF android5la7o!t(=idt>= Aill(parent android5la7o!t(>ei4>t= =rap(content android5text= @strin4E>ello EP4t;

BH Plt;ELinearLa7o!tP4t;

.omo pod!is ver vuelve a ser un xml $ es #ue Google ha elegido usar xml para representar las vistas. 2inear2a$out es un tipo de la$out #ue muestra los elementos uno debajo de otro. 0iene orientacin vertical $ ocupa toda la pantalla tanto a lo alto como a lo ancho. "entro podemos ver un campo de texto &/ext0iew' cu$o texto se encuentra en el archivostrin&s.xml visto antes.

Finalizando
Hemos visto paso por paso lo #ue hace Android para ejecutar un sencillo Hola -undo. 2o importante es/
Android ani#est.xml contiene todas las actividades indicando cul se

ejecuta primero.
0odas las actividades $ clases se encuentran en src. 2a actividad

Hola-undo usa el la$out main.xml


0odos los la$outs estn en res/layout. 3e programan en xml siguiendo las

eti#uetas del 3"B de Android.


En cual#uier sitio podemos referenciar a variables del fichero strings.xml.

Esto es mu$ +til para aplicaciones en varios idiomas.

Como &acer a#licaciones com#atibles con todas las versiones


Se uramente mas de uno se ha encontrado con el problema de no poder usar "uncionalidades del A./ ).) si quiere que su aplicacion si a siendo compatible con los moviles que aun tiene Android #.6 .ensando el otro d!a se me ocurri& este mtodo, espero que os sirva y lo encontreis til< $a mquina virtual tiene la particularidad de que mientras no se acceda a una clase con llamadas a "unciones de un A./ superior no salta la excepcion de validacion, por lo tanto se trata de no permitir que car ue en nin un momento esas clases. .ara ilustrarlo me%or pon o un e%emplo.

(ueremos llamar a un mtodo solo disponible en el A./ ).- como pueda ser<
Cdigo : ... o?erride/endin4'ransition(enter&nim" exit&nim); ...

Si un movil con, por e%emplo, una version de Android #.6 se encuentra al o as! en una de nuestras Activity no de%ara car arla y nos sacara del pro rama con una excepcion de validacion porque los bytecodes de ese mtodo no los reconoce. .ara evitar esto montamos las si uientes clases<
Cdigo : public class Compatibilit7 { public static int ?ersion() { iA (B!ild.6%$S)O+.SD2.eq!als( B.G )) return H; return &piG.?ersion(); } public static ?oid &cti?it7(o?erride/endin4'ransition(&cti?it7 me" int enter&nim" int exit&nim) { iA (?ersion()8G) return; &piG.&cti?it7(o?erride/endin4'ransition(me" enter&nim" exit&nim); } } public class &piG { public static int ?ersion() { return B!ild.6%$S)O+.SD2()+'; } public static ?oid &cti?it7(o?erride/endin4'ransition(&cti?it7 me" int enter&nim" int exit&nim) { me.o?erride/endin4'ransition(enter&nim" exit&nim); } }

3 nuestra llamada al mtodo problemtico quedar!a de la si uiente "orma<


Cdigo : ... Compatibilit7.&cti?it7(o?erride/endin4'ransition(this" enter&nim" exit&nim); ...

,on esto lo ramos que en caso de detectarse un A./ que no soporte ese mtodo 0version()<51 no hacemos nada, mientras que si s! se est e%ecutando en un A./ valido llamamos a la clase )C'? donde alo%aremos todo el c&di o problemtico y que nunca se car ar en m&viles con A./ menor a la version ).- ya que la clase Compatibilit9 "iltra todas las llamadas.

You might also like