Bienvenidos sean a este post, hoy veremos como acceder a un servicio web por medio de REST porque como dijimos antes para hacerlo por medio de SOAP es mas complejo y Android no dispone de ninguna libreria nativa para manipularlo. Para nuestro siguiente ejemplo deberemos usar la Books API de Google, la version vieja que nos devuelve la respuesta en formato XML, en cambio la version nueva devuelve el resultado en JSON y no es el formato que estamos estudiando ahora pero antes de crear nuestra app veremos algunos pasos previos, primero vayamos a la url de busqueda:

http://books.google.com/books/feeds/volumes?q=Jesus+tomas

Si lo ejecutan obtendra un resultado similar a este:

<?xml version='1.0' encoding='UTF-8'?&gt;<feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:gbs='http://schemas.google.com/books/2008' xmlns:gd='http://schemas.google.com/g/2005' xmlns:batch='http://schemas.google.com/gdata/batch' xmlns:dc='http://purl.org/dc/terms'&gt;<id&gt;http://www.google.com/books/feeds/volumes</id&gt;<updated&gt;2019-07-05T15:24:28.000Z</updated&gt;<category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/books/2008#volume'/&gt;<title type='text'&gt;Search results for Jesus tomas</title&gt;<link rel='alternate' type='text/html' href='http://www.google.com'/&gt;<link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://www.google.com/books/feeds/volumes'/&gt;<link rel='self' type='application/atom+xml' href='http://www.google.com/books/feeds/volumes?q=Jesus+tomas'/&gt;<link rel='next' type='application/atom+xml' href='http://www.google.com/books/feeds/volumes?q=Jesus+tomas&amp;start-index=11&amp;max-results=10'/&gt;<author&gt;<name&gt;Google Books Search</name&gt;<uri&gt;http://www.google.com</uri&gt;</author&gt;<generator version='beta'&gt;Google Book Search data API</generator&gt;<openSearch:totalResults&gt;1381</openSearch:totalResults&gt;<openSearch:startIndex&gt;1</openSearch:startIndex&gt;

Esto es solo una parte de la pagina que nos devuelve pero es para ver como es el codigo XML, de esta pagina nosotros vamos a necesitar un solo dato el cual es totalResults donde nos dara el valor de las coincidencias con nuestra busqueda, para la busqueda que hicimos de prueba el tag necesario seria este:

<openSearch:totalResults>1381</openSearch:totalResults>

Para este caso haremos una nueva aplicacion con Android Studio con las siguientes caracteristicas:

  • Application NameServicioWebLibros
  • Domain Companyexample.org
  • API SDK Minimum14
  • Add an ActivityEmpty Activity
  • Activity NameMainActivity
  • Layout Nameactivity_main

Una vez creada nuestra nueva aplicacion modificaremos el layout, para ello abriremos el archivo activity_main.xml y reemplazaremos su codigo con el siguiente:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <EditText
        android:id="@+id/EditText01"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Libro o Autor a buscar" />

    <Button
        android:id="@+id/Button01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="Buscar"
        android:text="Buscar libros" />

    <TextView
        android:id="@+id/TextView01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="8pt" />

</LinearLayout>

Este layout es bien simple, tendremos un EditText para ingresar nuestro texto a buscar, un boton para realizar nuestra busqueda y TextView para mostrar nuestro resultado, nuestra siguiente modificacion sera para la clase MainActivity con el siguiente codigo:

package org.example.servicioweblibros;

import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.StrictMode;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

import java.net.URL;
import java.net.URLEncoder;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

public class MainActivity extends AppCompatActivity {

