Cómo obtener páginas web desde Android

Hoy en día la opción más adecuada para consumir información ofrecida por algunas páginas webs, es hacer uso de sus APIs, basadas en servicios web o REST. Sin embargo, hay ocasiones en las que esto no es posible, por lo que no queda otra opción que hacerlo a la antigua usanza, obteniendo el html completo de la página web y extrayendo los fragmentos que se necesitan. En este artículo explico dos formas diferentes de obtener el html de las páginas web desde Android, la primera es mediante el uso de HttpURLConnection y la segunda utilizando el API de browser incluido en Android, HttpClient.

Obtención de páginas web mediante HttpURLConnection

A continuación se meustra el código necesario para obtener el html de una página web con HttpURLConnection.

HttpURLConnection con = null;
URL url;
String html;
try {
   url = new URL("http://www.example.com/");
   con = (HttpURLConnection) url.openConnection();
   con.setReadTimeout(10000 /* milliseconds */);
   con.setConnectTimeout(15000 /* milliseconds */);
   con.setRequestMethod("GET");
   con.setDoInput(true);
   con.addRequestProperty("Referer", "http://www.referrer.example.com");
   con.connect();
 
   html = readFromBuffer(
      new BufferedReader(
         new InputStreamReader(con.getInputStream())));
 
}catch (IOException e) {
   e.printStackTrace();
   // tratar excepción!!!
}
return html;

A partir de una url, en este caso «http://www.example.com», se crea una conexión HTTP representada como una instancia de la clase HttpURLConnection. A esta clase se le proporciona la información que se requiera para hacer la petición, en este caso los timeout, el método de petición (GET), y la página referer, que representa la página desde la que llega el usuario. Es posible realizar también peticiones POST proporcionando los parámetros correspondientes.

Aunque sencillo, hay que tener en cuenta que en muchas ocasiones hay que conocer bien el protocolo HTTP para utilizar correctamente esta clase, ya que es necesario indicar manualmente toda la información que hay que enviar al servidor. Así, por ejemplo, si queremos mantener una cookie entre varias peticiones, tendremos que preocuparnos de coger su String en la primera petición, y pasarlo como parámetro en cada una de las siguientes. El siguiente método nos permite abstraernos de estos inconvenientes.

Obtención de páginas web mediante HttpClient

A continuación se meustra el código necesario para obtener el html de una página web con HttpClient.

HttpURLConnection con = null;
URL url;
String html;
try {
 
   HttpGet httpGet = new HttpGet("http://www.example.com/");
   HttpClient httpclient = new DefaultHttpClient();
   HttpResponse response = httpclient.execute(httpGet);
 
   html = readFromBuffer(
      new BufferedReader(
         new InputStreamReader(response.getEntity().getContent())));
 
}catch (IOException e) {
   e.printStackTrace();
   // tratar excepción!!!
}
return html;

Como puede verse el código es más sencillo que el anterior, ya que es la propia clase la que se encarga de meter todos los parámetros necesarios para la conexión de forma automática, aunque también es posible configurarlos manualmente. Sin embargo, no es necesario configurar todas esta información en cada petición. A continuación se muestra un ejemplo (muy simplificado) en el que se utiliza esta clase para realizar el login en una página web y se solicita a continuación una página de la parte privada. Puede verse que la clase se encarga de llevar la gestión de la cookie de autenticación, sin que tengamos que preocuparnos de gestionarla manualmente.

 
HttpClient httpclient = new DefaultHttpClient();
 
String html;
 
try{
   HttpPost httpost = new HttpPost("https://www.example.com/login");
 
   List<NameValuePair> nvps = new ArrayList <NameValuePair>();
   nvps.add(new BasicNameValuePair("user", "pepito"));
   nvps.add(new BasicNameValuePair("password","12345678"));
 
   httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
   HttpResponse response = httpclient.execute(httpost);
   HttpEntity entity = response.getEntity();
   html = readFromBuffer(
      new BufferedReader(
         new InputStreamReader(entity.getContent(),"UTF-8")));
} catch(Exception e){
   e.printStackTrace();
   // Tratar excepción!!!
}
 
// habría que comprobar, analizando "html", que el login ha sido correcto
// suponemos que es así, por lo que se puede solicitar la página 
// de la zona privada
 
try{
   HttpGet httpget = new HttpGet("https://www.example.com/private/miperfil");
   HttpResponse response = httpclient.execute(httpget);
   HttpEntity entity = response.getEntity();
   html = readFromBuffer(
      new BufferedReader(
         new InputStreamReader(entity.getContent(),"UTF-8")));
 
} catch(Exception e){
   e.printStackTrace();
   // Tratar excepción!!!
}

Lectura desde un buffer

En los ejemplos anteriores se hace uso de un método que dado un buffer de lectura devuelve su contenido como un string. A continuación se indica el código de este método.

private String readFromBuffer(BufferedReader br){
   StringBuilder text = new StringBuilder();
   try{
      String line;
      while ((line = br.readLine()) != null) {
         text.append(line);
         text.append("\n");
      } 
   } catch (IOException e) { 
      e.printStackTrace();
      // tratar excepción!!!
   }
   return text.toString();
}
Twitter Digg Delicious Stumbleupon Technorati Facebook Email

3 Respuestas para “Cómo obtener páginas web desde Android”

  1. Ejemplo, obtener la HTML de un xat, se puede? con visual basic creo :S

  2. hola, este ejemplo serviria para por ejemplo: acceder a una webcam y pasarle los parametros usuario y contraseña?.

  3. Hola

    Al ejecutar:

    HttpResponse response = httpclient.execute(httpget);

    Me está dando el siguiente error:

    Thread [ main] (Suspended (exception NetworkOnMainThreadException))
    DefaultRequestDirector.execute(HttpHost, HttpRequest, HttpContext) line: 531
    DefaultHttpClient(AbstractHttpClient).execute(HttpHost, HttpRequest, HttpContext) line: 555
    DefaultHttpClient(AbstractHttpClient).execute(HttpUriRequest, HttpContext) line: 487
    DefaultHttpClient(AbstractHttpClient).execute(HttpUriRequest) line: 465
    PruebaInternetActivity.postData() line: 77
    PruebaInternetActivity$1.onClick(View) line: 55
    Button(View).performClick() line: 3511
    View$PerformClick.run() line: 14105
    ViewRootImpl(Handler).handleCallback(Message) line: 605
    ViewRootImpl(Handler).dispatchMessage(Message) line: 92
    Looper.loop() line: 137
    ActivityThread.main(String[]) line: 4424
    Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method]
    Method.invoke(Object, Object…) line: 511
    ZygoteInit$MethodAndArgsCaller.run() line: 784
    ZygoteInit.main(String[]) line: 551
    NativeStart.main(String[]) line: not available [native method]

    ¿Que se me pasa por alto?
    Gracias