martes, 21 de julio de 2009

Enviar datos POST o GET a un servidor desde android en modo JSON

Esta clase os puede ayudar para comunicarse con un servidor en base a datos simples. La idea es que tengáis un PerfilService (por ejemplo para enviar datos del perfil) que extienda esta clase JSONService y el metodo de enviar datos o recuperar datos llame a la funcion request.

public class JSONService {

public static final int METHOD_GET = 1;
public static final int METHOD_POST = 1;
/**
* Send data is an interface to send information to any JSONService.
*
*
* @param pvo
* @returns objeto json JSONObject
*/
public JSONObject request(String url, HashMap in, int method) {
Log.i(getClass().getSimpleName(), "send task - start");

JSONObject data=null;

UrlEncodedFormEntity entity=null;
if (in!=null) {
List pairs = new ArrayList();
for (Map.Entry i : in.entrySet()) {
if (i.getValue()!=null) {
pairs.add(new BasicNameValuePair(i.getKey(), i.getValue().trim()));
}
}
try {
entity = new UrlEncodedFormEntity(pairs);
} catch (UnsupportedEncodingException e) {
return null;
}

}


DefaultHttpClient client = new DefaultHttpClient();

//Instantiate a GET HTTP method
try {
HttpUriRequest metodo;
if (method==METHOD_GET) {
if (entity!=null) { url=url+"?"+JSONService.convertStreamToString(entity.getContent()).trim(); }
metodo=new HttpGet(url);
//((HttpGet)metodo).setEntity(entity);
} else {
metodo=new HttpPost(url);
if (entity!=null) {
((HttpPost)metodo).setEntity(entity);
}
}

HttpResponse response=client.execute(metodo);
InputStream is=response.getEntity().getContent();

data=new JSONObject(convertStreamToString(is));

return data;
} catch (Exception e) {
Log.e(this.getClass().getSimpleName(), "sendDataException", e);
}

Log.i(getClass().getSimpleName(), "send task - end");
return data;
}


/**
* Convierte un InputStream en un String
* @param is
* @return
*/
private static String convertStreamToString(InputStream is) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();

String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}


}

Y la clase PerfilService podría contener el siguiente método:



public boolean sendData(ProfileVO pvo)  {
Log.i(getClass().getSimpleName(), "send task - start");

HashMap params=new HashMap();
params.put("c1", pvo.getCampo1());
params.put("tel", pvo.getTelefono());


JSONObject resultado=request("http://www.example.com/sendData.php",params,JSONService.METHOD_GET);

Log.i(getClass().getSimpleName(), "send task - end");

try {
if (resultado==null) { return false; }
if (!("1".equals((String)resultado.get("ok")))) {
return false; //fail
}
} catch (JSONException e) {
Log.e(getClass().getSimpleName(),"excepcion sending data",e);
return false;
}

return true; //ok
}

Lo que si me pregunto es lo siguiente: ¿por que lo ha complicado tanto android con el tema de enviar parámetros? no hubiera sido mas facil hacer un conjutno de parametros independientes para get y post, y que en cada metodo, el httpclient los interpretara como debe?

Guardar datos persistentes en Android

¿Cómo se guardan datos persistentes en Android? (es decir, guardar información que luego se pueden recuperar otra vez).

Las aproximaciones son varias:
1.- Enviarlas a un servidor (generalmente cuando el servidor tiene q hacer trabajo con esa información que envías - y generalmente en común con la misma información enviada por varios dispositivos móviles).
2.- Guardarlas en fichero local (pocos datos, no estructurados).
3.- Guardarlas en una base de datos embebida en la propia android (sqlite).

Para la primera aproximación, en el siguiente post mostraremos un JSONService que nos ayudará a enviar y recibir datos con un servidor en modo JSON. Es muy básico, pero útil.

Para la tercera aproximación, este tutorial esta muy muy MUY bien:
http://www.helloandroid.com/node/110?page=0%2C1

Para la segunda aproximación, aquí tenemos un ejemplo muy práctico:
http://www.anddev.org/viewtopic.php?p=15101

lunes, 20 de julio de 2009

Ejecutar una ventana de cargando entre transiciones de pantallas

Enunciado:

Imaginemos que tenemos una pantalla o actividad A que llama a una actividad B. La actividad B a la hora de cargarse debe recoger datos de un servidor externo.

