MDW Guia Android 1

download MDW Guia Android 1

of 137

Transcript of MDW Guia Android 1

  • 8/6/2019 MDW Guia Android 1

    1/137

  • 8/6/2019 MDW Guia Android 1

    2/137

    CURSO ANDROID 2

    SOBRE LA GUA

    Curso Android:

    Versin 1 / junio 2011

    Nivel: Bsico / Intermedio

    Desarrollo de aplicaciones mviles

    El Curso Android se encuentra en lnea en:

    http://www.maestrosdelweb.com/editorial/curso-android

    Un proyecto de Maestros del Web

    Edicin: Stephanie Falla ArocheDiseo y diagramacin: Ivn E. MendozaAutor: Adrin Cataln

    Este trabajo se encuentra bajo una licencia Creative Commons

    Atribucin-NoComercial-CompartirIgual 3.0 Unported (CC BY-NC-SA3.0)

    El logotipo de Android es compartido por Google bajo licencia Creative Commons porAtribucin.

    Contacto

    http://www.maestrosdelweb.com/sitio/correo/

    Redes socialesFacebook: http://www.facebook.com/maestrosdelwebTwitter: http://www.twitter.com/maestros

  • 8/6/2019 MDW Guia Android 1

    3/137

    CURSO ANDROID 3

    SOBRE EL AUTOR

    Adrin Cataln

    Guatemalteco, Ingeniero en Sistemas con una Maestra en Tecnologas de Informacin con

    especialidaden Seguridad informtica y Redes de Computadoras de la Universidad Galileo.

    Es catedrtico de cursos sobre arquitectura de computadoras, mquinas y lenguajes, compiladbases de datos, ingeniera de software, desarrollo web, sistemas operativos, redes, voz sobre Iseguri-dad informtica y mtodos forenses en IT.

    Desarrollador de software, apasionado por aplicaciones web (Ruby On Rails) y mviles (Androifunda-dor del grupo de tecnologas de Google en Guatemala(GTUG) y co fundador de Elemental Gee

    unfirme creyente del infinito talento hispanoamericano, consciente de la necesidad de fomentarldarloa conocer.Puedes comunicarte a travs de redes sociales:

    Email: [email protected]: adrian.catalanTwitter: @ykro

  • 8/6/2019 MDW Guia Android 1

    4/137

    CURSO ANDROID 4

    NDICE

    1 | Sobre lagua ....................................................................................... 22 | Sobre elautor ..................................................................................... 33 | Construir un lector de feedssimple ................................................... 54 | Aumentar la funcionalidad de un lector de feeds ...........................

    235 |Trabajando con imgenes (cmara y galera) ..................................446 | Grabacin y reproduccin de vdeo..................................................557 | Geolocalizacin y utilizacin de mapas de Google ..........................648 |Trabajar con el acelermetro ...........................................................739 | Reproduccin de sonido en un ciclo infinito ...................................83

    10 | Envo de email utilizando Android ...................................................9011 |Trabajando con APIs (Facebook y Twitter) .......................................9912 | Conectndonos con Apis de Google ...............................................117

    13 | Comunidades android ...................................................................13414 | Otras guas de maestros del web ...................................................135

  • 8/6/2019 MDW Guia Android 1

    5/137

    captulo1

    Construir un lector defeeds simple

  • 8/6/2019 MDW Guia Android 1

    6/137

    CURSO ANDROID 6

    CAPTULO 1

    Construir un lector de feeds simpleBienvenidos al primer captulo del curso sobre Android daremos inicio con el funcionamiento darquitectura de esta plataforma mvil y los bloques bsicos de una aplicacin.

    Kernel de Linux

    En la base tenemos el kernel 2.6 de Linux, Android lo utiliza por su robustez demostrada y porimple-mentacin de funciones bsicas para cualquier sistema operativo, por ejemplo: seguridad,administra-cin de memoria y procesos, implementacin de conectividad de red (network stack) y variosinterpretes(drivers) para comunicacin con los dispositivos fsicos(hardware).

    Android utiliza como base el kernel de Linux pero los dos sistemas no son lo mismo, Android ncuentacon un sistema nativo de ventanas de Linux ni tiene soporte para glibc (libera estndar de C) tampocoes posible utilizar la mayora de aplicaciones de GNU de Linux.

    Adems de todo lo ya implementado en el kernel de Linux, Android agrega algunas cosasespecficaspara plataformas mviles como la comunicacin entre procesos (lograda a travs del binder), formade manejar la memoria compartida (ashmem) y la administracin de energa (con wakelocks).caractersticas nicas del kernel utilizado por Android encuentran ms informacin en Android

    KernelFeatures 1.

    Libreras y ejecucin

    Sobre el kernel, tenemos un conjunto de libreras de C y C++ utilizadas por el sistema para vafines

    1 http://elinux.org/Android_Kernel_Features

  • 8/6/2019 MDW Guia Android 1

    7/137

    CURSO ANDROID 7

    como el manejo de la pantalla (surface manager), mapas de bits y tipos de letra (Free Type),

    grficas en2D y 3D (SGL y OpenGL), manejo de multimedia (Media Framework), almacenamiento de dato(SQLite)y un motor para las vistas web y el navegador (WebKit).

    Junto a estas libreras, encontramos lo necesario para la ejecucin de las aplicaciones a travsmquina virtual Dalvik. Cada aplicacin utiliza una instancia de la mquina virtual ejecutando archivoDEX (Dalvik Executable) y el sistema est optimizado para que se ejecuten mltiples instanciamquina virtual. Se desarrolla en Java pero no se utiliza una mquina virtual de Sun para suejecucinni tampoco archivos CLASS.

    Estructura de aplicaciones

    Sobre las libreras encontramos una estructura que nos brinda un contexto para desarrollar, es

    framework permite a los desarrolladores aprovechar un sistema de vistas ya construido, adminnotificaciones y acessar datos a travs de proveedores de contenido entre otras cosas.

    Aplicaciones

    Las aplicaciones centrales que incluye el sistema por defecto son: telfono, navegador, manejocontactos, etc. En esta capa de la arquitectura es donde trabajaremos desarrollando aplicacion

    Bloques bsicos de una aplicacin

    Una vez vista la arquitectura, empezaremos con lo fundamental para desarrollar una aplicaci

  • 8/6/2019 MDW Guia Android 1

    8/137

    CURSO ANDROID 8

    componentes bsicos de una aplicacin son: activities, intents, views, services, contentproviders y broadcast receivers.

    Si dominan bien estos trminos pueden saltar directo al cdigo.

    1234

    Activities1: son componentes de la interfaz que corresponde a una pantalla. Podemosvisualizarlocomo un mazo de cartas en el que tenemos varias cartas pero solamente una est hasta Una aplicacin para una lista de cosas por hacer (remember the milk) puede tener unaactividadpara ingresar las cosas por hacer y otra actividad para mostrar el listado, en conjunto estaactivi-dades conforman la aplicacin.Intents2: son mensajes que provocan notificaciones o cambios de estatus, que al ser recibporactividades o servicios pueden levantar procesos. De esta forma se unen componentes de

    dela misma aplicacin o de diferentes aplicaciones.Views 3: son los componentes de la interfaz de usuario, diferentes vistas pueden agruparstravs de grupos logrando una jerarqua, esto se logra a travs de la disposicin de loscomponen-tes a travs de un archivo XML.Services4 : son componentes que ejecutan operaciones en segundo plano y no tienen unainterfazhttp://developer.android.com/guide/topics/fundamentals/activities.htmhttp://developer.android.com/guide/topics/intents/intents-filters.html

    http://developer.android.com/guide/topics/ui/index.htmlhttp://developer.android.com/guide/topics/fundamentals/services.html

  • 8/6/2019 MDW Guia Android 1

    9/137

    CURSO ANDROID 9

    de usuario. Por ejemplo, al escuchar msica, hay un servicio encargado de la reproduccise

    ejecuta de fondo y la aplicacin que manipulamos le manda mensajes a este servicio dicique se detenga, pause o reproduzca la siguiente cancin.Content Providers1: representan la abstraccin para almacenar y obtener datos permanenaplicaciones diferentes. El sistema incluye algunos proveedores de contenido tiles (audiovideo,etc) y adems pueden desarrollarse nuevos.Manifest2: El archivo AndroidManifest.xml es donde se configura la aplicacin, se agregandades, se asignan permisos, etc.Broadcast Receivers: son componentes que responden a avisos y anuncios de difusin (brcast). Estos avisos provienen del sistema (batera baja, una llamada entrante, etc) y deaplicaciones(pasando avisos de una aplicacin a otra). Aun que no muestran una interfaz de usuario

    algunasveces utilizan barras de progreso para mostrar avances. Estos se activan a travs de menasin-crnicos llamados intents (mencionados arriba).

    Ejemplo: Lector de feeds

    La aplicacin que realizaremos es un lector para el feed de Maestros del Web, queremos que afinalizarse vea de la siguiente forma:

    1 http://developer.android.com/guide/topics/providers/content-providers.html2 http://developer.android.com/guide/topics/manifest/manifest-intro.html

  • 8/6/2019 MDW Guia Android 1

    10/137

    CURSO ANDROID 10

    Disposicin inicial

    Arrancamos descargando el cdigo base1 que debe ser importado hacia un proyecto nuevo. Encaso,el cdigo descargado lo tengo en el folder /Users/ykro/Desktop/LectorFeedMDWBase:

    En este cdigo encontrars algunas cosas de ayuda para el desarrollo del proyecto. Si quisierainiciardesde cero, con un proyecto nuevo, lo mnimo que deberan hacer para tenerlo listo es:

    Darle permiso a la aplicacin para que pueda accesar a internet

    Para hacer esto, vamos al archivo AndroidManifest.xml y justo antes de la etiqueta que cierramanifest colocamos:



    1 https://github.com/androidMDW/guia1base

  • 8/6/2019 MDW Guia Android 1

    11/137

    CURSO ANDROID 11

    Tener un LinearLayout con orientacin vertical en el archivo de diseoprincipal.

    Para lograr esto, en el archivo /res/layout/main.xml es necesario tener:


    Tener una forma de reconocer XML.

    En el cdigo de demo se provee la clase src/com/android/mdw/demo/XMLParser.java. No vamorepa-sar el cdigo de cmo se hace el reconocimiento de XML, este parser tiene un funcionamientogeneralsin embargo para los fines de esta aplicacin nos interesa que devuelva una lista simplementedenada (LinkedList de Java) y en cada posicin un diccionario (HashMap de Java) porque de esformavamos a almacenar los datos.Esto se logra a travs de un mtodo llamado parse() y adicional a esto, en el constructor el

    XMLParserdebe recibir la direccin del feed que reconocer.

    Diseo

    Trabajaremos con los siguientes views para lograr el objetivo.

    LinearLayout1: agrupa los elementos en un solo sentido (vertical u horizontal).ListView2: muestra los elementos en un listado vertical con scroll.

    TextView3: una etiqueta para colocar texto.

    Button4: un botn para presiona.

    Vamos a colocar primero un LinearLayout con arreglo vertical y dentro de l doscosas:

    1234

    http://developer.android.com/guide/tutorials/views/index.htmlhttp://www.maestrosdelweb.com/editorial/curso-android-construir-lector-de-feeds/http://developer.android.com/reference/android/widget/TextView.htmlhttp://developer.android.com/reference/android/widget/Button.html

  • 8/6/2019 MDW Guia Android 1

    12/137

    CURSO ANDROID 12

    1 | LinearLayout con arreglo horizontal (para la etiqueta y el botn).2 | ListView para los elementos del feed.

    Nuestro archivo /res/layout/main.xml quedara entonces de la siguiente forma:



    android:orientation=vertical xmlns:android=http://schemas.android.com





    android:layout_height=wrap_content

    Es importante notar los identificadores que colocamos, ya que los utilizaremos msadelante.

  • 8/6/2019 MDW Guia Android 1

    13/137

    CURSO ANDROID 13

    Mostrar datos siguiendo el diseo

    Luego de terminado el diseo podemos enfocarnos en el cdigo que nos permitir poblar el Liscon los elementos del feed que vamos a leer.

    Trabajemos ahora en el archivo src/com/android/mdw/demo/Main.java.

    Inicialmente encontramos 2 constantes que utilizaremos para guardar la informacin en unHashMap.


    static final String DATA_TITLE = T;
    static final String DATA_LINK = L;

    Agregamos una estructura de datos esttica para guardar la informacin del feed una vez la fuatraer y reconocimos.


    static LinkedList data;

    En una aplicacin real esto no debera hacerse nunca, todo campo esttico (variable de clase)ra ser final1 y en este caso no lo es porque lo asignaremos luego de que el parser devuelva la Laforma correcta de realizar este almacenamiento voltil es utilizando clases de aplicacin, algo vere-mos en prximos captulos y si se quisiera almacenamiento no voltil se tiene acceso a base ddatos atravs de SQLite. Haremos tambin una funcin auxiliar que recibe una lista de mapas, y utilizestadata crea un adaptador para poblar al ListView del diseo.


    private void setData(LinkedList data){

    />

    SimpleAdapter sAdapter = new SimpleAdapter(getApplicationContext(), data,

  • 8/6/2019 MDW Guia Android 1

    14/137

    CURSO ANDROID 14

    new int[] { android.R.id.text1, android.R.id.text2 });

    ListView lv = (ListView) findViewById(R.id.lstData);

    lv.setAdapter(sAdapter);

    }

    Nuestro objetivo final es tomar una vista (ListView) creada en el diseo y poblarla de datos a tdeun adaptador . La informacin que representaremos por cada fila del listado es el ttulo del artel link del mismo. Para nuestro caso vamos a utilizar el adaptador simple (SimpleAdapter) que5parmetros.

    1 | Un contexto sobre el cual puede trabajar, lo obtenemos llamando a getApplicationCon-

    2|3|

    text()Un Listado de mapas con la data a mostrar, lo recibimos como parmetro en la funcin.Un Layout para cada fila, en este caso usaremos uno de los predeterminados de Androidllamadoandroid.R.layout.two_line_list_item este nos permite tener elementos con infor-macin en 2 lneas.Un arreglo de String con las llaves del diccionario que representarn los datos obtenidos dlista especificada anteriormente.Un arreglo de int con los identificadores de los elementos de cada lnea.

    4|

    5|

    Con esta configuracin, el adaptador nos dar elementos de 2 lneas mostrando en la primera ttulodel artculo y en la segunda el link del artculo. Esta configuracin resulta muy til porque todohecho, sin embargo no es personalizable, si queremos cambiar algunas cosas (fondo, color, letetc) decada elemento sera necesario agregar otro layout para cada fila y si deseamos mostrar msinforma-cin o no utilizar una lista de mapas entonces sera necesario hacer nuestro propio adaptador loharemos en prximos captulos).

    Carga de datos

    La carga de datos nos tomar cierto tiempo, vamos a mostrarle un aviso de que los datos se ecargando. Queremos que el aviso se muestre y como tarea de fondo cargue los datos (esto NOservicio) vamos a necesitar de un hilo de ejecucin1 que haga esta tarea.

    1 http://download.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html

  • 8/6/2019 MDW Guia Android 1

    15/137

    CURSO ANDROID 15

    Android nos presenta la restricciones que no podemos alterar, los elementos de interfaz grficunhilo de ejecucin que no sea el principal por lo que es necesario utilizar un manejador para envmensaje de un hilo a otro cuando la carga de datos haya terminado. Agregaremos entonces un

    variablepara el dilogo de progreso es necesaria una variable global porque iniciamos el dilogo en unfunciny lo ocultamos en otra.

    private ProgressDialog progressDialog;

    Otra para el manejador de mensajes entre hilos de ejecucin:


    private final Handler progressHandler = new Handler() {

    @SuppressWarnings(unchecked)

    if (msg.obj != null) {

    setData(data);

    }

    public void handleMessage(Message msg) {

    data = (LinkedList)msg.obj;

  • 8/6/2019 MDW Guia Android 1

    16/137

    CURSO ANDROID 16

    progressDialog.dismiss();

    }

    };

    Para el manejador, haremos una clase interna y annima1 este tipo de clases las vern seguidoagregar funcionalidades que requieren de clases pero su tarea es tan pequea que no vale la pdarleun nombre (y luego terminar con muchos nombres que se utilizan una sola vez).

    Dentro de la clase Handler hemos agregado la anotacin @SuppressWarnings(unchecked)para evitar una advertencia por la conversin de tipo (type casting) de objeto hacia lista realizadelante. Es necesario implementar el mtodo handleMessage(Message msg) y es aqu donde

    revisamos si viene un mensaje, lo convertimos a lista, llamamos al mtodo setData previamendefi-nido y cerramos el dilogo de progreso.

    Por ltimo, vamos a hacer una funcin auxiliar que inicia la carga de datos, muestra al usuariodilogode que se estn cargando los datos y levanta un thread para lograr la carga.


    private void loadData() {

    Main.this,

    ,

    ProgressDialog progressDialog = ProgressDialog.show(

    Por favor espere mientras se cargan los datos...,

    true);

    new Thread(new Runnable(){

    @Override

    public void run() {
    XMLParser parser = new XMLParser(feedUrl);

    msg.obj = parser.parse();

    }}).start();

    Message msg = progressHandler.obtainMessage();

    progressHandler.sendMessage(msg);

    1 http://www.google.com/url?q=http%3A%2F%2Fdownload.oracle.com%2Fjavase%2Ftutorial%2Fjava%2Fjav%2Fin

    nerclasses.html&sa=D&sntz=1&usg=AFQjCNEbFcVxidDxasA0Rg3ED01_7EDHfA

  • 8/6/2019 MDW Guia Android 1

    17/137

    CURSO ANDROID 17

    }

    Para el dilogo de progreso, le enviamos 4 argumentos:

    1 | Contexto, dado por la aplicacin, como esta funcin la vamos a llamar desde una claseinterna,el acceso es con el campo this de la clase Main.2 |Ttulo, no nos interesa que tenga ttulo el aviso.3 | Mensaje, le pedimos al usuario que espere.4 | Indeterminado, no se puede cuantificar cuanto tiempo falta o cuanto progreso se ha lograd

    entonces el aviso ser de duracin indeterminada.

    Luego tenemos un Thread a partir de otra clase interna y annima que es una instancia de Runydefinimos el mtodo run donde se especifica lo que har el hilo de ejecucin y llamamos al mstartpara iniciarlo. En el mtodo run instanciamos un parser nuevo de XML construimos un mensajepartirdel manejador y se lo enviamos con la data obtenida del parser.Llamando todo desde la funcin onCreate

    Trabajemos dentro de la funcin onCreate la cual se llama cuando la actividad es creada, prim

    ponemos un bonito ttulo a la ventana.

    setTitle(Lector de feed Maestros del Web);

    El siguiente paso es asociarle una accin al botn para que cargue los datos, primero obtenembotn haciendo uso de la funcin findViewById con el identificador colocado en el diseo para riormente colocarle las acciones a realizar cuando se presione a travs del mtodo setOnClickLner. Este mtodo recibe una instancia de la clase OnClickListener, de nuevo vamos a hacer unclaseannima y sobrecargaremos el mtodo onClick.


    Button btn = (Button) findViewById(R.id.btnLoad);

    btn.setOnClickListener(new OnClickListener() {

    @Override

    public void onClick(View v) {

  • 8/6/2019 MDW Guia Android 1

    18/137

    CURSO ANDROID 18

    }

    });

    Dentro de la funcin onClick validaremos si el ListView ya tiene datos, si no los tiene los carga-mos con una llamada a loadData pero si ya los tiene vamos a mostrarle un dilogo de alerta alrio preguntando si est seguro que desea hacerlo.


    ListView lv = (ListView) findViewById(R.id.lstData);

    if (lv.getAdapter() != null) {
    AlertDialog.Builder builder = new AlertDialog.Builder(Main.this);

    builder.setMessage(ya ha cargado datos, Est seguro de hacerlo de

    nuevo?)

    .setCancelable(false)

    {

    .setPositiveButton(Si, new DialogInterface.OnClickListener()

    public void onClick(DialogInterface dialog, int

    id) {

    }

    loadData();

    })

    {

    .setNegativeButton(No, new DialogInterface.OnClickListener()

    public void onClick(DialogInterface dialog, int

    id) {

    }

    dialog.cancel();

    })

    .create()

    .show();

    } else {

    }

    loadData();

  • 8/6/2019 MDW Guia Android 1

    19/137

    CURSO ANDROID 19

    Para crear el dilogo de alerta, encadenamos llamadas a partir de un constructor AlertDialog.Builder que recibe un contexto y de nuevo utilizamos Main.this.

    Estas llamadas encadenadas nos permiten:

    Establecer un mensaje (setMessage)Obligar al usuario a responder y no solo cerrar (setCancelable)Colocar una accin cuando la respuesta es positiva (setPositiveButton)Colocar una accin cuando la respuesta es negativa (setNegativeButton)Crear el dilogo (create)Mostrar el dilogo (show)

    Las ms complicadas son las llamadas para colocar acciones ante una respuesta positiva o negAmbas requieren de un Listener que se disparara cuando el usuario presione el botn. Dentro mtodo onClick de otra clase annima ms, cuando es positivo llamamos a loadData y cuandonegativo ocultamos el dilogo.

    El cdigo completo queda de esta forma:


    Button btn = (Button) findViewById(R.id.btnLoad);

    btn.setOnClickListener(new OnClickListener() {

    @Override

    public void onClick(View v) {

    ListView lv = (ListView) findViewById(R.id.lstData);

    if (lv.getAdapter() != null) {

    />AlertDialog.Builder builder = new AlertDialog.Builder(Main.this);

  • 8/6/2019 MDW Guia Android 1

    20/137

    CURSO ANDROID 20

    dialog, int id) {

    loadData();

    }

    })

    .setNegativeButton(No, new

    DialogInterface.OnClickListener() {

    public void onClick(DialogInterface

    dialog, int id) {

    dialog.cancel();

    }

    })
    .create()

    .show();

    } else {

    }

    }

    loadData();

    });

    Para terminar, queremos aprovechar que contamos con el link de cada artculo y que cuando eusuariopresione algn elemento en nuestra aplicacin pueda visitarse el artculo va el navegador.


    ListView lv = (ListView) findViewById(R.id.lstData);

    @Override

    {

    lv.setOnItemClickListener(new OnItemClickListener() {

    public void onItemClick(AdapterView av, View v, int position, long id)

    HashMap entry = data.get(position);

    Uri.parse(entry.get(DATA_LINK)));

    startActivity(browserAction);

    }

    });

    Intent browserAction = new Intent(Intent.ACTION_VIEW,

  • 8/6/2019 MDW Guia Android 1

    21/137

    CURSO ANDROID 21

    Esto lo conseguimos modificando el evento de click sobre los tems de la lista(setOnItemClickListener)

    primero obteniendo el elemento que ha sido presionado y luego con un intent de ACTION_VIEWintent predefinido realiza la accin ms obvia para mostrar datos al usuario, en nuestro caso senvaun URI2 lo que permite visualizarlo con el navegador.

    1 http://developer.android.com/reference/android/content/Intent.html#ACTION_VIEW2 http://developer.android.com/reference/android/net/Uri.html

    http://www.forosdelweb.com/f165/ https://github.com/androidMDW/guia1compl

  • 8/6/2019 MDW Guia Android 1

    22/137

    CURSO ANDROID 22

    Conclusin

    En esta gua hemos visto varias cosas:

    Arquitectura de Android: conocimos la forma en que est construda la arquitectura.Bloques bsicos de una aplicacin: los elementos principales de una aplicacin de AndroidManifest: aprendimos la forma y la ubicacin del manifest, archivo para configuracin de lcacin.LinearLayout, TextView y Button: tuvimos un primer acercamiento a los elementos de la Utravs de estos 3 controles, una forma de manejar el diseo (layout) y dos controles para inter-faz de la aplicacin.Eventos OnClick: aprendimos a manejar los eventos con listeners y asociar acciones paracuandoel usuario interacta con los elementos de la UI.Dialogs: iniciamos a trabajar con dilogos para mostrar avisos al usuario, en este casonicamentede confirmacin previo a la carga de datos.

    Threads y Handlers: el proceso de la carga y parsing de datos fue realizado con un threadypara la comunicacin con el thread principal utilizamos un Message Handler.Iniciar otras activities: aprendimos el mecanismo necesario para iniciar otras activities aunofueran hechas por nosotros.

  • 8/6/2019 MDW Guia Android 1

    23/137

    captulo2

    Aumentar lafuncionalidad de unlector de feeds

  • 8/6/2019 MDW Guia Android 1

    24/137

    CURSO ANDROID 24

    CAPTULO 2

    Aumentar la funcionalidad de un lector de feedsEl lector de feed que desarrollaremos en este captulo se diferencia del anterior porquepermitiremosal usuario decidir si al presionar sobre un elemento quiere verlo en una vista previa dentro de apli-cacin o en el navegador, para esta eleccin agregaremos un men y personalizaremos el Viecadafila del resultado.El ejemplo se ver de la siguiente manera:

    Disposicin inicialEmpecemos descargando el cdigo1 que debe ser importado hacia un nuevo proyecto es muysimilaral del captulo anterior, pero revisemos las diferencias:

    El XMLParser ahora obtiene no solo el link y ttulo de cada artculo, tambin su autor, fechdescrip-

    1 https://github.com/androidMDW/guia2base

  • 8/6/2019 MDW Guia Android 1

    25/137

    CURSO ANDROID 25

    cin y una imagen.Para ser ms ordenados, la informacin se guardar utilizando una clase de Java que

    represente acada artculo llamada Element (src/com/android/mdw/demo/Element.java)La Activity principal (Main) hereda de ListActivity y no de Activity facilitando ypermite caminos cortos para cosas especficas a una Activity que muestra un listado de coPorlo mismo, en el layout es necesario un ListView con el identificador @android:id/list

    Adems, tiene las especificaciones de la gua anterior.

    Es necesario darle permiso a la aplicacin para que pueda accesar a Internet, tener un LinLayout con orientacin vertical en el archivo de diseo principal por trabajar con una LisAc

    tambin necesitamos el ListView con id @android:id/list y tener una forma de reconocerXML.

    Diseo

    Trabajamos con Views del captulo anterior como: LinearLayout, ListView, TextView, Button yagregamosnuevas Views.

    ImageView1 : muestra una imagen que puede cargarse de diferentes fuentes para el ejemvamos a obtenerla de una direccin de Internet (etiqueta img de HTML dentro del artculorevisar(2d Graphics2).Menu3 y MenuItem4 : en este captulo aprenders cmo hacer un men de opciones en XMrevi-sar (Menus5 ).

    Para el layout principal, repetimos el procedimiento del captulo anterior de nuevo recordandoidentificador (android:id) del ListView debe ser @android:id/list.

    Adems, necesitaremos 3 Views adicionales:

    12345

    http://developer.android.com/reference/android/widget/ImageView.htmlhttp://developer.android.com/guide/topics/graphics/2d-graphics.htmlhttp://developer.android.com/reference/android/view/Menu.htmlhttp://developer.android.com/reference/android/view/MenuItem.htmlhttp://developer.android.com/guide/topics/ui/menus.html

  • 8/6/2019 MDW Guia Android 1

    26/137

    CURSO ANDROID 26

    Para el men menu.xmlPara la vista previa dentro de la aplicacin showelement.xml

    Para cada fila del listado row.xml

    Para agregar estos Views, hacemos click derecho sobre la carpeta /res/layout luego New > (nuother (otro):

    En el dilogo que aparece seleccionamos archivo XML de Android y hacemos click en Next >(siguiente):

  • 8/6/2019 MDW Guia Android 1

    27/137

    CURSO ANDROID 27

    Escribimos el nombre del archivo (es importante incluir la extensin XML), en el ejemplo el nomes

    menu.xml y hacemos click en el botn Finish (finalizar):

    Este procedimiento es necesario cada vez que necesitemos un Layout nuevo, para esta aplicacsernnecesarios 3: menu.xml, row.xml y showelement.xml describiremos a detalle cada uno de ello

    View para el men: menu.xml

    Utiliza un elemento men y dos elementos tem para cada opcin, le pondremos a cada tem telicono que trae por defecto la aplicacin, el archivo XML debe quedar as:

    El men debera verse de la siguiente forma:

  • 8/6/2019 MDW Guia Android 1

    28/137

    CURSO ANDROID 28

    View para preview: showelement.xml

    En esta vista previa mostraremos el ttulo del artculo, el autor y la descripcin, necesitamos vText-View dentro de un LinearLayout con orientacin vertical, el archivo XML debe quedar as:

    La vista previa debera verse de la siguiente forma:

  • 8/6/2019 MDW Guia Android 1

    29/137

    CURSO ANDROID 29

    View para fila: row.xml

    En este captulo en cada una de las filas de la lista no mostraremos dos lneas como en el anteahoravamos a tener una imagen del elemento y su ttulo agrupados por un LinearLayout con orientahori-zontal, el archivo XML debe quedar de la siguiente forma:

    Clases de apoyo

    En esta versin del lector de feeds tenemos varias clases que apoyan para facilitar eldesarrollo:

    Element: guarda los datos de cada artculo en el listado.MyApp: clase de aplicacin para representar datos voltiles dentro de la aplicacin.MyAdapter: adaptador personalizado que permite mostrar la imagen en cada fila dellistado.

    Para la vista previa del artculo necesitamos otra Activity que es otra clase que llamaremos Shment.java para agregar una clase es necesario hacer click derecho sobre com.android.mdw.de(bajosrc) luego New (nuevo) y por ltimo Class (clase).

    Despus colocamos el nombre MyApp para el ejemplo y la superclase (clase de la que heredandroid.

  • 8/6/2019 MDW Guia Android 1

    30/137

    CURSO ANDROID 30

    app.Application para el ejemplo y hacemos click en finalizar.

    El proceso es necesario para MyApp, MyAdapter y ShowElement la clase Element va incluida, aveamos el contenido de cada una de estas clases:

    Element

    Haremos un objeto Element, para aumentar el orden porque ahora guardaremos ms informaccada elemento del listado obtenido del feed. Esta clase est incluida en los archivos de pruebaesmuy complicada, maneja mtodos para colocar y obtener los atributos de cada elemento como

    Ttulo,Enlace, Autor, Descripcin, Fecha de publicacin, Imagen.

    SetImage es el mtodo diferente y se debe a la forma en que obtenemos las imgenes. El parsXMLbuscar dentro del contenido del artculo la primera ocurrencia de la etiqueta img de HTML y ealgu-nos casos la nica es la foto del autor del artculo.

  • 8/6/2019 MDW Guia Android 1

    31/137

    CURSO ANDROID 31

    Tomamos prestada la imagen del avatar de Twitter de @maestros1 el URL es:

    http://a1.twimg.com/profile_images/82885809/mdw_hr_reasonably_small.png

    La URL se recibe como parmetro en este mtodo, si al tratar de obtener la imagen algo fallarentoncestambin se establece la imagen del avatar de Twitter. Para obtener la imagen en base a un URutilizala ayuda de la funcin loadFromUrl que devuelve un Bitmap2 .

    Este mtodo abre una conexin hacia el URL especificado, luego decodifica el flujo (stream) derecibido y en base a ellos construye un objeto Bitmap. El cdigo de la clase Element (ya incluidel

    cdigo base de la gua) es el siguiente:

    package com.android.mdw.demo;

    import java.io.IOException;

    import java.io.InputStream;

    import java.net.URL;

    import java.net.MalformedURLException;

    import java.text.SimpleDateFormat;

    import java.util.Date;

    import android.graphics.Bitmap;

    public class Element {

    HH:mm:ss Z);

    import android.graphics.BitmapFactory;

    static SimpleDateFormat FORMATTER = new SimpleDateFormat(EEE, dd MMM yyyy

    private String title;

    private String link;

    private String author;

    private Bitmap image;

    private Date date;

    private String description;

    public String getTitle() {

    return this.title;

    1 http://twitter.com/maestros2 http://developer.android.com/reference/android/graphics/Bitmap.html

  • 8/6/2019 MDW Guia Android 1

    32/137

    CURSO ANDROID 32

    }

    public String getLink() {

    return this.link;

    }

    public String getDescription() {

    return this.description;

    }

    public String getDate() {

    }

    return FORMATTER.format(this.date);

    public Bitmap getImage(){return this.image;

    }

    public String getAuthor(){

    return this.author;

    }

    public void setTitle(String title) {

    this.title = title.trim();

    }

    public void setLink(String link) {

    this.link = link;

    }

    public void setDescription(String description) {

    this.description = description.trim();

    }

    public void setDate(String date) {

    try {

    this.date = FORMATTER.parse(date);

    e.printStackTrace();

    }

    }

    } catch (java.text.ParseException e) {

    public void setImage(String image){

    if (image.contains(autor)) {

    image = http://a1.twimg.com/profile_images/82885809

  • 8/6/2019 MDW Guia Android 1

    33/137

    CURSO ANDROID 33

    /mdw_hr_reasonably_small.png;

    }

    try {

    this.image = loadFromUrl(new URL(image));

    } catch (Exception e) {

    try {

    this.image = loadFromUrl(new URL(http://a1.twimg.com

    } catch (MalformedURLException e1) {}

    }

    }

    /profile_images/82885809/mdw_hr_reasonably_small.png));

    public void setAuthor(String author){

    this.author = author;

    }

    public String toString(){

    return this.title;

    }

    private Bitmap loadFromUrl(URL link) {

    Bitmap bitmap = null;

    try {

    InputStream in = null;

    in = link.openConnection().getInputStream();

    in.close();

    bitmap = BitmapFactory.decodeStream(in, null, null);

    } catch (IOException e) {}

    return bitmap;

    }

    }

    MyApp

    En el captulo anterior el listado de artculo los representamos como una lista esttica dentro dclasede la activity principal, mencion que esa no era la forma correcta por que deban utilizarse cladeaplicacin y para eso utilizaremos MyApp.

  • 8/6/2019 MDW Guia Android 1

    34/137

    CURSO ANDROID 34

    No es posible utilizar una variable local o una variable de instancia porque la Activity1 es constmente destruida y creada de nuevo. Por ejemplo, al rotar el telfono. A pesar de estar represedentro de una clase esta informacin no deja de ser voltil, para almacenamiento permanentenece-sario una base de datos de SQLite.

    Para decirle a la aplicacin que es de tipo MyApp es necesario editar el manifestAndroidManifest.xml yen los atributos de la etiqueta aplicacin agregar android:name=MyApp

    Inicialmente deca:

    Al modificarlo debe decir:

    Dentro de la clase MyApp vamos a guardar dos cosas:

    El listado de los artculosLa opcin seleccionada por el usuario para visualizar el artculo (ya sea en una vista previ

    dentrode la aplicacin o en el navegador)Adems de estas dos variables de instancia, vamos a incluir mtodos para guardar y devoestasvariables (getters y setters). Para representar la opcin elegida por el usuario utilizaremosenterosdentro de la Activity principal, estos estn incluidos en el cdigo base y fueron definidos a

    final static int APP_VIEW = 1;

    final static int BROWSER_VIEW = 2;

    Al iniciar la aplicacin, colocaremos el valor de APP_VIEW en el campo que guarda la preferencusuario dentro de la clase de aplicacin, el cdigo de la clase MyApp queda de la siguiente form

    package com.android.mdw.demo;

    import java.util.LinkedList;

    1 http://developer.android.com/reference/android/app/Activity.html

  • 8/6/2019 MDW Guia Android 1

    35/137

    CURSO ANDROID 35

    import android.app.Application;

    public class MyApp extends Application {

    private LinkedList data = null;

    public LinkedList getData(){

    return this.data;

    }

    private int selectedOption = Main.APP_VIEW;

    public void setData(LinkedList d){

    this.data = d;

    }

    public int getSelectedOption(){return this.selectedOption;

    }

    public void setSelectedOption(int selectedOption) {

    this.selectedOption = selectedOption;

    }

    }

    MyAdapter

    La clase MyAdapter ser una personalizacin de un ArrayAdapter1 , un adaptador que recibe uglo (o listado) de elementos. La clase MyAdapter hereda de ArrayAdapter, dentro dclasemanejaremos dos variables de instancia, un LayoutInflater2 esta clase se utilizar para instanciadiseo a partir de un archivo de XML hacia un View y adems un listado (LinkedList) de objetosestecaso, artculos, representados por la clase Element).

    Dentro del constructor, llamamos al padre (super) y asignamos a los campos (variables deinstancia).Adems, dado que queremos personalizar la representacin (rendering) de cada fila, necesitamsobrecargar revisar (Override3 ) el mtodo getView.

    Dentro de este mtodo, cuando sea necesario instanciamos el archivo de su diseo correspondrow.xml y le asignamos valor a sus Views (imagen y texto) a partir de la informacin guardada

    1 http://developer.android.com/reference/android/widget/ArrayAdapter.html2 http://developer.android.com/reference/android/view/LayoutInflater.html3 http://download.oracle.com/javase/tutorial/java/IandI/override.html

  • 8/6/2019 MDW Guia Android 1

    36/137

    CURSO ANDROID 36

    listado de artculos.

    El cdigo de la clase MyAdapter es el siguiente:

    package com.android.mdw.demo;

    import java.util.LinkedList;

    import android.content.Context;

    import android.view.View;

    import android.view.LayoutInflater;

    import android.view.ViewGroup;import android.widget.ArrayAdapter;

    import android.widget.ImageView;

    import android.widget.TextView;

    LayoutInflater inf;

    public class MyAdapter extends ArrayAdapter {

    LinkedList objects;

    public MyAdapter(Context context, int resource,

    int textViewResourceId,

    LinkedList objects) {

    super(context, resource, textViewResourceId, objects);

    this.inf = LayoutInflater.from(context);

    this.objects = objects;

    }

    public View getView(int position, View convertView,

    ViewGroup parent){

    View row = convertView;

    if (row == null) {

    }

    Element currentElement = (Element)objects.get(position);

    row = inf.inflate(R.layout.row, null);

    ImageView iv = (ImageView) row.findViewById(R.id.imgElement);

    iv.setImageBitmap(currentElement.getImage());

    iv.setScaleType(ImageView.ScaleType.FIT_XY);

    TextView tv = (TextView) row.findViewById(R.id.txtElement);

  • 8/6/2019 MDW Guia Android 1

    37/137

  • 8/6/2019 MDW Guia Android 1

    38/137

    CURSO ANDROID 38

    startActivity(backToMainActivity);

    Al finalizar, el cdigo de esta clase es el siguiente:

    package com.android.mdw.demo;

    import android.app.Activity;

    import android.os.Bundle;

    import android.content.Intent;

    import android.widget.TextView;

    @Overridepublic class ShowElement extends Activity {

    public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    Intent it = getIntent();

    if (position != -1) {

    setContentView(R.layout.showelement);

    int position = it.getIntExtra(Main.POSITION_KEY, -1);

    MyApp appState = ((MyApp)getApplication());

    Element e = appState.getData().get(position);

    txtTitle.setText(e.getTitle());

    TextView txtTitle = (TextView)findViewById(R.id.txtTitle);

    TextView txtAuthor = (TextView)findViewById(R.id.txtAuthor);

    txtAuthor.setText(por + e.getAuthor());

    txtDesc.setText(e.getDescription());

    } else {

    TextView txtDesc = (TextView)findViewById(R.id.txtDesc);

    Intent backToMainActivity = new Intent(this, Main.class);backToMainActivity.putExtra(Main.POSITION_KEY, -1);

    startActivity(backToMainActivity);

    }

    }

    }

    Esas son las clases adicionales luego el trabajo es sobre la Activity principal: la claseMain.java

  • 8/6/2019 MDW Guia Android 1

    39/137

    CURSO ANDROID 39

    Mostrar datos siguiendo el diseo

    La funcin auxiliar setData de la gua anterior se ve drsticamente reducida ya que ahora utiliznuestro adaptador y por tener una activity que hereda de ListActivity la asignacin al ListView hace-mos con setListAdapter.

    private void setData(){

    appState.getData()));

    }

    this.setListAdapter(new MyAdapter(this, R.layout.row, 0,

    Esta herencia de nuestra Activity, tambin nos permite colocar la funcin onListItemClick paraespeci-ficar la operacin a realizar cuando el usuario presiona click sobre un elemento. Validamos la oseleccionada por el usuario guardada en la clase de aplicacin y dependiendo del caso levantaunintent diferente.

    protected void onListItemClick(ListView l, View v, int position, long id) {

    super.onListItemClick(l, v, position, id);

    Intent nextActivity = null;

    if (appState.getSelectedOption() == APP_VIEW) {

    nextActivity.putExtra(POSITION_KEY, position);

    } else {

    LinkedList data = appState.getData();

    nextActivity = new Intent(this, ShowElement.class);

    nextActivity = new Intent(Intent.ACTION_VIEW,

    Uri.parse(data.get(position).getLink()));

    }

    }this.startActivity(nextActivity);

    Permanece la variable de instancia para el dilogo de progreso y el manejador es ligeramentedistintoporque ya no recibe los datos a travs del mensaje.

    private final Handler progressHandler = new Handler() {

  • 8/6/2019 MDW Guia Android 1

    40/137

    CURSO ANDROID 40

    public void handleMessage(Message msg) {

    setData();

    }

    progressDialog.dismiss();

    };

    Carga de datos

    La carga de datos no cambia mucho, seguimos teniendo el dilogo de progreso pero ahora ya nece-sitamos mandar los datos reconocidos por el parser a travs del manejador si no puedo guarda

    enla clase de aplicacin directamente y mando un mensaje vaco.

    private void loadData() {

    Main.this,

    ,

    progressDialog = ProgressDialog.show(

    Por favor espere mientras se cargan los datos...,

    true);

    new Thread(new Runnable(){

    @Override

    public void run() {

    XMLParser parser = new XMLParser(feedUrl);

    appState.setData(parser.parse());

    }}).start();

    }

    progressHandler.sendEmptyMessage(0);

    Agregando el men de opciones

    Necesitamos indicarle qu hacer cuando el usuario presione la tecla de men en el telfono, coeneste caso construimos el men en un XML solo es necesario crear una instancia.

    @Override

  • 8/6/2019 MDW Guia Android 1

    41/137

    CURSO ANDROID 41

    public boolean onCreateOptionsMenu(Menu menu) {

    MenuInflater inflater = getMenuInflater();

    inflater.inflate(R.layout.menu, menu);

    return true;

    }

    Adems, requerimos sobrecargar otra funcin que se dispara cuando el usuario elige alguna deopciones del men. Aqu guardaremos en la clase de aplicacin lo que sea que el usuario hayaelegido.

    @Overridepublic boolean onOptionsItemSelected(MenuItem item) {

    switch (item.getItemId()) {

    case R.id.mmElementApp:

    break;

    appState.setSelectedOption(APP_VIEW);

    case R.id.mmElementBrw:

    break;

    }

    }

    appState.setSelectedOption(BROWSER_VIEW);

    return true;

    Llamando todo desde la funcin onCreate

    Dentro del cuerpo de la function oCreate inicializamos la variable para nuestra clase deaplicacin:appState = ((MyApp)getApplication());

    Validamos si el intent lo levant alguna otra Activity y si viene un -1 en el mensaje mostramoserror:Intent it = getIntent();

    int fromShowElement = it.getIntExtra(POSITION_KEY, 0);

    if (fromShowElement == -1) {

    Toast.LENGTH_LONG);

    }

    Toast.makeText(this, Error, imposible visualizar el elemento,

  • 8/6/2019 MDW Guia Android 1

    42/137

    CURSO ANDROID 42

    La accin sobre el click del botn no cambia mucho, la verificacin la hemos cambiado y en lugver

    si el adaptar ya tiene datos revisamos si la clase de aplicacin devuelve algo diferente de null:LinkedList data = appState.getData();

    if (data != null) { }

    http://www.forosdelweb.com/f165/ https://github.com/androidMDW/guia2compl

  • 8/6/2019 MDW Guia Android 1

    43/137

    CURSO ANDROID 43

    Conclusin

    ListActivity: aprendimos la utilizacin de este tipo de actividad que nos da algunas ayudascuandonuestra actividad muestra una lista de datos.ImageView, Menu y MenuItem: en la parte de diseo, manejamos ImageView para mostraimge-nes, en el caso de nuestra aplicacin, la imagen se obtiene de una direccin de internet ybytesrecibidos se asignan para mostrarla. Tambin agregamos un men con opciones MenuIteparaelegir y colocar una configuracin muy simple de nuestra aplicacin.Guardar datos a travs de clases de aplicacin: como un medio de guardar el estado de la

    aplica-cin vimos la forma de utilizar una clase creada por nosotros y tambin los mecanismos pguar-dar y recuperar los datos guardados.Sobrecargar clases para personalizacin (MyAdapter): con el fin de personalizar la forma ese muestran los datos, utilizamos como base una clase ya existente y modificamos lo necpara que el rendering fuera a nuestro gusto.Incluir Activities a nuestra aplicacin: la aplicacin puede contener ms de una activity, vlonecesario para agregar y configurar en el manifest nuevas activities.Enviar datos a travs de intents: utilizamos intents no solo para levantar una nueva Activino

    tambin para enviarle datos de una Activity a otra.Recibir datos a travs de intents: para lograr la comunicacin entre mis activities no solo nece-sario enviar los datos si no en la activity llamada tambin obtenerlos para su utilizacin.

  • 8/6/2019 MDW Guia Android 1

    44/137

    captulo3

    Trabajando conimgenes (cmara ygalera)

  • 8/6/2019 MDW Guia Android 1

    45/137

    CURSO ANDROID 45

    CAPTULO 3

    Trabajando con imgenes(cmara y galera)

    En el tercer captulo trabajamos con el hardware de los telfonos y empezaremos con el manelacmara.

    Mostrar una imagen de la cmara o de la galeraLa aplicacin que realizaremos nos permitir mostrar una imagen, podemos obtenerla desde lcmarao desde la galera del telfono. Queremos que al finalizar se vea as:

    Con una imagen cargada se ver de la siguiente forma:

  • 8/6/2019 MDW Guia Android 1

    46/137

    CURSO ANDROID 46

    Disposicin inicial

    Empezaremos descargando el cdigo1 que debe importarse hacia un proyecto nuevo. Trabajamsobreun telfono con Android y cmara para desarrollar el ejemplo de este artculo. Para el deploymhacia eltelfono es necesario que el sistema operativo lo reconozca y adems debe colocarse en el macomouna propiedad de la etiqueta el valor android:debuggable=true.La etiqueta debe lucir de la siguiente forma:

    En la parte de diseo vamos a empezar con un RelativeLayout, el archivo /res/layout/main.xmestar as:

    1 https://github.com/androidMDW/guia3base

  • 8/6/2019 MDW Guia Android 1

    47/137

    CURSO ANDROID 47

    Diseo

    Trabajamos con otra disposicin de elementos para el diseo llamado RelativeLayout y agregaotros elementos de interfaz de usuario.

    RelativeLayout1: con este esquema los elementos se colocan en posicin relativa a otroselemen-tos o hacia el padre.RadioButton2: es un botn de dos estados (marcado y des-marcado) a diferencia delCheckButtoneste no permite des-marcarlo y cuando se encuentra en grupo solo uno de los botones degrupo

    puede estar marcado a la vez.RadioGroup3: permite agrupar un conjunto de RadioButtons para que solo uno a la vez estselec-cionado.

    Nuestro diseo tendr un botn para adquirir la imagen un RadioGroup que contendr a 3 botoun ImageView. Los 3 botones sern seleccionar de donde proviene la imagen ya sea de la cm(comovista previa o como imagen completa) o de la galera.

    El cdigo completo del layout es el siguente:

    Hemos orientado el botn hacia la derecha y el RadioGroup hacia la izquierda. Luego el Imageabajo del RadioGroup.

    El diseo de interfaces de usuario en ocasiones se vuelve complicado con eclipse por elloutilizaremos laherramienta gratuita DroidDraw4 que permite exportar e importar archivos XML para luego sol

    carlos en el archivo de diseo en eclipse, adems tiene ejecutables para Windows, Linux y OS

    1234

    http://developer.android.com/reference/android/widget/RelativeLayout.htmlhttp://developer.android.com/reference/android/widget/RadioButton.htmlhttp://developer.android.com/reference/android/widget/RadioGroup.htmlhttp://www.droiddraw.org/

  • 8/6/2019 MDW Guia Android 1

    48/137

    CURSO ANDROID 48

    Agregando cdigo para funcionalidad

    Definimos 3 constantes, con dos de ellas vamos a identificar la accin realizada (tomar unafotografa obien seleccionarla de la galera) y con la otra estableceremos un nombre para el archivo dondeescribi-remos la fotografa de tamao completo al tomarla.private static int TAKE_PICTURE = 1;

    private String name = ;

    private static int SELECT_PICTURE = 2;

    La forma ms sencilla de tomar fotografas es utilizar un intent con ACTION_IMAGE_CAPTURE, aque pertenece al Media Store1 y luego sobrecargar el mtodo onActivityResult para realizaralgo con el archivo recibido de la cmara. Dentro del mtodo onCreate asignaremos a la variainstancia name y luego vamos a trabajar sobre la accin al click del botn.

    Este nombre, inicializado con una llamada a getExternalStorageDirectory() guardar unarchivo en la tarjeta SD del telfono y el archivo se llamar test.jpg cada vez que grabemos un

    fotogra-fa de tamao completo se sobre escribe.

    name = Environment.getExternalStorageDirectory() + /test.jpg;

    Button btnAction = (Button)findViewById(R.id.btnPic);

    1 http://developer.android.com/reference/android/provider/MediaStore.html

  • 8/6/2019 MDW Guia Android 1

    49/137

    CURSO ANDROID 49

    btnAction.setOnClickListener(new OnClickListener() {

    @Override

    ...

    }

    }

    }

    public void onClick(View v) {

    Primero obtenemos los botones de imagen completa y de galera para revisar su estatus msadelante.Luego construimos un intent que es necesario si accesamos la cmara con la accin ACTION_IM

    CAPTURE, si accesamos la galera con la accin ACTION_PICK. En el caso de la vista previa (thunail) no se necesita ms que el intent, el cdigo e iniciar la Activity correspondiente. Por esoinicializamoslas variables intent y code con los valores necesarios para el caso del thumbnail as de ser el bselec-cionado no validamos nada en un if.RadioButton rbtnFull = (RadioButton)findViewById(R.id.radbtnFull);

    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

    RadioButton rbtnGallery = (RadioButton)findViewById(R.id.radbtnGall);

    Asignamos el cdigo a tomar fotografa, este cdigo junto al intent se utilizarn adelante para

    laActivity.int code = TAKE_PICTURE;

    Si el chequeado es el botn de vista previa no necesitamos agregar nada ms. Si el chequeadobotn de imagen completa, adems del intent y cdigo agregamos un URI para guardar all elresultado.Si el chequeado es el de la galera necesitamos un intent y cdigo distintos que asignamos en conse-cuencia del if.

    if (rbtnFull.isChecked()) {

    Uri output = Uri.fromFile(new File(name));

    } else if (rbtnGallery.isChecked()){

    intent.putExtra(MediaStore.EXTRA_OUTPUT, output);

    intent = new Intent(Intent.ACTION_PICK,

    code = SELECT_PICTURE;

    }

    android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI);

  • 8/6/2019 MDW Guia Android 1

    50/137

  • 8/6/2019 MDW Guia Android 1

    51/137

    CURSO ANDROID 51

    Si quisiramos incluir esa imagen en nuestra galera, utilizamos un MediaScannerConnectionC.

    new MediaScannerConnectionClient() {

    private MediaScannerConnection msc = null; {

    msc.connect();

    }

    msc = new MediaScannerConnection(getApplicationContext(), this);

    public void onMediaScannerConnected() {

    msc.scanFile(fileName, null);

    }public void onScanCompleted(String path, Uri uri) {

    msc.disconnect();

    }

    };

    Si viene de la galera recibimos el URI de la imagen y construimos un Bitmap a partir de un strdebytes:

    Uri selectedImage = data.getData();

    InputStream is;

    try {

    is = getContentResolver().openInputStream(selectedImage);

    BufferedInputStream bis = new BufferedInputStream(is);

    Bitmap bitmap = BitmapFactory.decodeStream(bis);

    iv.setImageBitmap(bitmap);

    ImageView iv = (ImageView)findViewById(R.id.imgView);

    } catch (FileNotFoundException e) {}

    Si estamos utilizando la cmara la vista ser de la siguiente forma:

    1http://developer.android.com/reference/android/media/MediaScannerConnection.MediaScannerConnectionCl

    html

  • 8/6/2019 MDW Guia Android 1

    52/137

    CURSO ANDROID 52

    Si estamos capturando de la galera ser as:

  • 8/6/2019 MDW Guia Android 1

    53/137

    CURSO ANDROID 53

    http://www.forosdelweb.com/f165/ https://github.com/androidMDW/guia3compl

  • 8/6/2019 MDW Guia Android 1

    54/137

    CURSO ANDROID 54

    Conclusin

    RelativeLayout, RadioButton y RadioGroup: aprendimos cmo pueden acomodarsecomponentesubicndolos en el diseo con posiciones relativas con respecto a otros componentes y tamloscontroles necesarios para el manejo de radio buttons y su agrupacin.Utilizacin de intents para utilizar la cmara y accesar la galera: se utilizaron intents parazar acciones especficas, la existencia de intents para acciones comunes predefinidas nosfacilitanmuchas tareas, en este caso no fue necesario accesar directamente el hardware de la cmnopudimos tomar una fotografa de una manera ms sencilla. Algo similar sucede con el acc

    lagalera de fotos.Utilizacin de la cmara de fotos: a travs de un ejemplo sencillo, aprendimos como utilizpartedel hardware del telfono. A partir de aqu podemos trabajar los imgenes guardadas ymodificar-las o utilizarla para lo que nos interese.

  • 8/6/2019 MDW Guia Android 1

    55/137

    captulo4

    Grabacin yreproduccin de vdeo

  • 8/6/2019 MDW Guia Android 1

    56/137

    CURSO ANDROID 56

    CAPTULO 4

    Grabacin y reproduccin de vdeoEn el cuarto captulo seguiremos trabajando con el hardware de los telfonos, ahora aprenderesobre cmo grabar vdeo desde la cmara y reproducirlo.

    Capturar vdeo y reproducirlo

    La aplicacin que realizaremos nos permitir grabar un vdeo, tener una vista previa mientras grabay luego reproducirlo. Queremos que al finalizar se vea as:

  • 8/6/2019 MDW Guia Android 1

    57/137

    CURSO ANDROID 57

    Disposicin inicial

    Iniciamos descargando el cdigo1 que debe ser importado hacia un nuevo proyecto, la configuinicial para este ejemplo tiene algunas caractersticas importantes para revisar:

    Configuracin de la rotacin de pantalla: para evitarnos problemas porque cada vez que smueveel telfono y rota la pantalla se destruye y re-crea la activity, en el manifiesto le hemosconfiguradoque no pueda rotarse con android:screenOrientation=portrait dentro de la etiqueta de lvity principal.Permisos en el manifiesto: por la utilizacin de la cmara para grabar audio y vdeo al SD

    requeri-mos de estos cuatro permisos:

    En el archivo principal de diseo res/layout/main.xml incluimos un LinearLayout.En la clase de la activity principal, implementaremos la interfaz SurfaceHolder.Callback pamanejo del SurfaceView que se agregar ms adelante. Esta interfaz requiere laimplementacin

    de los siguientes mtodos:

    @Override

    arg3) {

    }

    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int

    @Override

    }public void surfaceCreated(SurfaceHolder arg0) {

    @Override

    }

    public void surfaceDestroyed(SurfaceHolder arg0) {

    1 https://github.com/androidMDW/guia4base

  • 8/6/2019 MDW Guia Android 1

    58/137

    CURSO ANDROID 58

    Diseo

    Seguimos trabajando sobre un LinearLayout y agregamos un nuevoelemento:

    SurfaceView1: nos permite tener un espacio dedicado a dibujar los frames del vdeo para vistay la reproduccin.

    Nuestro diseo tendr tres botones: Grabar, Detener y Reproducir adems del ya menciSurfaceView El cdigo completo del layout es:

    Agregando cdigo para funcionalidad

    Vamos a definir 4 variables globales, las primeras dos son para gestionar la grabacin yreproduccin:private MediaRecorder mediaRecorder = null;

    private MediaPlayer mediaPlayer = null;

    Tambin tendremos una tercera variable de instancia para el nombre del archivo en el que se escri-bir:

    private String fileName = null;

    La cuarta variable de instancia para controlar cuando se est grabando:private boolean recording = false;

    De los mtodos heredados por la interface nos interesan 2: surfaceDestroyed donde vamos a llosrecursos y surfaceCreated donde vamos a inicializar.

    @Override

    1 http://developer.android.com/reference/android/view/SurfaceView.html

  • 8/6/2019 MDW Guia Android 1

    59/137

    CURSO ANDROID 59

    public void surfaceDestroyed(SurfaceHolder holder) {

    mediaRecorder.release();

    mediaPlayer.release();

    }

    Verificamos si las variables son nulas (para ejecutar este cdigo slo una vez) y luego deinicializarlas secoloca el SurfaceHolder como display para la vista previa de la grabacin y para la vista de lareproduc-cin:

    @Overridepublic void surfaceCreated(SurfaceHolder holder) {

    if (mediaRecorder == null) {

    mediaRecorder = new MediaRecorder();

    }

    mediaRecorder.setPreviewDisplay(holder.getSurface());

    if (mediaPlayer == null) {

    mediaPlayer = new MediaPlayer();

    mediaPlayer.setDisplay(holder);

    }}

    Adicionalmente, se agrega un mtodo para preparar la grabacin configurando los atributos defuentepara audio y vdeo, el formado y el codificador.

    public void prepareRecorder(){

    mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);

    mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);

    mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);

    }

    mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);

    Dentro del mtodo onCreate realizamos algunas inicializaciones, primero para la variable delnombredel archivo:

  • 8/6/2019 MDW Guia Android 1

    60/137

    CURSO ANDROID 60

    fileName = Environment.getExternalStorageDirectory() + /test.mp4;

    Tambin para el SurfaceView donde se reproducir el vdeo:SurfaceView surface = (SurfaceView)findViewById(R.id.surface);

    SurfaceHolder holder = surface.getHolder();

    holder.addCallback(this);

    holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

    Definimos los botones sobre los que vamos a trabajar en su evento de click:

    final Button btnRec = (Button)findViewById(R.id.btnRec);

    final Button btnStop = (Button)findViewById(R.id.btnStop);final Button btnPlay = (Button)findViewById(R.id.btnPlay);

    Botn de grabacin: al iniciar deshabilitamos los botones de grabar y reproducir luego habilitade detener. Llamamos el mtodo que configura el MediaRecorder y le decimos el archivo de saUnavez configurado todo llamamos al mtodo prepare que deja todo listo para iniciar la grabacininicia-mos la grabacin y actualizamos el estatus de la variable recording.

    btnRec.setOnClickListener(new OnClickListener() {

    @Override

    public void onClick(View v) {

    btnRec.setEnabled(false);

    btnStop.setEnabled(true);

    prepareRecorder();

    try {

    btnPlay.setEnabled(false);

    mediaRecorder.setOutputFile(fileName);

    mediaRecorder.prepare();

    } catch (IllegalStateException e) {

    } catch (IOException e) {

    } mediaRecorder.start();

    recording = true;

    }

  • 8/6/2019 MDW Guia Android 1

    61/137

    CURSO ANDROID 61

    Botn de reproducir: deshabilitamos los botones de grabar, reproducir y habilitamos el de deteSi concluye la reproduccin (porque el video se acab no porque el usuario haya presionado

    detener)habilitamos los botones de grabar, reproducir y deshabilitamos el de detener). Luego configuraelarchivo a partir del cual se reproducir, preparamos el Media Player e iniciamos la reproducci

    btnPlay.setOnClickListener(new OnClickListener() {

    @Override

    public void onClick(View v) {

    btnRec.setEnabled(false);

    btnStop.setEnabled(true);btnPlay.setEnabled(false);

    @Override

    mediaPlayer.setOnCompletionListener(new OnCompletionListener() {

    public void onCompletion(MediaPlayer mp) {

    btnRec.setEnabled(true);

    btnStop.setEnabled(false);

    btnPlay.setEnabled(true);

    }

    });

    try {

    mediaPlayer.setDataSource(fileName);

    mediaPlayer.prepare();

    } catch (IllegalStateException e) {

    } catch (IOException e) {

    }

    }

    mediaPlayer.start();

    });

  • 8/6/2019 MDW Guia Android 1

    62/137

    CURSO ANDROID 62

    http://www.forosdelweb.com/f165/ https://github.com/androidMDW/guia4compl

  • 8/6/2019 MDW Guia Android 1

    63/137

    CURSO ANDROID 63

    Conclusin

    SurfaceView: utilizamos este tipo de view que permite el manejo de grficas y provee unaformade dibujar, en nuestro caso las imgenes necesarias para la vista previa del video y luegosureproduccin.Manejo y configuracin de Media Recorder: para la captura de video, aprendimos a inicialconfigurar y utilizar el Media Recorder.Manejo y configuracin de Media Player: una vez grabado un video, el Media Player nos sipara reproducirlo.Utilizacin de la cmara de vdeo: hicimos uso de la cmara de nuevo pero ahora para lagrabacin

    de video, de una manera similar que en el caso de las fotos (gua anterior) no manejamostamente el hardware si no que a travs de las herramientas que nos provee Android utilizelcomponente sin complicaciones.

  • 8/6/2019 MDW Guia Android 1

    64/137

    captulo5

    Geolocalizacin yutilizacin de mapasde Google

  • 8/6/2019 MDW Guia Android 1

    65/137

    CURSO ANDROID 65

    CAPTULO 5

    Geolocalizacin y utilizacin de mapas de GoogleEn el quinto captulo seguiremos trabajando con el hardware de los telfonos, ahora noscorrespondeaprovechar el GPS y mostrar la ubicacin actual en un mapa.

    La aplicacin que realizaremos nos permitir mostrar la ubicacin y actualizarse cada vez que movimiento. Es importante notar que las pruebas de este captulo al igual que los captulos 4 ysonpara realizarlas en un telfono con Android es posible utilizar el emulador con algunos arreglos

    Ejemplo: obtener localizacin, monitorear sus cambios y mostrarla en un mapa a travs de maQueremos que al finalizar se vea de la siguiente forma:

  • 8/6/2019 MDW Guia Android 1

    66/137

    CURSO ANDROID 66

    Disposicin inicial

    Iniciamos descargando el cdigo1 que debe ser importado hacia un nuevo proyecto y que tienealgunascaractersticas importantes.

    Permisos en el Manifest, por el acceso a internet para el mapa y la ubicacin del GPS requerimestos2 permisos bajo el tag:

    Uso de la librera de mapas, tambin en el Manifest bajo el tag:

    En la clase de la actividad principal, utilizaremos herencia de MapActivity para facilitarnos el mdel mapa e implementaremos la interfaz LocationListener para detectar los cambios en lalocalizacin.

    Por heredar de MapActivity debemos implementar el mtodo:

    @Override

    protected boolean isRouteDisplayed() {

    return false;

    }

    Por implementar LocationListener debemos realizar los siguientes mtodos:

    @Override

    @Override

    @Override

    @Override

    public void onLocationChanged(Location location) {}

    public void onProviderDisabled(String provider) {}

    public void onStatusChanged(String provider, int status, Bundle extras) {}

    public void onProviderEnabled(String provider) {}

    1 https://github.com/androidMDW/guia5base

  • 8/6/2019 MDW Guia Android 1

    67/137

    CURSO ANDROID 67

    Diseo

    Utilizaremos una vista especial para el mapa es necesario un key para la utilizacin del serviciGoogle Maps1 y depende del certificado utilizado para firmar las aplicaciones, el valor del atribandroid:apiKey que aparece en el cdigo es vlida para mi certificado.

    android:layout_height=fill_parent

    android:apiKey=0xJ4uwRGDV296srCn4Iiy46oFmd1jecLr07BsAA

    Agregando cdigo

    La clase de la Activity para nuestra aplicacin extender de MapActivity para facilitarnos el ma

    de lavisualizacin del mapa e implementar LocationListener para el manejo de las actualizacionesubica-cin.public class Main extends MapActivity implements LocationListener

    De los mtodos disponibles, utilizaremos onProviderDisabled para forzar al usuario a tener el Gfuncionando antes de que la aplicacin inicie.

    @Override

    public void onProviderDisabled(String provider) {

    Intent intent = new Intent(

    startActivity(intent);

    }

    android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);

    Vamos a mostrar un marker en las diferentes ubicaciones detectadas, para ello haremos una cque

    1 http://code.google.com/android/add-ons/google-apis/mapkey.html

  • 8/6/2019 MDW Guia Android 1

    68/137

    CURSO ANDROID 68

    represente este Overlay mostrando la imagen seleccionada. Para este ejemplo se utilizar la imdel

    cono, al definirla dentro de la misma clase de la Activity principal entonces ser una clase privclass MyOverlay extends Overlay { }

    Tendremos una variable de instancia representando el punto donde se colocar el marcador y unparmetro recibido por el constructor:

    GeoPoint point;

    /* El constructor recibe el punto donde se dibujar el marker */

    public MyOverlay(GeoPoint point) {

    super();

    }this.point = point;

    Sobrecargaremos el mtodo draw para dibujar nuestro marker:

    @Override

    {

    public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when)

    super.draw(canvas, mapView, shadow);

    Point scrnPoint = new Point();

    //se traduce el punto geo localizado a un punto en la pantalla

    mapView.getProjection().toPixels(this.point, scrnPoint);

    //se construye un bitmap a partir de la imagen

    //se dibuja la imagen del marker

    marker.getHeight() / 2, null);return true;

    }

    Bitmap marker = BitmapFactory.decodeResource(getResources(), R.drawable.icon);

    canvas.drawBitmap(marker, scrnPoint.x - image.getWidth() / 2, scrnPoint.y -

    El cdigo completo de la clase para los overlays es el siguiente:

    class MyOverlay extends Overlay {

  • 8/6/2019 MDW Guia Android 1

    69/137

  • 8/6/2019 MDW Guia Android 1

    70/137

    CURSO ANDROID 70

    Movemos el centro del mapa hacia esta ubicacin:

    mapController.animateTo(point);

    mapController.setZoom(15);

    Posterior a esto, intentaremos hacer geolocalizacin del punto, obtener una direccin a partir dcoordenadas del punto. Primero instanciamos un objeto Geocoder que responder de acuerdo localidad configurada en el telfono.

    Geocoder geoCoder = new Geocoder(this, Locale.getDefault());

    A travs de este Geocoder y con el punto de la ubicacin intentamos obtener alguna direccinasociada

    y se lo hacemos saber al usuario por medio de un toast (aviso).

    try {

    List addresses = geoCoder.getFromLocation(point.getLatitudeE6() /

    1E6, point.getLongitudeE6() / 1E6, 1);

    String address = ;

    if (addresses.size() > 0) {

    for (int i = 0; i < addresses.get(0).getMaxAddressLineIndex(); i++)

    address += addresses.get(0).getAddressLine(i) + \n;

    }

    Toast.makeText(this, address, Toast.LENGTH_SHORT).show();

    } catch (IOException e) {

    e.printStackTrace();

    }

    Por ltimo, instanciamos la clase MyOverlay construda previamente para agregar un nuevo menel listado de overlays del mapa e invalidamos la vista para que vuelva a dibujarse todo.

    List mapOverlays = mapView.getOverlays();

    MyOverlay marker = new MyOverlay(point);

    mapOverlays.add(marker);

    mapView.invalidate();

    En el mtodo onCreate vamos a instanciar un LocationManager para mostrar el primer markersolici-tar actualizaciones:

  • 8/6/2019 MDW Guia Android 1

    71/137

    CURSO ANDROID 71

    MapView mapView = (MapView) findViewById(R.id.mapview);

    //habilitamos el control de zoom

    mapView.setBuiltInZoomControls(true);

    LocationManager locationManager =

    (LocationManager)getSystemService(Context.LOCATION_SERVICE);

    PROVIDER));

    updateLocation(locationManager.getLastKnownLocation(LocationManager.GPS_

    /* se actualizar cada minuto y 50 metros de cambio en la localizacin

    mientras ms pequeos sean estos valores ms frecuentes sern las

    actualizaciones */

    this);

    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 6000, 50,

    Luego en el mtodo onLocationChanged llamamos a nuestro mtodo updateLocation para quedibujeun nuevo marker cada vez que se actualice la localizacin:

    @Override

    public void onLocationChanged(Location location) {

    updateLocation(location);

    }

    http://www.forosdelweb.com/f165/ https://github.com/androidMDW/guia5compl

  • 8/6/2019 MDW Guia Android 1

    72/137

    CURSO ANDROID 72

    Conclusin

    En este captulo aprendimos sobre:

    Cmo manejar un mapa, la necesidad de una vista especial y solicitar un API Key.Cmo dibujar markers a travs de overlays sobre el mapa, adems personalizamos la imadelmarker.Cmo solicitar la ubicacin actual y actualizaciones ante el cambio de ubicacin.

  • 8/6/2019 MDW Guia Android 1

    73/137

    captulo6

    Trabajar con elacelermetro

  • 8/6/2019 MDW Guia Android 1

    74/137

    CURSO ANDROID 74

    CAPTULO 6

    Trabajar con el acelermetroEn el sexto captulo seguiremos trabajando con el hardware, ahora nos corresponde aprovechaacelermetro y usarlo para detectar movimiento del telfono.

    Ejemplo: Utilizando el acelermetro

    La aplicacin que realizaremos nos permitir ver en pantalla los valores del acelermetro y mounaviso cuando se detecte cierto movimiento del telfono.

    Es importante notar que el telfono cuenta con varios sensores (acelermetro, orientacin, cammagntico, luz, etc.) y de ellos vamos a utilizar nicamente uno el del acelermetro. Unacelermetro1es un sensor que mide la aceleracin relativa a la cada libre como marco de referencia.

    1 http://es.wikipedia.org/wiki/Aceler%C3%B3metro

  • 8/6/2019 MDW Guia Android 1

    75/137

    CURSO ANDROID 75

    En este caso, nuestra interfaz de usuario ser muy sencilla por lo que no utilizaremos ningn cbase.

    Diseo

    Mostraremos los valores de X, Y y Z del acelermetro, para ello necesitamos 3 etiquetasTextView.

    android:orientation=vertical

    android:layout_height=fill_parent

    android:layout_height=wrap_content

  • 8/6/2019 MDW Guia Android 1

    76/137

    CURSO ANDROID 76

    Agregando cdigo

    La clase de la Activity principal para nuestra aplicacin implementar SensorEventListener parmanejo de las actualizaciones de los sensores, en nuestro caso especfico nos interesa elacelermetro.

    public class Main extends Activity implements SensorEventListener

    Utilizaremos algunas variables de instancia para el control de los valores de los 3 ejes que midacele-rmetro (valor anterior y valor actual) y otras para guardar el timestamp de la ltima actualizalaltima vez que se detect movimiento.private long last_update = 0, last_movement = 0;

    private float prevX = 0, prevY = 0, prevZ = 0;private float curX = 0, curY = 0, curZ = 0;

    Al implementar esta interface debemos sobrecargar dos mtodos:

    @Override

    @Override

    public void onAccuracyChanged(Sensor sensor, int accuracy) {}

    public void onSensorChanged(SensorEvent event) {}

    Vamos a trabajar sobre onSensorChanged nuestro cdigo ser un synchronized statement (minfor-macin en la documentacin de Java1 ) para evitar problemas de concurrencia al estar trabajanconlos sensores.synchronized (this) {

    }

    A partir del evento recibido como parmetro vamos a obtener el timestamp de la fecha/hora a(seusar ms adelante) y los valores para los 3 ejes del acelermetro (X, Y, Z).

    long current_time = event.timestamp;curX = event.values[0];

    curY = event.values[1];

    curZ = event.values[2];

    Luego, revisamos si este cdigo ya se ha ejecutado alguna vez, es decir, si las variables queguardan los

    1 http://download.oracle.com/javase/tutorial/essential/concurrency/locksync.html

  • 8/6/2019 MDW Guia Android 1

    77/137

    CURSO ANDROID 77

    valores anteriores de X, Y y Z tiene valores diferentes de cero. Esto debera ejecutarse slo laprimera

    vez.if (prevX == 0 && prevY == 0 && prevZ == 0) {

    last_update = current_time;

    prevX = curX;

    prevY = curY;

    prevZ = curZ;

    }

    last_movement = current_time;

    Obtenemos la diferencia entre la ltima actualizacin y el timestamp actual, esto nos servir npara ver que si existe una diferencia de tiempos en las mediciones si no tambin para calcularmovi-miento. Para ello, tomamos la posicin actual (con las 3 coordenadas) y la restamos a la posicante-rior, puede ser que el movimiento sea en distintas direcciones por eso nos es til el valor abso

    long time_difference = current_time - last_update;

    if (time_difference > 0) {

    time_difference;

    ...

    }

    float movement = Math.abs((curX + curY + curZ) - (prevX - prevY - prevZ)) /

    Para decidir en que momento mostramos un aviso Toast indicando el movimiento vamos a usacomovalor de frontera de movimiento mnimo 110^-6; este valor es arbitrario mientras mayor seanece-sitar ms movimiento y mientras menor sea ms sensible ser el display del aviso.

    Manejamos tambin 2 variables para el control de tiempo, una para saber la ltima actualizaci(last_update) y otra para conocer la ltima vez que se registr movimiento last_movement y en esta

    delcdigo actualizamos su valor segn sea conveniente.

    int limit = 1500;

    float min_movement = 1E-6f;

    if (movement > min_movement) {

    if (current_time - last_movement >= limit) {

    Toast.makeText(getApplicationContext(), Hay movimiento de + movement,

  • 8/6/2019 MDW Guia Android 1

    78/137

    CURSO ANDROID 78

    Toast.LENGTH_SHORT).show();

    }

    }

    last_movement = current_time;

    Por ltimo actualizamos los valores de X, Y y Z anteriores para la prxima vez que se registrecambio enlos sensores.

    prevX = curX;

    prevY = curY;

    prevZ = curZ;

    last_update = current_time;

    Tambin actualizamos los valores de los 3 ejes del acelermetro en las etiquetas para visualizapantalla.

    ((TextView) findViewById(R.id.txtAccX)).setText(Acelermetro X: + curX);

    ((TextView) findViewById(R.id.txtAccY)).setText(Acelermetro Y: + curY);

    ((TextView) findViewById(R.id.txtAccZ)).setText(Acelermetro Z: + curZ);

    El cdigo completo queda de la siguiente forma:

    @Override

    public void onSensorChanged(SensorEvent event) {

    synchronized (this) {

    long current_time = event.timestamp;

    curX = event.values[0];

    curY = event.values[1];

    curZ = event.values[2];if (prevX == 0 && prevY == 0 && prevZ == 0) {

    last_update = current_time;

    prevX = curX;

    prevY = curY;

    prevZ = curZ;

    }

    last_movement = current_time;

  • 8/6/2019 MDW Guia Android 1

    79/137

    CURSO ANDROID 79

    long time_difference = current_time - last_update;

    if (time_difference > 0) {

    prevZ)) / time_difference;

    int limit = 1500;

    float movement = Math.abs((curX + curY + curZ) - (prevX - prevY -

    float min_movement = 1E-6f;

    if (movement > min_movement) {

    if (current_time - last_movement >= limit) {

    + movement, Toast.LENGTH_SHORT).show();

    }

    }

    last_movement = current_time;

    prevX = curX;

    prevY = curY;

    prevZ = curZ;

    }

    last_update = current_time;

    Toast.makeText(getApplicationContext(), Hay movimiento de

    ((TextView) findViewById(R.id.txtAccX)).setText(Acelermetro X: +

    curX);

    curY);

    curZ);

    }

    }

    ((TextView) findViewById(R.id.txtAccY)).setText(Acelermetro Y: +

    ((TextView) findViewById(R.id.txtAccZ)).setText(Acelermetro Z: +

    Una vez listo esto, es necesario registrar y anular el registro del Listener para el sensor segncorres-ponda, esto lo haremos en los mtodos onResume y onStop de la actividad (ms informacin dciclode vida de las Activities en la documentacin oficial1 ).

    Para el registro, obtenemos primero el servicio del sistema de sensores para asignarlo en un SManager y a partir de l obtenemos el acceso al acelermetro. Al realizar el registro del aceler

    1 http://developer.android.com/reference/android/app/Activity.html

  • 8/6/2019 MDW Guia Android 1

    80/137

  • 8/6/2019 MDW Guia Android 1

    81/137

    CURSO ANDROID 81

    http://www.forosdelweb.com/f165/ https://github.com/androidMDW/guia6compl

  • 8/6/2019 MDW Guia Android 1

    82/137

    CURSO ANDROID 82

    Conclusin

    En esta entrega del curso Android hemos aprendido a trabajar con el acelermetro, uno de lossensores includos en los telfonos, a travs de un Listener, nuestro cdigo de respuesta al eveseejecuta cuando hay algn cambio en los sensores y detectamos cuando hay cierto movimiento

  • 8/6/2019 MDW Guia Android 1

    83/137

    captulo7

    Reproduccin desonido en un cicloinfinito

  • 8/6/2019 MDW Guia Android 1

    84/137

    CURSO ANDROID 84

    CAPTULO 7

    Reproduccin de sonido en un ciclo infinitoEn el sptimo seguiremos trabajando con el hardware veremos cmo funcionan los servicios eAndroid.La aplicacin que realizaremos nos permitir iniciar y detener un servicio, cmo ejemplo esteservici seencargar de reproducir un sonido en un ciclo infinito.

    Disposicin inicialEn este caso, nuestra interfaz de usuario ser muy sencilla por lo que no utilizaremos ningncdigo base. Para configurar el servicio es necesario modificar el Manifest y agregar:

  • 8/6/2019 MDW Guia Android 1

    85/137

    CURSO ANDROID 85

    Diseo

    El diseo presenta dos botones, uno para detener y otro para iniciar el servicio. Se sugiere utillayouts, en nuestro caso el cdigo completo del layout es:

    android:orientation=vertical

  • 8/6/2019 MDW Guia Android 1

    86/137

    CURSO ANDROID 86

    Agregando cdigo

    Necesitamos de una clase adicional que represente al servicio, la llamaremos ElServicio y debeheredarde Service (en android.app). Esta clase debe sobrecargar el mtodo onBind pero en este captnos interesa que haga algo as que nicamente devolver null.

    Para que la clase funcione de la manera deseada, vamos a sobrecargar tres mtodos: onCreatonDestroy y onStart, en cada uno de ellos a travs de un toast vamos a verificar cuando el flujpasa por estos puntos.

    En onCreate vamos a inicializar lo que har el servicio ms adelante, en nuestro ejemplo utilizamos el media player ya reproducir un sonido, como demo he descargado uno desde soundjay1luegorenombrado a water_droplet por el convenio de nombres que no incluye guiones y por ltimocolocado en /res/raw/

    En onStart vamos a iniciar la reproduccin del sonido y en onDestroy vamos a detener el sonidse estaba reproduciendo. En resumen, lo necesario para cada uno de estos mtodos es:

    onCreate: Inicializar el Media Player e indicar que funcionar con un loop reproduciendo e

    sonido.onDestroy: Detener la reproduccin del sonidoonStart: Iniciar la reproduccin del audio.

    Es decir, el cdigo de nuestra clase de servicios completo queda de la siguienteforma:

    public class ElServicio extends Service {

    private MediaPlayer player;

    @Overridepublic IBinder onBind(Intent intent) {

    // TODO Auto-generated method stub

    return null;

    }

    @Override

    1 http://www.soundjay.com/nature/sounds/water-droplet-1.mp3

  • 8/6/2019 MDW Guia Android 1

    87/137

  • 8/6/2019 MDW Guia Android 1

    88/137

    CURSO ANDROID 88

    public void onClick(View src) {

    switch (src.getId()) {

    case R.id.btnInicio:

    break;

    startService(new Intent(this, ElServicio.class));

    case R.id.btnFin:

    break;

    }

    }

    stopService(new Intent(this, ElServicio.class));

    http://www.forosdelweb.com/f165/ https://github.com/androidMDW/guia7compl

  • 8/6/2019 MDW Guia Android 1

    89/137

  • 8/6/2019 MDW Guia Android 1

    90/137

    captulo8

    Envo de emailutilizando Android

  • 8/6/2019 MDW Guia Android 1

    91/137

    CURSO ANDROID 91

    CAPTULO 8

    Envo de email utilizando AndroidEn el octavo captulo veremos cmo enviar emails utilizando Android la aplicacin de ejemplo reali-zaremos nos permitir colocar la informacin para un correo electrnico (destinatario, asunto,nido del correo, adjuntos) y luego enviarlo a travs de la aplicacin de correo electrnico.

    Es importante notar que el ejemplo debe ejecutarse en un telfono o bien instalar una aplicaciparaenvo de emails en el emulador (por defecto no est instalada pero es relativamente simple).

    Queremosque al finalizar se vea as:

  • 8/6/2019 MDW Guia Android 1

    92/137

    CURSO ANDROID 92

    Disposicin inicial

    En este caso, nuestra interfaz de usuario ser muy sencilla por lo que no utilizaremos ningn cbase tampoco realizaremos ninguna configuracin adicional.

    Diseo

    El diseo presenta los campos necesarios para el envo del mail dentro de un contenedor globaeste caso utilizamos un LinearLayout) por cada fila tenemos otro contenedor que a su vez dentiene

    2 elementos: una TextView y un EditText eso se repite para la direccin de correo del destinatasunto y el cuerpo del correo.

    Por ltimo, se tiene una CheckBox para indicar si se desea enviar un adjunto (el cono de laaplicacin).El XML complete del diseo es el siguiente:

    android:layout_width=fill_parent

    android:orientation=vertical

    android:layout_height=wrap_content

    android:layout_height=wrap_content

    android:width=170dip

    android:id=@+id/etEmail>

  • 8/6/2019 MDW Guia Android 1

    93/137

    CURSO ANDROID 93

    android:layout_height=wrap_content

    android:width=170dip

    android:id=@+id/etSubject>

  • 8/6/2019 MDW Guia Android 1

    94/137

    CURSO ANDROID 94

    Agregando funcionalidad

    Asociaremos todo el cdigo del envo del email al evento de click sobre el botnEnviar:Button btnSend = (Button) findViewById(R.id.btnSend);

    btnSend.setOnClickListener(new OnClickListener() {

    @Override

    }

    public void onClick(View v) {

    });

    Obtenemos primero los elementos del form con los datos el email (destinatario, asunto, cuerpo

    maily adjunto):// obtenemos los datos para el envo del correo

    EditText etEmail = (EditText) findViewById(R.id.etEmail);

    EditText etBody = (EditText) findViewById(R.id.etBody);

    EditText etSubject = (EditText) findViewById(R.id.etSubject);

    CheckBox chkAttachment = (CheckBox) findViewById(R.id.chkAttachment);

    Luego construimos un intent que luego utilizaremos para levantar la Activity para el envo delcorreo,este debe ser del tipo ACTION_SEND, posteriormente indicamos cul ser el tipo de dato a env

    // es necesario un intent que levante la actividad deseada

    Intent itSend = new Intent(android.content.Intent.ACTION_SEND);

    itSend.setType(plain/text);

    // vamos a enviar texto plano a menos que el checkbox est marcado

    Colocamos todos los datos obtenidos del form, incluyendo el posible adjunto en caso de que elCheck-Box est marcado.

  • 8/6/2019 MDW Guia Android 1

    95/137

    CURSO ANDROID 95

    // colocamos los datos para el envo

    etEmail.getText().toString()});

    itSend.putExtra(android.content.Intent.EXTRA_EMAIL, new String[]{

    itSend.putExtra(android.content.Intent.EXTRA_SUBJECT,

    etSubject.getText().toString());

    itSend.putExtra(android.content.Intent.EXTRA_TEXT, etBody.getText());

    como

    // revisamos si el checkbox est marcado enviamos el cono de la aplicacin

    adjunto

    if (chkAttachment.isChecked()) {// colocamos el adjunto en el stream

    itSend.putExtra(Intent.EXTRA_STREAM, Uri.parse(android.resource:// +

    getPackageName() + / + R.drawable.icon));

    // indicamos el tipo de dato

    }

    itSend.setType(image/png);

    Por ltimo iniciamos la Activity para el envo.

    startActivity(itSend);

    El cdigo completo es el siguiente:

    Button btnSend = (Button) findViewById(R.id.btnSend);

    btnSend.setOnClickListener(new OnClickListener() {

    @Override

    public void onClick(View v) {//obtenemos los datos para el envo del correo

    EditText etEmail = (EditText) findViewById(R.id.etEmail);

    EditText etBody = (EditText) findViewById(R.id.etBody);

    EditText etSubject = (EditText) findViewById(R.id.etSubject);

    CheckBox chkAttachment = (CheckBox) findViewById(R.id.chkAttachment);

    //es necesario un intent que levante la actividad deseada

    Intent itSend = new Intent(android.content.Intent.ACTION_SEND);

  • 8/6/2019 MDW Guia Android 1

    96/137

    CURSO ANDROID 96

    //vamos a enviar texto plano a menos que el checkbox est marcado

    itSend.setType(plain/text);

    //colocamos los datos para el envo

    etEmail.getText().toString()});

    itSend.putExtra(android.content.Intent.EXTRA_EMAIL, new String[]{

    itSend.putExtra(android.content.Intent.EXTRA_SUBJECT,

    etSubject.getText().toString());

    itSend.putExtra(android.content.Intent.EXTRA_TEXT, etBody.getText());

    //revisamos si el checkbox est marcado enviamos el cono de la

    aplicacin como adjunto

    if (chkAttachment.isChecked()) {//colocamos el adjunto en el stream

    itSend.putExtra(Intent.EXTRA_STREAM, Uri.parse(android.resource://

    + getPackageName() + / + R.drawable.icon));

    //indicamos el tipo de dato

    }

    itSend.setType(image/png);

    //iniciamos la actividad

    startActivity(itSend);

    }

    });

  • 8/6/2019 MDW Guia Android 1

    97/137

    CURSO ANDROID 97

    http://www.forosdelweb.com/f165/ https://github.com/androidMDW/guia8compl

  • 8/6/2019 MDW Guia Android 1

    98/137

  • 8/6/2019 MDW Guia Android 1

    99/137

    captulo9

    Trabajando con APIs(Facebook y Twitter)

  • 8/6/2019 MDW Guia Android 1

    100/137

    CURSO ANDROID 100

    CAPTULO 9

    Trabajando con APIs (Facebook y Twitter)En el noveno captulo utilizaremos los APIs de Facebook y Twitter para autenticacin. La aplicaquerealizaremos nos permitir iniciar sesin y obtener algunos datos.

    Queremos que al finalizar se vea as:

    Disposicin inicial

    Para realizar la autenticacin es necesario solicitar una aplicacin en Facebook1 y una aplicaciTwitter2 . En el cdigo completo se incluyen el identificador de la aplicacin de Facebook de dedel1 http://www.facebook.com/developers/createapp.php2 https://dev.twitter.com/apps/new

  • 8/6/2019 MDW Guia Android 1

    101/137

    CURSO ANDROID 101

    SDK y un token/secret d