PDA

Ver la versión completa : Ayuda con Jsoup y Android



neostalker
07/08/2015, 17:36
Buenas, estoy haciendo una pequeña aplicación para Android Wear y necesito parsear una web para extraer su contenido, pero estoy recibiendo una excepción que no sé a qué se debe cuando hago get.

Para ahorraros tiempo, os diré que mi aplicación tiene permiso para usar internet en el AndroidManifest.xml, así como el código relativo a la conexión a la web en una AsyncTask.

La traza que recibo es esta (al get le paso la siguiente ruta: http://lema.rae.es/drae/?val=hola):


java.net.UnknownHostException: Unable to resolve host "lema.rae.es": No address associated with hostname
at java.net.InetAddress.lookupHostByName(InetAddress. java:457)
at java.net.InetAddress.getAllByNameImpl(InetAddress. java:252)
at java.net.InetAddress.getAllByName(InetAddress.java :215)
at com.android.okhttp.HostResolver$1.getAllByName(Hos tResolver.java:29)
at com.android.okhttp.internal.http.RouteSelector.res etNextInetSocketAddress(RouteSelector.java:232)
at com.android.okhttp.internal.http.RouteSelector.nex t(RouteSelector.java:124)
at com.android.okhttp.internal.http.HttpEngine.connec t(HttpEngine.java:272)
at com.android.okhttp.internal.http.HttpEngine.sendRe quest(HttpEngine.java:211)
at com.android.okhttp.internal.http.HttpURLConnection Impl.execute(HttpURLConnectionImpl.java:382)
at com.android.okhttp.internal.http.HttpURLConnection Impl.connect(HttpURLConnectionImpl.java:106)
at org.jsoup.helper.HttpConnection$Response.execute(H ttpConnection.java:512)
at org.jsoup.helper.HttpConnection$Response.execute(H ttpConnection.java:493)
at org.jsoup.helper.HttpConnection.execute(HttpConnec tion.java:205)
at org.jsoup.helper.HttpConnection.get(HttpConnection .java:194)
at com.balder1984.myapp.tasks.RaeParserTask.doInBackg round(RaeParserTask.java:54)
at com.balder1984.myapp.tasks.RaeParserTask.doInBackg round(RaeParserTask.java:23)
at android.os.AsyncTask$2.call(AsyncTask.java:292)
at java.util.concurrent.FutureTask.run(FutureTask.jav a:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTas k.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker( ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
Caused by: android.system.GaiException: android_getaddrinfo failed: EAI_NODATA (No address associated with hostname)
at libcore.io.Posix.android_getaddrinfo(Native Method)
at libcore.io.ForwardingOs.android_getaddrinfo(Forwar dingOs.java:55)
at java.net.InetAddress.lookupHostByName(InetAddress. java:438)
************at java.net.InetAddress.getAllByNameImpl(InetAddress. java:252)
************at java.net.InetAddress.getAllByName(InetAddress.java :215)
************at com.android.okhttp.HostResolver$1.getAllByName(Hos tResolver.java:29)
************at com.android.okhttp.internal.http.RouteSelector.res etNextInetSocketAddress(RouteSelector.java:232)
************at com.android.okhttp.internal.http.RouteSelector.nex t(RouteSelector.java:124)
************at com.android.okhttp.internal.http.HttpEngine.connec t(HttpEngine.java:272)
************at com.android.okhttp.internal.http.HttpEngine.sendRe quest(HttpEngine.java:211)
************at com.android.okhttp.internal.http.HttpURLConnection Impl.execute(HttpURLConnectionImpl.java:382)
************at com.android.okhttp.internal.http.HttpURLConnection Impl.connect(HttpURLConnectionImpl.java:106)
************at org.jsoup.helper.HttpConnection$Response.execute(H ttpConnection.java:512)
************at org.jsoup.helper.HttpConnection$Response.execute(H ttpConnection.java:493)
************at org.jsoup.helper.HttpConnection.execute(HttpConnec tion.java:205)
************at org.jsoup.helper.HttpConnection.get(HttpConnection .java:194)
************at com.balder1984.myapp.tasks.RaeParserTask.doInBackg round(RaeParserTask.java:54)
************at com.balder1984.myapp.tasks.RaeParserTask.doInBackg round(RaeParserTask.java:23)
************at android.os.AsyncTask$2.call(AsyncTask.java:292)
************at java.util.concurrent.FutureTask.run(FutureTask.jav a:237)
************at android.os.AsyncTask$SerialExecutor$1.run(AsyncTas k.java:231)
************at java.util.concurrent.ThreadPoolExecutor.runWorker( ThreadPoolExecutor.java:1112)
************at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:587)
************at java.lang.Thread.run(Thread.java:818)


Sabéis a qué se puede deber?

^MiSaTo^
07/08/2015, 18:19
Necesitas el permiso de internet y el de Network_State en el manifest. Estos dos:



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


Tienes ambos?

neostalker
07/08/2015, 22:01
Necesitas el permiso de internet y el de Network_State en el manifest. Estos dos:



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


Tienes ambos?

Sí, tengo ambos :)

pakoito
07/08/2015, 22:31
Que yo recuerde el host unknown debería escupir el protocolo, mira a ver que tengas la ruta completa "http://lema.rae.es/loquesea"

Si no, checkea la wifi del móvil, que no estés detrás de un firewall o que no bloqueen los agents que no sean de navegador. ¿Qué estas usando para las requests? EDIT: java a pelo, meh.

-----Actualizado-----

EW EWE EW EW EWWWWW estás usando asynctasks.

-----Actualizado-----

Probando con un app mia, no escupe el protocolo. Lo normal es que si no es lo de misato, tengas algo más en el proxy de la wifi del movil.

-----Actualizado-----

Chusca en un app de pruebas usando Volley para network. He usando una JsonRequest porque ya lo tenía preparado y me dice que no sabe parsear etiquetas HTML, asi que llegar llega. Checkea la conexión del móvil.

JJdroid
08/08/2015, 01:13
prueba a ponerle a piñon la Ip -> 193.145.222.107 Para ver

^MiSaTo^
08/08/2015, 09:21
Si te sigue sin ir y no son problemas de conexión con el móvil, pon el código accesible para que lo podamos mirar

neostalker
08/08/2015, 11:43
Si te sigue sin ir y no son problemas de conexión con el móvil, pon el código accesible para que lo podamos mirar

Por la tarde, nada más tenga un rato, os pongo lo que tengo. De momento es muy poca cosa, un par de clases contando la MainActivity y nada más, así que se mira rápido :)

