Login     Sign Up
Cyril Sermon (@admin)
9 months ago
45 Views

Notifications are a way for your applications to alert users, without using an Activity. Notifications are handled by the Notification Manger, and currently include the ability to:

❑Create a new status bar icon.

❑ Display additional information (and launch an Intent) in the extended status bar window. ❑ Flash the lights/LEDs.

❑Vibrate the phone.

❑Sound audible alerts (ringtones, media store sounds).

Notifications are the preferred way for invisible application components (Broadcast Receivers, Services, and inactive Activities) to alert users that events have occurred that require attention.

As a User Interface metaphor, Notifications are particularly well suited to mobile devices. It’s likely that your users will have their phones with them at all times but quite unlikely that they will be paying attention to them, or your application, at any given time. Generally, users will have several applications open in the background, and they won’t be paying attention to any of them.

In this environment, it’s important that your applications be able to alert users when specific events occur that require their attention.

Notifications can be persisted through insistent repetition, or (more commonly) by using an icon on the status bar. Status bar icons can be updated regularly or expanded to show additional information using the expanded status bar window shown in Figure 8-3.

To display the expanded status bar view, click a status bar icon and drag it toward the bottom of the screen. To “lock” it in place, ensure that you release your drag only after the window covers the entire screen. To hide it, simply drag it back upward.

Introducing the Notification Manager

The Notification Manager is a system Service used to handle Notifications. Get a reference to it using the getSystemService method, as shown in the snippet below:

String svcName = Context.NOTIFICATION_SERVICE;

NotificationManager notificationManager;

notificationManager = (NotificationManager)getSystemService(svcName);

Using the Notification Manager, you can trigger new Notifications, modify existing ones, or remove those that are no longer needed or wanted.

Creating Notifications

Creating and configuring a new Notification is done in three parts.

Firstly, you create a new Notification object, passing in the icon to display in the status bar, along with the status bar ticker-text, and the time of this Notification, as shown in the following code snippet:

Choose a drawable to display as the status bar icon int icon = R.drawable.icon;

Text to display in the status bar when the notification is launched String tickerText = “Notification”;

The extended status bar orders notification in time order

long when = System.currentTimeMillis();

Notification notification = new Notification(icon, tickerText, when);

The ticker-text will scroll along the status bar when the Notification is fired.

Secondly, configure the appearance of the Notification within the extended status window using the setLatestEventInfo method. This extended status window displays the icon and time defined in

the constructor and also shows a title and a details string. Notifications often represent a request for action or attention, so you can specify a PendingIntent that will be fired if a user clicks the Notification item.

The code snippet below uses setLatestEventInfo to set these values:

Context context = getApplicationContext();

Text to display in the extended status window String expandedText = “Extended status text”;

Title for the expanded status

String expandedTitle = “Notification Title”;

Intent to launch an activity when the extended text is clicked Intent

intent = new Intent(this, MyActivity.class);
PendingIntent launchIntent = PendingIntent.getActivity(context, 0, intent, 0);

notification.setLatestEventInfo(context,

expandedTitle,

expandedText,

launchIntent);

It’s good form to use one Notification icon to represent multiple instances of the same event (e.g., receiving multiple SMS messages). To demonstrate this to users, update the values set by setLatestEventInfo to reflect the most recent message and re-trigger the Notification to update its values.

You can also use the number property to display the number of events a status bar icon represents. Setting this value greater than 1, as shown below, overlays the values as a small number over the status bar icon:

notification.number++;

As with all changes to a Notification, you will need to re-trigger it to apply the change. To remove the overlay, set the number value to 0 or -1.

Finally, you can enhance Notifications using various properties on the Notification object to flash the device LEDs, vibrate the phone, and play audio files. These advanced features are detailed later in this chapter.

Triggering Notifications

To fire a Notification, pass it in to the notify method on the NotificationManager along with an integer reference ID, as shown in the following snippet:

int notificationRef = 1;

notificationManager.notify(notificationRef, notification);

To update a Notification that’s already been fired, re-trigger, passing the same reference ID. You can pass in either the same Notification object or an entirely new one. As long as the ID values are the same, the new Notification will be used to replace the status icon and extended status window details.

You also use the reference ID to cancel Notifications by calling the cancel method on the Notification

Manager, as shown below:

notificationManager.cancel(notificationRef);

Canceling a Notification removes its status bar icon and clears it from the extended status window.

Adding Notifications to the Earthquake Monitor

In the following example, the EarthquakeService is enhanced to trigger a Notification for each new earthquake. As well as displaying a status bar icon, the expanded Notification view will display the magnitude and location of the latest quake, and selecting it will open the Earthquake Activity.

