Android 7.0 has introduced a new reply feature to the notification system. Now you may send answers directly through the notification tray, rather than the app itself. This tutorial will explain how to implement this new functionality, as well as provide you with an example app.
Requirements
In order to finalize this tutorial you will need:
- Android Nougat SDK (API 24)
- Android Nougat Emulator or a mobile device running Android Nougat
- Android Studio 2.1+
Prepping up your application
build.gradle
Start by creating a new empty project. Modify the app/build.gradle file to match the example below:
android {
compileSdkVersion 24
buildToolsVersion "24.0.3"
defaultConfig {
minSdkVersion 24
targetSdkVersion 24
versionCode 1
versionName "1.0"
}
}
dependencies {
compile 'com.android.support:appcompat-v7:24.2.1'
}
MainActivity.java
Next, let’s create the classes we will need later. In the project view right-click on the project package, then “New / Java class“. Select MainActivity as the name of your new class. In the new file paste the code below. Don’t worry about the missing classes, we will be adding them shortly.
public class MainActivity extends AppCompatActivity {
public static final int NOTIFICATION_ID = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button buttonSend = (Button) findViewById(R.id.button_send_notifaction);
buttonSend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
sendNotification();
}
});
}
private void sendNotification() {
// Create a reply intent sending us back to the activity
Intent replyIntent = new Intent(this, MainActivity.class);
// Add a notification reply intent to the task stack
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addNextIntent(replyIntent);
// Create reply pending intent as broadcast
PendingIntent replyPendingIntent = PendingIntent.getBroadcast(
MainActivity.this,
0,
new Intent(MainActivity.this, ReplyBroadcastReceiver.class),
PendingIntent.FLAG_UPDATE_CURRENT
);
// Create the remote input - RemoteInput class is where we will collect the reply from the notification. It will be later added to the notification action, as you may notice below.
RemoteInput remoteInput = new RemoteInput.Builder(ReplyBroadcastReceiver.KEY_TEXT_REPLY)
.setLabel("Reply")
.build();
// Create the reply action - Actions define how you may respond to the notification. In this case, we also add the remoteInput defined above to the action so that we can store the typed answer and send it later to the receiver.
Notification.Action action =
new Notification.Action.Builder(
R.drawable.ic_arrow_forward_black_24dp,
"Reply",
replyPendingIntent)
.addRemoteInput(remoteInput)
.build();
// Build the notification
Notification newMessageNotification =
new Notification.Builder(this)
.setSmallIcon(R.drawable.ic_notifications_active_black_24dp)
.setContentTitle("Notification")
.addAction(action)
.build();
// Send the notification
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(NOTIFICATION_ID, newMessageNotification);
}
}
ReplyBroadcastReceiver.java
Let’s repeat the above process, this time choosing ReplyBroadcastReceiver as the class name. Open a new file and paste the code:
public class ReplyBroadcastReceiver extends BroadcastReceiver {
public static final String KEY_TEXT_REPLY = "key_text_reply";
public static final int REPLY_NOTIFICATION_ID = 2;
public ReplyBroadcastReceiver() {
}
@Override
public void onReceive(Context context, Intent intent) {
// Get remote input from received intent. Remote input is an answer a user has added to the reply. In our case it should contain a String.
Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
if (remoteInput == null) {
return;
}
// Get reply text
String reply = remoteInput.getString(KEY_TEXT_REPLY);
// Create reply notification
Notification replyNotification =
new Notification.Builder(context)
.setSmallIcon(R.drawable.ic_notifications_active_black_24dp)
.setContentTitle("Reply received!")
.setContentText(reply)
.build();
// Send a new reply notification. Note that his not replace the previous notification, only adds a new one.
NotificationManager notificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(REPLY_NOTIFICATION_ID, replyNotification);
}
}
AndroidManifest
Finally, we have to modify the AndroidManifest to include the newly created Activity, as well as register our receiver. Add the code below to your Application tag.
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<receiver
android:name=".ReplyBroadcastReceiver"
android:enabled="true"
android:exported="false"/>
App showcase
Sending notifications
Running the application will show the default screen. Go ahead and press the Send Notification button. It will run the sendNotification() function from the MainActivity class. As you may see in the screenshot Fig.1 , the newly received notification has the Reply action we designed during notification creation.
Replying to notifications
Clicking the Reply button will cause the answer tray to open, as shown in Fig.2. You may type any answer you like. Pressing the send arrow will cause a reply intent to be sent and consequently caught by the ReplyBroadcastReceiver we created.
Reply confirmation
After receiving the intent, the ReplyBroadcastReceiver will send a notification on its own, confirming the reply. You can see the example answer in Fig.3.