diff --git a/docs/html/guide/topics/ui/notifiers/notifications.jd b/docs/html/guide/topics/ui/notifiers/notifications.jd index 273b5f773b021..fbff532dc165a 100644 --- a/docs/html/guide/topics/ui/notifiers/notifications.jd +++ b/docs/html/guide/topics/ui/notifiers/notifications.jd @@ -1,646 +1,902 @@ -page.title=Status Notifications -parent.title=Notifications -parent.link=index.html +page.title=Notifications @jd:body
A status notification adds an icon to the system's status bar -(with an optional ticker-text message) and a notification message in the notifications window. -When the user selects the notification, Android fires an -{@link android.content.Intent} that is defined by the {@link android.app.Notification} (usually to -launch an {@link android.app.Activity}). -You can also configure the notification to alert the user with a sound, a vibration, and flashing -lights on the device.
- -A status notification should be used for any case in -which a background service needs to alert the user about an event that requires a response. A -background service -should never launch an activity on its own in order to receive user interaction. -The service should instead create a status notification that will launch the activity -when selected by the user.
- -Figure 1 shows the status bar with a notification icon on the left side.
-
-Figure 1. Status bar with a notification.
- -Figure 2 shows the notification's message in the notifications window.
- -
-Figure 2. The notifications window.
- - ++ A notification is a message you can display to the user outside of your application's + normal UI. When you tell the system to issue a notification, it first appears as an icon in the + notification area. To see the details of the notification, the user opens the + notification drawer. Both the notification area and the notification drawer + are system-controlled areas that the user can view at any time. +
++ Figure 1. Notifications in the notification area. +
+
++ Figure 2. Notifications in the notification drawer. +
Notification Design
-For design guidelines, read Android Design's Notifications guide.
++ Notification Design +
++ Notifications, as an important part of the Android UI, have their own design guidelines. To + learn how to design notifications and their interactions, read the Android Design Guide + Notifications topic. +
An {@link android.app.Activity} or {@link android.app.Service} can initiate a status -notification. Because an activity can perform actions only while it is -running in the foreground and its window has focus, you will usually create status notifications -from a -service. This way, the notification can be created from the background, -while the user is using another application or -while the device is asleep. To create a notification, you must use two -classes: {@link android.app.Notification} and {@link android.app.NotificationManager}.
- -Use an instance of the {@link android.app.Notification} class to define the properties of your -status notification, such as the status icon, the notification message, and extra settings -such as a sound to play. The {@link android.app.NotificationManager} is an Android system service -that executes and manages all status notifications. You do not instantiate the -{@link android.app.NotificationManager} directly. In order -to give it your {@link android.app.Notification}, you must retrieve a reference to the -{@link android.app.NotificationManager} with -{@link android.app.Activity#getSystemService(String) getSystemService()} and -then, when you want to notify the user, pass it your {@link android.app.Notification} with -{@link android.app.NotificationManager#notify(int,Notification) notify()}.
- -To create a status notification:
--String ns = Context.NOTIFICATION_SERVICE; -NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns); --
-int icon = R.drawable.notification_icon; -CharSequence tickerText = "Hello"; -long when = System.currentTimeMillis(); - -Notification notification = new Notification(icon, tickerText, when); --
-Context context = getApplicationContext(); -CharSequence contentTitle = "My notification"; -CharSequence contentText = "Hello World!"; -Intent notificationIntent = new Intent(this, MyClass.class); -PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); - -notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent); --
-private static final int HELLO_ID = 1; - -mNotificationManager.notify(HELLO_ID, notification); --
That's it. Your user has now been notified.
-A central part of the user's experience with a notification revolves around -how it interacts with the application's UI flow. You must implement -this correctly to provide a consistent user experience within your app.
- -Two typical examples of notifications are provided by Calendar, which can send out -notifications of upcoming events, and Email, which can send out notifications -when new messages arrive. These represent the two recommended patterns for handling -notifications: either launching into an activity that is separate from the -main application, or launching an entirely new instance of the application -showing the appropriate point for the notification.
- -The following scenario shows how the activity stack should work -in these two typical notification flows, first handling a Calendar notification: +
+ Note: This guide refers to the + {@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder} class + in the version 4 Support Library. + The class {@link android.app.Notification.Builder Notification.Builder} was added in API + level 11.
- -Handling an Email notification:
- -In an Email style of notification, the UI launched by the notification -shows the main application in a state representing that notification. -For example, when the Email application comes to the foreground from its -notification, it displays either the conversion list or a specific -conversation depending on whether there are multiple or only one new -email. To achieve this, we want to completely replace whatever current -state the application is in with a new activity stack representing the -new notification state.
- -The following code illustrates how to show this kind of notification. Of
-most interest is the makeMessageIntentStack() method, which constructs
-an array of intents representing the app's new activity stack for this state.
-(If you are using fragments, you may need to initialize your fragment and
-app state so that pressing Back will switch the UI back to its parent state.)
-The core of this is the {@link android.content.Intent#makeRestartActivityTask
-Intent.makeRestartActivityTask()} method, which constructs the root activity
-of the stack with the appropriate flags, such as
-{@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TASK Intent.FLAG_ACTIVITY_CLEAR_TASK}.
In a Calendar style of notification, the UI launched by the notification -is a dedicated activity that is not part of the normal application flow. -For example, when the user receives a Calendar notification, choosing that -notification starts a special activity that displays a list -of upcoming calendar events — this view is available only -from the notification, not through the Calendar's normal user -interface.
- -The code for posting this type of notification is very straight-forward; it -is like the above, but the {@link android.app.PendingIntent} is for just a single -activity, our dedicated notification activity.
- -{@sample development/samples/ApiDemos/src/com/example/android/apis/app/IncomingMessage.java - interstitial_notification} - -This is not enough, however. Normally Android considers all activities within
-an application to be part of that application's UI flow, so simply launching the
-activity like this can cause it to be mixed with your normal application back stack
-in undesired ways. To make it behave correctly, in the manifest declaration
-for the activity the attributes
-android:launchMode="singleTask",
-android:taskAffinity="" and
-android:excludeFromRecents="true"
-must be set. The full activity declaration for this sample is:
You must be careful when launching other activities from this initial activity,
-because this is not a top-level part of the application, does not appear in
-recents, and needs to be relaunched at any point from the notification with new data
-to show. This best approach is to make sure any activity launched from it is
-launched in its own task. When doing this care must be taken to make sure this
-new task interacts well with the current state of your exiting application's
-task. This is essentially
-the same as switching to the main application as described for the Email style
-notification shown before. Given the makeMessageIntentStack()
-method previously shown, handling a click then would look something like this:
The {@link android.app.NotificationManager} is a system service that manages all -notifications. You must retrieve a reference to it with the -{@link android.app.Activity#getSystemService(String) getSystemService()} method. -For example:
--String ns = Context.NOTIFICATION_SERVICE; -NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns); -- -
When you want to deliver your status notification, pass the {@link android.app.Notification} -to the {@link android.app.NotificationManager} with {@link -android.app.NotificationManager#notify(int,Notification)}. -The first parameter is the unique ID for the notification and the second is the {@link -android.app.Notification} object. -The ID uniquely identifies the notification from within your -application. The ID is necessary if you need to update the notification or (if -your application manages different kinds of notifications) select the appropriate action -when the user returns to your application via the intent defined in the notification.
- -To clear the status notification when the user selects it from the notifications -window, add the "FLAG_AUTO_CANCEL" flag to your {@link android.app.Notification}. You can -also clear it manually with {@link android.app.NotificationManager#cancel(int)}, passing it the -notification ID, or clear all your notifications with {@link -android.app.NotificationManager#cancelAll()}.
- - -A {@link android.app.Notification} object defines the details of the notification -message that is displayed in the status bar and notifications window, and any other -alert settings, such as sounds and blinking lights.
- -A status notification requires all of the following:
-Optional settings for the status notification include:
-The starter-kit for a new notification includes the -{@link android.app.Notification#Notification(int,CharSequence,long)} constructor and the -{@link android.app.Notification#setLatestEventInfo(Context,CharSequence,CharSequence,PendingIntent)} -method. These define all the required settings for a notification. -The following snippet demonstrates a basic notification setup:
--int icon = R.drawable.notification_icon; // icon from resources -CharSequence tickerText = "Hello"; // ticker-text -long when = System.currentTimeMillis(); // notification time -Context context = getApplicationContext(); // application Context -CharSequence contentTitle = "My notification"; // message title -CharSequence contentText = "Hello World!"; // message text - -Intent notificationIntent = new Intent(this, MyClass.class); -PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); - -// the next two lines initialize the Notification, using the configurations above -Notification notification = new Notification(icon, tickerText, when); -notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent); -- - -
You can update the information in your status notification as events -continue to occur in your application. For example, when a new SMS text message arrives -before previous messages have been read, the Messaging application updates the existing -notification to display the total number of new messages received. -This practice of updating an existing notification is much better than adding new -notifications, because it avoids clutter in the notifications window.
- -Because each notification is uniquely identified -by the {@link android.app.NotificationManager} with an integer ID, you can revise the notification -by calling {@link -android.app.Notification#setLatestEventInfo(Context,CharSequence,CharSequence,PendingIntent) -setLatestEventInfo()} with new values, change some field values of the notification, and then call -{@link android.app.NotificationManager#notify(int,Notification) notify()} again.
- -You can revise each property with the object member fields -(except for the {@link android.content.Context} and the notification title and text). You -should always revise the text message when you update the notification by calling -{@link android.app.Notification#setLatestEventInfo(Context,CharSequence,CharSequence,PendingIntent) -setLatestEventInfo()} with new values for contentTitle and contentText. -Then call {@link android.app.NotificationManager#notify(int,Notification) notify()} to update the -notification. (Of course, if you've created a custom notification -layout, then updating these title and text values has no effect.)
- - -You can alert the user with the default notification sound -(which is defined by the user) or with a sound specified by your application.
- -To use the user's default sound, add "DEFAULT_SOUND" to the defaults field:
--notification.defaults |= Notification.DEFAULT_SOUND; -- -
To use a different sound with your notifications, pass a Uri reference to the -sound field. -The following example uses a known audio file saved to the device SD card:
-
-notification.sound = Uri.parse("file:///sdcard/notification/ringer.mp3");
-
-
-In the next example, the audio file is chosen from the internal -{@link android.provider.MediaStore.Audio.Media MediaStore}'s {@link android.content.ContentProvider}:
--notification.sound = Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "6"); -- -
In this case, the exact ID of the media file ("6") is known and appended to the content -{@link android.net.Uri}. If you don't know the exact ID, you must query all the -media available in the {@link android.provider.MediaStore} with a {@link -android.content.ContentResolver}. -See the Content Providers -documentation for more information on using a ContentResolver.
- -If you want the sound to continuously repeat until the user responds to the notification -or the notification is cancelled, add {@link android.app.Notification#FLAG_INSISTENT} to the -flags field.
- -Note: If the defaults field includes -{@link android.app.Notification#DEFAULT_SOUND}, then the default sound overrides any sound defined -by the sound field.
- - -You can alert the user with the the default -vibration pattern or with a vibration pattern defined by your application.
- -To use the default pattern, add {@link android.app.Notification#DEFAULT_VIBRATE} to the -defaults field:
--notification.defaults |= Notification.DEFAULT_VIBRATE; -- -
To define your own vibration pattern, pass an array of long values to the -vibrate field:
-
-long[] vibrate = {0,100,200,300};
-notification.vibrate = vibrate;
-
-
-The long array defines the alternating pattern for the length of vibration off and on -(in milliseconds). The first value is how long to wait (off) before beginning, the second -value is the length of the first vibration, the third is the next length off, and so on. -The pattern can be as long as you like, but it can't be set to repeat. + + +
+ Notifications in the notification drawer appear in two main visual styles, normal view and + big view. +
+ ++ A notification in normal view appears in an area that's up to 64 dp tall. Even if you create a + notification with a big view style, it will appear in normal view until it's expanded. This + is an example of a normal view: +
+
++ Figure 3. Notification in normal view. +
++ The callouts in the illustration refer to the following: +
++ A notification's big view appears only when the notification is expanded, which happens when the + notification is at the top of the notification drawer, or when the user expands the + notification with a gesture. +
++ The following screenshot shows an inbox-style notification: +
+
++ Figure 4. Big view notification. +
++ Notice that the big view shares most of its visual elements with the normal view. The + only difference is callout number 7, the details area. Each big view style sets this area in + a different way. The available styles are:
- -Note: If the defaults field includes -{@link android.app.Notification#DEFAULT_VIBRATE}, then the default vibration overrides any vibration -defined by the -vibrate field.
- - -To alert the user by flashing LED lights, you can implement the default -light pattern (if available), or define your own color and pattern for the lights.
- -To use the default light setting, add {@link android.app.Notification#DEFAULT_LIGHTS} to the -defaults field:
--notification.defaults |= Notification.DEFAULT_LIGHTS; -- -
To define your own color and pattern, define a value for the ledARGB field -(for the color), the ledOffMS field (length of time, in milliseconds, to -keep the light off), the ledOnMS (length of time, in milliseconds, to keep the light on), -and also add {@link android.app.Notification#FLAG_SHOW_LIGHTS} to the flags field:
--notification.ledARGB = 0xff00ff00; -notification.ledOnMS = 300; -notification.ledOffMS = 1000; -notification.flags |= Notification.FLAG_SHOW_LIGHTS; -- -
In this example, the green light repeatedly flashes on for 300 milliseconds and -turns off for one second. Not every color in the spectrum is supported by the -device LEDs, and not every device supports the same colors, so the hardware -estimates to the best of its ability. Green is the most common notification color.
- - -You can add several more features to your notifications -using {@link android.app.Notification} fields and flags. Some useful features include the -following:
-+ All of the big view styles also have the following content options that aren't + available in normal view: +
++ Applying a big view style to a notification is described in the section + Applying a big view style to a notification. +
+ + ++ You specify the UI information and actions for a notification in a + {@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder} object. + To create the notification itself, you call + {@link android.support.v4.app.NotificationCompat.Builder#build + NotificationCompat.Builder.build()}, which returns a {@link android.app.Notification} object + containing your specifications. + To issue the notification, you pass the {@link android.app.Notification} object to the system + by calling {@link android.app.NotificationManager#notify NotificationManager.notify()}. +
+ ++ A {@link android.app.Notification} object must contain the following: +
++ All other notification settings and contents are optional. To learn more about them, + see the reference documentation for {@link android.support.v4.app.NotificationCompat.Builder}. +
+ ++ Although they're optional, you should add at least one action to your notification. + An action allows users to go directly from the notification to an + {@link android.app.Activity} in your application, where they can look at one or more events + or do further work. +
++ A notification can provide multiple actions. You should always define the action that's + triggered when the user touches the notification; usually this action opens an + {@link android.app.Activity} in your application. You can also add buttons to the notification + that perform additional actions such as snoozing an alarm or responding immediately to a text + message. +
++ Inside a {@link android.app.Notification}, the action itself is defined by a + {@link android.app.PendingIntent} containing an {@link android.content.Intent} that starts + an {@link android.app.Activity} in your application. To associate the + {@link android.app.PendingIntent} with a gesture, call the appropriate method of + {@link android.support.v4.app.NotificationCompat.Builder}. For example, if you want to start + {@link android.app.Activity} when the user touches the notification text in + the notification drawer, you add the {@link android.app.PendingIntent} by calling + {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent setContentIntent()}. +
++ Starting an {@link android.app.Activity} when the user touches the notification is the most + common action scenario. You can also start an {@link android.app.Activity} when the user + dismisses an {@link android.app.Activity}, and you can start an {@link android.app.Activity} + from an action button. To learn more, read the reference guide for + {@link android.support.v4.app.NotificationCompat.Builder}. +
+ ++ The following snippet illustrates a simple notification that specifies an activity to open when + the user touches the notification. Notice that the code creates a + {@link android.support.v4.app.TaskStackBuilder} object and uses it to create the + {@link android.app.PendingIntent} for the action. This pattern is explained in more detail + in the section + Preserving Navigation when Starting an Activity: +
+
+NotificationCompat.Builder mBuilder =
+ new NotificationCompat.Builder(this)
+ .setSmallIcon(R.drawable.notification_icon)
+ .setContentTitle("My notification")
+ .setContentText("Hello World!");
+// Creates an explicit intent for an Activity in your app
+Intent resultIntent = new Intent(this, ResultActivity.class);
-See the {@link android.app.Notification} class reference for more information about additional
-features that you can customize for your application.
-
-
-Creating a Custom Notification Layout
-
-
-
-Figure 3. Notification with a custom layout.
-
-
-By default, the notification that appears in the notifications window includes a title
-and the message text.
-These are defined by the contentTitle and contentText
-parameters of the {@link android.app.Notification#setLatestEventInfo(Context,CharSequence,CharSequence,PendingIntent)
-setLatestEventInfo()} method. However, you can also define a custom layout for the
-notification using
-{@link android.widget.RemoteViews}. Figure 3 shows an example of a
-custom notification layout. It looks similar to the default notification, but is
-actually created with a custom XML layout.
-
-To define your own layout for the notification,
-instantiate a {@link android.widget.RemoteViews} object that inflates a custom layout file, then
-pass the {@link android.widget.RemoteViews} to the contentView field of your
-Notification.
-
-Creating a custom notification layout is best understood with an example:
+// The stack builder object will contain an artificial back stack for the
+// started Activity.
+// This ensures that navigating backward from the Activity leads out of
+// your application to the Home screen.
+TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
+// Adds the back stack for the Intent (but not the Intent itself)
+stackBuilder.addParentStack(ResultActivity.class);
+// Adds the Intent that starts the Activity to the top of the stack
+stackBuilder.addNextIntent(resultIntent);
+PendingIntent resultPendingIntent =
+ stackBuilder.getPendingIntent(
+ 0,
+ PendingIntent.FLAG_UPDATE_CURRENT
+ );
+mBuilder.setContentIntent(resultPendingIntent);
+NotificationManager mNotificationManager =
+ (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+// mId allows you to update the notification later on.
+mNotificationManager.notify(mId, mBuilder.build());
+
+That's it. Your user has now been notified.
+ ++ To have a notification appear in a big view when it's expanded, first create a + {@link android.support.v4.app.NotificationCompat.Builder} object with the normal view options + you want. Next, call {@link android.support.v4.app.NotificationCompat.Builder#setStyle + Builder.setStyle()} with a big view style object as its argument. +
++ For example, the following code snippet demonstrates how to alter the notification created + in the previous snippet to use the Inbox big view style: +
+
+NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
+ .setSmallIcon(R.drawable.notification_icon)
+ .setContentTitle("Event tracker")
+ .setContentText("Events received")
+NotificationCompat.InboxStyle inboxStyle =
+ new NotificationCompat.InboxStyle();
+String[] events = new String[6];
+// Sets a title for the Inbox style big view
+inboxStyle.SetBigContentTitle("Event tracker details:");
+...
+// Moves events into the big view
+for (int i=0; i < events.length; i++) {
+ inboxStyle.addLine(events[i]);
+}
+// Moves the big view style object into the notification object.
+mBuilder.setStyle(inBoxStyle);
+...
+// Issue the notification here.
+
+
+
++ When you need to issue a notification multiple times for the same type of event, you + should avoid making a completely new notification. Instead, you should consider updating a + previous notification, either by changing some of its values or by adding to it, or both. +
++ For example, Gmail notifies the user that new emails have arrived by increasing its count of + unread messages and by adding a summary of each email to the notification. This is called + "stacking" the notification; it's described in more detail in the + Notifications Design guide. +
++ The following section describes how to update notifications and also how to remove them. +
++ To set up a notification so it can be updated, issue it with a notification ID by + calling {@link android.app.NotificationManager#notify(int, Notification) + NotificationManager.notify(ID, notification)}. To update this notification once you've issued + it, update or create a {@link android.support.v4.app.NotificationCompat.Builder} object, + build a {@link android.app.Notification} object from it, and issue the + {@link android.app.Notification} with the same ID you used previously. If + the previous notification is still visible, the system updates it from the contents of + the {@link android.app.Notification} object. If the previous notification has been dismissed, a + new notification is created instead. +
++ The following snippet demonstrates a notification that is updated to reflect the + number of events that have occurred. It stacks the notification, showing a summary: +
+
+mNotificationManager =
+ (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+// Sets an ID for the notification, so it can be updated
+int notifyID = 1;
+mNotifyBuilder = new NotificationCompat.Builder(this)
+ .setContentTitle("New Message")
+ .setContentText("You've received new messages.")
+ .setSmallIcon(R.drawable.ic_notify_status)
+numMessages = 0;
+// Start of a loop that processes data and then notifies the user
+...
+ mNotifyBuilder.setContentText(currentText)
+ .setNumber(++numMessages);
+ // Because the ID remains unchanged, the existing notification is
+ // updated.
+ mNotificationManager.notify(
+ notifyID,
+ mNotifyBuilder.build());
+...
+
++ This produces a notification that looks like this: +
+
++ Figure 5. Updated notification displayed in the notification drawer. +
+ ++ Notifications remain visible until one of the following happens: +
++ When you start an {@link android.app.Activity} from a notification, you must preserve the + user's expected navigation experience. Clicking Back should take the user back through + the application's normal work flow to the Home screen, and clicking Recents should show + the {@link android.app.Activity} as a separate task. To preserve the navigation experience, you + should start the {@link android.app.Activity} in a fresh task. How you set up the + {@link android.app.PendingIntent} to give you a fresh task depends on the nature of the + {@link android.app.Activity} you're starting. There are two general situations: +
++ Notifications from the Gmail app demonstrate this. When you touch a notification for + a single email message, you see the message itself. Touching Back takes you + backwards through Gmail to the Home screen, just as if you had entered Gmail from the + Home screen rather than entering it from a notification. +
++ This happens regardless of the application you were in when you touched the + notification. For example, if you're in Gmail composing a message, and you click a + notification for a single email, you go immediately to that email. Touching Back + takes you to the inbox and then the Home screen, rather than taking you to the + message you were composing. +
++ To set up a {@link android.app.PendingIntent} that starts a direct entry + {@link android.app.Activity}, follow these steps: +
custom_notification.xml:
+ <meta-data>
+ element as the child of the
+<activity>.
+
+ For this element, set
+android:name="android.support.PARENT_ACTIVITY".
+ Set
+android:value="<parent_activity_name>"
+ where <parent_activity_name> is the value of
+android:name
+ for the parent
+<activity>
+ element. See the following XML for an example.
+
android:parentActivityName
+ attribute to the
+<activity>
+ element of the {@link android.app.Activity} you're starting.
+ + The final XML should look like this: +
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/layout" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:padding="10dp" > - <ImageView android:id="@+id/image" - android:layout_width="wrap_content" - android:layout_height="fill_parent" - android:layout_alignParentLeft="true" - android:layout_marginRight="10dp" /> - <TextView android:id="@+id/title" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_toRightOf="@id/image" - style="@style/NotificationTitle" /> - <TextView android:id="@+id/text" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_toRightOf="@id/image" - android:layout_below="@id/title" - style="@style/NotificationText" /> -</RelativeLayout> +<activity + android:name=".MainActivity" + android:label="@string/app_name" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> +</activity> +<activity + android:name=".ResultActivity" + android:parentActivityName=".MainActivity"> + <meta-data + android:name="android.support.PARENT_ACTIVITY" + android:value=".MainActivity"/> +</activity>- -
Notice that the two {@link android.widget.TextView} elements include the {@code style} -attribute. It's important that you use style resources for the text in your custom -notifications, because the background color of the notification can vary across different -devices and platform versions. Beginning with Android 2.3 (API level 9), the system defines a -style for the text it uses for the default notification layouts. Thus, you should apply -that style when running on Android 2.3 or higher to ensure that your text is visible against -the background.
- -For example, to use the standard text colors on versions of Android lower than 2.3, you -should use the following styles for {@code res/values/styles.xml}:
--<?xml version="1.0" encoding="utf-8"?> -<resources> - <style name="NotificationText"> - <item name="android:textColor">?android:attr/textColorPrimary</item> - </style> - <style name="NotificationTitle"> - <item name="android:textColor">?android:attr/textColorPrimary</item> - <item name="android:textStyle">bold</item> - </style> - <!-- If you want a slightly different color for some text, - consider using ?android:attr/textColorSecondary --> -</resources> --
Then, to apply the system's default colors for notifications on Android -2.3 and higher, use the following styles for {@code res/values-v9/styles.xml}:
--<?xml version="1.0" encoding="utf-8"?> -<resources> - <style name="NotificationText" parent="android:TextAppearance.StatusBar.EventContent" /> - <style name="NotificationTitle" parent="android:TextAppearance.StatusBar.EventContent.Title" /> -</resources> --
Now, when running on Android 2.3 (API level 9) or higher, the text in your custom view will -use the same colors that the system does for default notifications. This is important because later -versions of Android actually change the background color of the notifications to be dark. Inheriting -the system's styles ensures that your text will be light in such cases, but also if the background -is some other unexpected color, your text will also change as appropriate.
--RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.custom_notification_layout); -contentView.setImageViewResource(R.id.image, R.drawable.notification_image); -contentView.setTextViewText(R.id.title, "Custom notification"); -contentView.setTextViewText(R.id.text, "This is a custom layout"); -notification.contentView = contentView; -- -
As shown here, pass the application's package name and the layout - resource ID to the RemoteViews constructor. Then, define the content for the ImageView and TextView, - using the {@link android.widget.RemoteViews#setImageViewResource(int, int) setImageViewResource()} - and {@link android.widget.RemoteViews#setTextViewText(int, CharSequence) setTextViewText()}. - In each case, pass the reference ID of the appropriate View object that you want to set, along with - the value for that View. Finally, the RemoteViews object is passed to the Notification in the - contentView field.
--Intent notificationIntent = new Intent(this, MyClass.class); -PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); -notification.contentIntent = contentIntent; --
mNotificationManager.notify(CUSTOM_VIEW_ID, notification);-
+ Note: Although the argument to + {@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()} + is a reference to the started {@link android.app.Activity}, the method call + doesn't add the {@link android.content.Intent} that starts the + {@link android.app.Activity}. Instead, that's taken care of in the next step. +
++ The following code snippet demonstrates the process: +
++... +Intent resultIntent = new Intent(this, ResultActivity.class); +TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); +// Adds the back stack +stackBuilder.addParentStack(ResultActivity.class); +// Adds the Intent to the top of the stack +stackBuilder.addNextIntent(resultIntent); +// Gets a PendingIntent containing the entire back stack +PendingIntent resultPendingIntent = + stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT); +... +NotificationCompat.Builder builder = new NotificationCompat.Builder(this); +builder.setContentIntent(resultPendingIntent); +NotificationManager mNotificationManager = + (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); +mNotificationManager.notify(id, builder.build()); ++ +
+ The following section describes how to set up a special activity + {@link android.app.PendingIntent}. +
++ A special {@link android.app.Activity} doesn't need a back stack, so you don't have to + define its {@link android.app.Activity} hierarchy in the manifest, and you don't have + to call + {@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()} to build a + back stack. Instead, use the manifest to set up the {@link android.app.Activity} task options, + and create the {@link android.app.PendingIntent} by calling + {@link android.app.PendingIntent#getActivity getActivity()}: +
+<activity>
+ element for the {@link android.app.Activity}
+ android:name="activityclass"
+ android:taskAffinity=""
+ android:excludeFromRecents="true"
+ + This snippet shows the element: +
++<activity + android:name=".ResultActivity" +... + android:launchMode="singleTask" + android:taskAffinity="" + android:excludeFromRecents="true"> +</activity> +... ++
+ The following code snippet demonstrates the process: +
++// Instantiate a Builder object. +NotificationCompat.Builder builder = new NotificationCompat.Builder(this); +// Creates an Intent for the Activity +Intent notifyIntent = + new Intent(new ComponentName(this, ResultActivity.class)); +// Sets the Activity to start in a new, empty task +notifyIntent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK); +// Creates the PendingIntent +PendingIntent notifyIntent = + PendingIntent.getActivity( + this, + 0, + notifyIntent + PendingIntent.FLAG_UPDATE_CURRENT +); +// Puts the PendingIntent into the notification builder +builder.setContentIntent(notifyIntent); +// Notifications are issued by sending them to the +// NotificationManager system service. +NotificationManager mNotificationManager = + (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); +// Builds an anonymous Notification object from the builder, and +// passes it to the NotificationManager +mNotificationManager.notify(id, builder.build()); ++
+ Notifications can include an animated progress indicator that shows users the status + of an ongoing operation. If you can estimate how long the operation takes and how much of it + is complete at any time, use the "determinate" form of the indicator + (a progress bar). If you can't estimate the length of the operation, use the + "indeterminate" form of the indicator (an activity indicator). +
++ Progress indicators are displayed with the platform's implementation of the + {@link android.widget.ProgressBar} class. +
++ To use a progress indicator, call + {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}. The + determinate and indeterminate forms are described in the following sections. +
+ +
+ To display a determinate progress bar, add the bar to your notification by calling
+ {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()
+ setProgress(max, progress, false)} and then issue the notification. As your operation proceeds,
+ increment progress, and update the notification. At the end of the operation,
+ progress should equal max. A common way to call
+ {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}
+ is to set max to 100 and then increment progress as a
+ "percent complete" value for the operation.
+
+ You can either leave the progress bar showing when the operation is done, or remove it. In + either case, remember to update the notification text to show that the operation is complete. + To remove the progress bar, call + {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress() + setProgress(0, 0, false)}. For example: +
+
+...
+mNotifyManager =
+ (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+mBuilder = new NotificationCompat.Builder(this);
+mBuilder.setContentTitle("Picture Download")
+ .setContentText("Download in progress")
+ .setSmallIcon(R.drawable.ic_notification);
+// Start a lengthy operation in a background thread
+new Thread(
+ new Runnable() {
+ @Override
+ public void run() {
+ int incr;
+ // Do the "lengthy" operation 20 times
+ for (incr = 0; incr <= 100; incr+=5) {
+ // Sets the progress indicator to a max value, the
+ // current completion percentage, and "determinate"
+ // state
+ mBuilder.setProgress(100, incr, false);
+ // Displays the progress bar for the first time.
+ mNotifyManager.notify(0, mBuilder.build());
+ // Sleeps the thread, simulating an operation
+ // that takes time
+ try {
+ // Sleep for 5 seconds
+ Thread.sleep(5*1000);
+ } catch (InterruptedException e) {
+ Log.d(TAG, "sleep failure");
+ }
+ }
+ // When the loop is finished, updates the notification
+ mBuilder.setContentText("Download complete")
+ // Removes the progress bar
+ .setProgress(0,0,false);
+ mNotifyManager.notify(ID, mBuilder.build());
+ }
+ }
+// Starts the thread by calling the run() method in its Runnable
+).start();
+
++ The resulting notifications are shown in figure 6. On the left side is a snapshot of the + notification during the operation; on the right side is a snapshot of it after the operation + has finished. +
+
++Figure 6. The progress bar during and after the operation.
+ ++ To display an indeterminate activity indicator, add it to your notification with + {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress(0, 0, true)} + (the first two arguments are ignored), and issue the notification. The result is an indicator + that has the same style as a progress bar, except that its animation is ongoing. +
++ Issue the notification at the beginning of the operation. The animation will run until you + modify your notification. When the operation is done, call + {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress() + setProgress(0, 0, false)} and then update the notification to remove the activity indicator. + Always do this; otherwise, the animation will run even when the operation is complete. Also + remember to change the notification text to indicate that the operation is complete. +
++ To see how activity indicators work, refer to the preceding snippet. Locate the following lines: +
++// Sets the progress indicator to a max value, the current completion +// percentage, and "determinate" state +mBuilder.setProgress(100, incr, false); +// Issues the notification +mNotifyManager.notify(0, mBuilder.build()); ++
+ Replace the lines you've found with the following lines: +
++ // Sets an activity indicator for an operation of indeterminate length +mBuilder.setProgress(0, 0, false); +// Issues the notification +mNotifyManager.notify(0, mBuilder.build()); ++
+ The resulting indicator is shown in figure 7: +
+
+Figure 7. An ongoing activity indicator.
-The {@link android.widget.RemoteViews} class also includes methods that you can use to easily add -a {@link android.widget.Chronometer} or {@link android.widget.ProgressBar} -in your notification's layout. For more information about creating custom layouts for your -notification, refer to the {@link android.widget.RemoteViews} class reference.
- -Caution: -When creating a custom notification layout, you must take special care to ensure that your -custom layout functions properly in different device orientations and resolutions. While this -advice applies to all View layouts created on Android, it is especially important in this case -because your layout real estate is very restricted. So don't make your custom layout too -complex and be sure to test it in various configurations.
- - - + + + + ++ The notifications framework allows you to define a custom notification layout, which + defines the notification's appearance in a {@link android.widget.RemoteViews} object. + Custom layout notifications are similar to normal notifications, but they're based on a + {@link android.widget.RemoteViews} defined in a XML layout file. +
++ To define a custom notification layout, start by instantiating a + {@link android.widget.RemoteViews} object that inflates an XML layout file. Then, + instead of calling methods such as + {@link android.support.v4.app.NotificationCompat.Builder#setContentTitle setContentTitle()}, + call {@link android.support.v4.app.NotificationCompat.Builder#setContent setContent()}. To set + content details in the custom notification, use the methods in + {@link android.widget.RemoteViews} to set the values of the view's children: +
+.xml
+ + The {@link android.widget.RemoteViews} class also includes methods that you can use to easily + add a {@link android.widget.Chronometer} or {@link android.widget.ProgressBar} + to your notification's layout. For more information about creating custom layouts for your + notification, refer to the {@link android.widget.RemoteViews} reference documentation. +
++ Caution: When you use a custom notification layout, take special care to + ensure that your custom layout works with different device orientations and resolutions. While + this advice applies to all View layouts, it's especially important for notifications because + the space in the notification drawer is very restricted. Don't make your custom layout too + complex, and be sure to test it in various configurations. +
+ ++ Always use style resources for the text of a custom notification. The background color of the + notification can vary across different devices and platform versions, and using style resources + helps you account for this. Starting in API level 9, the system defined a style for the + standard notification layout text. If you use the same style in applications that target API + level 9 or higher, you'll ensure that your text is visible against the display background. +
diff --git a/docs/html/images/ui/notifications/activity_indicator.png b/docs/html/images/ui/notifications/activity_indicator.png new file mode 100644 index 0000000000000..e21fae261086c Binary files /dev/null and b/docs/html/images/ui/notifications/activity_indicator.png differ diff --git a/docs/html/images/ui/notifications/bigpicture_notification.png b/docs/html/images/ui/notifications/bigpicture_notification.png new file mode 100644 index 0000000000000..ced638095d4a3 Binary files /dev/null and b/docs/html/images/ui/notifications/bigpicture_notification.png differ diff --git a/docs/html/images/ui/notifications/bigpicture_notification_callouts.png b/docs/html/images/ui/notifications/bigpicture_notification_callouts.png new file mode 100644 index 0000000000000..e2d313aaf6b28 Binary files /dev/null and b/docs/html/images/ui/notifications/bigpicture_notification_callouts.png differ diff --git a/docs/html/images/ui/notifications/bigtext_notification.png b/docs/html/images/ui/notifications/bigtext_notification.png new file mode 100644 index 0000000000000..cd6e764f533a1 Binary files /dev/null and b/docs/html/images/ui/notifications/bigtext_notification.png differ diff --git a/docs/html/images/ui/notifications/bigtext_notification_callouts.png b/docs/html/images/ui/notifications/bigtext_notification_callouts.png new file mode 100644 index 0000000000000..4cfa403d31d81 Binary files /dev/null and b/docs/html/images/ui/notifications/bigtext_notification_callouts.png differ diff --git a/docs/html/images/ui/notifications/custom_message.png b/docs/html/images/ui/notifications/custom_message.png new file mode 100755 index 0000000000000..00b763239c401 Binary files /dev/null and b/docs/html/images/ui/notifications/custom_message.png differ diff --git a/docs/html/images/ui/notifications/iconic_notification.png b/docs/html/images/ui/notifications/iconic_notification.png new file mode 100644 index 0000000000000..4cabfdbe0a445 Binary files /dev/null and b/docs/html/images/ui/notifications/iconic_notification.png differ diff --git a/docs/html/images/ui/notifications/inbox_notification.png b/docs/html/images/ui/notifications/inbox_notification.png new file mode 100644 index 0000000000000..fb182d52c8909 Binary files /dev/null and b/docs/html/images/ui/notifications/inbox_notification.png differ diff --git a/docs/html/images/ui/notifications/inbox_notification_callouts.png b/docs/html/images/ui/notifications/inbox_notification_callouts.png new file mode 100644 index 0000000000000..2ec818e2f8e03 Binary files /dev/null and b/docs/html/images/ui/notifications/inbox_notification_callouts.png differ diff --git a/docs/html/images/ui/notifications/normal_notification.png b/docs/html/images/ui/notifications/normal_notification.png new file mode 100644 index 0000000000000..3cf02311be4cf Binary files /dev/null and b/docs/html/images/ui/notifications/normal_notification.png differ diff --git a/docs/html/images/ui/notifications/normal_notification_callouts.png b/docs/html/images/ui/notifications/normal_notification_callouts.png new file mode 100644 index 0000000000000..db57dafbe0f22 Binary files /dev/null and b/docs/html/images/ui/notifications/normal_notification_callouts.png differ diff --git a/docs/html/images/ui/notifications/notifications_window.png b/docs/html/images/ui/notifications/notifications_window.png new file mode 100755 index 0000000000000..0354ee92bda45 Binary files /dev/null and b/docs/html/images/ui/notifications/notifications_window.png differ diff --git a/docs/html/images/ui/notifications/progress_bar_summary.png b/docs/html/images/ui/notifications/progress_bar_summary.png new file mode 100644 index 0000000000000..073e697d471a6 Binary files /dev/null and b/docs/html/images/ui/notifications/progress_bar_summary.png differ diff --git a/docs/html/images/ui/notifications/progress_indicator_1.png b/docs/html/images/ui/notifications/progress_indicator_1.png new file mode 100644 index 0000000000000..f4c23657b0d1d Binary files /dev/null and b/docs/html/images/ui/notifications/progress_indicator_1.png differ diff --git a/docs/html/images/ui/notifications/progress_indicator_2.png b/docs/html/images/ui/notifications/progress_indicator_2.png new file mode 100644 index 0000000000000..975c90ef15b30 Binary files /dev/null and b/docs/html/images/ui/notifications/progress_indicator_2.png differ diff --git a/docs/html/images/ui/notifications/status_bar.png b/docs/html/images/ui/notifications/status_bar.png new file mode 100755 index 0000000000000..f0240a5f0b52d Binary files /dev/null and b/docs/html/images/ui/notifications/status_bar.png differ diff --git a/docs/html/images/ui/notifications/updated_notification.png b/docs/html/images/ui/notifications/updated_notification.png new file mode 100644 index 0000000000000..f69fa4b07c774 Binary files /dev/null and b/docs/html/images/ui/notifications/updated_notification.png differ