clase 6
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
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.");
}
}
...
}
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.");
}
}
...
}
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;
}
...
}
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());
}
}
}
}
}
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();
}
});
}
...
}
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;
}
...
}
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();
}
}
}
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.
Un service puede tomar 2 estados:
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);
}
}
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;
}
};
...
}
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.