    private EditText entrada;
    private TextView salida;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        entrada=(EditText) findViewById(R.id.EditText01);
        salida=(TextView) findViewById(R.id.TextView01);
        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy
                .Builder().permitNetwork().build());
    }

    public void Buscar(View view){
        String palabras = entrada.getText().toString();
        salida.append(palabras + " -- ");
        new BuscarGoogle().execute(palabras);
    }

    String resultadosSW(String palabras) throws Exception{
        URL url = new URL("http://books.google.com/books/feeds/volumes?q=\""
                + URLEncoder.encode(palabras,"UTF-8") + "\"");
        SAXParserFactory fabrica = SAXParserFactory.newInstance();
        SAXParser parser = fabrica.newSAXParser();
        XMLReader lector = parser.getXMLReader();
        ManejadorXML manejadorXML = new ManejadorXML();
        lector.setContentHandler(manejadorXML);
        lector.parse(new InputSource(url.openStream()));
        return manejadorXML.getTotalResults();
    }

    class BuscarGoogle extends AsyncTask<String, Void, String> {
        private ProgressDialog progreso;

        @Override
        protected void onPreExecute(){
            progreso = new ProgressDialog(MainActivity.this);
            progreso.setProgressStyle(ProgressDialog.STYLE_SPINNER);
            progreso.setMessage("Accediendo a Google...");
            progreso.setCancelable(false);
            progreso.show();
        }

        @Override
        protected String doInBackground(String... palabras){
            try{
                return resultadosSW(palabras[0]);
            }
            catch (Exception e){
                cancel(true);
                Log.e("HTTP", e.getMessage(), e);
                return null;
            }
        }

        @Override
        protected void onPostExecute(String res){
            progreso.dismiss();
            salida.append(res + "\n");
        }

        @Override
        protected void onCancelled(){
            progreso.dismiss();
            salida.append("Error al conectarlo.\n");
        }
    }

    public class ManejadorXML extends DefaultHandler{

        private String totalResults;
        private StringBuilder cadena = new StringBuilder();

        public String getTotalResults(){
            return totalResults;
        }

        @Override
        public void startElement(String uri, String nombreLocal,
                                 String nombreCualif,
                                 Attributes atributos)
                throws SAXException{
            cadena.setLength(0);
        }

        @Override
        public void characters(char ch[], int comienzo, int lon){
            cadena.append(ch,comienzo,lon);
        }

        @Override
        public void endElement(String uri, String nombreLocal,
                               String nombreCualif) throws SAXException{
            if(nombreLocal.equals("totalResults")){
                totalResults = cadena.toString();
            }
        }
    }
}

Lo primero de nuestro codigo sera la creacion de dos objetos llamados entrada y salida de tipo EditText y TextView respectivamente, estos dos objetos serviran para crear un enlace entre el codigo Java y el layout. El metodo onCreate() no solamente carga el layout sino a su vez le asigna los elementos del layout a los dos objetos antes creados, por ultimo tendremos un StrictMode, este metodo esta simplemente para indicarle al programador ante un posible fallo como al utilizar la conexion por medio del hilo principal pero en este caso no le haremos caso.

En nuestro siguiente metodo, Buscar(), tendremos primero una variable llamada palabras a la cual le asignaremos el texto contenido en entrada, despues le asignaremos un texto y por ultimo llamaremos al metodo execute() de la clase BuscarGoogle, de la cual hablaremos mas adelante, y enviandole el valor almacenado en palabras.

En el metodo resultadosSW(), primero crearemos un objeto llamado url del tipo URL y en esta asignaremos la url antes descripta con la diferencia de que en lugar de enviar una palabra enviamos el contenido almacenado en palabras, despues usaremos a SAX, para una mejor explicacion sobre estas clases les sugiero este post y este otro, primero crearemos a fabrica, el cual luego nos permitira crear un parser, este objeto nos permitira crear a lector, el cual nos permitira leer el XML. Nuestro siguiente objeto llamado manejadorXML del tipo ManejadorXML, el cual veremos mas adelante, el metodo setContentHandler sera el encargado de manejar a lector por medio de manejadorXML, despues utilizaremos parse para obtener la informacion solicitada, y por ultimo devolvemos el valor del metodo getTotalResults de la clase ManejadorXML.

La clase BuscarGoogle es exactamente igual a cuando la explicamos en este post, donde cambiamos solamente esta linea:

return resultadoGoogle(palabras[0]);

Por esta otra:

return resultadosSW(palabras[0]);

Es decir que utilice este metodo en lugar del otro, despues el resto funciona de la misma forma, por ultimo hablaremos sobre la nueva clase ManejadorXML.

Esta clase sera la encargada de manejar nuestro archivo XML, en esta crearemos un variable llamada totalResults de tipo String y por medio de StringBuilders crearemos un objeto llamada cadena, luego tendremos un metodo llamado getTotalResults() el cual se encargara de devolver el valor almacenado en totalResults, despues tres elementos que redefiniremos:

  • startElement(), basicamente sera el encargado de iniciar a nuestra variable llamada cadena
  • characters(), esta sera la encargada de agregar caracter por caracter en cadena
  • endElement(), chequea que si nombreLocal recibido sea igual a “totalResults” y en caso de ser cierto asigna el valor de cadena a totalResults

Con esto podemos decir que se logro obtener el dato que necesitamos extraer, una ultima modificacion que nos falta es en el AndroidManifest.xml donde agregaremos la siguiente linea:

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

La cual nos permitira acceder a internet por medio de nuestro dispositivo, podemos probar compilando y ejecutando nuestra app en un emulador o en un dispositivo como se ve en el siguiente video

Como pueden ver en el video obtenemos el dato limpio cuando ejecutamos la busqueda a diferencia de cuando vimos el ejemplo de http en este post.

En resumen, hoy hemos visto como obtener informacion de la API Books de Google, trabajar con SAX y Android, como manejar nuestra conexion por medio de AsyncTask, espero les haya sido util sigueme en Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Anuncios