PDA

Ver la Versión Completa : Problema con servicio web


androizado
24/03/13, 11:24:49
Hola compañeros mi problema es que he creado con PHP un servicio web, el cual me sale perfecto y codificado en JSON, vale hasta ahí esta todo bien, mi problema viene a la hora de crear mi aplicación, para leer esos datos que recibo en JSON y listarlos en una lista.

Explico tengo un layout llamado, main.xml, en el tengo una ListView, y una clase llamada Peliculas extendida en Activity. Os pongo el codigo:

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONObject;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class Peliculas extends Activity{

private ListView lstPeliculas;

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

lstPeliculas = (ListView)findViewById(R.id.lstPeliculas);

HttpClient httpClient = new DefaultHttpClient();
HttpGet url = new HttpGet("h htp://192.168.0.11/android/libros/service.libros.php");

url.setHeader("content-type", "application/json");

try{
HttpResponse resp = httpClient.execute(url);
String respStr = EntityUtils.toString(resp.getEntity());

JSONArray respJSON = new JSONArray(respStr);

String[] peliculas = new String[respJSON.length()];

for(int i=0; i<respJSON.length(); i++){
JSONObject obj = respJSON.getJSONObject(i);

String titLib = obj.getString("libro");
String isbnLib = obj.getString("isbn");

peliculas[i] = titLib + " - " + isbnLib;
}

ArrayAdapter<String> adaptador =
new ArrayAdapter<String>(Peliculas.this,
android.R.layout.simple_list_item_1, peliculas);

lstPeliculas.setAdapter(adaptador);
}
catch(Exception ex){
Log.e("ServicioWeb","Error!", ex);
}
}
}El problema me viene al ejecutar la aplicación que no me sale nada, donde estoy errando?

NOTA: no es que me haya equivocado en la url ;) lo puesto así a posta para que me dejara postar.

kriogeN
24/03/13, 11:48:36
En primer lugar, no es correcto hacer llamadas HTTP en el UI Thread, tienes que crear un Thread (o mejor aún, un AsyncTask) para hacerlas. Te está funcionando porque estás compilando para Android 2.3 o inferior, si compilases para Android 4.0 no te funcionaría.

En segundo lugar, doy por supuesto que la respuesta contiene datos, y por tanto peliculas[] se rellena (Esto puedes comprobarlo poniendo un punto de interrupción justo después del for). Quitado de esto, lo único que se me ocurre es que le hagas al Adapter un NotifyDataSetChanged justo después de asignarlo, aunque teóricamente la primera vez que asignas el setAdapter debería ser implícito.

androizado
24/03/13, 12:51:27
Gracias de antemano por rápida la respuesta, te comento estoy un poco verde en este tema, me explico, en servicio web me retorna lo siguiente:

{ "libros" : [ { "id" : 1, "libro": "Don Quijote de la Mancha", "isbn": "978-84-8427-800-9" } , { "id" : 2, "libro": "La Celestina", "isbn": "978-84-87876-39-4 " } , { "id" : 3, "libro": "El esperpento", "isbn": "978-84-85178-27-8" } , { "id" : 4, "libro": "Manolito Gafotas", "isbn": "978-84-204-5807-6" } ] } yo pienso que el array peliculas se rellena con los datos de los distintos libros.

Querría probar el AsyncTask pero opte por no usarlo porque no super sacarlo adelante, si me pudieras poner el código de tal cual quedaría bien hecho te lo agradecería, porque usando el AsyncTask como te dije me volví un tanto loco, a si que si no es mucho problema y ayudarme un poquito en el código te lo agradecería mucho kriogeN.

:-):-):-)

kriogeN
24/03/13, 14:56:54
Como te digo hay que ir por pasos.

¿El array se rellena bien? Como te digo puedes comprobarlo poniendo un punto de interrupción justo después del for.

androizado
24/03/13, 15:27:40
buenas compañero perdón por mi latazo, soy principiante en este lenguaje, y ok pongo una interrucción como esta:
Thread.sleep(4000);

pero como se si esta relleno el array??

