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:

  1. 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.
  2. 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

  • 609