En este post veremos como enviar solicitudes GET y POST a un API RestFul desde un dispositivo con android.
Nuestra aplicación consistirá en un pequeño formulario para escribir un nombre y una edad y enviar estos al servidor quien dará una respuesta (Result:200). Si bien GET se utiliza más que todos para realizar consultas y POST para insertar datos por la cantidad de información que maneja cada uno, GET también puede ser utilizada para enviar pequeña cantidad de datos.
Necesitamos
Si se usara el Emulador android necesitamos:
Si se usara un dispositivo físico necesitamos
Nivel: Intermedio
Tiempo: 20 minutos
Proyecto en Eclipse
1. ApiRest
Construir un Api REST no esta entre los objetivos de este tutorial, por lo que reduciremos nuestro api de prueba a un archivo PHP que recibirá peticiones GET/ POST y retornara un resultado en formato JSON, el nombre del archivo es «apirest.php» y el código es el siguiente
<?php if( $_GET ) { $data = json_encode($_GET); $datares = array( 'Result'=>"200" ); print ( json_encode( $datares ) ); saveLog($data,"GET"); } else { $data = file_get_contents("php://input"); $datares = array( 'Result'=>"200", 'data'=>$data ); print ( json_encode( $datares ) ); saveLog($data,"POST"); } function saveLog($data,$peticion) { $linea = "-------------------------------------------------------------------------------"; $buffer = $peticion . " :: " .$data . "\r\n" . $linea; $file = 'log.txt'; if (file_exists($file)) { $buffer = file_get_contents($file) . "\r\n" . $buffer; } $success = file_put_contents($file, $buffer); } ?>
Crea este archivo en tu servidor local o sube a tu hosting, la dirección para acceder a este archivo es de la forma: «http://localhost/api/apirest.php» y lo que hace es procesar peticiones GET o POST darles un formato JSON, guardar en un archivo log.txt y retornar un resultado también en formato JSON de la forma:
{"Result":"200","data":""}
donde Result:200 quiere decir que el proceso se realizo correctamente.
2. Proyecto Android
Crea un nuevo proyecto android en Eclipse que se llamará RestFulGP, a continuación dale la siguiente estructura:
Nuestro proyecto contará con:
3. Permisos
Necesitamos añadir un permiso de Internet al archivo AndroidManifest.xml, ábrelo y añade:
<uses-permission android:name="android.permission.INTERNET" />
4. Interfaz de usuario
Abre el activity_main.xml y pega el siguiente código:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/LinearLayout1" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <TextView android:id="@+id/textView1" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/str_name" /> <EditText android:id="@+id/txtName" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:ems="10" android:inputType="textPersonName" > <requestFocus /> </EditText> <TextView android:id="@+id/textView2" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="32dp" android:text="@string/str_edad" /> <EditText android:id="@+id/txtAge" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:ems="10" android:inputType="number" /> <Button android:id="@+id/btnGet" android:layout_marginTop="20dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/str_btnGet" /> <Button android:id="@+id/btnPost" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="@string/str_btnPost" /> <TextView android:id="@+id/txtResponse" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:text="@string/str_status" android:textAppearance="?android:attr/textAppearanceLarge" /> </LinearLayout>
Abre el archivo strings.xml y añade:
<string name="str_name">Nombre completo</string> <string name="str_edad">Edad</string> <string name="str_btnGet">Enviar por GET</string> <string name="str_btnPost">Enviar por Post</string> <string name="str_status">Status:</string>
Guarda todo y en el diseñador gráfico debes tener algo como esto:
Si todo bien continuemos
5. MyRestFulGP
Como dijimos al principio, esta clase nos permite trabajar con el API REST implementando dos métodos uno para GET y otro para POST, el código es pequeño y esta comentado. Lo importante aquí es indicar en la variable HTTP_EVENT la dirección del apirest.php ya sea en local o internet.
package com.bolivia.restfulgp; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URLEncoder; import java.util.UUID; import org.apache.http.Header; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; 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.message.BasicHeader; import org.apache.http.protocol.HTTP; import org.json.JSONException; import org.json.JSONObject; import android.util.Log; public class MyRestFulGP { private final String HTTP_EVENT="http://localhost/api/apirest.php"; private HttpClient httpclient; /** * Envia los datos por GET * @throws IOException * @throws ClientProtocolException * @throws JSONException * */ public String addEventGet(String name, String age) throws ClientProtocolException, IOException, JSONException { httpclient = new DefaultHttpClient(); //los datos a enviar String uuid = UUID.randomUUID().toString(); name = URLEncoder.encode(name,"UTF-8"); age = URLEncoder.encode(age,"UTF-8"); //url, cabecera JSON y ejecuta HttpGet httpget = new HttpGet(HTTP_EVENT + "?name="+name+"&age="+age+"&uuid="+uuid ); httpget.addHeader("Content-Type", "application/json"); HttpResponse response = httpclient.execute(httpget); //obtiene la respuesta del servidor se transforma a objeto JSON String jsonResult = inputStreamToString(response.getEntity().getContent()).toString(); JSONObject object = new JSONObject(jsonResult); Log.i("jsonResult",jsonResult); if( object.getString("Result").equals("200")) { return "Petición GET: Exito"; } return "Petición GET: Fracaso"; } /** * Envia los datos por POST * @throws IOException * @throws ClientProtocolException * @throws JSONException * */ public String addEventPost(String name, String age) throws ClientProtocolException, IOException, JSONException { httpclient = new DefaultHttpClient(); String uuid = UUID.randomUUID().toString(); //url y tipo de contenido HttpPost httppost = new HttpPost(HTTP_EVENT); httppost.addHeader("Content-Type", "application/json"); //forma el JSON y tipo de contenido JSONObject jsonObject = new JSONObject(); jsonObject.put("uuid", uuid ); jsonObject.put("name", name ); jsonObject.put("age", age ); StringEntity stringEntity = new StringEntity( jsonObject.toString()); stringEntity.setContentType( (Header) new BasicHeader(HTTP.CONTENT_TYPE, "application/json")); httppost.setEntity(stringEntity); //ejecuta HttpResponse response = httpclient.execute(httppost); //obtiene la respuesta y transorma a objeto JSON String jsonResult = inputStreamToString(response.getEntity().getContent()).toString(); JSONObject object = new JSONObject(jsonResult); Log.i("jsonResult",jsonResult); if( object.getString("Result").equals("200")) { return "Petición POST: Exito"; } return "Petición POST: Fracaso"; } /** * Transforma el InputStream en un String * @return StringBuilder * */ private StringBuilder inputStreamToString(InputStream is) { String line = ""; StringBuilder stringBuilder = new StringBuilder(); BufferedReader rd = new BufferedReader( new InputStreamReader(is) ); try { while( (line = rd.readLine()) != null ) { stringBuilder.append(line); } } catch( IOException e) { e.printStackTrace(); } return stringBuilder; } }
Vemos que en esta clase, hacemos uso de una variable llamada UUID el cual generamos con randomUUID y tiene la forma de «ecf02d7e-c10a-4904-aad1-1bb294845ac0«, UUID son las siglas en inglés de Identificador Universalmente Único y se usa para que las peticiones que lleguen al servidor, no sean repetidas, esto porque a un api rest le llegan cientos sino es que miles de peticiones y este debe saber como identificarlas para por ejemplo no insertar el mismo registro dos veces. En el ejemplo de este post, no se le esta dando ningún uso, sin embargo hay que tenerlo en cuenta para futuros proyectos.
6. MyAsyncTask
Esta clase que se extiende de AsyncTask nos permite realizar tareas en segundo plano, mostrará un ProgressDialog mientras se realiza la tarea, al terminar pasara el resultado a la interfaz, el resultado es un string.
package com.bolivia.restfulgp; import java.io.IOException; import org.apache.http.client.ClientProtocolException; import org.json.JSONException; import android.app.ProgressDialog; import android.content.Context; import android.os.AsyncTask; import android.widget.TextView; public class MyAsyncTask extends AsyncTask<String,Void,String>{ private ProgressDialog progressDialog; private Context context; TextView textView; /**Constructor de clase */ public MyAsyncTask(Context context, TextView textView) { this.context = context; this.textView = textView; } /** * Realiza la tarea en segundo plano * @param params[0] Comando GET/POST * @param params[1] Nombre * @param params[2] Edad * */ @Override protected String doInBackground(String... params) { if( params[1].length()==0 || params[2].length()==0 ) { return "Todos los campos son obligatorios"; } else { MyRestFulGP myRestFulGP = new MyRestFulGP(); try { if( params[0].equals("GET")) { return myRestFulGP.addEventGet(params[1],params[2]); }else if( params[0].equals("POST")) { return myRestFulGP.addEventPost(params[1],params[2]); } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } } return ""; } /** * Antes de comenzar la tarea muestra el progressDialog * */ @Override protected void onPreExecute() { super.onPreExecute(); progressDialog = ProgressDialog.show( context, "Por favor espere", "Procesando..."); } /** * Cuando se termina de ejecutar, cierra el progressDialog y retorna el resultado a la interfaz * **/ @Override protected void onPostExecute(String resul) { progressDialog.dismiss(); textView.setText(resul); } }
7. MainActivity
Para terminar implementaremos en el MainActivity el evento CLIC para los botones GET y POST que ejecutaran una instancia del MyAsyncTask para cada una de las peticiones de la siguiente manera:
public class MainActivity extends Activity { Button btnGet; Button btnPost; EditText txtName; EditText txtAge; TextView txtResponse; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnGet = (Button) findViewById( R.id.btnGet ); btnPost = (Button) findViewById( R.id.btnPost ); txtName = (EditText) findViewById( R.id.txtName ); txtAge = (EditText) findViewById( R.id.txtAge ); txtResponse = (TextView) findViewById( R.id.txtResponse ); //Evento para el boton GET btnGet.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View view) { new MyAsyncTask(MainActivity.this, txtResponse) .execute("GET", txtName.getText().toString(), txtAge.getText().toString()); } }); //Evento para el boton POST btnPost.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View view) { new MyAsyncTask(MainActivity.this, txtResponse) .execute("POST", txtName.getText().toString(), txtAge.getText().toString()); } }); }
Ejecuta
Si la petición tuvo éxito te avisara en la interfaz, así tambien las peticiones que se envien tanto por GET como por POST, se almacenaran en un archivo de texto en el servidor con el nombre de log.txt, después de realizar unas cuantas peticiones al apirest, el archivo log tendrá la forma de:
------------------------------------------------------------------------------- GET :: {"name":"Lago Losina","age":"23","uuid":"da29ec34-a45d-4e78-be4d-f0f844815ea2"} ------------------------------------------------------------------------------- POST :: {"age":"65","name":"Subiran Alatorre","uuid":"eeac4133-6ee7-4411-962f-4b8705953d5b"} -------------------------------------------------------------------------------
enjoy!!!
En este post veremos una muy pequeña introducción de lo que es el mundo de la programación en shell de Linux. Necesitamo[...]
Uno de los mayores problemas que se presenta en el desarrollo de una aplicación, es el acceso a la base de datos y el mé[...]
En la estructura del proyecto, nuestro modelo mvc esta compuesto por tres paquetes, la vista, el modelo y controlador. L[...]
El SystemTray/Bandeja del Sistema o como también se le llama «Área de Notificación» es la sección de la barra de tareas[...]
Se utiliza la paginación para poder mostrar al usuario una gran cantidad de datos de una forma ordenada en forma de «pag[...]
El JTable de Java es un gran componente para mostrar datos en una tabla de una forma rápida y sencilla, sin embargo en v[...]