pakoito
08/08/2015, 12:21
Por la tarde, nada más tenga un rato, os pongo lo que tengo. De momento es muy poca cosa, un par de clases contando la MainActivity y nada más, así que se mira rápido :)
En Android Studio puedes publicar a github en un par de clicks.

neostalker
08/08/2015, 16:05
En Android Studio puedes publicar a github en un par de clicks.

Tendré que echarle un ojo cuando tenga algo más de tiempo. Entre tanto, aquí os dejo el código:

MainActivity


package com.balder1984.myapp;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Intent;
import android.os.Bundle;
import android.support.wearable.view.WatchViewStub;
import android.view.View;
import android.widget.ImageButton;
import android.widget.TextView;
import android.speech.RecognizerIntent;

import com.balder1984.myapp.tasks.RaeParserTask;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;

import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

public class MainActivity extends Activity {

private static final Logger LOGGER = Logger.getLogger(MainActivity.class.getCanonicalNa me() + " Logger");
private static final int SPEECH_REQUEST_CODE = 0;
private static final String CADENA_VACIA = "";
private TextView textoVersion;
private ImageButton botonBuscar;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final WatchViewStub stub = (WatchViewStub) this.findViewById(R.id.watch_view_stub);
stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
@Override
public void onLayoutInflated(WatchViewStub stub) {
MainActivity.this.textoVersion = (TextView) stub.findViewById(R.id.textoVersion);
MainActivity.this.botonBuscar = (ImageButton) stub.findViewById(R.id.botonBuscar);

MainActivity.this.botonBuscar.setOnClickListener(o nClickListenerBotonBuscar());
MainActivity.this.textoVersion.setText(R.string.te xto_version);
}
});
}

private View.OnClickListener onClickListenerBotonBuscar() {
return new View.OnClickListener() {
@Override
public void onClick(View v) {
MainActivity.this.reconocerVoz();
}
};
}

private void reconocerVoz() {
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MO DEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);

startActivityForResult(intent, SPEECH_REQUEST_CODE);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == SPEECH_REQUEST_CODE && resultCode == RESULT_OK) {
List<String> results = data.getStringArrayListExtra(
RecognizerIntent.EXTRA_RESULTS);
String busqueda = results.get(0);

if(CADENA_VACIA.equals(busqueda)) {
return;
}

String urlDrae = "http://lema.rae.es/drae/?val=" + busqueda.trim().toLowerCase();
System.err.println(urlDrae);

RaeParserTask parserTask = new RaeParserTask(this, urlDrae, busqueda);

parserTask.execute();
}
super.onActivityResult(requestCode, resultCode, data);
}
}



RaeParserTask


package com.balder1984.myapp.tasks;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.os.AsyncTask;

import com.balder1984.myapp.R;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

public class RaeParserTask extends AsyncTask<Void, Void, Void> {
private static Logger LOGGER = Logger.getLogger(RaeParserTask.class.getCanonicalN ame() + " Logger");

private Activity parent;
private ProgressDialog progressDialog;
private String url;
private String busqueda;

public RaeParserTask(Activity parent, String url, String busqueda) {
this.parent = parent;
this.url = url;
this.busqueda = busqueda;
}

private String getString(int resId) {
return this.parent.getString(resId);
}

@Override
protected void onPreExecute() {
super.onPreExecute();
this.progressDialog = new ProgressDialog(parent);
this.progressDialog.setTitle(getString(R.string.ti tulo_dialogo_espera));
this.progressDialog.setMessage(getString(R.string. mensaje_dialogo_espera));
this.progressDialog.setIndeterminate(false);
this.progressDialog.show();
}

@Override
protected Void doInBackground(Void... params) {
try {
Document pagina = Jsoup.connect(this.url).get();
Elements descripcion = pagina.select("meta[name=content]");

LOGGER.log(Level.INFO, descripcion.attr("content") + " " + this.busqueda);
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "No se ha podido conectar con el origen de datos:", e);
}
return null;
}

