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.

Made with Slides.com