{"id":27810,"date":"2016-09-20T14:00:50","date_gmt":"2016-09-20T21:00:50","guid":{"rendered":"https:\/\/blog.xamarin.com\/?p=27810"},"modified":"2016-09-20T14:00:50","modified_gmt":"2016-09-20T21:00:50","slug":"enhanced-notifications-in-android-n-with-direct-reply","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/xamarin\/enhanced-notifications-in-android-n-with-direct-reply\/","title":{"rendered":"Enhanced Notifications in Android N with Direct Reply"},"content":{"rendered":"<p>\t\t\t\tOne of my favorite parts of Android has to be it&#8217;s notification system enabling developers to directly connect to their users outside of the main application. With the launch of Android N, notifications are getting a visual make-over including a new material design with re-arranged and sized content to make them easier to digest and some new details specific for Android N such as app name and an expander. Here is a nice visual overview of the change from Android M to N:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/image07.png\" alt=\"Android N Notification\" width=\"640\" height=\"293\" class=\"aligncenter size-full wp-image-27814\" \/><\/p>\n<p>Visuals aren&#8217;t the only thing getting updated in Android N, as there are a bunch of great new features for developers to take advantage of. <strong>Bundled Notifications<\/strong> allow developers to group notifications together by using the Builder.SetGroup() method. <strong>Custom Views<\/strong> have been enhanced and it is now possible to use the system notification headers, actions, and expanded layouts with a custom view. Finally, my favorite new feature has to be <strong>Direct Reply<\/strong>, allowing users to reply to a message within a notification so they don&#8217;t even have to open up the application. This is similar to how Android Wear applications could send text back to the main application. <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/2016-09-19_1810.png\" alt=\"2016-09-19_1810\" width=\"400\" class=\"aligncenter size-full wp-image-27821\" \/><\/p>\n<h2>Getting Started<\/h2>\n<p>In previous versions of Android, all developers could handle was notification and action tap events, which would launch an Activity or a service\/broadcast receiver when using an action. The idea of Direct Reply is to extend an action with a RemoteInput to enable users to reply to a message without having to launch the application. It&#8217;s best practice to handle responding to messages inside of an Activity as the user may decide to tap on the notification or may be on an older operating system.<\/p>\n<p>A pre-requisite to implementing Direct Reply is that we must have a broadcast receiver or service implemented that can receive and process the incoming reply from the user. For this example, we&#8217;ll be launching a notification from our MainActivity that will send an Intent with a value of <strong>&#8220;com.xamarin.directreply.REPLY&#8221; <\/strong>that our broadcast receiver will filter on.<\/p>\n<p>First, ensure that the latest <a href=\"https:\/\/www.nuget.org\/packages\/Xamarin.Android.Support.v4\/\">Android Support Library v4 NuGet<\/a> is installed in the Android application to use the compatibility mode for notifications. <\/p>\n<p>In our MainActivity, we&#8217;ll create a few constant strings that can be referenced later in the code:<\/p>\n<pre class=\"theme:vs2012 lang:csharp decode:true\">\nint requestCode = 0;\n\npublic const string REPLY_ACTION = \"com.xamarin.directreply.REPLY\";\npublic const string KEY_TEXT_REPLY = \"key_text_reply\";\npublic const string REQUEST_CODE = \"request_code\";\n<\/pre>\n<h2>Create a Pending Intent<\/h2>\n<p>An Android Pending Intent is a description of an Intent and target action to perform with it. In this case, we want to create one that will trigger our reply action if the user is on Android N, or that will launch the Main Activity if the user is on an older devices.<\/p>\n<pre class=\"theme:vs2012 lang:csharp decode:true\">\nIntent intent = null;\nPendingIntent pendingIntent= null;\n\/\/If Android N then enable direct reply, else launch main activity.\nif ((int)Build.VERSION.SdkInt &gt;= 24)\n{\n    intent = new Intent(REPLY_ACTION)\n\t\t\t.AddFlags(ActivityFlags.IncludeStoppedPackages)\n\t\t\t.SetAction(REPLY_ACTION)\n\t\t\t.PutExtra(REQUEST_CODE, requestCode);\n\n    pendingIntent = PendingIntent.GetBroadcast(this, requestCode, intent, PendingIntentFlags.UpdateCurrent);\n}\nelse\n{\n    intent = new Intent(this, typeof(MainActivity));\n    intent.AddFlags(ActivityFlags.ClearTop | ActivityFlags.NewTask);\n\n    pendingIntent = PendingIntent.GetActivity(this, requestCode, intent, PendingIntentFlags.UpdateCurrent);\n}\n<\/pre>\n<h2>Create and Attach RemoteInput<\/h2>\n<p>The key to direct reply is to create and attach a RemoteInput, which will tell Android that this action that we&#8217;re adding is a direct reply and thus should allow the user to enter text.<\/p>\n<pre class=\"theme:vs2012 lang:csharp decode:true\">\nvar replyText = \"Reply to message...\";\n\n\/\/create remote input that will read text\nvar remoteInput = new Android.Support.V4.App.RemoteInput.Builder(KEY_TEXT_REPLY)\n\t\t\t\t\t\t        .SetLabel(replyText)\n                                                        .Build();\n<\/pre>\n<p>After we have the RemoteInput we can create a new action and attach it to it a new action:<\/p>\n<pre class=\"theme:vs2012 lang:csharp decode:true\">\n\nvar action = new NotificationCompat.Action.Builder(Resource.Drawable.action_reply,\n                                                   replyText,\n                                                   pendingIntent)\t\t\t\t\t\t\t\t\t\t\t          \n                                                  .AddRemoteInput(remoteInput)\n                                                  .Build();\n<\/pre>\n<h2>Build and Send Notification<\/h2>\n<p>With our action with remote input created, it&#8217;s finally time to send the notification.<\/p>\n<pre class=\"theme:vs2012 lang:csharp decode:true\">\nvar notification = new NotificationCompat.Builder(this)\n\t\t\t\t\t .SetSmallIcon(Resource.Drawable.reply)\n\t\t\t\t\t .SetLargeIcon(BitmapFactory.DecodeResource(Resources, Resource.Drawable.avatar))\n\t\t\t\t\t .SetContentText(\"Hey, it is James! What's up?\")\n\t\t\t\t\t .SetContentTitle(\"Message\")\n\t\t\t\t\t .SetAutoCancel(true)\n                                         .AddAction(action)\n\t\t\t\t\t .Build();\n\nusing (var notificationManager = NotificationManagerCompat.From(this))\n{\n\tnotificationManager.Notify(requestCode, notification);\n}\n<\/pre>\n<p>Now our notification is live with the remote input visible:\n<img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/Notification.png\" alt=\"notification\" width=\"400\" class=\"aligncenter size-full wp-image-27819\" \/><\/p>\n<h2>Processing Input<\/h2>\n<p>When the user inputs text into the direct reply, we&#8217;re able to retrieve the text from the Intent that is passed in with just a few lines of code:<\/p>\n<pre class=\"theme:vs2012 lang:csharp decode:true\">\nvar remoteInput = RemoteInput.GetResultsFromIntent(Intent);\nvar reply = remoteInput?.GetCharSequence(MainActivity.KEY_TEXT_REPLY) ?? string.Empty;\n<\/pre>\n<p>This should be done in a background service or broadcast receiver with the &#8220;com.xamarin.directreply.REPLY&#8221; Intent Filter specified.<\/p>\n<p>Here&#8217;s our final BroadcastReceiver that will pop up a toast message and will update the notification to stop the progress indicator in the notification: <\/p>\n<pre class=\"theme:vs2012 lang:csharp decode:true\">\n[BroadcastReceiver(Enabled = true)]\n[Android.App.IntentFilter(new[] { MainActivity.REPLY_ACTION })]\n\/\/\/ <summary>\n\/\/\/ A receiver that gets called when a reply is sent\n\/\/\/ <\/summary>\npublic class MessageReplyReceiver : BroadcastReceiver\n{\n\tpublic override void OnReceive(Context context, Intent intent)\n\t{\n\t\tif (!MainActivity.REPLY_ACTION.Equals(intent.Action))\n\t\t\treturn;\n\t\t\n\n\t\tint requestId = intent.GetIntExtra(MainActivity.REQUEST_CODE, -1);\n\t\tif (requestId == -1)\n\t\t\treturn;\n\n\t\tvar reply = GetMessageText(intent);\n\t\tusing (var notificationManager = NotificationManagerCompat.From(context))\n\t\t{\n\t\t\t\/\/Create new notification to display, or re-build existing conversation to update with new response\n\t\t\tvar notificationBuilder = new NotificationCompat.Builder(context);\n\t\t\tnotificationBuilder.SetSmallIcon(Resource.Drawable.reply);\n\t\t\tnotificationBuilder.SetContentText(\"Replied\");\n\t\t\tvar repliedNotification = notificationBuilder.Build();\n\n\n\t\t\t\/\/Call notify to stop progress spinner. \n\t\t\tnotificationManager.Notify(requestId, repliedNotification);\n\t\t}\n\n\t\tToast.MakeText(context, $\"Message sent: {reply}\", ToastLength.Long).Show();\n\t}\n\n\t\/\/\/ <summary>\n\t\/\/\/ Get the message text from the intent.\n\t\/\/\/ Note that you should call  \n\t\/\/\/ to process the RemoteInput.\n\t\/\/\/ <\/summary>\n\t\/\/\/ The message text.\n\t\/\/\/ Intent.\n\tstatic string GetMessageText(Intent intent)\n\t{\n\t\tvar remoteInput = RemoteInput.GetResultsFromIntent(intent);\n\t\treturn remoteInput?.GetCharSequence(MainActivity.KEY_TEXT_REPLY) ?? string.Empty;\n\t}\n}\n<\/pre>\n<h2>Learn More<\/h2>\n<p>To learn more about the great new features in Android N, including Notification enhancements, be sure to read our full <a href=\"https:\/\/developer.xamarin.com\/guides\/android\/platform_features\/introduction-to-nougat\/\">Android N Getting Started Guide<\/a>. You can find a full example of Direct Reply and other notification enhancements in our <a href=\"https:\/\/developer.xamarin.com\/samples\/monodroid\/android-n\/MessagingService\/\">Samples Gallery<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>One of my favorite parts of Android has to be it&#8217;s notification system enabling developers to directly connect to their users outside of the main application. With the launch of Android N, notifications are getting a visual make-over including a new material design with re-arranged and sized content to make them easier to digest and [&hellip;]<\/p>\n","protected":false},"author":544,"featured_media":27821,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2],"tags":[5,4],"class_list":["post-27810","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-developers","tag-android","tag-xamarin-platform"],"acf":[],"blog_post_summary":"<p>One of my favorite parts of Android has to be it&#8217;s notification system enabling developers to directly connect to their users outside of the main application. With the launch of Android N, notifications are getting a visual make-over including a new material design with re-arranged and sized content to make them easier to digest and [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/27810","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/users\/544"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/comments?post=27810"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/27810\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media?parent=27810"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/categories?post=27810"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/tags?post=27810"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}