Within the EarthquakeService, start by creating a new Notification instance variable to store the Notification object used to control the status bar icon and extended status window item details.

private Notification newEarthquakeNotification; public static final int NOTIFICATION_ID = 1;

Extend the onCreate method to create this Notification object.

@Override

public void onCreate() {

updateTimer = new Timer(“earthquakeUpdates”);

int icon = R.drawable.icon;

String tickerText = “New Earthquake Detected”; long when = System.currentTimeMillis();

newEarthquakeNotification= new Notification(icon, tickerText, when);

}

Now extend the announceNewQuake method to trigger the Notification after each new earth-quake is added to the Content Provider. Before initiating the Notification, update the extended details using setLatestEventInfo.

private void announceNewQuake(Quake quake) { String svcName = Context.NOTIFICATION_SERVICE; NotificationManager notificationManager;

notificationManager = (NotificationManager)getSystemService(svcName);

Context context = getApplicationContext(); String expandedText = quake.getDate().toString();

String expandedTitle = “M:” + quake.getMagnitude() + “ “ + quake.getDetails();

Intent startActivityIntent = new Intent(this, Earthquake.class); PendingIntent launchIntent = PendingIntent.getActivity(context,

0,

startActivityIntent,

0);

newEarthquakeNotification.setLatestEventInfo(context,

expandedTitle,

expandedText,

launchIntent);

newEarthquakeNotification.when = java.lang.System.currentTimeMillis();

notificationManager.notify(NOTIFICATION_ID, newEarthquakeNotification);

Intent intent = new Intent(NEW_EARTHQUAKE_FOUND); intent.putExtra(“date”, quake.getDate().getTime()); intent.putExtra(“details”, quake.getDetails()); intent.putExtra(“longitude”, quake.getLocation().getLongitude()); intent.putExtra(“latitude”, quake.getLocation().getLatitude()); intent.putExtra(“magnitude”, quake.getMagnitude());

sendBroadcast(intent);

}

The final step is to clear and disable Notifications within the two Activity classes. This is done to dismiss the status icon when the application is active.

4.1. Starting with the Earthquake Activity, modify the onCreate method to get a ref-erence to the Notification Manager.

NotificationManager notificationManager;

@Override

public void onCreate(Bundle icicle) {

[ ... existing onCreate ... ]

String svcName = Context.NOTIFICATION_SERVICE;

notificationManager = (NotificationManager)getSystemService(svcName);

}

4.2. Modify the onReceive method of the EarthquakeReceiver. As this is only reg-istered (so it will only execute) when the Activity is active, you can safely cancel all Notification earthquake Notifications here as soon as they’re triggered.

@Override

public void onReceive(Context context, Intent intent) { loadQuakesFromProvider();

notificationManager.cancel(EarthquakeService.NOTIFICATION_ID);

}

4.3. Next, extend the onResume method to cancel the Notification when the Activity becomes active.

@Override

public void onResume() {

notificationManager.cancel(EarthquakeService.NOTIFICATION_ID);

IntentFilter filter;

filter = new IntentFilter(EarthquakeService.NEW_EARTHQUAKE_FOUND); receiver = new EarthquakeReceiver(); registerReceiver(receiver, filter); super.onResume();

}

4.4. Repeat the same process with the EarthquakeMap Activity.

NotificationManager notificationManager;

@Override

public void onCreate(Bundle icicle) {

super.onCreate(icicle);

setContentView(R.layout.earthquake_map);

ContentResolver cr = getContentResolver(); earthquakeCursor = cr.query(EarthquakeProvider.CONTENT_URI,

null, null, null, null);

MapView earthquakeMap = (MapView)findViewById(R.id.map_view); earthquakeMap.getOverlays().add(new EarthquakeOverlay(earthquakeCursor));

String svcName = Context.NOTIFICATION_SERVICE;

notificationManager = (NotificationManager)getSystemService(svcName);

}

@Override

public void onResume() {

notificationManager.cancel(EarthquakeService.NOTIFICATION_ID);

earthquakeCursor.requery();

IntentFilter filter;

filter = new IntentFilter(EarthquakeService.NEW_EARTHQUAKE_FOUND); receiver = new EarthquakeReceiver(); registerReceiver(receiver, filter);

super.onResume();

}

public class EarthquakeReceiver extends BroadcastReceiver { @Override

public void onReceive(Context context, Intent intent) { notificationManager.cancel(EarthquakeService.NOTIFICATION_ID);

earthquakeCursor.requery();

MapView earthquakeMap = (MapView)findViewById(R.id.map_view); earthquakeMap.invalidate();

}

}