Skip to content

Commit

Permalink
[Android] notification with inline reply (zo0r#612)
Browse files Browse the repository at this point in the history
  • Loading branch information
lluis-sancho authored and elburu committed Mar 12, 2023
1 parent ed54290 commit 3229807
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 8 deletions.
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,31 @@ Make sure you have the receiver in `AndroidManifest.xml`:

For iOS, you can use this [package](https://github.com/holmesal/react-native-ios-notification-actions) to add notification actions.

Notifications with inline reply:

You must register an action as "ReplyInput", this will show in the notifications an input to write in.

EXAMPLE:
```javascript
PushNotification.localNotificationSchedule({
message: "My Notification Message", // (required)
date: new Date(Date.now() + (60 * 1000)), // in 60 secs
actions: ["ReplyInput"],
reply_placeholder_text: "Write your response...", // (required)
reply_button_text: "Reply" // (required)
});
```

To get the text from the notification:

```javascript
...
if(notification.action === "ReplyInput"){
console.log("texto", notification.reply_text)// this will contain the inline reply text.
}
...


## Set application badge icon

`PushNotification.setApplicationIconBadgeNumber(number: number)`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.core.app.NotificationManagerCompat;

Expand Down Expand Up @@ -41,6 +40,7 @@

public class RNPushNotification extends ReactContextBaseJavaModule implements ActivityEventListener {
public static final String LOG_TAG = "RNPushNotification";// all logging should use this tag
public static final String KEY_TEXT_REPLY = "key_text_reply";

private RNPushNotificationHelper mRNPushNotificationHelper;
private final SecureRandom mRandomNumberGenerator = new SecureRandom();
Expand Down Expand Up @@ -95,7 +95,7 @@ public void onNewIntent(Intent intent) {
mJsDelivery.notifyNotification(bundle);
}
}

@ReactMethod
public void invokeApp(ReadableMap data) {
Bundle bundle = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.bridge.ReactContext;
import androidx.core.app.RemoteInput;

import static com.dieam.reactnativepushnotification.modules.RNPushNotification.LOG_TAG;
import static com.dieam.reactnativepushnotification.modules.RNPushNotification.KEY_TEXT_REPLY;

public class RNPushNotificationActions extends BroadcastReceiver {
@Override
Expand All @@ -28,7 +30,15 @@ public void onReceive(final Context context, Intent intent) {
}

final Bundle bundle = intent.getBundleExtra("notification");
Bundle remoteInput = null;

if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT_WATCH){
remoteInput = RemoteInput.getResultsFromIntent(intent);
}
if (remoteInput != null) {
// Add to reply_text the text written by the user in the notification
bundle.putCharSequence("reply_text", remoteInput.getCharSequence(KEY_TEXT_REPLY));
}
// Dismiss the notification popup.
NotificationManager manager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
int notificationID = Integer.parseInt(bundle.getString("id"));
Expand Down Expand Up @@ -87,4 +97,4 @@ public void onReactContextInitialized(ReactContext context) {
});
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ public class RNPushNotificationAttributes {
private static final String TIMEOUT_AFTER = "timeoutAfter";
private static final String ONLY_ALERT_ONCE = "onlyAlertOnce";
private static final String ONGOING = "ongoing";
private static final String REPLY_BUTTON_TEXT = "reply_button_text";
private static final String REPLAY_PLACEHOLDER_TEXT = "reply_placeholder_text";
private static final String ALLOW_WHILE_IDLE = "allowWhileIdle";
private static final String IGNORE_IN_FOREGROUND = "ignoreInForeground";

Expand Down Expand Up @@ -84,6 +86,8 @@ public class RNPushNotificationAttributes {
private final double timeoutAfter;
private final boolean onlyAlertOnce;
private final boolean ongoing;
private final String reply_button_text;
private final String reply_placeholder_text;
private final boolean allowWhileIdle;
private final boolean ignoreInForeground;

Expand Down Expand Up @@ -122,6 +126,8 @@ public RNPushNotificationAttributes(Bundle bundle) {
timeoutAfter = bundle.getDouble(TIMEOUT_AFTER);
onlyAlertOnce = bundle.getBoolean(ONLY_ALERT_ONCE);
ongoing = bundle.getBoolean(ONGOING);
reply_button_text = bundle.getString(REPLY_BUTTON_TEXT);
reply_placeholder_text = bundle.getString(REPLAY_PLACEHOLDER_TEXT);
allowWhileIdle = bundle.getBoolean(ALLOW_WHILE_IDLE);
ignoreInForeground = bundle.getBoolean(IGNORE_IN_FOREGROUND);
}
Expand Down Expand Up @@ -162,6 +168,8 @@ private RNPushNotificationAttributes(JSONObject jsonObject) {
timeoutAfter = jsonObject.has(TIMEOUT_AFTER) ? jsonObject.getDouble(TIMEOUT_AFTER) : -1;
onlyAlertOnce = jsonObject.has(ONLY_ALERT_ONCE) ? jsonObject.getBoolean(ONLY_ALERT_ONCE) : false;
ongoing = jsonObject.has(ONGOING) ? jsonObject.getBoolean(ONGOING) : false;
reply_button_text = jsonObject.has(REPLY_BUTTON_TEXT) ? jsonObject.getString(REPLY_BUTTON_TEXT) : null;
reply_placeholder_text = jsonObject.has(REPLAY_PLACEHOLDER_TEXT) ? jsonObject.getString(REPLAY_PLACEHOLDER_TEXT) : null;
allowWhileIdle = jsonObject.has(ALLOW_WHILE_IDLE) ? jsonObject.getBoolean(ALLOW_WHILE_IDLE) : false;
ignoreInForeground = jsonObject.has(IGNORE_IN_FOREGROUND) ? jsonObject.getBoolean(IGNORE_IN_FOREGROUND) : false;
} catch (JSONException e) {
Expand Down Expand Up @@ -259,6 +267,8 @@ public Bundle toBundle() {
bundle.putDouble(TIMEOUT_AFTER, timeoutAfter);
bundle.putBoolean(ONLY_ALERT_ONCE, onlyAlertOnce);
bundle.putBoolean(ONGOING, ongoing);
bundle.putString(REPLY_BUTTON_TEXT, reply_button_text);
bundle.putString(REPLAY_PLACEHOLDER_TEXT, reply_placeholder_text);
bundle.putBoolean(ALLOW_WHILE_IDLE, allowWhileIdle);
bundle.putBoolean(IGNORE_IN_FOREGROUND, ignoreInForeground);
return bundle;
Expand Down Expand Up @@ -301,6 +311,8 @@ public JSONObject toJson() {
jsonObject.put(TIMEOUT_AFTER, timeoutAfter);
jsonObject.put(ONLY_ALERT_ONCE, onlyAlertOnce);
jsonObject.put(ONGOING, ongoing);
jsonObject.put(REPLY_BUTTON_TEXT, reply_button_text);
jsonObject.put(REPLAY_PLACEHOLDER_TEXT, reply_placeholder_text);
jsonObject.put(ALLOW_WHILE_IDLE, allowWhileIdle);
jsonObject.put(IGNORE_IN_FOREGROUND, ignoreInForeground);
} catch (JSONException e) {
Expand Down Expand Up @@ -349,6 +361,8 @@ public String toString() {
", timeoutAfter=" + timeoutAfter +
", onlyAlertOnce=" + onlyAlertOnce +
", ongoing=" + ongoing +
", reply_button_text=" + reply_button_text +
", reply_placeholder_text=" + reply_placeholder_text +
", allowWhileIdle=" + allowWhileIdle +
", ignoreInForeground=" + ignoreInForeground +
'}';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
import android.os.Bundle;
import android.service.notification.StatusBarNotification;
import android.util.Log;
import androidx.core.app.RemoteInput;

import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;

import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;
Expand All @@ -46,6 +50,7 @@

import static com.dieam.reactnativepushnotification.modules.RNPushNotification.LOG_TAG;
import static com.dieam.reactnativepushnotification.modules.RNPushNotificationAttributes.fromJson;
import static com.dieam.reactnativepushnotification.modules.RNPushNotification.KEY_TEXT_REPLY;

public class RNPushNotificationHelper {
public static final String PREFERENCES_KEY = "rn_push_notification";
Expand Down Expand Up @@ -514,13 +519,35 @@ public void sendToNotificationCentreWithPicture(Bundle bundle, Bitmap largeIconB

PendingIntent pendingActionIntent = PendingIntent.getBroadcast(context, notificationID, actionIntent,
PendingIntent.FLAG_UPDATE_CURRENT);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
notification.addAction(new NotificationCompat.Action.Builder(icon, action, pendingActionIntent).build());
} else {
notification.addAction(icon, action, pendingActionIntent);
if(action.equals("ReplyInput")){
//Action with inline reply
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT_WATCH){
RemoteInput remoteInput = new RemoteInput.Builder(KEY_TEXT_REPLY)
.setLabel(bundle.getString("reply_placeholder_text"))
.build();
NotificationCompat.Action replyAction = new NotificationCompat.Action.Builder(
icon, bundle.getString("reply_button_text"), pendingActionIntent)
.addRemoteInput(remoteInput)
.setAllowGeneratedReplies(true)
.build();

notification.addAction(replyAction);
}
else{
// The notification will not have action
break;
}
}
else{
// Add "action" for later identifying which button gets pressed
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
notification.addAction(new NotificationCompat.Action.Builder(icon, action, pendingActionIntent).build());
} else {
notification.addAction(icon, action, pendingActionIntent);
}
}
}

}

// Remove the notification from the shared preferences once it has been shown
Expand Down

0 comments on commit 3229807

Please sign in to comment.