En el artículo anterior dedicado a los servicios web REST hemos visto cómo crear fácilmente un servicio de este tipo utilizando el framework ASP.NET MVC 3. En esta segunda parte vamos a describir cómo podemos construir una aplicación Android que acceda a este servicio web REST.
Y tal como hicimos en el caso de SOAP, vamos a crear una aplicación de ejemplo que llame a las distintas funciones de nuestro servicio web. En este caso la aplicación se compondrá de 5 botones, uno por cada una de las acciones que hemos implementado en el servicio web (insertar, actualizar, eliminar, recuperar un cliente, y listar todos los clientes).
A diferencia del caso de SOAP, en esta ocasión no vamos a utilizar ninguna librería externa para acceder al servicio web, ya que Android incluye todo lo necesario para realizar la conexión y llamada a los métodos del servicio, y tratamiento de resultados en formato JSON.
Como ya hemos comentado, al trabajar con servicios web de tipo REST, las llamadas al servicio no se harán a través de una única URL, sino que se determinará la acción a realizar según la URL accedida y la acción HTTP utilizada para realizar la petición (GET, POST, PUT o DELETE). En los siguientes apartados veremos uno a uno la implementación de estos botones.
Insertar un nuevo cliente
Como ya comentamos en el artículo anterior, la inserción de un nuevo cliente la realizaremos a través de la siguiente URL:
http://10.0.2.2:2731/Api/Clientes/Cliente
Utilizaremos la acción http POST y tendremos que incluir en la petición un objeto en formato JSON que contenga los datos del nuevo cliente (tan sólo Nombre y Teléfono, ya que el ID se calculará automáticamente). El formato de este objeto de entrada será análogo al siguiente:
{Nombre:»cccc», Telefono:12345678}
Pues bien, para conseguir esto comenzaremos por crear un nuevo objeto HttpClient, que será el encargado de realizar la comunicación HTTP con el servidor a partir de los datos que nosotros le proporcionemos. Tras esto crearemos la petición POST creando un nuevo objeto HttpPost e indicando la URL de llamada al servicio. Modificaremos mediante setHeader() el atributo http content-type para indicar que el formato de los datos que utilizaremos en la comunicación, que como ya indicamos será JSON (cuyo MIME-Type correspondiente es «application/json«).
HttpClient httpClient = new DefaultHttpClient(); HttpPost post = new HttpPost("http://10.0.2.2:2731/Api/Clientes/Cliente"); post.setHeader("content-type", "application/json");
El siguiente paso será crear el objeto JSON a incluir con la petición, que deberá contener los datos del nuevo cliente a insertar. Para ello creamos un nuevo objeto JSONObject y le añadimos mediante el método put() los dos atributos necesarios (nombre y teléfono) con sus valores correspondientes, que los obtenemos de los cuadros de texto de la interfaz, llamados txtNombre y txtTelefono.
Por último asociaremos este objeto JSON a nuestra petición HTTP convirtiéndolo primero al tipo StringEntity e incluyéndolo finalmente en la petición mediante el método setEntity().
//Construimos el objeto cliente en formato JSON JSONObject dato = new JSONObject(); dato.put("Nombre", txtNombre.getText().toString()); dato.put("Telefono", Integer.parseInt(txtTelefono.getText().toString())); StringEntity entity = new StringEntity(dato.toString()); post.setEntity(entity);
Una vez creada nuestra petición HTTP y asociado el dato de entrada, tan sólo nos queda realizar la llamada al servicio mediante el método execute() del objeto HttpClient y recuperar el resultado mediante getEntity(). Este resultado lo recibimos en forma de objeto HttpEntity, pero lo podemos convertir fácilmente en una cadena de texto mediante el método estático EntityUtils.toString().
HttpResponse resp = httpClient.execute(post); String respStr = EntityUtils.toString(resp.getEntity()); if(respStr.equals("true")) lblResultado.setText("Insertado OK.");
En nuestro caso, el método de inserción devuelve únicamente un valor booleano indicando si el registro se ha insertado correctamente en la base de datos, por lo que tan sólo tendremos que verificar el valor de este booleano («true» o «false») para conocer el resultado de la operación, que mostraremos en la interfaz en una etiqueta de texto llamada lblResultado.
Como ya dijimos en el apartado anterior sobre servicios SOAP, a partir de la versión 3 de Android no se permite realizar operaciones de larga duración dentro del hilo principal de la aplicación, entre ellas conexiones a internet como estamos haciendo en esta ocasión. Para solucionar este problema y que la aplicación funcione correctamente en todas las versiones de Android debemos hacer la llamada al servicio mediante una tarea asíncrona, o AsynTask, que se ejecute en segundo plano. Una vez más no entraré en detalles porque el curso contiene un capítulo dedicado exclusivamente a este tema. A modo de ejemplo, el código anterior trasladado a una AsyncTask quedaría de la siguiente forma:
private class TareaWSInsertar extends AsyncTask<String,Integer,Boolean> { protected Boolean doInBackground(String... params) { boolean resul = true; HttpClient httpClient = new DefaultHttpClient(); HttpPost post = new HttpPost("http://10.0.2.2:2731/Api/Clientes/Cliente"); post.setHeader("content-type", "application/json"); try { //Construimos el objeto cliente en formato JSON JSONObject dato = new JSONObject(); dato.put("Nombre", params[0]); dato.put("Telefono", Integer.parseInt(params[1])); StringEntity entity = new StringEntity(dato.toString()); post.setEntity(entity); HttpResponse resp = httpClient.execute(post); String respStr = EntityUtils.toString(resp.getEntity()); if(!respStr.equals("true")) resul = false; } catch(Exception ex) { Log.e("ServicioRest","Error!", ex); resul = false; } return resul; } protected void onPostExecute(Boolean result) { if (result) { lblResultado.setText("Insertado OK."); } } }
Y la llamada a la tarea asíncrona desde el evento onClick del botón de Insertar sería tan sencilla como ésta:
btnInsertar.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { TareaWSInsertar tarea = new TareaWSInsertar(); tarea.execute( txtNombre.getText().toString(), txtTelefono.getText().toString()); } });
Actualizar un cliente existente
La URL utilizada para la actualización de clientes será la misma que la anterior:
http://10.0.2.2:2731/Api/Clientes/Cliente
Pero en este caso, el objeto JSON a enviar como entrada deberá contener no sólo los nuevos valores de nombre y teléfono sino también el ID del cliente a actualizar, por lo que tendría una estructura análoga a la siguiente:
{Id:123, Nombre:»cccc», Telefono:12345678}
Para actualizar el cliente procederemos de una forma muy similar a la ya comentada para la inserción, con las únicas diferencias de que en este caso la acción HTTP utilizada será PUT (objeto HttpPut) y que el objeto JSON de entrada tendrá el campo ID adicional.
HttpClient httpClient = new DefaultHttpClient(); HttpPut put = new HttpPut("http://10.0.2.2:2731/Api/Clientes/Cliente"); put.setHeader("content-type", "application/json"); try { //Construimos el objeto cliente en formato JSON JSONObject dato = new JSONObject(); dato.put("Id", Integer.parseInt(txtId.getText().toString())); dato.put("Nombre", txtNombre.getText().toString()); dato.put("Telefono", Integer.parseInt(txtTelefono.getText().toString())); StringEntity entity = new StringEntity(dato.toString()); put.setEntity(entity); HttpResponse resp = httpClient.execute(put); String respStr = EntityUtils.toString(resp.getEntity()); if(respStr.equals("true")) lblResultado.setText("Actualizado OK."); } catch(Exception ex) { Log.e("ServicioRest","Error!", ex); }
Eliminación de un cliente
La eliminación de un cliente la realizaremos a través de la URL siguiente:
http://10.0.2.2:2731/Api/Clientes/Cliente/id_cliente
donde id_cliente será el ID del cliente a eliminar. Además, utilizaremos la acción http DELETE (objeto HttpDelete) para identificar la operación que queremos realizar. En este caso no será necesario pasar ningún objeto de entrada junto con la petición, por lo que el código quedará aún más sencillo que los dos casos anteriores.
HttpClient httpClient = new DefaultHttpClient(); String id = txtId.getText().toString(); HttpDelete del = new HttpDelete("http://10.0.2.2:2731/Api/Clientes/Cliente/" + id); del.setHeader("content-type", "application/json"); try { HttpResponse resp = httpClient.execute(del); String respStr = EntityUtils.toString(resp.getEntity()); if(respStr.equals("true")) lblResultado.setText("Eliminado OK."); } catch(Exception ex) { Log.e("ServicioRest","Error!", ex); }
Como podéis ver, al principio del método obtenemos el ID del cliente desde la interfaz de la aplicación y lo concatenamos con la URL base para formar la URL completa de llamada al servicio.
Obtener un cliente
Esta operación es un poco distinta a las anteriores, ya que en este caso el resultado devuelto por el servicio será un objeto JSON y no un valor simple como en los casos anteriores. Al igual que en el caso de eliminación de clientes, la URL a utilizar será del tipo:
http://10.0.2.2:2731/Api/Clientes/Cliente/id_cliente
En este caso utilizaremos un tipo de petición http GET (objeto HttpGet) y la forma de realizar la llamada será análoga a las anteriores. Donde aparecerán las diferencias será a la hora de tratar el resultado devuelto por el servicio tras llamar al método getEntity(). Lo que haremos será crear un nuevo objeto JSONObject a partir del resultado textual de getEntity(). Hecho esto, podremos acceder a los atributos del objeto utilizando para ello los métodos get() correspondientes, según el tipo de cada atributo (getInt(), getString(), etc). Tras esto mostraremos los datos del cliente recuperado en la etiqueta de resultados de la interfaz (lblResultados).
HttpClient httpClient = new DefaultHttpClient(); String id = txtId.getText().toString(); HttpGet del = new HttpGet("http://10.0.2.2:2731/Api/Clientes/Cliente/" + id); del.setHeader("content-type", "application/json"); try { HttpResponse resp = httpClient.execute(del); String respStr = EntityUtils.toString(resp.getEntity()); JSONObject respJSON = new JSONObject(respStr); int idCli = respJSON.getInt("Id"); String nombCli = respJSON.getString("Nombre"); int telefCli = respJSON.getInt("Telefono"); lblResultado.setText("" + idCli + "-" + nombCli + "-" + telefCli); } catch(Exception ex) { Log.e("ServicioRest","Error!", ex); }
Una vez más como podéis comprobar el código es muy similar al ya visto para el resto de operaciones.
Obtener listado completo de clientes
Por último vamos a ver cómo podemos obtener el listado completo de clientes. El interés de esta operación está en que el resultado recuperado de la llamada al servicio será un array de objetos de tipo cliente, por supuesto en formato JSON. La acción http utilizada será una vez más la acción GET, y la URL para recuperar el listado de clientes será:
http://10.0.2.2:2731/Api/Clientes
De nuevo, la forma de llamar al servicio será análoga a las anteriores hasta la llamada a getEntity() para recuperar los resultados. En esta ocasión, dado que recibimos un array de elementos, convertiremos este resultado a un objeto JSONArray, y hecho esto podremos acceder a cada uno de los elementos del array mediante una llamada a getJSONObject(), al que iremos pasando el índice de cada elemento. Para saber cuántos elementos contiene el array podremos utilizar el método length() del objeto JSONArray. Por último, el acceso a los atributos de cada elemento del array lo realizamos exactamente igual como ya lo hicimos en la operación anterior de obtención de cliente por ID.
HttpClient httpClient = new DefaultHttpClient(); HttpGet del = new HttpGet("http://10.0.2.2:2731/Api/Clientes"); del.setHeader("content-type", "application/json"); try { HttpResponse resp = httpClient.execute(del); String respStr = EntityUtils.toString(resp.getEntity()); JSONArray respJSON = new JSONArray(respStr); String[] clientes = new String[respJSON.length()]; for(int i=0; i<respJSON.length(); i++) { JSONObject obj = respJSON.getJSONObject(i); int idCli = obj.getInt("Id"); String nombCli = obj.getString("Nombre"); int telefCli = obj.getInt("Telefono"); clientes[i] = "" + idCli + "-" + nombCli + "-" + telefCli; } //Rellenamos la lista con los resultados ArrayAdapter<String> adaptador = new ArrayAdapter<String>(ServicioWebRest.this, android.R.layout.simple_list_item_1, clientes); lstClientes.setAdapter(adaptador); } catch(Exception ex) { Log.e("ServicioRest","Error!", ex); }
Tras obtener nuestro array de clientes, para mostrar los resultados hemos añadido a la interfas de nuestra aplicación de ejemplo un control tipo ListView (llamado lstClientes) que hemos rellenado a través de su adaptador con los datos de los clientes recuperados.
A modo de ejemplo, en la siguiente imagen puede verse el resultado de ejecutar la operación de listado completo de clientes:
Y con esto hemos terminado. Espero haber ilustrado con claridad en los dos últimos artículos la forma de construir servicios web tipo REST mediante ASP.NET y aplicaciones cliente Android capaces de acceder a dichos servicios.
Puedes consultar y/o descargar el código completo de los ejemplos desarrollados en este artículo accediendo a la página del curso en GitHub.
Curso de Programación Android en PDF
¿Te ha sido de utilidad el Curso de Programación Android? ¿Quieres colaborar de forma económica con el proyecto? Puedes contribuir con cualquier cantidad, unos céntimos, unos euros, cualquier aportación será bienvenida. Además, si tu aportación es superior a una pequeña cantidad simbólica recibirás como agradecimiento un documento con la última versión del curso disponible en formato PDF. Sea como sea, muchas gracias por colaborar!
Más información:
64 comentarios
Sgoliver muy buen material, esperamos la parte 5 de este tema donde nos enseñes como implementarlo en un terminal real.
Hola YoGo, en un terminal real sería exactamente igual, no habría cambios en el código, tan sólo tendrías que cambiar la URL del servicio web por la del servicio real (online) al que quieras acceder.
Buenas, excelente blog, me gustaria saber si hay algun servicio de creacion de bbdd online gratuito que soporte REST para realizar pruebas, un saludo :)
buenas sera que podraias hacer un tutorial para el uso de handlers para los mensajes. muchas gracias
excelente información… pero como se podría en lugar de mostrar la lista de clientes… generar una búsqueda de cliente a la BD y mostrar la información del cliente??? bueno se que ya con lo que has dado hay bastante info pero bueno tu que eres el máster me podrías ilustrar.
Hola , pero si quisiera enviar algo como esto
&%/&%&YTSAUóéúíí89008 878/(/))hjsjdhsjdhsjhdjs?????sss
tambien si quisiera enviarlo como atributo en alguna clase , se que da error , como se recuelve
Hola, que buen material, pero tengo un par de preguntas. Hace un tiempo realice algo similar pero usando servicios en java, y cuando trabajaba en esto me encontraba con una excepcion de que las operaciones de red no deben estar en el hilo principal, que debia hacer una asynctask para correr las peticiones Http, me pregunto porque en este caso la aplicacion no da quejas por esto si todo se encuentra en la misma actividad? tambien si quisiera hacerlo en un hilo aparte que se deberia cambiar? buen tutorial de nuevo, fue de mucha ayuda
Hola Amigo, muy interesante tu articulo, pero no lo puedo echar a andar, con el web service no hay problema, lo hice paso a paso y lo pruebo desde mi explorador y si lo puedo consumir, pero el problema es en la aplicación android, (no hay errores de sintaxis), ya me fije que sea el mismo puerto, la ip pues la deje igual (10.0.2.2) que es la que hay que dejar por default (sustituye a127.0.0.1 cierto? ), se ejectuta la aplicación correctamente, pero los botones de insertar, actualizar y eliminar, no hacen nada al darles clic, pero tampoco marca error) y en los botones en Obtener y de Listar ahi si me marca error, varios errores, el primero es:
org.json.JSONException: Value <!DOCTYPE of type java.lang.String cannot be converted to JSONObject
podrías ayudarme por favor?
De antemano muchas gracias, si gustas puedes contactarme a mi email por si necesitas mi código o algo.
saludos !!!
Hola, buen sitio y tutoriales.
Hablando de este en particular. Me gustaría conocer tu punto de vista acerca de las Ventajas, Desventajas en comparativa con el uso de servlets en java vs REST. Se que este ejemplo lo hiciste con .net pero es igual para java.
A lo que voy es en el performance del aplicativo, manejo de errores, soporte de peticiones, seguridad. etc.etc.
Ya que la comunicación con android es muy similar mediante http y con json dado el caso.
Saludos.
Alguien lo pudo echar a andar??? podrían pasar el código funcionando?
Buenas, primero, excelente trabajo con tu blog, ya no puedo contar las veces que me ha salvado.
Pero resulta que tengo un problema en la parte de tu codigo que usas la funcion «respJSON.getJSONObject(i);», ya que a mi me dice que solo acepta Strings, no int. Usas alguna version especifica de Android? Podrias quizas concretar que imports usas?
Muchas gracias por todo.
ola una pregunta copmo uedo validar si una url es valida..porke cuando pongo una url invalida se cae la palicacion…alguna idea de poner un validador..para ver si no me trae la respuesta en x segundos mandar un mensaje??..lo que pasa esque necesito poner la ip en un edittext..gracias.
Hola! Muchisimas gracias por este tutorial!
Tengo una duda, en caso de que quisiera hacer un HttpPost de un tipo DateTime desde android, como podria resolverlo?
Desde java, hago: dato.put(«FechaNacimiento», new Date());
El tema es que al recibirlo desde MVC 3, el campo FechaNacimiento no viene con la fecha correcta.. Imagino que ASP no sabe como manejar la fecha en formato JSON.
Gracias!
Hola, gracias por el curso, me está sirviendo de mucho.
Tengo un problema con esta parte, la cosa es que estoy desarrollando una aplicacion que hace uso de un servidor, y entonces cuando hago peticiones, las meto en un asynctask porque si no no me deja hacer… mi problema es que si pongo un dialog para que el usuario no diga «esto se ha bloqueado», lo hago correctamente, pongo la creación en onpreexecute y el dismiss en onpostexecute, pero tan sólo sale una vez se ha completado la operación, y no consigo dar con la solución a ello.
Tras mucho darle vueltas llegué a la conclusión de que las peticiones http bloquean el ui thread, pero por mucho que intente esto y aquello creando threads adicionales y demás, no consigo solucionar el problema.
Si pudieras darme una solución te lo agradecería mucho.
hola Exelente tutorial, tengo la duda como separo en otra clase de java este codigo, o sea, tengo un activity prinipal y quiero separar este codigo en otro Activity o clase
Saludos!!!
Hola, respondiendo a Yogo comentaste que para probar en un terminar real (desde un celular) tendrias que cambiar la URL por la del servicio real (online). Podrias explicarlo mejor por favor? Como creo un servicio real? solo requiero una guia.
Gracias
Quiero enviar no solo un id, sino tambien un nombre de usuario y una contraseña al servicio, cual es la sintaxis para el servicio?
Buenas, tengo un problema con mi servidor rest y mi aplicacion android. el tutorial me ha ayudado mucho con inconcluencias que tenia en el codigo, pero ahora solo em funciona en local. Al poner la app android en la misma subred que el servidor y usando un router debidamente configurado (lo he puesto en modo DM> para abrir todo) el router me hace cosas raras y hace lo que quiere.
pongo la IP de mi ordenador y el puerto 801 puesto que los HTTPGET y HTTPPOST van por ese puerto.
sik alguien me puede ayudar se lo agradeceria encarecidamente.
Muchas gracias
Con tus tutoriales aprendi muchisimo muchas gracias!!!
Necesito hacer un web service en lo posible en PHP vos haces tutoriales sobre eso o conoces algun sitio que valga la pena?
Genial !
Después de buscar y probar un montón de ejemplos es el primero que me funciona sin problemas.
¡Gracias!
Si lo que quiero hacer son varias operaciones en distintas tablas , utilizo un stored procedure pero como trabajo en MVC3 y que tipo de peticion http realizo en android y como extraigo los datos de salida del stored procedure? Es posible?
gracias,!
hola a alguien le ha salido el ejemplo, yo he cambiado algunas cosas y me da un error en el web service de que no lo encuentra
al crear el objeto que llama al servicio he probado así:
HttpGet del =
new HttpGet(«http://10.0.2.2/personas.php»);
no se si falta el número de puerto, tambien he probado con elllo y no funciona:
HttpGet del =
new HttpGet(«http://10.0.2.2:80/personas.php»);
alguna ayuda, este es el log:
10-14 20:09:36.740: E/ServicioRestError(2416): Error!
10-14 20:09:36.740: E/ServicioRestError(2416): java.net.SocketException: Network unreachable
10-14 20:09:36.740: E/ServicioRestError(2416): at org.apache.harmony.luni.platform.OSNetworkSystem.connectStreamWithTimeoutSocketImpl(Native Method)
10-14 20:09:36.740: E/ServicioRestError(2416): at org.apache.harmony.luni.platform.OSNetworkSystem.connect(OSNetworkSystem.java:115)
10-14 20:09:36.740: E/ServicioRestError(2416): at org.apache.harmony.luni.net.PlainSocketImpl.connect(PlainSocketImpl.java:244)
10-14 20:09:36.740: E/ServicioRestError(2416): at org.apache.harmony.luni.net.PlainSocketImpl.connect(PlainSocketImpl.java:533)
10-14 20:09:36.740: E/ServicioRestError(2416): at java.net.Socket.connect(Socket.java:1055)
10-14 20:09:36.740: E/ServicioRestError(2416): at org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:119)
10-14 20:09:36.740: E/ServicioRestError(2416): at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:143)
10-14 20:09:36.740: E/ServicioRestError(2416): at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
10-14 20:09:36.740: E/ServicioRestError(2416): at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
10-14 20:09:36.740: E/ServicioRestError(2416): at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:348)
10-14 20:09:36.740: E/ServicioRestError(2416): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
10-14 20:09:36.740: E/ServicioRestError(2416): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
10-14 20:09:36.740: E/ServicioRestError(2416): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
10-14 20:09:36.740: E/ServicioRestError(2416): at com.example.serviciopersona.MainActivity$1.onClick(MainActivity.java:66)
10-14 20:09:36.740: E/ServicioRestError(2416): at android.view.View.performClick(View.java:2408)
10-14 20:09:36.740: E/ServicioRestError(2416): at android.view.View$PerformClick.run(View.java:8818)
10-14 20:09:36.740: E/ServicioRestError(2416): at android.os.Handler.handleCallback(Handler.java:587)
10-14 20:09:36.740: E/ServicioRestError(2416): at android.os.Handler.dispatchMessage(Handler.java:92)
10-14 20:09:36.740: E/ServicioRestError(2416): at android.os.Looper.loop(Looper.java:123)
10-14 20:09:36.740: E/ServicioRestError(2416): at android.app.ActivityThread.main(ActivityThread.java:4627)
10-14 20:09:36.740: E/ServicioRestError(2416): at java.lang.reflect.Method.invokeNative(Native Method)
10-14 20:09:36.740: E/ServicioRestError(2416): at java.lang.reflect.Method.invoke(Method.java:521)
10-14 20:09:36.740: E/ServicioRestError(2416): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
10-14 20:09:36.740: E/ServicioRestError(2416): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
10-14 20:09:36.740: E/ServicioRestError(2416): at dalvik.system.NativeStart.main(Native Method)
Buenas a mi tampoco me llega a conectar con el webservice ,
yo creo que aqui http://10.0.2.2:2731/Api/Clientes/Cliente/ lo que falla es el numero de puerto. ¿Alguna solución?
Gracias
Buenas compañeros si funciona con las direcciones externas lo que deben de colocar es el numero de puerto para eso despues de la direccion ip le colocan el :80 que es el de comunicaciones y para probarlo en la maquina deben de verificar el puerto donde se ha montado el servicio en visual estudio eso puede cambiar solo corran la aplicacion una vez cargada en el navegador ahi aprecera localhost:2731 2731 es el puesto donde se ha montado ese puede variar
Para los que quieran saber como es el formato del JSON «http://www.cheesejedi.com/rest_services/get_big_cheese?level=1» , con esa URL pueden hacer pruebas.
[{«id»:»755″,»level»:»1″,»time_in_secs»:»3″,»par»:»0″,»initials»:»KiB»,»quote»:»Got’cha!»,»time_stamp»:»2012-04-09 22:50:52″},{«id»:»874″,»level»:»1″,»time_in_secs»:»3″,»par»:»0″,»initials»:»WJF»,»quote»:»Look, Ma. No hands!»,»time_stamp»:»2012-05-25 15:44:10″},{«id»:»59″,»level»:»1″,»time_in_secs»:»4″,»par»:»0″,»initials»:»TMF»,»quote»:»Hey hey ole ‘ hickery»,»time_stamp»:»2012-03-03 04:36:15″},{«id»:»61″,»level»:»1″,»time_in_secs»:»4″,»par»:»0″,»initials»:»WJF»,»quote»:»I’m on a boat!»,»time_stamp»:»2012-03-03 04:38:54″},{«id»:»150″,»level»:»1″,»time_in_secs»:»4″,»par»:»0″,»initials»:»lja»,»quote»:»Look, Ma. No hands!»,»time_stamp»:»2012-03-04 00:57:02″}]
estoy realizando este ejemplo pero ahora ocupo qe ademas de traerme el los campos de texto me regrese una imagen y la muestre en un imageview como puedo hacerlo ???
Hola, esa muy bien el tutorial. Yo solo use la segunda parte, ya que el webservice lo hice con netbeans. Me gustaría saber que dirección ip poner en lugar de la 10.0.2.2 para depurarlo vía usb en el movil, porque en depurador me funciona a la perfección pero en el movil no tiene ninguna intención de depurar. He probado con varias ips y no consigo que funcione
ALGUIEN SABE COMO SOLUCIONAR ESTOS ERRORES:
EL WEB SERVICE YA FUNCIONA
UTILIZO SOLO STRING EN EL ID DE CLIENTE
OBTENER 1 CLIENTE:
org.json.JSONException: Value false of type java.lang.Boolean cannot be converted to JSONObject
OBTENER UN LISTADO DE CLIENTES:
org.json.JSONException: Value of type java.lang.String cannot be converted to JSONArray
como puedo enviar un parametro con tres valores con los cuales me traere la lista completa
por ejemplo tengo una clase de tipo Parametros
declaro:
Parametros p = new Parametros() ;
p.id = 1;
p.filtro = «jugo»;
p.num_res = «10»;
aqui envio elparamaetro al webservice
HttpGet del = new HttpGet(«http://10.0.2.2:49469/Api/Productos/» + p);
pero en el web service me no me llega mas qe los de tipo string,int y eso.
alguien sabe como puedo mandar este tipo de parametros??
Buenas, al recibir el JSON, obtengo esta respuesta:
401 Unauthorized
401 Unauthorized
Your client does not have permission to get URL /Api/Clients from this server.
y los consiguientes errores que conlleva esta recepción de datos,¿Que tengo que cambiar en mi ordenador para que todo el mundo tenga permisos o en el programa?
Gracias por los tutoriales, son excelentes…en mi aplicación ya funciona perfecto el sincronizar mi BD desde android en tiempo real…pero en el caso de que cuando este ingresando los datos no tenga servicio de internet? como puedo sincronizar mis datos en la bd del dispositivo con la bd en el servidor? …sin internet guardaria los datos en la bd del dispositivo pero como hago la sincronizacion despues?…porfavooor una ayudita!
hay alguna manera de enviar caracteres que no sean letras ni numeros en el HttpGet
como por ejemplo = , & , % , $ , : , ; [, ] , { , } , etc.
ya que me sale que envio un caracter ilegal
java.lang.IllegalArgumentException: Illegal character in path at index 36: http://10.0.2.2:50108/Api/MiAplicacion/{«pag»:0,»funcion»:»1″}
at java.net.URI.create(URI.java:970)
hay alguna forma de que acepte estos valores???
Hola a todos. Yo estoy intentando hacer funcionar el código desde el teléfono físico y un servicio real pero no lo consigo. Ahora mismo estoy en un punto que ya no se que probar.
Alguien lo ha podido hacer funcionar desde el teléfono a través de una ip real ??
Aprovecho también para agradecer los magníficos tutoriales de este curso, son una maravilla para dar los primeros pasos con el funcionamiento de aplicaciones en Android.
Hola de nuevo. Finalmente conseguí hacer funcionar el servicio en IIS, que era el motivo por el cuál no podía realizar correctamente la conexión a través del teléfono con la aplicación instalada. Me faltaba añadir el Framework 4.0 al grupo de aplicaciones en IIS7.
Gracias de nuevo. Saludines
Hola.. Todo muy bien.. solo que creo q tengo problemas encuanto al codigo de PHP que no.. retorna nada con el JSON.. Creo q mi error es en php.. ayuda.. solo quiero obtener todos los datos de una tabla.
hola, duda estoy manteniendo una APP que antes consumia un WS que regresaba un XML, ese WS lo modifique y serialize el XML, ya consumo la cadena JSON en la app movil, pero como puede deserializar esa cadena JSON y pasarla a un XML, esto con la idea de no modificar toda la APP que ya esta hecha
Hola buenas. Tengo un problema en la segunda parte de ambos apartados (SOAP y REST). He conseguido montar el servidor en mi localhost usando Visual Studio 2012, todo sin problema. Desde el navegador todo funciona perfectamente. El conflicto viene a la hora de acceder al servidor desde el emulador. He revisado una y otra vez los parámetros a configurar, y utilizo la URL «http://10.0.2.2:puerto/Api/Clientes», cuando quiero listar la base de datos, por ejemplo (puerto = 63105 en mi caso), pero el LogCat informa de una respuesta HTTP 400 (Bad Request). Esto me lleva a pensar que la conexión se produce, pero el Web Service «no entiende» lo que se la reclama. Me gustaría saber si a alguien le ha ocurrido lo mismo, y de qué manera se puede solucionar. Muchas gracias.
Hola buenas, primero que nada muchas al autor por el blog lo felicito por ello me ha resultado muy útil, y en lo que tenga la tarjeta de credito voy ha hacer la donación correspondiente.
voy al grano con respecto a mi duda, siguiendo el articulo e logrado conectarme contra un web service que cree con netbeans y glassfish, este web services en sus metodos get y post tiene la capacidad de trabajar con json y xml por defecto.
con el metodo post no tengo problemas pues envio la información y el web services la procesa sin problema alguno.
mi problema esta en los get, si bien el web services me responde tanto en xml como json (lo he probado por mi lado y doy fe de que lo que envia es lo que debe de enviar), la aplicación en android solo recibe una respuesta xml, a pesar que en el get seteo el header como json, no logro identificar verdaderamente el problema.
no se si al setear el header en el get le indica al get que lo que recibe es un json del servidor, o si el header debe indicarle al web service que lo que debe enviar es un json, la verdad ya estoy un poco confundido con este problema, pues me interesa que el web services trabaje con xml y json, pero quiero que la app en android solicite todo por json, por favor podrias indicarme cual es mi error y como solucionarlo?
muchas gracias de manera adelantada y perdona todas las molestias que esto puede causar.
Atte
Otacon Rex
como puedo ordenar los campos de la base de datos obtenidos dentro de una listview, ya que me los muestra todos pegados uno al lado del otro.
Hola muchísimas gracias por el articulo, esta muy bien explicado y ya lo pude hacer funcionar con php.
Mi duda es como puedo hacer para que el usuario que agregue, edite, elimine o liste esa información este autorizado ( registrado )
Saludos Javier
Tengo una duda de diseño.
Tengo una aplicacion que se comunica mediante JSON a un servidor web que contiene las paginas php que realizan las operaciones en la base de datos.
Por ahora todo bien, me funciona y sin problemas.
Lo que quiero hacer y no se como es que la aplicacion en lugar de preguntar continuamente al servidor cuando quiere mostrar, insertar modificar y borrar datos no se conecte al servidor sino que lo haga en una base de datos sqlite en local y un hilo este sincronizando los datos de la base de datos sqlite con la base de datos mysql del servidor.
Alguien puede indicarme como realizar esta sincronizacion o darme un pequeño tutorial?
Hola Sergio excelentes tus tutoriales, muchas gracias, los estoy usando para aprender Android.
Tengo una duda quiza me puedas ayudar:
Cuando el servicio web REST en visual Studio recibe
POST /Api/Clientes/Cliente { Nombre:”nombre”, Telefono:1234 }
como o donde transforma la informacion JSON a Cliente? ya que en la consulta SQL usas Cliente cli. No entiendo esa parte!!!
Muchas Gracias
Hola,
Tengo un problema a la hora de conectarme a mi servicio WEB REST desde la aplicaciones móvil, por ejemplo usando el boton listar, no soy capaz de establecer comunicacion.
El error es: Timed out connection.
He tratado a conectarme desde PC’s de la red local a través de la url y obtengo que :
la sesión ha caducado.
Solo puedo acceder desde el pc en el que se ejecuta como localhost el servicio…
¿Alguna sugerencia?
PD: Enhorabuena por tu BLOG, es buenisimo.
Un saludo.
Buenas tardes, buenísimo tu blog y el curso. tengo un inconveniente, ya tengo el servicio web en un iis y la aplicación en Android andando. el inconveniente aparece cuando quiero hacer borrar y actualizar un cliente, la aplicación no da ningún tipo de error, pero tampoco lo borra o lo actualiza, muy diferente en el proceso de insertar, listar y obtener que me anda de maravillas.
alguna idea?
desde ya muchas gracias
Hola muy buen articulo, fabuloso diria yo. Solo un pequeña inquietud el archivo que genera el JSOn en vez de crearlo con .net, lo podremos crear con php, pienso que es mas facil, se monta en un servidor apache cualquiera y listo. Gracias por dedicar su tiempo a compartir su conocimiento
Excelente artículo.
En los GET he tenido que cambiar el header para que devuelva el resultado en formato JSON en lugar de XML. En lugar de setHeader(«Content-Type», «application/json»), he tenido que poner setHeader(«Acceptance», «application/json»).
Aclarar que mi web service está montado en java con JAX-RS, por si a alguien le sirve. Un saludo.
En primer lugar, felicitarte por tu blog, es de lo mejorcito que hay sobre Android en español.
Veo que vas ampliando o actualizando contenidos, y me pregunto si te has planteado ampliar el ejemplo de «Servicios Web REST» incorporando autentificación con OAuth2.
Hace tiempo monté, en plan autodidacta, un sencillo ejemplo de cliente REST en Android, conectandose a un servicio Azure (siguiendo un tutorial de VStudio 2013), para lo queeste blog me fue de muchísima utilidad… pero cuando intento aplicar OAuth2 en esa misma demo (la parte cliente casi calcada al ejemplo de tu blog), no veo como hacerlo, y no encuentro por ningún sitio de la web algo con lo que terminar de entender cómo se consume servicios REST protegidos por OAuth2.
Estoy convencido que si lo explicaras en tu blog, manteniendo ese estilo tan didáctico y ejemplos claros y prácticos, novatos como yo podríamos conseguirlo.
Hola, qué framework puedes recomendar para conectarse a servicios REST desde Android y facilitar todo el proceso?
hola muy bueno, y como le pondriamos el nombre a las columnas en el Listview de la lista
Hola,
el servicio web que hemos creado en el articulo anterior se deberia de publicar en el IIS para que se pueda acceder desde el movil?yo no consigo conectar el movil al servicio de ninguna manera
Hola Buen articulo, el comentario que hago es el siguiente: Podrían actualizar el articulo usando Asp.Net Web Api, por que en la actualidad esta es la ultima tecnologia para servir datos via Http, segun entiendo.
Saludos y muchas gracias.
Saludos amigo,
Ayúdame con una inquietud.
En esta linea de código:
String respStr = EntityUtils.toString(resp.getEntity())
En teléfonos celular (Smarphone normal versión android 4.1.2) al ejecutarlo toma 5 segundos máximo.
Pero desde una TABLET (versión android 4.0.4), toma 60 segundos.
alguna idea del porque podría ser?
Gracias!
Hola,
llevo unos días tratando de realizar la conexión con la base de datos mediante un servicio web en php y con JSON para los datos. Mi problema es que la app llama al archivo php pero no llegan los datos que le envío. ¿Alguna idea de por qué no recibe los datos? Pongo el código por si hay algo que yo no puedo ver, soy bastante nuevo en esto de android.
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(Url);
httppost.setHeader(«content-type», «application/json»);
HttpResponse response;
JSONObject jsonobject=new JSONObject();
StringEntity se;
try {
jsonobject.put(«f_name», «Martin»);
jsonobject.put(«f_last_name», «Martin»);
jsonobject.put(«f_2_apellido», «Martin»);
se = new StringEntity(jsonobject.toString());
httppost.setEntity(se);
response = httpclient.execute(httppost);
Muy buen tutorial, me fue muy util, los felicito y los animo a que sigan subiendo tutos porque ayudan bastante. Estuve practicado con los métodos del rest pero a la hora de querer usar un método post con un array y enviarlo al servidor solo me reconoce el primer registro, estoy desarrollando una aplicación con rest y quiero sincronizarlo con un servidor de manera que pueda trabajar offline he visto algo de syncAdapter pero no lo entiendo aún, si me pueden ayudar
[…] necesitemos manejar. Hay muy buenos tutoriales sobre esto en internet, podéis ver ejemplos aquí, aquí o aquí (o excelentes vídeos como el de Xamarín aquí) y por tanto no voy a desarrollar más […]
[…] Servicios Web REST en Android (2/2) [v3] […]
Muy buen articulo.
Pero me gustaría saber como se puede hacer esto en una aplicación web en java, lo de la conexion y las las llamadas get y post usando json.
Espero me puedan ayudar.
Gracias!
no me reconoce ninguna de las importaciones de httpComponents si me pueden dar el link de donde descargarlo les agradecería mucho. gracias
Muy buen explicado, pero tendrias una opcion para el Api 23 ya que HttpClient ha sido deprecated para este Api
Para la Api 23 hay que añadir la siguiente linea en el fichero build.grade y funciona correctamente
dependencies {
// ——-
compile group: ‘cz.msebera.android’ , name: ‘httpclient’, version: ‘4.4.1.1’
}
Como siempre dentro de este curso de Android, muy buen aporte, amigo. Simplemente comentar, como ya ha anotado alguien en un comentario anterior, que a partir de la Api 23 el HttpClient ha sido eliminado, y buscando un poco por la red creo que la opción nativa mediante HttpURLConnection es la nueva alternativa para hacerlo. Pongo a continuación la parte de código que iría en la tarea de insertar, que lo he probado y funciona correctamente:
boolean resul = true;
String url = «http://10.0.2.2:2731/api/Clientes/Cliente»;
try{
URL object = new URL(url);
HttpURLConnection con =
(HttpURLConnection)object.openConnection();
con.setDoOutput(true);
con.setDoInput(true);
con.setRequestProperty(«Content-Type», «application/json»);
con.setRequestProperty(«Accept», «application/json»);
con.setRequestMethod(«POST»);
JSONObject dato = new JSONObject();
dato.put(«Nombre», params[0]);
dato.put(«Telefono», Integer.parseInt(params[1]));
OutputStreamWriter wr =
new OutputStreamWriter(con.getOutputStream());
wr.write(dato.toString());
wr.flush();
int httpResponse = con.getResponseCode();
if(httpResponse == HttpURLConnection.HTTP_OK)
{
BufferedReader br = new BufferedReader(
new InputStreamReader(con.getInputStream(), «utf-8»));
String valorDevuelto = null;
valorDevuelto = br.Line();
if(!valorDevuelto.equals(«true»))
resul = false;
}
else
{
Log.e(«ServicioRest», «Error resultado » + httpResponse);
resul = false;
}
}
catch(Exception ex)
{
Log.e(«ServicioRest», «Error!», ex);
resul = false;
}
Espero que le sirva a alguien!!!!
Saludos!!!!
Te felicito por este curso de Android, lo estoy siguiendo desde hace algunos meses y es un contenido muy útil para aquellos que estamos empezando a desarrollar aplicaciones moviles android.
Gracias
Felicidades por tu blog!, es muy didáctico y aprende uno mucho, sin embargo, hoy las librerías de apache ya están obsoletas para android 28 y requieren el uso de HttpURLConnection…. yo soy nuevo en esto y a lo mejor ya no contestas pero, ¿alguien sabe como hacer ese cambio?
Saludos!
Hola, recién escribí y te quería comentar que, siguiendo el comentario de «Cristóbal», logré implementarlo, lo dejo a continuación porque el que él puso estaba incompleto. Ya lo probé y me funcionó al 100%.
Muchas gracias!
private class TareaWSInsertar extends AsyncTask {
protected Boolean doInBackground(String… params) {
boolean resul = true;
try {
try {
URL url = new URL(«http://1.1.1.1/Api/Clientes/Cliente»);
try {
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setDoOutput(true);
con.setDoInput(true);
con.setRequestProperty(«Content-Type», «application/json»);
con.setRequestProperty(«Accept», «application/json»);
con.setRequestMethod(«POST»);
JSONObject dato = new JSONObject();
try {
dato.put(«Nombre», params[0]);
dato.put(«Telefono», Integer.parseInt(params[1]));
} catch (JSONException e) {
Log.e(«MYAPP», «unexpected JSON exception», e);
finish();
}
OutputStreamWriter wr = new OutputStreamWriter(con.getOutputStream());
wr.write(dato.toString());
wr.flush();
int httpResponse = con.getResponseCode();
if(httpResponse == HttpURLConnection.HTTP_OK)
{
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), «utf-8»));
String valorDevuelto = null;
valorDevuelto = br.readLine();
if(!valorDevuelto.equals(«true»))
resul = false;
} else {
Log.e(«ServicioRest», «Error resultado» + httpResponse);
resul = false;
}
} catch(Exception ex) {
Log.e(«ServicioRest», «Error!», ex);
resul = false;
}
} catch(IOException ex) {
ex.printStackTrace();
resul = false;
}
} catch(Exception ex) {
Log.e(«ServicioRest»,»Error!», ex);
resul = false;
}
return resul;
}
protected void onPostExecute(Boolean result) {
if (result)
{
lblResultado.setText(«Insertado OK.»);
}
}
}