Tecnologías Móviles
clase 6
Ejercicio de la clase anterior
REST API
Ejercicio de la clase anterior
public class RestClient {
public static Context context;
private static class Config {
public String url = null;
public String method = null;
public Result handler = null;
public JSONObject data = null;
}
private static class BGResult {
public String error = null;
public String result = null;
public Result handler = null;
}
public interface Result {
public void onResult(Object result);
public void onError(String message);
}
...
}
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
RestClient
AndroidManifest
Ejercicio de la clase anterior - RestClient
public class RestClient {
...
public static void get(String url, Result handler) {
Config config = new Config();
config.handler = handler;
config.method = "GET";
config.url = url;
ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
new RestTask().execute(config);
} else {
handler.onError("No internet connection.");
}
}
public static void post(String url, JSONObject data, Result handler) throws IOException {
Config config = new Config();
config.handler = handler;
config.url = url;
config.method = "POST";
config.data = data;
ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
new RestTask().execute(config);
} else {
handler.onError("No internet connection.");
}
}
...
}
Ejercicio de la clase anterior - RestClient
public class RestClient {
...
public static void put(String url, JSONObject data, Result handler) throws IOException {
Config config = new Config();
config.handler = handler;
config.url = url;
config.method = "PUT";
config.data = data;
ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
new RestTask().execute(config);
} else {
handler.onError("No internet connection.");
}
}
public static void delete(String url, Result handler) {
Config config = new Config();
config.handler = handler;
config.method = "DELETE";
config.url = url;
ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
new RestTask().execute(config);
} else {
handler.onError("No internet connection.");
}
}
...
}
Ejercicio de la clase anterior - RestClient
public class RestClient {
...
private static class RestTask extends AsyncTask<Config, Void, BGResult>{
protected BGResult doInBackground(Config... configs) {
Config config=configs[0];
OutputStreamWriter writer = null;
BGResult result = new BGResult();
result.handler = config.handler;
try {
URL url = new URL(config.url);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod(config.method);
conn.setDoInput(true);
if(config.data != null) {
conn.setDoOutput(true);
conn.setChunkedStreamingMode(0);
conn.setRequestProperty("Content-Type", "application/json");
writer = new OutputStreamWriter(
conn.getOutputStream());
writer.write(config.data.toString());
writer.close();
}
result.result = IOUtils.toString(conn.getInputStream());
} catch (IOException e) {
result.error = e.getMessage();
} finally {
if(writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
...
}
Ejercicio de la clase anterior - RestClient
public class RestClient {
...
private static class RestTask extends AsyncTask<Config, Void, BGResult>{
...
@Override
protected void onPostExecute(BGResult result) {
if(result.error != null) {
result.handler.onError(result.error);
} else {
JSONTokener tokener = new JSONTokener(result.result);
try {
result.handler.onResult(tokener.nextValue());
} catch (JSONException e) {
result.handler.onError(e.getMessage());
}
}
}
}
}
Ejercicio de la clase anterior - UserAdapter
public class UserAdapter extends BaseAdapter {
private Context mContext;
public static String mUrl = "http://tm5-agmoyano.rhcloud.com/";
private RestClient.Result resultHandler = null;
JSONArray usrs = new JSONArray();
public void fetchUsers() {
RestClient.get(mUrl, new RestClient.Result() {
@Override
public void onResult(Object result) {
usrs = (JSONArray) result;
notifyDataSetChanged();
}
@Override
public void onError(String message) {
Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show();
}
});
}
...
}
Ejercicio de la clase anterior - UserAdapter
public class UserAdapter extends BaseAdapter {
...
public UserAdapter(Context context) {
mContext = context;
resultHandler = new RestClient.Result() {
@Override
public void onResult(Object result) {
fetchUsers();
}
@Override
public void onError(String message) {
Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show();
}
};
}
...
public JSONObject getItem(int position) {
try {
return usrs.getJSONObject(position);
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
...
}
Ejercicio de la clase anterior - UserAdapter
public class UserAdapter extends BaseAdapter {
...
public void rmItem(int position) {
RestClient.delete(mUrl + String.valueOf(position), resultHandler);
}
public void addItem(JSONObject usuario) {
try {
RestClient.post(mUrl, usuario, resultHandler);
} catch (IOException e) {
e.printStackTrace();
}
}
public void setItem(Integer pos, JSONObject usuario) {
try {
RestClient.put(mUrl+pos, usuario, resultHandler);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Service
Componente que permite realizar operaciones de larga duración.
No provee interfaz de usuario.
Siempre es iniciado por otro componente, y puede seguir corriendo aunque la aplicación que lo inició haya terminado.
Otros componentes pueden vincularse (bind) al service para interactuar con el mismo.
Un service corre en el thread principal del proceso que lo creó, por lo que operaciones pesadas deberían utilizar AsyncTask u otro mecanismo.
Service
Un service puede tomar 2 estados:
- Started: Un service está en estado "started" cuando otro componente lo inició mediante startService(). Este tipo de service puede correr en background inclusive si el componente que lo inició fue destruido. Cuando concluye todas sus tareas, el service debería parar su ejecución.
- Bound: Un service está en estado "bound" cuando otro componente realiza un "bindService()". Este tipo de service ofrece una interface que permite a otros componentes interactuar con él mismo. A demás, sólo vive mientras que haya al menos un componente vinculado al mismo.
Service
- onStartCommand(): Se llama cuando un componente llamó a startService(). Ahora el service se ejecuta indefinidamente. Se debe parar con stopSelf() o stopService() desde un cliente.
- onBind(): Se llama cuando un cliente se quiere vincular al service. Devuelve un objeto que implemente la interfaz IBinder.
- onUnbind(): Se llama cuando todos los componentes llamaron a unbindService().
Service - Ejemplo de Service
public class LocalService extends Service {
// Binder given to clients
private final IBinder mBinder = new LocalBinder();
// Random number generator
private final Random mGenerator = new Random();
/**
* Class used for the client Binder. Because we know this service always
* runs in the same process as its clients, we don't need to deal with IPC.
*/
public class LocalBinder extends Binder {
LocalService getService() {
// Return this instance of LocalService so clients can call public methods
return LocalService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/** method for clients */
public int getRandomNumber() {
return mGenerator.nextInt(100);
}
}
Service - Ejemplo de bind
public class BindingActivity extends Activity {
/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
...
}
Service - Ejemplo de bind
public class BindingActivity extends Activity {
...
protected void onStart() {
super.onStart();
// Bind to LocalService
Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
protected void onStop() {
super.onStop();
// Unbind from the service
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
/** Called when a button is clicked (the button in the layout file attaches to
* this method with the android:onClick attribute) */
public void onButtonClick(View v) {
if (mBound) {
int num = mService.getRandomNumber();
Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
}
}
}
Ejercicio
A la aplicación creada en el ejercicio de la clase anterior, crear un service que viva el mismo tiempo que la aplicación que lo creó.
El service se debe encargar de toda la comunicación con la api rest.
El service debe obtener la lista de usuarios cada 5 segundos, y se debe refrescar en el ListView.
Tecnologías Móviles - Clase 6
By Agustin Moyano
Tecnologías Móviles - Clase 6
- 616