@Override
protected void onPostExecute(Void result) {
this.progressDialog.dismiss();
}
}


-----Actualizado-----

Y aquí lo que tengo en el AndroidManifest.



<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.balder1984.myapp" >

<uses-feature android:name="android.hardware.type.watch" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

<application
android:allowBackup="true"
android:icon="@mipmap/myapp_ico"
android:label="@string/app_name"
android:theme="@android:style/Theme.DeviceDefault" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>

^MiSaTo^
08/08/2015, 16:32
Estás usando el emulador? Si es así asegúrate que el emulador tiene red. Que a veces cuando estás por wifi se queda imbécil perdido. No se si sigue pasando eso a día de hoy pero a mi me ha pasado en su día.

neostalker
08/08/2015, 19:52
Estás usando el emulador? Si es así asegúrate que el emulador tiene red. Que a veces cuando estás por wifi se queda imbécil perdido. No se si sigue pasando eso a día de hoy pero a mi me ha pasado en su día.

Sí, estoy usando el emulador de momento :-P

Probaré a conectar el ordenador por cable, a ver si así.

pakoito
08/08/2015, 20:05
No uses nunca jamás el emulador bajo ningún concepto. El emulador es basura. El emulador es una pila de bugs que no sirven ni para unitest, hasta Google lo reconoce.

Las licencias personales de Genymotion (emulador decente) son gratis. Todos los desarrolladores con los que he hablado o tienen una o apenas usan el emulador.

^MiSaTo^
08/08/2015, 20:12
No uses nunca jamás el emulador bajo ningún concepto. El emulador es basura. El emulador es una pila de bugs que no sirven ni para unitest, hasta Google lo reconoce.

Las licencias personales de Genymotion (emulador decente) son gratis. Todos los desarrolladores con los que he hablado o tienen una o apenas usan el emulador.

Y eso que el de ahora es bastante más decente que el que había hace 2-3 años cuando lo usaba yo xDDD
Pero sí, yo siempre he desarrollado directamente en los móviles. De ahí que mi casa pareciese un Phone House cuando era autónoma

pakoito
08/08/2015, 20:51
El nuevo emulador de x86 va más rápido, que no mejor. Es una proof of concept que montó Intel para seguir empujando los portátiles y tabletas Android de ARM a x86.

neostalker
08/08/2015, 21:26
Entonces probaré directamente sobre mi Moto 360, si el emulador vale tan poco la pena, mejor el sistema original.

chipan
08/08/2015, 21:42
Entonces probaré directamente sobre mi Moto 360, si el emulador vale tan poco la pena, mejor el sistema original.

Hazlo! es mas engorroso pero al menos te sirve para testear de verdad.

^MiSaTo^
08/08/2015, 22:32
Hazlo! es mas engorroso pero al menos te sirve para testear de verdad.

Hombre, si por engorroso entiendes enchufarle por cable al ordenador...

chipan
08/08/2015, 22:44
Hombre, si por engorroso entiendes enchufarle por cable al ordenador...

Pues si y mas si es tu único teléfono y te llegan mensajes, mails y llamadas mientras trasteas con él.

^MiSaTo^
08/08/2015, 23:29
Pues si y mas si es tu único teléfono y te llegan mensajes, mails y llamadas mientras trasteas con él.

Mucho mejor para testear bien la apli y ver si has tenido en cuenta bien eso :)
No se, no me parece ningún engorro, al contrario. Y bueno mejor no hablamos entonces de probar en varios terminales distintos no? xD

chipan
09/08/2015, 00:35
Mucho mejor para testear bien la apli y ver si has tenido en cuenta bien eso :)
No se, no me parece ningún engorro, al contrario. Y bueno mejor no hablamos entonces de probar en varios terminales distintos no? xD

Hombre, es mil veces más efectivo testear en el telefono, pero tambien es algo mas engorroso por tener que tener un teléfono enchufado y configurado, no es un gran engorro, pero un emulador perfecto sería casi lo ideal, por ejemplo, podrías probar todas las resoluciones de pantalla sin liarte a enchufar 20 terminales. Tampoco te voy a discutir mucho, tu vives de esto y evidentemente sabes lo que resulta más práctico mientras que yo no es que haya desarrollado mucho para android, un par de apps chorras para probar y ya.

pakoito
09/08/2015, 01:19
Se pueden configurar los teléfonos para testear y debuggear por wifi, no es complicado.

Para 20 cacharros, hay un servidor web opensource que controla arrays de usbs, pero eso es más ya en la oficina. Y google y otras compañías están sacando sus propios servicios de test time en granjas de cacharros, pagando por minuto.