Some tasks take a long time, or events may occur when the user is not using our app. Because some tasks take a long time, we run them in the background. As a result, we need to let the user know when a task is complete, or that some extra information is needed.
If we are going to support Android versions prior to 3.0, we will have to install the Xamarin Support Library v4 NuGet or component into our project.
If an event occurs when the user is not using our app, we can let the user know about it by using a Notification
instance from the following steps:
NotificationCompat.Builder
instance:var builder = new NotificationCompat.Builder(this) .SetSmallIcon(Android.Resource.Drawable.StatNotifySync) .SetContentTitle("Simple Notification") .SetContentText("Hello World!") .SetAutoCancel(true);
Notification.Builder
instance:var builder = new Notification.Builder(this) .SetSmallIcon(Android.Resource.Drawable.StatNotifySync) .SetContentTitle("Simple Notification") .SetContentText("Hello World!") .SetAutoCancel(true);
NotificationManager
type and an ID used to reference this notification once displayed:const int notificationId = 123; var manager = NotificationManager.FromContext(this);
Build()
method and display it using the Notify()
method of the NotificationManager
type:manager.Notify(notificationId, builder.Build());
Often, we will want to navigate the user to a specific activity in our app, and for this we add a content intent to the notification:
PendingIntent
instance that holds the Intent
instance to launch the activity:var intent = new Intent( this, typeof(NotificationActivity)); var pendingIntent = PendingIntent.GetActivity( this, 0, intent, PendingIntentFlags.UpdateCurrent);
SetContentIntent()
method:builder.SetContentIntent(pendingIntent);
If we want to provide a back stack for when the user presses the back button once the notification activity is shown, we can do so using the TaskStackBuilder
type:
ParentActivity
property of the [Activity]
attribute for our notification activity:[Activity(..., ParentActivity = typeof(MainActivity))]
[MetaData]
attribute:[MetaData( "android.support.PARENT_ACTIVITY", Value = "com.xamarincookbook.MainActivity")]
[Register("com.xamarincookbook.MainActivity")]
Intent
instance using the AddNextIntentWithParentStack()
method of the TaskStackBuilder
type:var intent = new Intent( this, typeof(NotificationActivity)); var backStack = TaskStackBuilder.Create(this) .AddNextIntentWithParentStack(intent); var pendingIntent = backStack.GetPendingIntent( 0, (int)PendingIntentFlags.UpdateCurrent);
Some tasks take a long time and the user will switch to another app while such a task is running. When the task is finished, we may want to let the user know. Or an event may occur in the background while the user is using another app. Regardless of what the user is doing, we can use a Notification
instance to display information in the system status bar.
When the user decides that they want to respond to the notification, they can tap it and it will launch right into the activity that relates to the notification. The whole notification could be used as the entry point, with buttons that provide additional actions.
Almost all notifications provide an action, even if it is just to launch the app or an activity in the app. To do this, we use a PendingIntent
instance, which holds the actual Intent
instance that we wish to trigger. The PendingIntent
instance can hold any Intent
instance with any amount of extras or back stacks that will be required to get the user directly to the desired point. We can attach the intent using the SetContentIntent()
method of the builder.
Setting the intent is not required, but is both expected and recommended because the user expects that something will happen after tapping the notification. However, if action buttons are used, the intent does not have to be attached to the actual notification but to the action buttons.
To create the actual Notification
instance, we use the NotificationCompat.Builder
instance, or if we are only supporting Android versions 3.0 and above, we use Notification.Builder
. We construct an instance of the builder and use the many setter methods to create the structure of the notification.
There are three required properties of a notification: the icon, set by SetSmallIcon
; the title, set by SetTitle
; and the detail text, set by SetContentText
. The user also expects that the notification will be removed from the status bar when it is tapped. We could remove this manually, but we can do this automatically by passing true
to the SetAutoCancel()
method.
When we are ready to display the notification, we use the NotificationManager
instance. To obtain the actual notification that is to be displayed, we invoke the Build()
method on the builder. We then invoke the Notify()
method on the manager with both an ID and the notification. The ID allows us to locate, update, or remove a notification once it has been displayed, if need be.
Unless the notification takes the user to a special activity, we should also specify a back stack on the intent. Without a back stack, the notification will launch the activity, and when the user presses back, the activity will close and return the user to exactly where they were. By specifying a back stack, we can allow the user to navigate upwards, just as if they had entered the app from the home screen.
The back stack is created by setting the parent activity for the notification activity. We do this by adding attributes to the notification activity, which describe how to get to the parent activity. Typically, we would provide the type of the parent activity for the ParentActivity
property of the [Activity]
attribute. Because we are supporting versions of Android prior to 4.1, we also add a [MetaData]
attribute. This attribute has a string value of the full name of the parent activity as it appears to Android. In order to know what the compiler will use as the name, we need to specify exactly what we want. By adding a [Register]
attribute to the parent activity, we can control what the name will be. We then use this name in our notification activity's metadata.
When creating the back stack, we use the TaskStackBuilder
type. This type has been around since Android version 3.0, but we use the type from the support library instead. If we do not, the app will crash on older Android versions. Both types work the same, and we use the AddNextIntentWithParentStack()
method to attach the intents for both the destination activity and its parents. One difference is that on Android versions prior to 3.0, the back stack is ignored.
Once we have built our back stack, we get the PendingIntent
instance using the GetPendingIntent()
method. We can then pass this pending intent to the notification builder using the SetContentIntent()
method.
We can also add many features to the notification, such as action buttons using the AddAction()
method. To do this, we provide an icon, some text, and a PendingIntent
instance. The PendingIntent
instance is triggered when the user has tapped a button and we then respond when we receive it. We can also add various extra features such as tickers and vibrations, as well as more information to notifications. All these features can be added using the various setter methods on the Builder
object.