Sería recomendable por tanto, que a la hora de cargar los datos de dicho servidor, se mostrara una ventana de Cargando.

¿Cómo se hace?

Respuesta:

La ventana que muestra un cargando se llama ProgressDialog. Tras mostrar dicho dialog debes ejecutar la acción que quieras (por ejemplo, recoger datos de un servidor) en un thread aparte. Debido a que una vez que se recuperan los datos se debe cerrar la ventana e interactuar con la UI (para colocar los datos cargados, por ejemplo), no se puede hacer en la clase Thread, con lo que debemos utilizar un Handler (como el callback handler típico de las aplicaciones asíncronas - ajax, para los javascripteros).

Todo esto se resume en:

- Cargo la pantalla usando una funcion setupData:

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.b);
setupData();
...
}

- Escribo el metodo setupData():


private void setupData() {
dialog=ProgressDialog.show(B.this, "",
"Loading. Please wait...", true);

new Thread() {
public void run() {
try{
new BService().doSomeWork(); // Toda la logica de negocio va aqui
getDataHandler.sendEmptyMessage(0);
} catch (Exception e) {
Log.e(getClass().getSimpleName(),"excepcion en thread",e);
}
}
}.start();
}

La variable dialog es una variable a nivel UI, de modo que la pueda referenciar desde el handler:

- Defino mi handler (getDataHandler, es decir, el que recoge los datos).

private Handler getDataHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
dialog.dismiss(); //cierro ventana
//hago lo que sea con el resultado del BService anterior
//Tambien podria mostrar unmensaje de error si ha existido error a la hora de recuperar datos
}
};

Eso es todo. La verdad es que da pie a crear una clase ProgressActivity que haga esto de por sí, y las actividades que quieras que tengan este comportamiento heredarían de esta actividad e implementarían las clases abstractas de hacerPre() -llamado en el Thread- y hacerPost() --llamado tras ejecutar el Thread-.

¿alguien se atreve? ;-)

Recuperar datos del teléfono desde la SDK

Para recuperar los datos del teléfono desde una aplicación android, se debe utilizar el TelephonyManager:

TelephonyManager telephony = (TelephonyManager)miActividad.getSystemService(Activity.TELEPHONY_SERVICE);

Por ejemplo, se puede recoger el número de teléfono del teléfono así:

String miTelefono=telephony.getLine1Number()

Importante: dar permisos a la aplicación a través del manifest.xml:

<uses-permission
android:name="android.permission.READ_PHONE_STATE">

Y yo me pregunto: si los programadores pueden asociar todos los datos del usuario a través de esta API, ¿qué sentido tiene obligarles a registrarse con anterioridad?

viernes, 17 de julio de 2009

Instalación de Eclipse y el SDK de Android en Ubuntu

Instalación de Eclipse y el SDK de Android en Ubuntu:

1. DESCARGAR EL SDK DE ANDROID

Descargamos la última versión de la página de android y lo descomprimimos en el directorio que queramos.

2. INSTALAR ECLIPSE:

La versión de eclipse que actualmente viene en los repositorios de Ubuntu es la 3.2. Nosotros nos bajamos la última versión desde la página de eclipse. Elegimos Eclipse IDE for Java Developers (91MB). Descomprimimos el zip y ejecutamos el fichero eclipse desde consola.

Por ejemplo, si hubiesemos descomprimido el fichero en el directorio inigo, simplemente abriríamos la consola y escribiríamos:

/home/inigo/eclipse/eclipse

Personalmente he preferido crear un "acceso directo" a dicho comando para no tener que abrir una consola la siguiente vez.

3. CONFIGURAR ECLIPSE:

Una vez que hemos abierto eclipse. Vamos a Help->Install new Software y donde pone Work with: metemos https://dl-ssl.google.com/android/eclipse/

Aceptamos todo y marcamos todos los checkbox. Cuando termine de instalarlo todo reiniciamos eclipse (nos lo pregunta el propio eclipse).

Después de reiniciar vamos a Window->Preferences, en el menu derecho elegimos Android y en SDK Location introducimos el directorio donde hemos descomprimido el SDK en el paso 1. Clicamos Apply y ya tenemos nuestro entorno de desarrollo preparado,

Para probarlo todo, clicamos File->New->Proyect->Android->Android Project

y a programar nuestras aplicaciones!!!