7

When my application is launched, it performs an API call and then schedules notifications based on the results. This amounts to around ~10 notifications being scheduled. There seems to be an issue with the timestamp displayed on the actual notification being incorrect.

Since I am creating these notifications and then scheduling an alarm with an AlarmManager, the default time present on the notification will be the time at which the notification is created (System.currentTimeMillis()).

I've tried to use the .setWhen() method on my Notification.Builder to set it to the time I am using to schedule the previously mentioned alarm. This is a little better, however, because notifications are not guaranteed to be delivered at the exact time specified, I often get notifications a few minutes in the past.

Additionally, I tried to manually override the when field on the notification in my BroadcastReceiver, right before .notify() is actually called:

public class NotificationPublisher extends BroadcastReceiver {

    public static String NOTIFICATION_ID = "notification_id";
    public static String NOTIFICATION = "notification";

    public void onReceive(Context context, Intent intent) {

        NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);

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

    }
}

However, in the above scenario, it seems that .when is ignored.

Frankly, I am simply looking for a way to have the timestamp displayed on the notification be the time at which it is actually displayed.

Orbit
  • 2,985
  • 9
  • 49
  • 106

3 Answers3

3

I would suggest passing in your notification's information as extras then building the notification inside of the BroadcastReceiver. This will build the notification just before it is issued, so it will have the same time your AlarmManager triggers the BroadcastReceiver.

From wherever you're scheduling the notification:

private void scheduleNotification(){

    // Create an intent to the broadcast receiver you will send the notification from
    Intent notificationIntent = new Intent(this, SendNotification.class);

    // Pass your extra information in
    notificationIntent.putExtra("notification_extra", "any extra information to pass in");

    int requestCode = 1;

    // Create a pending intent to handle the broadcast intent
    PendingIntent alarmIntent = PendingIntent
                .getBroadcast(this, requestCode, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

    // Set your notification's trigger time
    Calendar alarmStart = Calendar.getInstance();
    alarmStart.setTimeInMillis(System.currentTimeMillis());
    alarmStart.set(Calendar.HOUR_OF_DAY, 6); // This example is set to approximately 6am

    AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);

    // Set the alarm with the pending intent
    // be sure to use set, setExact, setRepeating, & setInexactRepeating 
    // as well as RTC_WAKEUP, ELAPSED_REALTIME_WAKEUP, etc. 
    // where appropriate
    alarmManager.set(AlarmManager.RTC_WAKEUP, alarmStart.getTimeInMillis(), alarmIntent);
}

Then, inside your BroadcastReceiver's onReceive:

String notificationExtra = null;

// Retrieve your extra data
if(intent.hasExtra("notification_extra")){
    notificationExtra = intent.getStringExtra("notification_extra");
}

//Build the notification
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context);
mBuilder.setSmallIcon(notificationIcon)
        .setContentTitle(notificationTitle)
        .setContentText(notificationMessage)
        .setAutoCancel(true); // Use AutoCancel true to dismiss the notification when selected

// Check if notificationExtra has a value
if(notificationExtra != null){
    // Use the value to build onto the notification
}

//Define the notification's action
Intent resultIntent = new Intent(context, MainActivity.class); // This example opens MainActivity when clicked

int requestCode = 0;

PendingIntent resultPendingIntent =
        PendingIntent.getActivity(
                context,
                requestCode,
                resultIntent,
                PendingIntent.FLAG_UPDATE_CURRENT
        );

//Set notification's click behavior
mBuilder.setContentIntent(resultPendingIntent);

// Sets an ID for the notification
int mNotificationId = 1;

// Gets an instance of the NotificationManager service
NotificationManager mNotifyMgr =
        (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

// Builds the notification and issues it.
mNotifyMgr.notify(mNotificationId, mBuilder.build());
Sammy T
  • 1,924
  • 1
  • 13
  • 20
  • can you tell me how to create Multiple notification.? it can be done by providing mNotificationId ? then i need to cancel the same! – xbadal May 18 '17 at 07:32
  • and there is one more issue. if i click on notification. i move to new the Activity but notification is still there. how to clear that? setAutoCancel(true) is not working. thats it. thanks in Advance. – xbadal May 18 '17 at 07:40
  • @xbadal Yes, to create multiple notifications, you would have to provide a different Id for each notification. And as I understand it, `.setAutoCancel()` works with the default notification click behavior. Did you use `.addAction()` in building your notification or do you have anything that would take focus away from the default notification click? If so, you may have to call the Notification Manager's `.cancel(notificationId)` to dismiss the notification. – Sammy T May 18 '17 at 17:13
  • 1
    to cancel i used tag and id as same as the tag and id used to create the notification. it working now. yes i used .addAction() to close on click i used notification.flags |= Notification.FLAG_AUTO_CANCEL; all problem is fixed. Thankyou@sammy – xbadal May 19 '17 at 05:58
0

I have also been struggling with this for a bit, but your question actually brought me to the best answer. I checked out setWhen() and it seems like now this just works fine (checked with API lvl 30 & 31). As this post is a few years old, maybe this issue was fixed in the meantime. So here's how I did it in Kotlin:

class NotificationPublisher : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
    val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    val notification = intent.getParcelableExtra<Notification>(NOTIFICATION)
    notification?.`when` = System.currentTimeMillis()                               // overwriting the creation time to show the current trigger time when the notification is shown
    val postId = intent.getIntExtra(NOTIFICATION_ID, 0)

    notificationManager.notify(postId, notification)
}
Patrick Lang
  • 501
  • 6
  • 9
-1

Your NotificationPublisher's onReceive() method will be invoked only when scheduled alarm triggers as specified time. When you crate a notification from onReceive() method, it will definitely show the current time. No need to require to use .when or .setWhen() method.

Try this one:

public class NotificationPublisher extends BroadcastReceiver {

    public static String NOTIFICATION_ID = "notification_id";
    public static String NOTIFICATION = "notification";

    public void onReceive(Context context, Intent intent) {

        int id = intent.getIntExtra(NOTIFICATION_ID, 0);

        // Notification
        Notification notification = new Notification.Builder(context)       
            .setContentTitle("This is notification title")
            .setContentText("This is notification text")
            .setSmallIcon(R.mipmap.ic_launcher).build();

        notification.flags |= Notification.FLAG_AUTO_CANCEL;

        // Notification Manager
        NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

        notificationManager .notify(id, notification);
    }
}

If you want to redirect to an activity when click on Notification, then you can use PendingIntent and set it to your Notification.

public class NotificationPublisher extends BroadcastReceiver {

    public static String NOTIFICATION_ID = "notification_id";
    public static String NOTIFICATION = "notification";

    public void onReceive(Context context, Intent intent) {

        int id = intent.getIntExtra(NOTIFICATION_ID, 0);

        Intent intent = new Intent(context, YourTargetActivity.class);
        intent.putExtra("KEY_ID", id); // Pass extra values if needed

        PendingIntent pI = PendingIntent.getActivity(context, id, intent, PendingIntent.FLAG_UPDATE_CURRENT);

        // Notification
        Notification notification = new Notification.Builder(context)       
            .setContentTitle("This is notification title")
            .setContentText("This is notification text")
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentIntent(pI).build();

        notification.flags |= Notification.FLAG_AUTO_CANCEL;

        // Notification Manager
        NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

        notificationManager .notify(id, notification);
    }
}

Hope this will help~

Ferdous Ahamed
  • 21,438
  • 5
  • 52
  • 61