Wednesday 19 March 2014

The All Important setDeleteIntent for Notifications

My app, BreakFree, notifies the user in case of any event like using the phone for a total of 1 hour, or launching a particular app 15 times or more, etc. Now, there is also an option in my app wherein the user gets to see his phone addiction score as a persistent notification. This is updated at every unlock. My problem here was that I did not want to overwrite the event notification with the addiction score notification till the user clears the event notification himself. 

Now, call me dumb, but for the love of God I found it impossible to find documentation on how to detect the user clearing the notification. After a lot of searching I found the missing link. Actually there are two. setDeleteIntent and setContentIntent.

Here is how I coded the solution:

1) In my function which updates my notifications, I created two pendingIntents, one two be called when the user deletes my notification (swiping it, or using the Clear All button). And the second to be called when the user clicks the notification. Both call the same receiver class (NotificationReceiver), but with different Extras. Pay particular attention to the flags for the Pending Intent.

//create pending intent to be called when user deletes the notification
Intent notiDeleted = new Intent(ctx, NotificationReceiver.class);
notiDeleted.putExtra(ctx.getString(R.string.noti_deleted), true);
PendingIntent notiDeletedIntent = PendingIntent.getBroadcast(ctx, 0, notiDeleted, 0);
   
//create pending intent to be called when user clicks the notification
Intent notiClicked = new Intent(ctx, NotificationReceiver.class);
notiClicked.putExtra(ctx.getString(R.string.noti_clicked), true);
PendingIntent notiClickedIntent = PendingIntent.getBroadcast(ctx, 1, notiClicked, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_ONE_SHOT);


2) I then created a SharedPreference flag saying that the notification is still present in the notification tray. This flag tells my code not to show the second notification.

//create a flag that an event noti is being shown
spEdit.putBoolean(ctx.getString(R.string.SPCEventNotiVisible), true);
spEdit.commit();

3) Build the notification. Use the setDeleteIntent and setContentIntent.
// build notification
NotificationCompat.Builder nb = new NotificationCompat.Builder(ctx);
nb.setSmallIcon(R.drawable.ic_jump_outline);
nb.setContentIntent(notiClickedIntent);
nb.setDeleteIntent(notiDeletedIntent);
nb.setAutoCancel(true);

Notification bfN = nb.build();

4) Next we create our receiver class.
public class NotificationDeleteReceiver extends BroadcastReceiver{

@Override
public void onReceive(Context context, Intent intent) {

  //make flag to noti not shown
  SharedPreferences spObj =
  context.getSharedPreferences(context.getString(R.string.SPPrevSetting), 0);
  SharedPreferences.Editor spEdit = spObj.edit();
  spEdit.putBoolean(context.getString(R.string.SPCEventNotiVisible), false);
  spEdit.commit();

  //if called from user click then show app
  if(intent.getExtras().containsKey(context.getString(R.string.noti_clicked))){
Intent i = new Intent(context, MainScreen.class);
        i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |            Intent.FLAG_ACTIVITY_CLEAR_TOP | 
        Intent.FLAG_ACTIVITY_SINGLE_TOP);                
i.putExtra(context.getString(R.string.noti_on_click),                              intent.getExtras().getString(context.getString(R.string.noti_on_click)));
context.startActivity(i);
}
  }

}

As you can the receiver changes the SharedPreference flag to false regardless of whether the notification was cleared or clicked. It then checks the extras and if the notification was clicked it then opens up the app.

Hope this helps you guys.

No comments:

Post a Comment