Find notifications that can be replied to

There’s a lot that you can use notifications for outside of replying to them but for the purpose of this article I’m going to talk about how to retrieve only messages that can be replied to from the NotificationListener service. Again the method I use to do this is in the library, inside NotificationUtils calls getQuickReplyAction.

public static Action getQuickReplyAction(Notification n, String packageName) {

NotificationCompat.Action action = null;

if(Build.VERSION.SDK_INT >= 24)

action = getQuickReplyAction(n);

if(action == null)

action = getWearReplyAction(n);

if(action == null)

return null;

return new Action(action, packageName, true);

}

This method check if the Notification object you’ve just received from your NotificationListener service has an Action, if so does that action have a RemoteInput (the method the notification system uses to receive some input) & if so does it’s RemoteInput have a resultKey with the word “reply” in it. Again, this is a pretty primitive method of going about things but everything we’re doing here is not how any of this was intended to be used.

private static NotificationCompat.Action getQuickReplyAction(Notification n) {

for(int i = 0; i < NotificationCompat.getActionCount(n); i++) {

NotificationCompat.Action action = NotificationCompat.getAction(n, i);

for(int x = 0; x < action.getRemoteInputs().length; x++) {

RemoteInput remoteInput = action.getRemoteInputs()[x];

if(remoteInput.getResultKey().toLowerCase().contains(REPLY_KEYWORD))

return action;

}

}

return null;

}

I use multiple methods to try & find a way to reply to a notification, the first being looking for the quick reply option introduced in Nougat. If no replyable action is found I then check for Android Wear actions as these can often be replied to from the watch and therefore we can make use of that functionality to allow our app to reply.

private static NotificationCompat.Action getWearReplyAction(Notification n) {

NotificationCompat.WearableExtender wearableExtender = new NotificationCompat.WearableExtender(n);

for (NotificationCompat.Action action : wearableExtender.getActions()) {

for (int x = 0; x < action.getRemoteInputs().length; x++) {

RemoteInput remoteInput = action.getRemoteInputs()[x];

if (remoteInput.getResultKey().toLowerCase().contains(REPLY_KEYWORD))

return action;

}

}

return null;

}

If we found an Action object that matched our criteria we can now use it to reply to whichever notification it belongs to.

You might also notice the getQuickReplyAction method wraps the action it returns in it’s own Action object, the reason for this being the Notification.Action object isn’t parcelable, & for my own apps this is how I want to move the object around before I’m ready to reply, so I created a handy class that essentially recreates the Notification.Action object as a parcelable. Pretty handy in real world use.