Tecnologías Móviles
clase 7
Ejercicio de la clase anterior
REST API
SERVICE
Ejercicio de la clase anterior
public class MainActivity extends AppCompatActivity {
ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mBinder = (ApiClientService.APIBinder) service;
mBinder.setActivity(MainActivity.this);
mBinder.findUsers();
}
@Override
public void onServiceDisconnected(ComponentName name) {
mBinder = null;
}
};
@Override
protected void onStart() {
super.onStart();
Intent i = new Intent(this, ApiClientService.class);
bindService(i, mConnection, BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
unbindService(mConnection);
}
...
}
MainActivity
Ejercicio de la clase anterior
public class MainActivity extends AppCompatActivity {
...
public void rmUser(Integer pos) {
if(mBinder!=null) {
mBinder.rmUser(pos);
}
}
public void setUser(JSONObject user, Integer pos) {
if(user != null) {
if (pos == null) mBinder.addUser(user);
else mBinder.setUser(pos, user);
}
if(isPort) {
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.container, list);
transaction.commit();
}
}
}
MainActivity
Ejercicio de la clase anterior
public class ApiClientService extends Service {
APIBinder mBinder = new APIBinder();
public static String mUrl = "http://tm5-agmoyano.rhcloud.com/";
private Timer timer = new Timer();
public ApiClientService() {
}
@Override
public void onCreate() {
timer.schedule(new TimerTask() {
@Override
public void run() {
mBinder.findUsers();
}
}, 0, 5000);
}
@Override
public void onDestroy() {
timer.cancel();
}
...
}
Service
Ejercicio de la clase anterior
public class ApiClientService extends Service {
public class APIBinder extends Binder {
MainActivity mActivity=null;
RestClient.Result resultHandler = new RestClient.Result() {
@Override
public void onResult(Object result) {
findUsers();
}
@Override
public void onError(String message) {
Toast.makeText(ApiClientService.this, message, Toast.LENGTH_SHORT);
}
};
public void setActivity(MainActivity activity) {
mActivity = activity;
}
...
}
...
}
Service
Ejercicio de la clase anterior
public class ApiClientService extends Service {
public class APIBinder extends Binder {
...
public void findUsers() {
if(mActivity != null) {
RestClient.get(mUrl, new RestClient.Result() {
@Override
public void onResult(Object result) {
UserAdapter.getInstance().setUsers((JSONArray) result);
}
@Override
public void onError(String message) {
Toast.makeText(ApiClientService.this, message, Toast.LENGTH_SHORT);
}
});
}
}
public void addUser(JSONObject usuario) {
try {
RestClient.post(mUrl, usuario, resultHandler);
} catch (IOException e) {
e.printStackTrace();
}
}
...
}
...
}
Service
Ejercicio de la clase anterior
public class ApiClientService extends Service {
public class APIBinder extends Binder {
...
public void setUser(Integer pos, JSONObject usuario) {
try {
RestClient.put(mUrl + pos, usuario, resultHandler);
} catch (IOException e) {
e.printStackTrace();
}
}
public void rmUser(Integer pos) {
RestClient.delete(mUrl+pos, resultHandler);
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
Service
Notificaciones
Son mensajes que se le pueden enviar al usuario, fuera de la interfaz de la aplicación.
Las acciones y la información de la interfaz para una notificación se especifican con NotificationCompat.Builder.
Toda notificación debe contener un ícono (setSmallIcon()), un título (setContentTitle()) y un detalle (setContentText()).
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Hello World!");
mNotificationManager.notify(mId, mBuilder.build());
Notificaciones
Se puede setear la prioridad de la notificación (setPriority()). Esto le indica a la UI como debería mostrar esta notificación.
Las prioridades disponibles son
PRIORITY_MIN, PRIORITY_LOW, PRIORITY_DEFAULT,
PRIORITY_HIGH y PRIORITY_MAX
Heads-up notification
Las notificaciones se muestran de esta forma cuando el dispositivo está activo, y la prioridad es una de las 2 mas altas.
Notificaciones
Siempre es recomendable agregar una acción a la notificación, aunque agregar una acción es opcional. Una notificación puede proveer más de una acción.
Una acción está definida por un PendingIntent, que a su vez, contiene el Intent que apunta a un Activity.
Para asociar un PendingIntent con una acción del usuario, se debe pasar como parámetro al método correspondiente de NotificationCompat.Builder.
Por ejemplo, si queremos que se inicie un Activity cuando el usuario hace click en la notificación, debemos pasar el PendingIntent al método setContentIntent()
Notificaciones
Cuando uno inicia un Activity, se debería preservar el comportamiento de navegación esperado por el usuario.
Como setear el PendingIntet depende de la naturaleza del Activity.
- Activity Común: Activity que es parte de la aplicación. En este caso se debe configurar el PendingIntent con un Back Stack que reproduzca el comportamiento normal de la aplicación.
- Activity Especial: Es un Activity que solamente es accesible desde una acción de una notificación. Generalmente se utilizan para ampliar la información de la notificación, que de otra forma sería difícil mostrar.
Notificaciones
Pending Intent de Activity Común
1. Configurar la gerarquía de Activities en AndroidManifest
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ResultActivity"
android:parentActivityName=".MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity"/>
</activity>
Notificaciones
Pending Intent de Activity Común
2. Aplicar el Back Stack basado en el Intent que inicia el Activity
...
Intent resultIntent = new Intent(this, ResultActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack
stackBuilder.addParentStack(ResultActivity.class);
// Adds the Intent to the top of the stack
stackBuilder.addNextIntent(resultIntent);
// Gets a PendingIntent containing the entire back stack
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
...
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(id, builder.build());
Notificaciones
Pending Intent de Activity Especial
1. Configurar el Activity en AndroidManifest
<activity
android:name=".ResultActivity"
...
android:launchMode="singleTask"
android:taskAffinity=""
android:excludeFromRecents="true">
</activity>
Notificaciones
Pending Intent de Activity Especial
2. Construir la notificación
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// Creates an Intent for the Activity
Intent notifyIntent =
new Intent(this, ResultActivity.class);
// Sets the Activity to start in a new, empty task
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
// Creates the PendingIntent
PendingIntent notifyPendingIntent =
PendingIntent.getActivity(
this,
0,
notifyIntent,
PendingIntent.FLAG_UPDATE_CURRENT
);
// Puts the PendingIntent into the notification builder
builder.setContentIntent(notifyPendingIntent);
// Notifications are issued by sending them to the
// NotificationManager system service.
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Builds an anonymous Notification object from the builder, and
// passes it to the NotificationManager
mNotificationManager.notify(id, builder.build());
Notificaciones
Cuando se necesitan enviar múltiples notificaciones del mismo tipo, no se deberían agregar nuevas notificaciones, sino modificar la ya existente.
mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Sets an ID for the notification, so it can be updated
int notifyID = 1;
mNotifyBuilder = new NotificationCompat.Builder(this)
.setContentTitle("New Message")
.setContentText("You've received new messages.")
.setSmallIcon(R.drawable.ic_notify_status)
numMessages = 0;
// Start of a loop that processes data and then notifies the user
...
mNotifyBuilder.setContentText(currentText)
.setNumber(++numMessages);
// Because the ID remains unchanged, the existing notification is
// updated.
mNotificationManager.notify(
notifyID,
mNotifyBuilder.build());
...
Notificaciones
Para eliminar notificaciones, debe pasar uno de los siguientes eventos:
- El usuario desecha la notificación.
- El usuario hace click en la notificación y se configuró setAutoCancel(true)
- Se llamó al método cancel(id) de NotificationManager.
- Se llamó al método cancelAll() de NotificationManager.
Ejercicio - pag. 1
Modificar la aplicación creada en el ejercicio de la clase anterior, para que el service siga activo más allá de la aplicación.
Si la aplicación está activa, no se deben generar notificaciones.
Si la aplicación no está activa, se deben crear notificaciones cuando se agrega un nuevo usuario. Cuando se hace click en la notificación, se debe abrir el Activity y mostrar el listado de usuarios.
Si ya exite una notificación, se debe modificar la misma cuando haya que generar una nueva.
Si hay notificaciones y el usuario ingresa a la aplicación, ya sea porque hizo click en el launcher o en la notificación, las notificaciones existentes deben ser canceladas.
Ejercicio - pag. 2
Tener en cuenta que ahora la API en
http://tm5-agmoyano.rhcloud.com/
ha cambiado.
Cada usuario devuelve un id, y las llamadas a la API con los verbos PUT y DELETE deben incluir dicho id en la url, en lugar de la posición en el array.
Tecnologías Móviles - Clase 7
By Agustin Moyano
Tecnologías Móviles - Clase 7
- 690