android - notification - Programo una Notificación local en una hora específica, usando el interruptor pero no se activa a la hora establecida
notificaciones push ionic 3 (2)
Estoy usando un interruptor que, cuando se enciende, activará la alarma e iniciará las notificaciones.
Inicialmente funcionó bien y activó la alarma a la hora establecida. Después de cambiar la hora manualmente, comenzó a funcionar la notificación extraña se activa al instante cuando se enciende el interruptor, pero no en el tiempo establecido especificado.
Aquí está el código para el cambio:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
aSwitch = (Switch) findViewById(R.id.switch1);
prefs = PreferenceManager.getDefaultSharedPreferences(this);
Boolean switchState = prefs.getBoolean("locked", false);
if(switchState) {
aSwitch.setChecked(true);
} else {
aSwitch.setChecked(false);
}
aSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked) {
prefs.edit().putBoolean("locked", true).apply();
NotificationEventReceiver.setupAlarm(getApplicationContext());
aSwitch.setChecked(true);
} else {
prefs.edit().putBoolean("locked", false).apply();
NotificationEventReceiver.cancelAlarm(getApplicationContext());
aSwitch.setChecked(false);
}
}
});
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
}
Cuando se activa el interruptor, activará las notificaciones utilizando el receptor WakefullBroadcast
.
Aquí está el código para la clase de receptor:
public class NotificationEventReceiver extends WakefulBroadcastReceiver {
private static final String ACTION_START_NOTIFICATION_SERVICE = "ACTION_START_NOTIFICATION_SERVICE";
private static final String ACTION_DELETE_NOTIFICATION = "ACTION_DELETE_NOTIFICATION";
public static void setupAlarm(Context context) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 07);
calendar.set(Calendar.MINUTE, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent alarmIntent = getStartPendingIntent(context);
alarmManager.setExact(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(),
alarmIntent);
}
public static void cancelAlarm(Context context) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent alarmIntent = getStartPendingIntent(context);
if(alarmManager!= null) {
alarmManager.cancel(alarmIntent);
}
}
private static PendingIntent getStartPendingIntent(Context context) {
Intent intent = new Intent(context, NotificationEventReceiver.class);
intent.setAction(ACTION_START_NOTIFICATION_SERVICE);
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
public static PendingIntent getDeleteIntent(Context context) {
Intent intent = new Intent(context, NotificationEventReceiver.class);
intent.setAction(ACTION_DELETE_NOTIFICATION);
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Intent serviceIntent = null;
if (ACTION_START_NOTIFICATION_SERVICE.equals(action)) {
Log.i(getClass().getSimpleName(), "onReceive from alarm, starting notification service");
serviceIntent = NotificationIntentService.createIntentStartNotificationService(context);
} else if (ACTION_DELETE_NOTIFICATION.equals(action)) {
Log.i(getClass().getSimpleName(), "onReceive delete notification action, starting notification service to handle delete");
serviceIntent = NotificationIntentService.createIntentDeleteNotification(context);
}
if (serviceIntent != null) {
// Start the service, keeping the device awake while it is launching.
startWakefulService(context, serviceIntent);
}
}
}
Y usé el servicio para activar la notificación.
Aquí hay un código para el servicio en segundo plano:
public class NotificationIntentService extends IntentService {
private static final int NOTIFICATION_ID = 1;
private static final String ACTION_START = "ACTION_START";
private static final String ACTION_DELETE = "ACTION_DELETE";
public NotificationIntentService() {
super(NotificationIntentService.class.getSimpleName());
}
public static Intent createIntentStartNotificationService(Context context) {
Intent intent = new Intent(context, NotificationIntentService.class);
intent.setAction(ACTION_START);
return intent;
}
public static Intent createIntentDeleteNotification(Context context) {
Intent intent = new Intent(context, NotificationIntentService.class);
intent.setAction(ACTION_DELETE);
return intent;
}
@Override
protected void onHandleIntent(Intent intent) {
Log.d(getClass().getSimpleName(), "onHandleIntent, started handling a notification event");
try {
String action = intent.getAction();
if (ACTION_START.equals(action)) {
processStartNotification();
}
} finally {
WakefulBroadcastReceiver.completeWakefulIntent(intent);
}
}
private void processDeleteNotification(Intent intent) {
// Log something?
}
private void processStartNotification() {
// Do something. For example, fetch fresh data from backend to create a rich notification?
final NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentTitle("Scheduled Notification")
.setAutoCancel(true)
.setColor(getResources().getColor(R.color.colorAccent))
.setContentText("This notification has been triggered by Notification Service")
.setSmallIcon(R.drawable.notification_icon);
Intent mainIntent = new Intent(this, NotificationActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
NOTIFICATION_ID,
mainIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(pendingIntent);
builder.setDeleteIntent(NotificationEventReceiver.getDeleteIntent(this));
final NotificationManager manager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(NOTIFICATION_ID, builder.build());
}
}
Editar 1
Aquí está el registro:
06-23 11:19:56.807 5630-5630/logi.com.notificationbyschedule I/String: On setupAlarm
06-23 11:19:56.807 5630-5630/logi.com.notificationbyschedule I/String: PendingIntent Started
06-23 11:19:56.809 5630-5630/logi.com.notificationbyschedule V/AAAAA-AlarmManager: logi.com.notificationbyschedule
06-23 11:19:56.810 978-4653/? I/AlarmManager/AlarmPowerSavingMode: the following package : logi.com.notificationbyschedule is trusted app
06-23 11:19:56.810 978-4653/? I/AlarmManager/AlarmPowerSavingMode: logi.com.notificationbyschedule not in the white list or system app, do not use exact interface.
06-23 11:19:56.810 978-4653/? I/AlarmManager/AlarmPowerSavingMode: logi.com.notificationbyschedule in whitelist or system app not forece batched
06-23 11:19:56.810 978-4653/? V/AlarmManager: set(PendingIntent{16198c6a: PendingIntentRecord{1ed2c203 logi.com.notificationbyschedule broadcastIntent}}) : type=0 triggerAtTime=1466645456807 win=-1 tElapsed=309263486 maxElapsed=309263486 interval=0 standalone=true intent=Intent { act=ACTION_START_NOTIFICATION_SERVICE cmp=logi.com.notificationbyschedule/.broadcast_receivers.NotificationEventReceiver }
06-23 11:19:56.813 978-4014/? I/AlarmManager/AlarmPowerSavingMode: logi.com.notificationbyschedule Wakeup System : 6 times
06-23 11:19:56.836 5630-5630/logi.com.notificationbyschedule I/NotificationEventReceiver: onReceive from alarm, starting notification service
06-23 11:19:56.836 5630-5630/logi.com.notificationbyschedule I/String: CreateIntentServiceStart
06-23 11:19:56.967 5630-11858/logi.com.notificationbyschedule D/NotificationIntentService: onHandleIntent, started handling a notification event
06-23 11:19:56.967 5630-11858/logi.com.notificationbyschedule I/String: ProcessStartNotification
06-23 11:19:56.974 5630-11858/logi.com.notificationbyschedule I/String: PendingIntent Deleted
06-23 11:23:58.820 5630-5630/logi.com.notificationbyschedule I/String: On CancelAlarm
06-23 11:23:58.820 5630-5630/logi.com.notificationbyschedule I/String: PendingIntent Started
06-23 11:23:58.823 5630-5630/logi.com.notificationbyschedule I/String: Inside alarmManager not null
Intenta cambiar el método de activación a esto:
private static long getTriggerAt(Date now) {
Calendar calendar = new GregorianCalendar();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 7);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
if (System.currentTimeMillis() > calendar.getTimeInMillis()){
calendar.setTimeInMillis(calendar.getTimeInMillis()+ 24*60*60*1000);// Okay, then tomorrow ...
}
return calendar.getTimeInMillis();
}
Te permitirá configurar la alarma después del 24 de abril
Para cualquiera que busque una buena solución para lograr lo anterior, también consulte esta página: https://developer.android.com/topic/performance/scheduling.html
Personalmente, soy un fanático de la solución Firebase JobDispatcher, que ofrece una solución robusta que incluso puede desencadenar eventos programados durante el reinicio de un dispositivo.