+1 voto

Buenos noches,

En primer lugar me gustaría agradecer la publicación del libro  "Android 100%" el cúal estoy usando para mi aprendizaje en el desarrollo de aplicaciones en android.

Viajando un poco más al grano: Estoy tratando de desarrollar un cliente REST en Android para consumir mis "resources" del RESTful WebService. En una primera instancia estuve comprobando estos recursos con un cliente RESTful en Java, hasta ahí bien.

Mis puntos de partida son:

  • Servicio Web RESTful implementado con Jersey (1.X) -> aunque hay posibilidad de "migrar" a 2.X
  • BD MySQL

Mi problema es que, tras muchas horas de búsqueda no consigo desarrollar mi cliente (en mi app Android) que consuma los recursos ofrecidos por mi RESTful WS.

Ahora me surgen las siguientes dudas las cuales voy a intentar de clasificarlas.

  1. Relativo a las tecnologías
    1. He visto que hay multitud de APIs para desarrollar clientes REST en Android, ya sean, Retrofit, Volley, RESTDroid... ¿Tenéis alguna recomendación en especial? Estoy bastante perdido
    2. He leido en stackoverflow que tanto que android no soporta el uso de un cliente Jersey para consumir tu servicio web como otros post en los que sí. (En la documentación de Jersey dice algo así como que a partir de la version 2.16 es posible usar este cliente en una app de Android, pero que aún hay temas sin resolver). Podría re-implementar el servicio web para la version 2.X de Jersey, ¿pero merecía la pena?
    3. Creo y, espero que me corrijan, que otra buena opción es usar Spring. Por lo que he leido dicen que es una buena opción para el desarrollo de aplicaciones android cuyos clientes tengan que consumir servicios web RESTful
  2. Relativo a no tener que volver a empezar
    1. ¿Hay alguna forma de poder consumir mi RESTful WS desarrollado en Jersey (ya sea 1.x o 2.x) desde mi aplicacion en android?

Siento la extensión, pero creo que el estructurar la duda desde las distintas ópticas puede facilitar la compresión del problema en sí.

Gracias, y espero respuestas. Saludos ;)

por en Aplicaciones Móviles

1 Respuesta

+1 voto
Mejor respuesta
Para servicios con Android siempre es mejor utilizar JSON (ver como en http://developer.android.com/intl/ru/reference/android/util/JsonReader.html). Pero si no te que da otra que utilizar SOAP para Android lo mejor es utilizar la biblioteca gratuita de terceros KSoap2 (ver en http://simpligility.github.io/ksoap2-android/index.html). Pero sigue siendo mejor JSON, pues consumen muy poco en comparación con SOAP.

Spring es un Framework que te facilita mucho esto. Aunque para servidores es muy potente y lo recomiendo, para Android no lo he probado; no podría decirte, aunque todo lo que sea meterle Frameworks de más a un móvil hay que meditar sus ventajas (ojo a la batería).
por
seleccionada por

En primer lugar, muchas gracias por la respuesta. 

Estoy seguro de que JSON va a ser la opción elegida, como tú bien dices. Por otro lado, he conseguido hacer que mi aplicación android consuma un recurso de mi RESTful WS. Esto me lleva a pensar, evidentemente, que no "necesito" que android soporte ningún tipo de cliente ya sea Jersey(en mi caso) o Spring (aunque éste si lo soporta).

Dicho consumo lo he llevado a cabo con el cliente HTTP de android. Supongo que hasta aquí el problema de la "búsqueda de un cliente de mi servicio web rest" ha concluido.

Ahora, mi problema estriba en que no puedo consumir el recurso que escribo a continuación. 

Mi cliente Android "AndroidRESTClient"

    - Tengo añadidos los permisos en el AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
package com.example.androidrestclient;

import java.io.BufferedReader;
import java.io.InputStreamReader;

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

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class Principal extends Activity {
	private EditText nro1,nro2;
	private Button sumar,saludo;
	private String resultado="";
	private TareaSumar tareaSumar = null;
	private TareaSaludar tareaSaludar = null;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_principal);
		
		nro1=(EditText) findViewById(R.id.nro1);
		nro2=(EditText) findViewById(R.id.nro2);
		sumar=(Button) findViewById(R.id.suma);
		saludo=(Button) findViewById(R.id.saludo);
		
		// Este sí funciona correctamente
		saludo.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View arg0) {
				System.out.println("Pulsamos boton saludo");
				tareaSaludar = new TareaSaludar();
				tareaSaludar.execute();
			}
		});
		
		
		sumar.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View arg0) {
				// TODO Auto-generated method stub
				tareaSumar = new TareaSumar();
				tareaSumar.execute();
			}
		});
	}
	
	private class TareaSumar extends AsyncTask<Void, Void, Boolean> {
		 @Override
		 protected Boolean doInBackground(Void... params) {
			 // TODO: attempt authentication against a network service.
			
			DefaultHttpClient httpClient = new DefaultHttpClient();
			 
			 HttpPost post = new HttpPost("http://192.168.1.104:8080/RESTfulTestMaven/rest/hello/sumar");
			 
			 post.setHeader("content-type", "application/json");
			 
			 try {
				 //Construimos el objeto cliente en formato JSON
				 JSONObject dato = new JSONObject();
						 
				 dato.put("nro1", nro1.getText().toString());
				 dato.put("nro2", nro2.getText().toString());
				 System.out.println(dato);
				 
				 StringEntity entity = new StringEntity(dato.toString());
				 post.setEntity(entity);
				 System.out.println("Enviamos el post");
				 
				 HttpResponse resp = httpClient.execute(post);
				 resultado = EntityUtils.toString(resp.getEntity());
				// JSONObject json = new JSONObject(resultado);
				 
				 System.out.println("Nos llega: "+ resultado.toString() +"");
				 
			 } catch(Exception ex)		 {
				 Log.e("ServicioRest","Error!", ex);
				 return false;
			 }		 
			 return true;
		 }
		 
		@Override
		 protected void onPostExecute(final Boolean success) {
			 if(success==false){
				 Toast.makeText(getApplicationContext(), "Error", Toast.LENGTH_LONG).show();
			 }else{
				 Toast.makeText(getApplicationContext(), "El resultado es: "+resultado, Toast.LENGTH_LONG).show();
			 }
		 }
		 
		@Override
		 protected void onCancelled() {
			Toast.makeText(getApplicationContext(), "Error", Toast.LENGTH_LONG).show();
		 }
	}
}

