Acceder

Ver la Versión Completa : [ CONSULTA ] Notificaciones en Android


kaiser75
12/06/17, 12:37:55
Vereis, tengo una aplicacion la cual le quiero añadir notificaciones, el tema es que no se cual es el mejor metodo para hacerlo cuidando al maximo la bateria del dispositivo, bien sea con notificaciones en la propia app (Service, AlarmManager, etc) o el servicio Firebase de Google?

mocelet
12/06/17, 13:51:42
Habría que distinguir si hablamos de notificaciones generadas por un servidor (notificaciones push) o si hablamos de mostrar una notificación programada por la app en local a modo de recordatorio.

Para lo primero Google/Firebase Cloud Messaging, para lo segundo el AlarmManager.

kaiser75
12/06/17, 16:12:21
Pues creo que seria una especie de recordatorio, incluso si la app esta cerrada.

kaiser75
24/07/17, 21:08:29
Bueno, ya tengo implementado el sistema de notificaciones y funcionando correctamente. Queria saber ahora es si hay manera de cancelar la alarma al pulsar en el intent que me abre la actividad cuando pulso sobre la notificacion, o es mejor cancelarla por ejemplo cuando se dispara y te mustra la notificacion esperar unos 10,15 segundos y con un Handler cancelarla?

mocelet
24/07/17, 22:00:06
No he entendido muy bien a qué te refieres y qué quieres cancelar exactamente.

Las alarmas puedes cancelarlas desde donde quieras, únicamente necesitas construir un Intent igual que el que va a lanzarse y pasárselo al cancel del AlarmManager.

P.D: ¿Has considerado también el caso de que el teléfono se apague y vuelva a encenderse? Hay que establecer las alarmas otra vez porque entre reinicios se pierden

kaiser75
24/07/17, 23:36:11
El boot completed lo he puesto y al apagar y encender el telefono me sigue funcionando el alarmManager si estan activadas las notificaciones, lo que quiero hacer es una vez me haya saltado la notificacion cuando el usuario pulse la notificacion (por defecto abre una activity) se cancele el alarmManager. Las notificaciones las activo y desactivo desde la pantalla de preferencias con un checkbox, luego con un "Calendar" y unas fechas y dias concretos se activa el alarmManager y salta la notification a una hora concreta.

kaiser75
27/07/17, 12:30:34
Hay manera de poder cancelar el AlarmManager al pulsar la notificacon o al desplazar a la izda/dcha para borrar la notificacion?

mocelet
27/07/17, 13:56:10
Tanto al pulsar como al borrar puedes hacer que se llame al intent que quieras (con el contentIntent y el deleteIntent al construir la notificación) y ahí ya cancelas lo que necesites.

kaiser75
29/07/17, 20:37:41
Pues no doy con el tema, Tengo el AlarmManager que dispara la notificacion a un dia especifico, ahi todo correcto, la alarma la uso con "PendigIntent.FLAG_ONE_SHOT" (suponiendo que sea esta opcion :rolleyes:) ya que no quiero que se repita hasta otra fecha especifica, ya que quiero que se muestre la misma notificacion pero en diferentes fechas a lo largo del año. La cuestion es si al disparar un alarmManager por ejemplo el dia 24, hay que detener despues la alarma para que se dispare por ejemplo el dia 29?

Tengo una clase "Alarm" con este codigo, que me dispara la notificacion por ejemplo dia 24 a las 18:30 (funciona correctamente), pero la siguiente de dia 29 ya no la muestra, hay que detener la anterior para poder activar otra vez alarmManager?


public void startAlarm()... // se activa desde ajustes con un checkbox

Calendar calendar = Calendar.getInstance();
...todo lo del calendar aqui...

if (month == Calendar.JULY && diaDelMes == 24 && hour == 18 && min <= 30) {
activarNot(context,calendar);
}
if (month == Calendar.JULY && diaDelMes == 29 && hour == 18 && min <= 30) {
activarNot(context,calendar);
}
... etc mas fechas

// Activar alarmmanager
public void activarNot(Context context, Calendar calendar){
aManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
Intent alarmIntent = new Intent(context, Notificacion.class);
pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, PendingIntent.FLAG_ONE_SHOT);
aManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);

ComponentName receiver = new ComponentName(context, AutoStart.class);
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
}

// Detener la Alarma
public void stopAlarm(Context context) {
if (aManager != null) {
aManager.cancel(pendingIntent);
}

ComponentName receiver = new ComponentName(context, AutoStart.class);
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
}

mocelet
29/07/17, 20:48:17
Si quieres activar dos alarmas tienes que asignarle un requestCode de broadcast diferente a cada una. Según está le pasas 0 a todas las alarmas que creas y el PendingIntent para android es como si fuera el mismo, que quizá por eso no se te dispara.

PendingIntent.getBroadcast(context, 0, alarmIntent, PendingIntent.FLAG_ONE_SHOT);