Edito: no sabia que podía poner un System.out.... no al parecer no rellena el array :(

he hecho:
System.out.println(peliculas);
Thread.sleep(4000);

androizado
24/03/13, 17:48:55
kriogeN bien logre lo que me dijiste hacerlo creando AsyncTask, antes de seguir comentando mi siguiente problema, GRACIAS POR EL CONSEJO DE USAR ASYNCTASK, pero mi problema es que sigo sin lograr traer los datos del servicio web creado en PHP que son estos:

{ "libros" : [ { "id" : 1, "libro": "Don Quijote de la Mancha", "isbn": "978-84-8427-800-9" } , { "id" : 2, "libro": "La Celestina", "isbn": "978-84-87876-39-4 " } , { "id" : 3, "libro": "El esperpento", "isbn": "978-84-85178-27-8" } , { "id" : 4, "libro": "Manolito Gafotas", "isbn": "978-84-204-5807-6" } ] }

A ver si alguien me podría echar una manilla con el código a poner en el metodo doInBackground(), esto es lo que estoy haciendo:

@Override
protected Boolean doInBackground(Void... params) {

for(int i=1; i<=10; i++) {
tareaLarga();
publishProgress(i*10);
}
HttpResponse resp = httpClient.execute(url);
String respStr = EntityUtils.toString(resp.getEntity());

JSONArray respJSON = new JSONArray(respStr);

String[] peliculas = new String[respJSON.length()];

for(int i=0; i<respJSON.length(); i++){
JSONObject obj = respJSON.getJSONObject(i);

String titLib = obj.getString("libro");
String isbnLib = obj.getString("isbn");

peliculas[i] = titLib + " - " + isbnLib;
}

ArrayAdapter<String> adaptador =
new ArrayAdapter<String>(Peliculas.this,
android.R.layout.simple_list_item_1, peliculas);

lstPeliculas.setAdapter(adaptador);
return true;
}

y en el metodo onCreate():

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

listView1 = (ListView)findViewById(R.id.listView1);

HttpClient httpClient = new DefaultHttpClient();
HttpGet url = new HttpGet("http://192.168.0.11/android/libros/service.libros.php");

url.setHeader("content-type", "application/json");

pDialog = new ProgressDialog(MainActivity.this);
pDialog.setProgressStyle(ProgressDialog.STYLE_SPIN NER);
pDialog.setMessage("Actualizando datos...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();

tarea2 = new MiTareaAsincronaDialog();
tarea2.execute();
}


Como siempre GRACIAS DE ANTEMANO por las respuestas :-):-):-)

set92
24/03/13, 18:16:58
Yo estoy teniendo que hacer algo parecido para un proyecto y estoy usando esta libreria http://loopj.com/android-async-http/ que ya tiene bastantes metodos y no tienes que andar creando otros hilos para poder ejecutar, y ahora tengo que encontrar un buen parser de JSON para cojer los distintos valores de la url porque lo intente hacer haciendo substrings de la URL pero el chico que me esta enseñando como hacer las cosas y asi me ha dicho que eso no se hace asi y que buscara un buen parser de JSON, seguramente siga alguno de estos tutoriales http://www.androidhive.info/2012/01/android-json-parsing-tutorial/ o http://androcode.es/2012/05/parseando-json-en-android/

Y luego el uso de loopj tienes ejemplo en la web que te he pasado pero basicamente es
AsyncHttpClient client = new AsyncHttpClient();
client.get("http://www.google.com", new AsyncHttpResponseHandler() {
@Override
public void onSuccess(String response) {
System.out.println(response);
}
});

Y luego en response recibes el JSON o los datos que quieras. Lo unico si tienes que mandar unos parametros o logearte en el server tendrias que usar
RequestParams params = new RequestParams();
params.put("key", "value");
params.put("more", "data");

y para logearte
client.setBasicAuth("username","password/token");

Igual con eso consigues hacerlo mas facil, con las librerias de android por defecto no las he usado nunca osea no te puedo echar una mano, sorry.

kriogeN
24/03/13, 18:20:28
No estoy muy seguro de que el System.out te muestre algo por la consola, en todo caso tendrías que hacer un Log.d. Cuando hablo de punto de interrupción no me refiero a que hagas una pausa en el código, me refiero a que con el Eclipse pongan un punto donde el código se para y ejecutes en modo depuración. Con esto podrás observar el contenido de las variables.

