GroovinChip
GroovinChip

Reputation: 375

Scheduling a notification to a specific date and time

I'm the developer of Call Manager, and I'm trying to implement a notification reminder feature to my app. The idea is that the user can set themselves a reminder to call a specific person in the list. At first, when implementing this feature, the notification would show up immediately without being scheduled - this was due to an incorrect setting of values that resulted in negative milliseconds. However, now that I have corrected that, notifications do not get scheduled at all, even though I have the correct millisecond value to give the AlarmManager.

The method that schedules the notification is below:

public void scheduleReminder(Notification notification, String date, String time){
        String[] dateArray = date.split("/");
        String[] timeArray = time.split(":|\\s+");
        Date currentDate = new Date();
        int notHour;

        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(System.currentTimeMillis());
        cal.clear();
        if(timeArray[2].equals("PM")){
            notHour = Integer.parseInt(timeArray[0]);
            notHour = notHour + 12;
            cal.set(Calendar.YEAR, Integer.parseInt(dateArray[2]));
            cal.set(Calendar.MONTH, Integer.parseInt(dateArray[0]) - 1);
            cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(dateArray[1]));
            cal.set(Calendar.HOUR_OF_DAY, notHour);
            cal.set(Calendar.MINUTE, Integer.parseInt(timeArray[1]));
        }
        else{
            cal.set(Calendar.YEAR, Integer.parseInt(dateArray[2]));
            cal.set(Calendar.MONTH, Integer.parseInt(dateArray[0]) - 1);
            cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(dateArray[1]));
            cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(timeArray[0]));
            cal.set(Calendar.MINUTE, Integer.parseInt(timeArray[1]));
        }

        Date reminderDate = cal.getTime();
        long diffInMillis  = reminderDate.getTime() - currentDate.getTime();

        Intent notificationIntent = new Intent(this, NotificationPublisher.class);
        notificationIntent.putExtra(NotificationPublisher.NOTIFICATION_ID, 1);
        notificationIntent.putExtra(NotificationPublisher.NOTIFICATION, notification);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

        AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
        alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + diffInMillis, pendingIntent);
    }

My Broadcast receiver class is as follows:

package groovinchip.com.callmanager;

import android.app.Notification;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class NotificationPublisher extends BroadcastReceiver {

    public static String NOTIFICATION_ID = "notification-id";
    public static String NOTIFICATION = "notification";

    @Override
    public void onReceive(Context context, Intent intent) {
        NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);

        Notification notification  = intent.getParcelableExtra(NOTIFICATION);
        int id = intent.getIntExtra(NOTIFICATION_ID, 0);
        notificationManager.notify(id, notification);
    }
}

And the relevant Android Manifest declarations are as follows:

<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

<receiver android:name="groovinchip.com.callmanager.NotificationPublisher"
     android:enabled="true">
</receiver>

I'm stumped as to why this isn't working - I've pored over my Google results trying to figure it out. I've switched between: 1) Setting AlarmManager with System.ELAPSED_REALTIME_WAKEUP 2) Passing SystemClock.elapsedRealTime() + diffInMillies 3) Only passing diffInMillis 4) passing an Integer value representing only a few seconds instead of diffInMillis to see if it would work at all

Anyone able to help with this? Thank you so much!

Upvotes: 0

Views: 2511

Answers (1)

David Yarzebinski
David Yarzebinski

Reputation: 56

When you create your Notification are you setting a channel id? If you are testing on API 26 the alarm will not go off if there isn't one set, as well as a a channel in the broadcast receiver.

I have two methods that create and set the reminder from a timepicker and an alarm that the user chooses. Here is the source code for them

private void createReminder(Notification notification) {
    Intent notificationIntent = new Intent(this, NotificationPublisher.class);
    notificationIntent.putExtra(NotificationPublisher.NOTIFICATION_ID, 1);
    notificationIntent.putExtra(NotificationPublisher.NOTIFICATION, notification);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    long delay = alarmCalendar.getTimeInMillis() - Calendar.getInstance().getTimeInMillis();
    long futureInMillis = SystemClock.elapsedRealtime() + delay;
    AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, futureInMillis, pendingIntent);
}

private Notification getNotification() {
    String channelId = "Reminders";
    PendingIntent newEntryActivityPendingIntent = PendingIntent.getActivity(this, 1, new Intent(this, NewEntryActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);
    NotificationCompat.Builder builder = new NotificationCompat.Builder(this, channelId)
            .setContentTitle(getString(R.string.app_name))
            .setContentText(getString(R.string.reminder_content))
            .setTicker(getString(R.string.app_name))
            .setSmallIcon(R.drawable.notebook_notification_white)
            .setDefaults(Notification.DEFAULT_SOUND)
            .setAutoCancel(true)
            .setContentIntent(newEntryActivityPendingIntent);
    Log.i(TAG, "notification built");
    return builder.build();
}

In my app I have a notification reminder and I have a seperate class for my broadcast reciever similar to you and this how mine looks

    public class NotificationPublisher extends BroadcastReceiver {

    private static final String TAG = "NotificationPublisher";
    public static String NOTIFICATION_ID = "notification-id";
    public static String NOTIFICATION = "notification";

    @Override
    public void onReceive(Context context, Intent intent) {
        NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        if (Build.VERSION.SDK_INT >= 26) {
            NotificationChannel channel = new NotificationChannel("Reminders", "Reminders", NotificationManager.IMPORTANCE_DEFAULT);
            notificationManager.createNotificationChannel(channel);
        }
        Notification notification = intent.getParcelableExtra(NOTIFICATION);
        int id = intent.getIntExtra(NOTIFICATION_ID, 0);
        Log.i(TAG, "notification sent");
        notificationManager.notify(id, notification);
    }
}

Almost exactly like yours, from the looks of it.

And this works well for me. Let me know if I can help any other way.

Upvotes: 2

Related Questions