Por otro lado mi REST WS

package com.josvalbae.rest;

import javax.ws.rs.Consumes;

//Importamos las librerias necesarias
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.xml.bind.annotation.XmlRootElement;

import org.json.JSONObject;

@XmlRootElement
@Path("/hello")
public class HelloResource {
	
	@POST
	@Path("/sumar")
	@Consumes("application/json")
	public JSONObject sumar(JSONObject inputJsonObj) throws Exception {
		System.out.println("Dentro de la suma");
	    String nro1 = (String) inputJsonObj.get("nro1");
	    String nro2 = (String) inputJsonObj.get("nro2");
	    
	    int n1=Integer.parseInt(nro1);
	    int n2=Integer.parseInt(nro2);
	    
	    int res = n1+n2;
	    System.out.println("Estamos en el WS: "+res);
	    
	    String result = Integer.toString(res);
	    
	    //String output = "The input you sent is :" + nro1 + "and: " + nro2 +"";
	    
	    String output = "The input you sent is :" + nro1 + "and: " + nro2 +" and the result is = "+ result+"";
	    
	    JSONObject outputJsonObj = new JSONObject();
	    outputJsonObj.put("output", output);
	
	    return outputJsonObj;
	 }
		
}
	

El error en cuestión que no consigo arreglar, busque dónde busque es el siguiente. He añadido al web.xml , pensando que así Jersey conseguirá mapear Json/objetos, pero no me ayuda

 <init-param>
		<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
		<param-value>true</param-value>
</init-param>

 

ago 19, 2015 8:39:17 PM com.sun.jersey.spi.container.ContainerRequest getEntity
GRAVE: A message body reader for Java class org.json.JSONObject, and Java type class org.json.JSONObject, and MIME media type application/json was not found.
The registered message body readers compatible with the MIME media type are:
*/* ->
  com.sun.jersey.core.impl.provider.entity.FormProvider
  com.sun.jersey.core.impl.provider.entity.StringProvider
  com.sun.jersey.core.impl.provider.entity.ByteArrayProvider
  com.sun.jersey.core.impl.provider.entity.FileProvider
  com.sun.jersey.core.impl.provider.entity.InputStreamProvider
  com.sun.jersey.core.impl.provider.entity.DataSourceProvider
  com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$General
  com.sun.jersey.core.impl.provider.entity.ReaderProvider
  com.sun.jersey.core.impl.provider.entity.DocumentProvider
  com.sun.jersey.core.impl.provider.entity.SourceProvider$StreamSourceReader
  com.sun.jersey.core.impl.provider.entity.SourceProvider$SAXSourceReader
  com.sun.jersey.core.impl.provider.entity.SourceProvider$DOMSourceReader
  com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$General
  com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$General
  com.sun.jersey.core.impl.provider.entity.XMLRootObjectProvider$General
  com.sun.jersey.core.impl.provider.entity.EntityHolderReader

 

Es extraño, pero no consigo encontrar ningú repo dónde comprobar si hago buen uso de JSON en el WS. Muchas gracias y, espero que alguien me guíe =)