Ese 0 de ahí tiene que ser diferente para la alarma del 24 y para la del 29 (que siendo un entero puedes pasarle simplemente el 24 o el 29 y así sabes qué pending intent corresponde a cada una rápidamente sin tener que guardar ids ni nada)

Edit: Además no entiendo del código que has puesto, ¿al startAlarm cuándo lo llamas exactamente? Porque según está o programa una alarma o programa otra, pero nunca las dos. Así que cuando salga la del 24 tendrás que programar la del 29 o bien programar las dos a la vez, si no solo tendrás una notificación.

kaiser75
30/07/17, 20:08:13
Edit: Además no entiendo del código que has puesto, ¿al startAlarm cuándo lo llamas exactamente? Porque según está o programa una alarma o programa otra, pero nunca las dos. Así que cuando salga la del 24 tendrás que programar la del 29 o bien programar las dos a la vez, si no solo tendrás una notificación.


El startAlarm lo activo en las preferencias de la aplicacion, con un checkbox, check = startAlarm, uncheck = stopAlarm.
Intento que en las preferencias al marcar el checkbox me active el alarmmanager, que me funciona correctamente y como tu bien has dicho mocelet, solo me muestra una notificacion.
Resumiendo... activar alarmManager con un "if()" dentro de startAlarm para que me muestre la notificacion en diferentes fechas del calendario.


if (month == Calendar.JULY && diaDelMes == 24 && hour == 18 && min <= 30) {
activarNot(context,calendar); // solo muestra esta notificacion
}
if (month == Calendar.JULY && diaDelMes == 29 && hour == 18 && min <= 30) {
// aqui crear otro alamrmanager o se puede usar el de dia 24 por ejemplo?
}

//...etc

mocelet
30/07/17, 20:45:14
Sigo sin entender el porqué de esos if. ¿Qué es ese month, diaDelMes, hour y min? ¿La hora actual? ¿Y el calendar que le pasas para la notificación qué es entonces? ¿Es lo mismo?

¿Qué necesidad hay de comparar fechas, horas y minutos si luego la llamada a activarNot es siempre la misma?

Sin conocer más de la app en sí da la impresión que todo eso sobra, lo que tendrás que hacer en el startAlarm es programar las siguientes alarmas que te haga falta programar, con su fecha y su pending intent.

AlarmManager solo hay uno, es un servicio de Android. PendingIntent sí que es posible que tengas que crear varios (con distintos requestCodes si quieres controlar cada uno por separado)

kaiser75
31/07/17, 11:58:30
Bueno ya he conseguido mostrar la notificacion en diferentes horas y dias lanzando la misma notificacion, como tu has dicho mocelet no hay necesidad de comparar fechas, horas y minutos si luego la llamada a activarNot es siempre la misma, por lo que he puesto todo lo relacionado con Calendar en la clase activarNot() con un id diferente en cada una y llamando despues a esta clase sin comparar nada, simplemente poniendo la fecha y la hora que quiero la notificacion.

quedandome ahora asi

// id pIntent, mes, dia, hora, min, sec
activarNot(context,24,8,24,18,30,0);
activarNot(context,29,8,29,18,30,0);
...etc


Otra duda que me queda es acerca de las banderas del pendingIntent, actualmente uso pendingIntent.FLAG_ONE_SHOT, eso quiere decir que se dispara el una vez solo no?, y si uso por ejemplo pendingIntent.FLAG_UPDATE_CURRENT ? se actualizaria la notificacion? por ejemplo en caso de que el usuario no haya borrado la anterior?

kaiser75
21/08/17, 12:35:59
Una pregunta, cuando estableceis una hora y minutos en AlarmManager, es indiferente si por ejemplo la hora es 5 y 5 de la mañana que usariamos?

ponemos 0 o no?
calendar.set(Calendar.HOUR_OF_DAY, 5);
calendar.set(Calendar.MINUTE, 05);

Porque poniendo por ejemplo las 08:05 de la mañana o 8:5 me funciona igual :rolleyes:

mocelet
21/08/17, 14:03:06
ponemos 0 o no?
calendar.set(Calendar.MINUTE, 05);


Da igual, es un parámetro de tipo int, no es una String.

Cómo lo escribas en el editor da igual, 05 y 5 matemáticamente es el mismo entero y el compilador lo va a tratar como tal. Es como si haces un calendar.set(Calendar.MINUTE, 2 + 3)

Otra cosa sería que usaras los parsers y tuvieras que escribir la hora formateada como String, entonces sí que tendrás que escribir la String de acuerdo a cómo se suele representar la hora, esto es, con dos dígitos para los minutos ("5:05" o "05:05").

kaiser75
22/08/17, 16:32:02
Queda claro... Gracias mocelet :ok:

kaiser75
22/09/17, 12:00:58
Retomo el post, ya tengo el tema de las notificaciones funcionando correctamente, bueno casi, tengo creadas notificaciones programadas en la aplicacion con AlarmManager y un "BroadcastReceiver" que me reactiva las alarmas al reiniciar o apagar el telefono, el problema que tengo es que por ejemplo con Android 4.0 me funciona perfecto, pero con 6.0, 7.0 no, al apagar el movil y encenderlo de nuevo ya no se activan mas, creo que por problema con Doze, sabeis alguna manera de solucionar el problema?

