Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to utilize Android Nougat's Direct Reply feature with a NotificationListener?

My app is using a NotificationListener to read out messages from various 3rd party apps, for example WhatsApp.

So far I was able to send a reply if only one chat is unread, the code is below.

However, in the case with WhatsApp, getNotification().actions returns a null object when more than two chats are unread, as the messages are bundled together. As you can see in the pictures below, if the notifications are extended there is an option to send a direct reply as well, therefore I am certain that it is possible to utilize this, also I think apps like PushBullet are using this method.

How could I access the RemoteInput of that notification?

public static ReplyIntentSender sendReply(StatusBarNotification statusBarNotification, String name) {

            Notification.Action actions[] = statusBarNotification.getNotification().actions;

            for (Notification.Action act : actions) {
                if (act != null && act.getRemoteInputs() != null) {
                    if (act.title.toString().contains(name)) {
                        if (act.getRemoteInputs() != null)
                            return new ReplyIntentSender(act);
                    }
                }
            }
            return null;
        }



public static class ReplyIntentSender {
      [...]

    public final Notification.Action action;

    public ReplyIntentSender(Notification.Action extractedAction) {
            action = extractedAction;
     [...]
    }

private boolean sendNativeIntent(Context context, String message) {
            for (android.app.RemoteInput rem : action.getRemoteInputs()) {
                Intent intent = new Intent();
                Bundle bundle = new Bundle();
                bundle.putCharSequence(rem.getResultKey(), message);
                android.app.RemoteInput.addResultsToIntent(action.getRemoteInputs(), intent, bundle);
                try {
                    action.actionIntent.send(context, 0, intent);
                } catch (Exception e) {
                    e.printStackTrace();
                    return false;
                }
                return true;
            }
            return false;
        }
    }

Some explanation how the above code works: Once a notification is received the app tries to get the actions and checks if the name is in the title of a remoteInput (normally it is in the format of "Reply to $NAME"), if that is found the Action is saved into a ReplyIntentSender class, which, when triggered by sendNativeIntent, cycles through all RemoteInputs of that Action and adds the message to the intent. If more than one chat is unread, getNotification().actions returns null.

Below are two screenshots, the first one where it is working without any problems and the second one where it doesn't.

I can reply to this message

I cannot reply to this message

like image 634
Force Avatar asked Nov 01 '16 22:11

Force


1 Answers

You can consider this as my suggestion. I have done bit research on this and come up with following conclusions.(Also it looks like you have done plenty of research on this so it might be possible that you aware about what I wrote below)

Numerous apps send Wear specific notifications, and many of those contain actions accessible from an Android Wear device. We can grab those Wear notifications on the device, extracting the actions, finding the reply action (if one exists), populating it with our own response and then executing the PendingIntent which sends our response back the original app for it to send on to the recipient.

To do so you can refer this link (A nice workaround by Rob J). You can also refer this link in this context (Great research work done by Michał Tajchert).(You might need to work around with NotificationCompat.isGroupSummary)

This is what I feel(Might be I am totally wrong)

.actions method returns Array of all Notification.Action structures attached to current notification by addAction(int, CharSequence, PendingIntent), Here addAction method is deprecated one so it might not working as intended.

I am not able to test this at my end otherwise I will love to provide a working solution with code.

Hope this will help you. Happy Coding!!!

like image 102
Pravin Divraniya Avatar answered Oct 11 '22 19:10

Pravin Divraniya