Si no sabes de que te estoy hablando, quizás deberías empezar con algún tutorial básico de Android en Eclipse. Como yo siempre digo, tan importante como saber programar bien es saber depurar bien.

EDITO: No conocía esa librería set92, me habría venido bien hacer 1 par de meses, que precisamente programé una librería para hacer eso mismo, obtener respuestas asíncronas en el UI Thread de un AsyncTask que hace una petición HTTP.

mariancm
24/03/13, 19:17:21
El System.out imprime en el logcat con el tag System.out

Por que no utilizas una librería para parsear el Json, Gson de Google esta bastante bien y es fácil de utilzar

set92
24/03/13, 19:30:58
Osea marian mejor que hacerlo con las funciones/librerias que vienen ya con android es mejor usar GSON o Jackson? Me imagino que porque sera mas facil y tendra mas potencia?
He visto este tutorial por si ha alguien les interesa http://www.adictosaltrabajo.com/tutoriales/tutoriales.php?pagina=GsonJavaJSON

androizado
24/03/13, 19:32:01
Gracias por la respuestas.

kriogeN es la primera vez que estoy haciendo una app con este lenguaje y creo que si he de aprender a depurar bien el código, me aconsejas una tutorial bueno para Eclipse? Es la primera vez que también trabajo con este programa.

El System.out no me daba salida ni me mostraba nada, ya entendí lo de el punto de interrupción, pero me remito a lo de antes es la primera vez que uso este programa y si debería leer un poco sobre el para programar mejor.

En cuanto a la librería de set92, muchas gracías la probaré.

set92
24/03/13, 19:47:34
Tutoriales de eclipse tardan un rato en enseñarte cosas y tampoco he visto asi ninguno bueno, aun asi los puntos de parada y la depuracion en general en android no es que sea mi favorita http://www.youtube.com/watch?v=V-jfcL1K5BU ahi tendrias como se hace con cualquier codigo de java, para android tienes mas los Log.e o Log.d.... http://www.inforjmr.es/?p=172 que tienes tambien otro tuto en esa pagina con los breakpoints, aun asi a mi no me termina de convencer ninguno de los dos metodos, normalmente cuando me falla algo me aparece en el LogCat una parrafada roja, y ahi miro cual dice que es el error y en todas las lineas te dice en que linea de que archivo esta fallando, osea miro en que archivos mios esta fallando y que linea, y miro haber que puede ser y porque.

Lo del system.out(syso para acortar) si que te lo muestra en el logcat, y si quieres puedes hacer un filtro que solo te muestre los mensajes que saques tu por el syso, y asi no tienes todos los demas mensajes del movil/emulador.

Yo creo que siempre que cojes un IDE nuevo es bueno customizarlo y probar todas sus cosillas, por ejemplo los atajos que mas vayas a usar como el control espacio que te muestra todos los metodos que puedes usar, tener la ultima version actualizada del eclipse desde Check for Updates en Help, mirar si quieres activarle el git para tener una copia de respaldo de lo que estes haciendo...etc etc, luego tambien tienes el control shift O que te ordena y limpia los imports, el control shift F creo que era que te indexa y te pone el codigo como debe, luego hay otra opcion que te pone todo el codigo hasta X caracteres que tu le hayas dicho, asi que si le dices que tus lineas son como maximo de largo de 117 caracteres, al darle a esa opcion te va recortando las lineas y asi.

androizado
24/03/13, 20:02:48
Muchas gracias compañero (set92) por el tuto, si tengo que ponerme las pilas, la verdad que sigo lo que tu dices cuando sale el subrayado en rojo es mirar que te dice y corregir, por eso no me habia puesto a mirar lo de depurar, pero de todas maneras si hay que ponerse las pilas con Eclipse porque lo veo un IDE de lo mejorcito :)

androizado
24/03/13, 22:44:43
Bueno tras una tarde de trabajo, pufff lo consegui muchisimas gracias a todos los que me habeis ayudado con los tutos y demas consejos se agradece :)