Uso "aManager.setAndAllowWhileIdle..." para activar la alarma en Android 6.0 y 7.0
"aManager.setExact..." en KitKat
y "aManager.set..." en 4.0 y anteriores

kaiser75
20/01/18, 10:35:26
Vereis, tengo un monton de alarmas que muestran una notificacion en determinadas fechas a la misma hora, al activar las alarmas estas funcionan correctamente, pero el problema es que cuando desactivo las alarmas y volverlas a activar por ejemplo pasados Enero y Febrero, se vuelven a activar correctamente, pero se disparan las alarmas ya pasadas, en este caso Enero y Febrero quedando pendiente la de Abril, como se puede prevenir que no se disparen las alarmas ya pasadas?, comparando el mes y el dia?, me tiene ahi encasquillado :rolleyes:.

Este es el codigo para activar las notificaciones

int hora = 10;
int min = 25

public void start_Al() {
activarNot(context, 1, Calendar.JANUARY, 14, hora, min);
activarNot(context, 2, Calendar.FEBRUARY, 25, hora, min);
activarNot(context, 3, Calendar.APRIL, 18, hora, min);
... etc, asi hasta unas 30 Alarmas que muestran la misma notificacion
}

mocelet
20/01/18, 20:53:35
se disparan las alarmas ya pasadas, en este caso Enero y Febrero quedando pendiente la de Abril

En la documentación del AlarmManager indica que si programas una alarma con fecha anterior a la actual se disparará inmediatamente. "If the stated trigger time is in the past, the alarm will be triggered immediately", así que si estás en marzo 2018 no programes las alarmas de enero 2018 y febrero 2018.

Para eso tendrás que comparar las fechas claro. Además, tampoco tiene mucho sentido programar las alarmas de todo el año con antelación, con tener las dos o tres siguientes e ir programando las nuevas cada vez que se notifique una ya basta.

kaiser75
20/01/18, 23:47:33
Gracias por tu respuesta mocelet, antes lo tenia comparando fechas y no funcionaba demasiado bien, aparte de tener mogollon de codigo comparando, activando y desactivando alarmas. Creo que ya lo he solucionado poniendo este pequeño fragmento justo antes de llamar los intents y alarmmanagers, etc , le digo que si la fecha es antes de la actual del dispositivo me añada un dia, asi no me dispara las alarmas pasadas, lo he estado probando hoy en mi movil y funciona correctamente, incluso cuando apagas o reinicias el movil me activa solo las alarmas actuales y no suenan las que ya han pasado.


if (calendar.before(Calendar.getInstance())) {
calendar.add(Calendar.DATE, 1);
}

mocelet
21/01/18, 10:46:46
No he entendido para qué añades un día, si lo que quieres es no activar una alarma que ya ha pasado simplemente ignora esa fecha, ¿no? De hecho, si fueran 12 notificaciones, una mensual, entendería que si la fecha ha pasado añadas un año para así tener siempre programados los 12 meses siguientes incluso si estamos en diciembre.

Sin conocer mucho sobre el código y la lógica interna, sobre el mogollón de código comparando, activando y desactivando me atrevería a decir que estás abusando del copy-paste y podrías simplificarlo con un array que tenga la lista de meses/días y un bucle. De paso te ahorras escribir 30 veces activarNot con todos los parámetros iguales salvo el mes y el día.

kaiser75
21/01/18, 19:37:58
La verdad es que no lo se, pero me funciona correctamente :silbando:, aunque es buena idea lo del array :ok:

kaiser75
16/03/18, 11:02:42
Volviendo al post de las notificaciones, tengo una duda sobre el Alarmmanager, a ver si me podeis echar una mano. Necesito crear una alarma que se ejecute cada X dias a una misma hora, cual es el mejor metodo para conseguirlo?, he hecho la prueba repitiendo cada 5 minutos y funciona correctamente, pero el tema es que:

1- Si pongo por ejemplo 10 dias, como sabe alarmmanager los dias que han pasado desde que se activo? ... en caso de reactivar la alarma?
2- El dispositivo debe apagarse cada dos dias mas o menos y reactivar la alarma al encenderse de nuevo, aqui es donde no entiendo si realmente Alarmmanager tiene en cuenta los dias pasados desde que se activo, o debo decirselo de alguna manera?

Aqui es como activo la repeticion cada 5 min.

// repetir cada 5 min
aManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 1000 * 60 * 5, pendingIntent);

mocelet
16/03/18, 12:32:13
Al AlarmManager le da igual el tiempo que haya pasado, simplemente programa una alarma para el momento que le digas y está pendiente de que llegue ese momento. Si apagas el dispositivo las alarmas se borran y tienes que reprogramarlas, es responsabilidad de tu app echar la cuenta de cuándo toca programarla.