Aplicacin Android Servicio PHP

download Aplicacin Android Servicio PHP

of 27

Transcript of Aplicacin Android Servicio PHP

  • Aplicacin Android + Servicio PHPby SamuGG - http://samuel-granados.com/blog/aplicacion-android-servicio-php/

    Aplicacin Android + Servicio PHP

    Tutorial para crear una aplicacin en Android que consulta datos de una pgina web en PHP(como un webservice), la cual a su vez realiza consultas a una base de datos MySQL.

    Este tutorial representa un buen punto de partida para los iniciados en Android que quieren aprender a hacer unaaplicacin de las que se usan en el mundo real, sin complicarse en el diseo ni en cuestiones monetarias. Laaplicacin que os voy a ensear es una consulta sencilla a una base de datos de pelculas que podemos tenertodos en casa y ahora en nuestro mvil.

    Descripcin

    Vamos a desarrollar una aplicacin para Android que busca pelculas en nuestra base de datos segn una partedel ttulo que el usuario quiera poner o todas las que hay si el usuario no especifica ningn filtro.Dicha aplicacin ser la interfaz grfica para que el usuario vea el listado de pelculas. Su funcin es capturar losparmetros de bsqueda que quiera especificar el usuario; en nuestro caso solo habr 2: una parte del ttulo y elnmero mximo de resultados devueltos que desea ver. Luego enviar estos datos o filtros de bsqueda a unwebservice, que en nuestro caso no es ms que una pgina PHP sin ms complicaciones.La pgina enviar la consulta correspondiente a la base de datos con los parmetros recogidos por la aplicacinpara filtrar la bsqueda; y por ltimo, transformar dichos datos en un archivo descargable para la aplicacinAndroid, la cual leer estos datos y presentar en un listado las pelculas resultantes.

    Resumiendo, los elementos ms importantes de los que se compone este tutorial son los siguientes:

    Aplicacin Android: Aplicacin desde la cual obtendremos un listado de pelculas.Base de Datos: Una base de datos en MySQL muy sencilla con una tabla pelculas.Transferencia de datos: Una pgina web PHP que recibir peticiones de la aplicacin Android y le devolverdatos para presentar el listado.

    Tcnicas Utilizadas

    Lo ms laborioso para un iniciado pueden ser estos cuatro puntos, aunque no son nada complicados, ya lo vers.

    Construir una pgina PHP que reciba 2 parmetros y conecte con la base de datos MySQL pasndoleuna sentencia con dichos parmetros.Transferir los datos recuperados de la base de datos a la aplicacin Android por GET HTTP; para ello losvamos a serializar en un archivo binario y la pgina PHP no mostrar nada si no que descargar dichoarchivo.La serializacin y deserializacin de los datos binarios del archivo que transfiere la pgina PHP a laaplicacin Android la realizaremos utilizando Google protocol buffers.Mostrar el listado de resultados en otra pantalla Android distinta a la que ejecut la consulta.

    Qu Necesito?

    Servidor Web que compile PHP: Apache o IISServidor de Bases de Datos MySQL: pgina de descargaEntorno de desarrollo Eclipse con Android ADT. Si vas a la pgina oficial de Android Developers puedes

    pgina 1 / 27

  • Aplicacin Android + Servicio PHPby SamuGG - http://samuel-granados.com/blog/aplicacion-android-servicio-php/

    descargar las dos cosas en un mismo paquete sin necesidad de instalacin.Compilador prtobuf: archivo protoc.exeUtilidad de generacin de clases PHP para protobuf: pb4phpLibrera precompilada Google protobuf Java (archivo .jar) para deserializar datos en Android.

    Debemos utilizar la librera JAR de la misma versin que el compilador protoc.exe. Si por ejemplo,descargamos el compilador 2.4.0 necesitamos el JAR 2.4.0, de lo contrario, si utilizamos versiones diferentes nofuncionar.

    Lo que yo he utilizado

    Servidor web: IIS con PHP 5.4.6Servidor bbdd: MySQL 5.5.20 x86Eclipse 4.2.1Android ADT plugin para Eclipse r21.0.0Compilador protoc 2.4.1 x86pb4php 0.25

    Cmo lo he configurado

    1. Descargu el archivo .zip de la seccin VC9 x86 Thread Safe de la pgina oficial de PHP y lodescomprim en C:\PHP\. Luego configur mi IIS como en el artculo de mi blog.

    2. Descargu el archivo mysql-5.5.20-win32.msi de la pgina oficial de MySQL y lo instal con las opcionespredeterminadas en mi mquina local (127.0.0.1)

    3. Descargu el paquete completo de desarrollo Android de la pgina oficial de Android SDK, luegodescomprim su contenido en C:\adt-bundle-windows\

    4. Descargu el archivo protoc-2.4.1-win32.zip de la pgina oficial de Google y lo descomprim en C:\Archivos de programa\protoc.exe

    5. Descargu el archivo protocolbuf_025.zip de la pgina oficial y descomprim los subdirectorios messagey parser completos bajo mi carpeta C:\inetpub\wwwroot\php\peliculas\lib\pb4php\, adems de extraerel archivo example\protoc.php del zip al mismo sitio.

    6. Descargu el archivo protobuf-java-2.4.1.jar de aqu y lo he colocado en la carpeta libs del proyectoEclipse para la aplicacin Android. (Llegaremos a este punto ms adelante)

    Base De Datos

    Slamente vamos a necesitar una tabla llamada peliculas con id y ttulo. A continuacin el script para crear labase de datos y la tabla con algunas filas de ejemplo:

    CREATE DATABASE IF NOT EXISTS peliculas;USE peliculas;

    DROP TABLE IF EXISTS `pelicula`;CREATE TABLE `pelicula` ( `PEL_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT, `PEL_titulo` varchar(64) COLLATE utf8_spanish_ci NOT NULL, PRIMARY KEY (`PEL_id`), KEY `ix_titulo` (`PEL_titulo`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci;

    INSERT INTO `pelicula` (`PEL_id`,`PEL_titulo`) VALUES (1,'Rocky'), (2,'El Seor de los anillos'), (3,'Terminator 2'),

    pgina 2 / 27

  • Aplicacin Android + Servicio PHPby SamuGG - http://samuel-granados.com/blog/aplicacion-android-servicio-php/

    (4,'Esta casa es una ruina'), (5,'Apolo XIII'), (6,'Alien'), (7,'Parque Jursico'), (8,'Parque Jursico 2'), (9,'Misin Imposible'), (10,'Torrente');

    Una vez que tenemos la base de datos funcionando vamos a crear la pgina web que conecta a dicha base dedatos.

    top

    Webservice PHP

    El webservice es una pgina normal PHP que no muestra nada, en vez de eso, devuelve los resultados enforma de un archivo descargable.

    Crea una pgina web vaca llamada index.php en tu servidor, yo la he creado en C:\inetpub\wwwroot\php\peliculas\index.php

    Antes de soltar todo el cdigo fuente de la pgina PHP, me gustara explicar algunos conceptos que heconsiderado

    Este sera un fragmento de PHP para capturar los parmetros de la pgina

    if (isset($_GET['t'])) { $pTitle = $_GET['t']; // ttulo a consultar}if (isset($_GET['r'])) { $pMaxResults = $_GET['r']; // nm. mx. de resultados a devolver}

    Con lo cual llamaramos a la pgina as:

    Para obtener todos los resultados:http://localhost/php/peliculas/index.phpPara obtener 3 resultados:http://localhost/php/peliculas/index.php?r=3Para buscar las que contengan parque jursico:http://localhost/php/peliculas/index.php?t=parque%20jursicoPara buscar las 5 primeras que contengan parque:http://localhost/php/peliculas/index.php?t=parque&r=5

    Observa que la parte textual del ttulo debe estar codificada, ya que si ponemos t=parque jursico separadospor un espacio en blanco, el servidor pensara que estamos pasando el parmetro t=parque y luego hay otroparmetro suelto llamado jursico sin valor. No te preocupes, hay una funcin que hace esto. Por ahora, slo esun detalle que debes tener en cuenta.

    pgina 3 / 27

  • Aplicacin Android + Servicio PHPby SamuGG - http://samuel-granados.com/blog/aplicacion-android-servicio-php/

    Con este fragmento de cdigo conectamos a una base de datos y recogemos los datos.

    // Crea la conexin a la base de datos e intenta conectar$con = new mysqli('127.0.0.1', 'root', 'password', 'peliculas');if ($con->connect_errno) { echo 'Connect failed: ', $con->connect_error; exit();}$con->set_charset('utf8');

    // Forma la consulta SQL$sql = 'SELECT PEL_id, PEL_titulo FROM `pelicula` ';

    // Si el parmetro ttulo contiene algo, inserta la condicinif (isset($pTitle)) { $pTitle = trim($pTitle); if (0 != strlen($pTitle)) { $sql .= 'WHERE PEL_titulo LIKE CONCAT(?, \'%\') '; }}

    // Indica el orden de los resultados$sql .= 'ORDER BY PEL_titulo';

    // Lmite de resultados, si el parmetro ha sido especificadoif (isset($pMaxResults)) { $sql .= ' LIMIT '.$pMaxResults;}

    // Inicializa la sentencia antes de ejecutarla$stmt = $con->stmt_init();if ($stmt->prepare($sql)) {

    // Inserta el valor del parmetro para el ttulo en la sentencia // (en caso de que lo hubiera) if (isset($pTitle)) { $stmt->bind_param('s', $pTitle); }

    // Ejecuta la sentencia SQL $stmt->execute();

    // Los campos devueltos por la sentencia se almacenarn // en las variables que indicamos a continuacin $stmt->bind_result($col_id, $col_titulo);

    // Recorre cada fila devuelta e imprime los campos obtenidos while($stmt->fetch()) { echo $col_id.' - '.$col_titulo.''; }

    // Cierra elementos abiertos y libera memoria $stmt->close(); unset($stmt);}

    pgina 4 / 27

  • Aplicacin Android + Servicio PHPby SamuGG - http://samuel-granados.com/blog/aplicacion-android-servicio-php/

    // Cierra la conexin a la base de datos y libera variables$con->close();unset($con);unset($sql);

    Ahora falta la parte ms difcil: generar un archivo binario con los resultados obtenidos, en vez de imprimirlos.Aqu es donde interviene el mtodo de serializacin de datos Google protocol buffers. Te puedes familiarizar coneste mtodo leyendo mis artculos:Serializar en JavaProtocol Buffers en JavaProtocol Buffers en C#

    Serializar los resultados a un archivo binario y transferirloEl mtodo usado por Google es muy prctico porque se transfieren los datos mnimos de informacin por lo queocupa poco espacio y es muy rpido. Ahora bien, si habis ledo algo sobre este mtodo sabris que consiste encrear un mensaje (archivo .proto) y pasarlo por el compilador protobuf para obtener el archivo de cdigo fuentecon el que podremos trabajar (en nuestro caso, un archivo de clase .php).

    Queremos una clase llamada Pelcula en PHP.Pues entonces creamos un archivo ANSI (no UTF-8!) como este:

    message Pelicula { required int32 id = 1; required string titulo = 2;}

    message ListaPeliculas { repeated Pelicula pelicula = 1;}

    Y lo guardamos en C:\inetpub\wwwroot\php\peliculas\lib\Peliculas.proto.

    Con esto generaremos dos clases en PHP:- clase Pelicula: Para cada elemento individual.- clase ListaPeliculas: Para manejar la lista de resultados fcilmente con un objeto de esta clase.

    En la pgina oficial encontrars informacin sobre cmo especificar tus estructuras de datos en archivos .proto.

    Como el compilador de Google protoc.exe no es capaz de convertir el archivo .proto que acabamos de crear encdigo fuente PHP, echaremos mano de la utilidad pb4php.

    Primero vamos a editar el archivo C:\inetpub\wwwroot\php\peliculas\lib\pb4php\protoc.php para que tenga elsiguiente contenido:

  • Aplicacin Android + Servicio PHPby SamuGG - http://samuel-granados.com/blog/aplicacion-android-servicio-php/

    $parser->parse('../Peliculas.proto');

    echo 'File parsing done!';?>

    Y abrimos la siguiente direccin en nuestro navegador:http://localhost/php/peliculas/lib/pb4php/protoc.php

    Verifica si ha creado el archivo C:\inetpub\wwwroot\php\peliculas\lib\pb4php\pb_proto_Pelicula.php, encaso contrario, es posible que no tengas permisos de escritura en dicha carpeta. Slo tienes que drseloshaciendo click derecho en la carpeta y marcar la casilla de Modificar en los permisos del grupo de usuarios IIS_IUSRS. Luego vuelve a llamar a protoc.php

    Si ya tienes el archivo pb_proto_Pelicula.php creado, muvelo a la carpeta C:\inetpub\wwwroot\php\peliculas\lib.Este archivo, dentro contiene la clase Pelicula y la clase ListaPeliculas con las que vamos a terminar de hacernuestro index.php.

    Finalmente

  • Aplicacin Android + Servicio PHPby SamuGG - http://samuel-granados.com/blog/aplicacion-android-servicio-php/

    $sql .= 'ORDER BY PEL_titulo, PEL_id';

    // Aade lmite de resultados a la consulta si se especificif (isset($pMaxResults)) { $sql .= ' LIMIT '.$pMaxResults;}

    $stmt = $con->stmt_init();if ($stmt->prepare($sql)) {

    // Asigna valor al parmetro 'ttulo' de la consulta SQL if (isset($pTitle)) { $stmt->bind_param('s', $pTitle); }

    // Ejecuta la consulta SQL $stmt->execute();

    // Los campos devueltos del resultado de cada fila, se // introducirn en las siguientes variables: $stmt->bind_result($PEL_id, $PEL_titulo);

    // Crea una nueva lista de peliculas donde almacenar // el resultado obtenido de la consulta en la bbdd. $lista_resultado = new ListaPeliculas();

    while($stmt->fetch()) { // Crea un nuevo elemento en la lista y le asigna sus campos $m = $lista_resultado->add_pelicula(); $m->set_id($PEL_id); $m->set_titulo($PEL_titulo); }

    // Cierra elementos y libera memoria $stmt->close(); unset($row); unset($result); unset($stmt);

    // Convierte en binario todo el resultado (Serializacin) $bytes = $lista_resultado->SerializeToString();}

    // Cierra la conexin SQL y libera las variables$con->close();unset($con);unset($sql);

    // Prepara la salida de datos de esta pgina$size = strlen($bytes);

    header('Content-Length: '.$size);header('Content-type: application/octet-stream');header('Content-Disposition: attachment; filename="datos.bin"');

    pgina 7 / 27

  • Aplicacin Android + Servicio PHPby SamuGG - http://samuel-granados.com/blog/aplicacion-android-servicio-php/

    header('Content-Transfer-Encoding: binary');

    ob_flush();ob_clean();// Escribe los datos binarios en la salida de esta pginaecho $bytes;ob_end_flush();exit();?>

    Si pruebas abrir la pgina http://localhost/php/peliculas/index.php?r=5 se descargar el fichero datos.bin que hagenerado con los resultados recuperados, esto es, las 5 primeras pelculas de tu base de datos, en formatobinario.

    Hasta ahora lo que hemos hecho ha sido generar los datos que va a consumir nuestra aplicacin de Android.Ahora continuaremos creando dicha aplicacin y consumiendo estos datos para mostrarlos al usuario en unalista.

    top

    Aplicacin Android

    Primeros pasos en EclipseEl entorno de desarrollo Eclipse no necesita instalacin, podemos iniciarlo haciendo doble click directamente en eclipse.exe. La primera vez que lo inicies te preguntar dnde quieres colocar la carpeta workspace quecontendr tus proyectos.

    pgina 8 / 27

  • Aplicacin Android + Servicio PHPby SamuGG - http://samuel-granados.com/blog/aplicacion-android-servicio-php/

    Primero de todo debes asegurarte de que tu sistema tiene Java instalado. Puedes descargarte la ltima verisnde aqu o actualizar la que ya tienes (desinstalando primero la versin vieja).

    Luego puedes optar por una de las dos opciones siguientes:

    1. Descargar Eclipse, el SDK de Android para Windows y el plugin de Android para Eclipse (ADT), einstalarlo todo individualmente.

    2. Descargar el paquete de desarrollo Eclipse preparado de la pgina oficial de desarrollo Android aqu, quelo trae todo junto y configurado.

    Es preferible la primera opcin, pero s que muchos de vosotros escogeris la segunda por la facilidad queaporta bajarse un zip, descomprimir y listo para empezar a programar.De todas formas, si eliges la primera opcin, sigue estos pasos:

    1. Descarga el Eclipse Classic de la pgina oficial.2. Descomprime el paquete en una carpeta donde tengas permisos de escritura. Si no ests seguro extrelo

    a C:\Eclipse.3. Hazte un acceso directo donde quieras al ejecutable, brelo e inicia los primeros pasos para especificar la

    carpeta workspace.4. Descarga el instalador de Windows Android SDK de aqu, en la seccin Download for other platforms >

    SDK Tools only. Luego instlalo.5. Ahora ve al Eclipse > Help > Install new software.6. En la ventana que aparece pulsa el botn Add y en el dilogo escribe Name: ADT Plugin, Location:

    https://dl-ssl.google.com/android/eclipse/. Guarda y cuando cargue selecciona Developer Tools y yacontina la instalacin aceptando las licencias y tal.

    7. Una vez que tenemos instalado el plugin, reiniciamos Eclipse y vamos al men Window. Ya vers

    pgina 9 / 27

  • Aplicacin Android + Servicio PHPby SamuGG - http://samuel-granados.com/blog/aplicacion-android-servicio-php/

    opciones nuevas para Android. Entra en Preferences > Android y escribe en SDK location la ruta a lacarpeta donde instalaste el SDK de Windows. Aplica los cambios.

    8. Abre el men Window > Android SDK Manager, revisa que tienes la ltima versin de todo yopcionalmente puedes instalar las Google APIs.

    9. Luego ve a Window > AVD Manager y agrega un dispositivo virtual Android con las opciones por defecto.Aqu puedes crear telfonos mviles, tabletas, etc.

    10. Si quieres probar el dispositivo Android que has creado pulsa el botn Start del AVD Manager.

    Si elegiste la segunda opcin (bajarse el Eclipse preparado con todo), slo debes realizar los pasos anteriores apartir del 8 en adelante.var $jq = jQuery.noConflict(); $jq(document).ready(function() { $jq('#EclipseInstallADT').coinslider({ width: 300,height: 260, spw: 7, sph: 5, delay: 5000, sDelay: 30, opacity: 0.7, titleSpeed: 1500, effect: 'fade', navigation: true,links : true, stickynav: false, hoverPause: true }); });

    pgina 10 / 27

  • Aplicacin Android + Servicio PHPby SamuGG - http://samuel-granados.com/blog/aplicacion-android-servicio-php/

    pgina 11 / 27

  • Aplicacin Android + Servicio PHPby SamuGG - http://samuel-granados.com/blog/aplicacion-android-servicio-php/

    pgina 12 / 27

  • Aplicacin Android + Servicio PHPby SamuGG - http://samuel-granados.com/blog/aplicacion-android-servicio-php/

    La aplicacin AndroidCrea un nuevo proyecto Android llamado Peliculas con un icono que te guste utilizando el asistente de Eclipse.Crear todo un rbol de directorios y la pantalla inicial de la aplicacin.var $jq = jQuery.noConflict(); $jq(document).ready(function() { $jq('#EclipseNewProject').coinslider({ width: 300,height: 275, spw: 7, sph: 5, delay: 5000, sDelay: 30, opacity: 0.7, titleSpeed: 1500, effect: 'fade', navigation: true,links : true, stickynav: false, hoverPause: true }); });

    pgina 13 / 27

  • Aplicacin Android + Servicio PHPby SamuGG - http://samuel-granados.com/blog/aplicacion-android-servicio-php/

    pgina 14 / 27

  • Aplicacin Android + Servicio PHPby SamuGG - http://samuel-granados.com/blog/aplicacion-android-servicio-php/

    pgina 15 / 27

  • Aplicacin Android + Servicio PHPby SamuGG - http://samuel-granados.com/blog/aplicacion-android-servicio-php/

    pgina 16 / 27

  • Aplicacin Android + Servicio PHPby SamuGG - http://samuel-granados.com/blog/aplicacion-android-servicio-php/

    En la carpeta libs del proyecto, pega la librera protobuf-java-2.4.1.jar.

    Abre el archivo AndroidManifest.xml y en la pestaa Permissions aade INTERNET para que la aplicacinpueda acceder a Internet, puesto que necesitaremos que llame a nuestra pgina PHP.

    Ahora crea una clase nueva que extienda la super clase Application, bajo la carpeta src/peliculas, as:

    package peliculas;import android.app.Application;public class Peliculas extends Application { public ListaPeliculas lPeliculas; public Peliculas() { }}

    Aqu hemos puesto una variable global llamada lPeliculas para poder compartir los datos entre pantallas. Laclase de esta variable: ListaPeliculas todava no la hemos creado, pero tampoco la podemos crearmanualmente. El compilador de protobuf protoc.exe ser el que la cree automticamente a partir del archivo .proto que creamos anteriormente.

    Para ello, dentro de la carpeta src del proyecto crea una subcarpeta llamada proto. En ella, pega el archivo Pelicula.proto. Luego, desde la lnea de comandos, bajo este mismo directorio ejecuta el siguiente comandotodo seguido en una lnea:

    "C:\Program Files (x86)\protoc.exe" --java_out=C:\users\samuel\workspace\peliculas\src\

    pgina 17 / 27

  • Aplicacin Android + Servicio PHPby SamuGG - http://samuel-granados.com/blog/aplicacion-android-servicio-php/

    --proto_path=C:\users\samuel\workspace\peliculas\src\protoC:\users\samuel\workspace\peliculas\src\proto\Peliculas.proto

    Modifica las rutas a los archivos segn tu instalacin y tu sistema.

    El compilador de protocol buffers habr generado nuestras clases java a partir del archivo .proto. Coloca elarchivo resultante bajo la carpeta src\peliculas.Ahora ya tienes las clases Pelicula y ListaPeliculas en Java para poder trabajar con ellas.

    Ahora vamos a crear la pantalla inicial

    El layout debe ir en res\layout

    pgina 18 / 27

  • Aplicacin Android + Servicio PHPby SamuGG - http://samuel-granados.com/blog/aplicacion-android-servicio-php/

    Para que quede algo as (modifica los textos a tu gusto en el archivo res\values\strings.xml):

    Esta pantalla va a llevar a cabo una tarea asncrona (descargar un archivo del webservice) que no sabemoscunto va a tardar, por eso Android tiene la super clase AsyncTask.

    Al implementar una clase de esta super clase, Android abre otro hilo de ejecucin para que este tipo de tareastarden lo que necesiten sin paralizar el hilo de ejecucin principal, porque si la tarea queda esperando a que elservidor web le responda, nuestra interfaz grfica se quedara congelada mientras tanto, dando la sensacin deque el programa se ha colgado.

    Necesitamos crear una clase que derive de AsyncTask para realizar el proceso de llamar al webservice, recogerlos datos devueltos y deserializarlos. Todo este proceso es asncrono y no debe bloquear el programa. Al pulsarel botn Buscar ejecutaremos esta nueva clase.

    package peliculas;

    import java.io.BufferedInputStream;import java.io.ByteArrayOutputStream;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.URL;

    pgina 19 / 27

  • Aplicacin Android + Servicio PHPby SamuGG - http://samuel-granados.com/blog/aplicacion-android-servicio-php/

    import android.content.Context;import android.os.AsyncTask;import android.util.Log;import peliculas.ListaPeliculas;

    public class QueryMovies extends AsyncTask {

    private Context context;

    public QueryMovies(Context pContext) { this.context = pContext; }

    @Override protected ListaPeliculas doInBackground(String... arg0) { if (arg0.length != 0) { return getMovies(arg0[0]); } else { return null; } }

    protected ListaPeliculas getMovies(String arg0){ // Resultado a devolver ListaPeliculas res = ListaPeliculas.getDefaultInstance();

    HttpURLConnection httpcon; try { // Conecta con la pgina web cuya direccin tenemos en arg0 URL url = new URL(arg0); httpcon = (HttpURLConnection)url.openConnection(); httpcon.connect();

    // En caso de respuesta afirmativa del servidor. if (HttpURLConnection.HTTP_OK == httpcon.getResponseCode()) {

    // Leemos la informacin que llega por respuesta y la almacenamos // en una variable llamada buffer, de tipo byte[]. InputStream ist = httpcon.getInputStream(); BufferedInputStream b_input = new BufferedInputStream(ist); ByteArrayOutputStream b_output = new ByteArrayOutputStream(); byte[] buffer = new byte[4096]; int read = b_input.read(buffer, 0, 4096);

    while (-1 != read) { b_output.write(buffer, 0, read); read = b_input.read(buffer, 0, 4096); }

    // Dejamos en buffer los datos resultantes obtenidos, // es decir, el listado de resultados en formato binario. buffer = b_output.toByteArray();

    pgina 20 / 27

  • Aplicacin Android + Servicio PHPby SamuGG - http://samuel-granados.com/blog/aplicacion-android-servicio-php/

    // Cierra streams y conexin b_output.close(); b_input.close(); ist.close(); httpcon.disconnect();

    // Slo para PHP en servidores IIS // Nos debemos deshacer de los 3 primeros caracteres de la respuesta /*if (buffer.length > 2) { System.arraycopy(buffer, 3, buffer, 0, buffer.length - 3); }*/

    // Deserializacin con PROTOCOL BUFFERS res = ListaPeliculas.parseFrom(buffer);

    } else { httpcon.disconnect(); Log.e("QueryMovies()", httpcon.getResponseMessage()); }

    } catch(Exception e) { e.printStackTrace(); }

    return res; }

    @Override protected void onPostExecute(ListaPeliculas result) { super.onPostExecute(result); ((IMyActivity)this.context).TaskCallback(result); }

    }

    doInBackground es lo que se va a ejecutar al ejecutar esta clase. Y cuando termine, se ejecutarautomticamente (sin que tengamos que hacer nada) onPostExecute.

    La manera de proceder de la clase QueryMovies es sencilla: crearemos la clase desde el contexto de la pantallainicial (de ah el constructor), luego le pasaremos por parmetro la URL del webservice ya formada para quedevuelva los resultados de la consulta en formato binario (serializado), despus, en un bucle leer bloques debytes hasta haber ledo todo lo que devuelve el webservice (de 4KB en 4KB), luego deserializa los bytesrecogidos para obtener el listado de pelculas correspondiente y por ltimo onPostExecute llama de vuelta a lafuncin TaskCallback de la pantalla que inici esta tarea asncrona (nuestra pantalla inicial de bsqueda),devolvindole por parmetro la lista de pelculas resultante.

    En la lnea 93 la pantalla que llam a esta clase (MainActivity) est en this.context, pero adems vers que le hepuesto delante el tipo de datos IMyActivity. Explico el por qu:

    Cualquier pantalla de nuestra aplicacin podra crear una clase QueryMovies por lo que en la lnea 93this.context podra ser cualquier clase. He aqu un prequeo problema, que no tenemos la funcin TaskCallback() en cualquier clase. Nosotros sabemos que est en MainActivity pero no sabemos si est en

    pgina 21 / 27

  • Aplicacin Android + Servicio PHPby SamuGG - http://samuel-granados.com/blog/aplicacion-android-servicio-php/

    alguna otra.Para solucionar este inconveniente obligamos a la clase MainActivity (y todas aquellas que vayan a utilizar QueryMovies) a tener la funcin TaskCallback() implementada mediante el uso de una Interface.

    Haremos la inteface IMyActivity en src\peliculas

    package peliculas;

    public interface IMyActivity { public void TaskCallback(ListaPeliculas result);}

    Y las pantallas que utilicen QueryMovies la deben implementar siempre.

    package peliculas;

    import java.net.URLEncoder;

    import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.util.Log;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.widget.EditText;import android.widget.Toast;

    public class MainActivity extends Activity implements IMyActivity {

    @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);

    // Establece el nmero mx. de resultados por defecto EditText et = (EditText)findViewById(R.id.txtSearchLimit); et.setText("25"); }

    public void sendQuery(View v) { QueryMovies q = new QueryMovies(this);

    StringBuilder sb = new StringBuilder(); sb.append("http://127.0.0.1/peliculas/index.php");

    try { EditText et = (EditText)findViewById(R.id.txtSearchTitle); String txtTitle = et.getText().toString(); txtTitle = txtTitle.trim();

    et = (EditText)findViewById(R.id.txtSearchLimit);

    pgina 22 / 27

  • Aplicacin Android + Servicio PHPby SamuGG - http://samuel-granados.com/blog/aplicacion-android-servicio-php/

    String txtLimit = et.getText().toString();

    if (!txtTitle.isEmpty() || !txtLimit.isEmpty()) { sb.append("?");

    if (!txtTitle.isEmpty()) { sb.append("t="); sb.append(URLEncoder.encode(txtTitle, "utf-8"));

    if(!txtLimit.isEmpty()) { sb.append("&r="); sb.append(txtLimit); }

    } else if(!txtLimit.isEmpty()) { sb.append("r="); sb.append(txtLimit); } }

    q.execute(sb.toString()); } catch(Exception e) { e.printStackTrace(); } }

    public void TaskCallback(ListaPeliculas result) { if (null != result) { if (0 != result.getPeliculaCount()) {

    // Guarda en la variable global de la aplicacin el listado resultante ((Peliculas)getApplicationContext()).lPeliculas = result;

    // Inicia una nueva pantalla donde mostrar el listado al usuario Intent i = new Intent(this, ResultsActivity.class); startActivity(i);

    } else { Toast.makeText(getApplicationContext(), "La bsqueda no devolvi ningn resultado.", Toast.LENGTH_LONG).show(); } } else { Toast.makeText(getApplicationContext(), "No fue posible recuperar resultados.", Toast.LENGTH_LONG).show(); } }

    }

    - La funcin sendQuery es la accin que se lleva a cabo al pulsar el botn Buscar. Segn los campos

    pgina 23 / 27

  • Aplicacin Android + Servicio PHPby SamuGG - http://samuel-granados.com/blog/aplicacion-android-servicio-php/

    introducidos, forma la URL que debe llamar a nuestro webservice PHP.

    En la lnea 59 ejecuta la tarea asncrona que implementamos en la clase QueryMovies y el cdigo sigue sucurso, ya que la tarea asncrona se est ejecutando de fondo, en otro hilo de ejecucin. Al terminar este otro hilo,la siguiente funcin ser ejecutada.

    - La funcin TaskCallback es ejecutada en cuanto la tarea asncrona termine y smplemente comprueba que sivienen resultados hay que abrir una nueva pantalla para mostrarlos.

    top

    La pantalla de resultados slamente contiene el control para el listado: un listview, cuyo layout ser:

    Cada elemento del listado aparecer en pantalla cmo lo configuremos en su propio layout tambin. Acontinuacin pongo el layout de un elemento del listado:

    Slo hay un TextView para poner el ttulo de la pelcula. Suficiente para nuestras necesidades.Si quisiramos que a la izquierda del ttulo de cada elemento de la lista, se mostrara la cartula, slo debemos

    pgina 24 / 27

  • Aplicacin Android + Servicio PHPby SamuGG - http://samuel-granados.com/blog/aplicacion-android-servicio-php/

    modificar el layout listado_item.xml aadiendo un ImageView al cual habr que darle la direccin de la imagen alformar el listado.

    Bueno, con esto ya tenemos clara la apariencia de la pantalla; a continuacin tenemos el cdigo fuente de lamisma:

    package peliculas;

    import java.util.List;

    import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.view.Menu;import android.view.MenuItem;import android.widget.ListView;import android.widget.Toast;import peliculas.ListaPeliculas;

    public class ResultsActivity extends Activity {

    private List list;

    @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_listado);

    list = ((Peliculas)getApplicationContext()).lPeliculas.getMovieList();

    ListadoAdapter lad = new ListadoAdapter(this, android.R.layout.simple_list_item_1, list); ListView lv = (ListView)findViewById(R.id.lvListado); lv.setAdapter(lad); }

    }

    Al crear esta pantalla, coge la lista de pelculas de la variable global de la aplicacin y la conserva localmente ensu propia variable privada (lneas 16 y 23). Las tres lneas siguientes instancian el listado en base a la lista depelculas.

    En Android, un listview siempre se alimenta de un Adapter. Existen varios tipos. Sin entrar en ms detalle, elque ms nos conviene utilizar para nuestro ejemplo es el ArrayAdapter.

    Haremos una clase ArrayAdapter en nuestro directorio de clases res\peliculas. Cuando implementamos lasuper clase ArrayAdapter hacemos tambin la funcin getView() que es la que crea la visualizacin para cadaelemento del listview (listado).

    package peliculas;

    import java.util.List;

    pgina 25 / 27

  • Aplicacin Android + Servicio PHPby SamuGG - http://samuel-granados.com/blog/aplicacion-android-servicio-php/

    import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.ArrayAdapter;import android.widget.TextView;import peliculas.ListadoPeliculas;

    public class ListadoAdapter extends ArrayAdapter {

    public List list; private Context context;

    public ListadoAdapter(Context context, int textViewResourceId, List objects) { super(context, textViewResourceId, objects); this.list = objects; this.context = context; }

    @Override public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); View rowView = inflater.inflate(R.layout.listado_item, parent, false); TextView textView = (TextView) rowView.findViewById(R.id.listado_item_title);

    textView.setText(list.get(position).getTitulo());

    return rowView; }

    }

    El constructor recibe unos parmetros muy concretos:

    Context: La pantalla que instancia el adaptador.textViewResourceId: El identificador del control (View) que mostrar la informacin de cada elemento.Puedes pasar null o el identificador de algn control propio que hayas puesto en el layout.objects: La lista o array de elementos del listado.

    Lo interesante est en la funcin getView(); es la responsable de la visualizacin de cada elemento del listado.Como te habrs fijado, uno de sus parmetros es el ndice del elemento de nuestro array o lista de elementos.Este parmetro es position, as que cuando Android llame a esta funcin automticamente para visualizar elquinto elemento de nuestra lista de pelculas, simplemente coge dicho elemento de nuestra lista, coge tambin el TextView que hicimos en nuestro layout listado_item.xml y le asigna el ttulo del elemento pelcula. De igualmodo para cualquier otro elemento, es el propio Android el que llamar a esta funcin cuando lo necesite,pasando al parmetro position aqul que necesite visualizar.

    pgina 26 / 27

  • Aplicacin Android + Servicio PHPby SamuGG - http://samuel-granados.com/blog/aplicacion-android-servicio-php/

    Descargar cdigo fuente

    top

    Powered by TCPDF (www.tcpdf.org)

    pgina 27 / 27