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

In the following sections, you’ll learn to enhance Notifications to provide additional alerting through hardware, in particular, by making the device ring, flash, and vibrate.

As each enhancement is described, you will be provided with a code snippet that can be added to the Earthquake example to provide user feedback on the severity of each earthquake as it’s detected.

To use the Notification techniques described here without also displaying the status bar icon, simply cancel the Notification directly after triggering it. This stops the icon from displaying but doesn’t inter-rupt the other effects.

Making Sounds

Using an audio alert to notify the user of a device event (like incoming calls) is a technique that pre-dates the mobile, and has stood the test of time. Most native phone events from incoming calls to new messages and low battery are announced by an audible ringtone.

Android lets you play any audio file on the phone as a Notification by assigning a location URI to the sound property, as shown in the snippet below:

notification.sound = ringURI;

To use your own custom audio, push the file onto your device, or include it as a raw resource, as described in Chapter 6.

The following snippet can be added to the announceNewQuake method within the Earthquake Service from the earlier example. It adds an audio component to the earthquake Notification, ringing one of the default phone ringtones if a significant earthquake (one with magnitude greater than 6) occurs.

if (quake.getMagnitude() > 6) {

Uri ringURI = Uri.fromFile(new File(“/system/media/audio/ringtones/ringer.mp3”)); newEarthquakeNotification.sound = ringURI;

}

Vibrating the Phone

You can use the phone’s vibration function to execute a vibration pattern specific to your Notification. Android lets you control the pattern of a vibration; you can use vibration to convey information as well as get the user’s attention.

To set a vibration pattern, assign an array of longs to the Notification’s vibrate property. Construct the array so that every alternate number is the length of time (in milliseconds) to vibrate or pause, respectively.

Before you can use vibration in your application, you need to be granted permission. Add a uses-permission to your application to request access to the device vibration using the following code snippet:

<uses-permission android:name=”android.permission.VIBRATE”/>

The following example shows how to modify a Notification to vibrate in a repeating pattern of 1 second on, 1 second off, for 5 seconds total.

long[] vibrate = new long[] { 1000, 1000, 1000, 1000, 1000 }; notification.vibrate = vibrate;

You can take advantage of this fine-grained control to pass information to your users. In the following update to the announceNewQuake method, the phone is set to vibrate in a pattern based on the power of the quake. Earthquakes are measured on an exponential scale, so you’ll use the same scale when creat-ing the vibration pattern.

For a barely perceptible magnitude 1 quake, the phone will vibrate for a fraction of a second; but for magnitude 10, an earthquake that would split the earth in two, your users will have a head start on the Apocalypse when their devices vibrate for a full 20 seconds. Most significant quakes fall between

3 and 7 on the Richter scale, so the more likely scenario is a more reasonable 200-millisecond to 4-second vibration duration range.

double vibrateLength = 100*Math.exp(0.53*quake.getMagnitude()); long[] vibrate = new long[] {100, 100, (long)vibrateLength }; newEarthquakeNotification.vibrate = vibrate;

The current Android Emulator does not visually or audibly indicate that the device is vibrating. To confirm that your Notification is behaving appropriately, you can monitor the log for “Vibration On”/“Vibration Off.”

Flashing the Lights

Notifications also include properties to configure the color and flash frequency of the device’s LED.

The ledARGB property can be used to set the LED’s color, while the ledOffMS and ledOnMS proper-ties let you set the frequency and pattern of the flashing LED. You can turn the LED on by setting the ledOnMS property to 1 and the ledOffMS property to 0, or turn it off by setting both properties to 0.

Once you have configured the LED settings, you must also add the FLAG_SHOW_LIGHTS flag to the Notification’s flags property.

The following code snippet shows how to turn on the red device LED:

notification.ledARGB = Color.RED;

notification.ledOffMS = 0;

notification.ledOnMS = 1;

notification.flags = notification.flags | Notification.FLAG_SHOW_LIGHTS;

Controlling the color and flash frequency is another opportunity to pass additional information to users.

In the Earthquake monitoring example, you can help your users perceive the nuances of an exponential scale by also using the device’s LED to help convey the magnitude. In the snippet below, the color of the LED depends on the size of the quake, and the frequency of the flashing is inversely related to the power of the quake:

int color;

if (quake.getMagnitude() < 5.4)

color = Color.GREEN;

else if (quake.getMagnitude() < 6)

color = Color.YELLOW;

else

color = Color.RED;

newEarthquakeNotification.ledARGB = color; newEarthquakeNotification.ledOffMS = (int)vibrateLength; newEarthquakeNotification.ledOnMS = (int)vibrateLength; newEarthquakeNotification.flags = newEarthquakeNotification.flags |

Notification.FLAG_SHOW_LIGHTS;

The current Android Emulator does not visually illustrate the LEDs. This makes it quite difficult to confirm that your LEDs are flashing correctly. In hardware, each device may have different limitations in regard to setting the color of the LED. In such cases, as close an approximation as possible will be used.

Ongoing and Insistent Notifications

Notifications can be configured as ongoing and/or insistent by setting the FLAG_INSISTENT and FLAG_ONGOING_EVENT flags.

Notifications flagged as ongoing, as in the snippet below, are used to represent events that are currently in progress (such as an incoming call). Ongoing events are separated from “normal” Notifications within the extended status bar window.

notification.flags = notification.flags | Notification.FLAG_ONGOING_EVENT;

Insistent Notifications repeat continuously until canceled. The code snippet below shows how to set a

Notification as insistent:

notification.flags = notification.flags | Notification.FLAG_INSISTENT;

Insistent Notifications are handled by continuously repeating the initial Notification effects until the Notification is canceled. Insistent Notifications should be reserved for situations like Alarms, where timely and immediate response is required.

Using Alarms

Alarms are an application independent way of firing Intents at predetermined times.

Alarms are set outside the scope of your applications, so they can be used to trigger application events or actions even after your application has been closed. They can be particularly powerful in combina-tion with Broadcast Receivers, allowing you to set Alarms that launch applications or perform actions without applications needing to be open and active until they’re required.

For example, you can use Alarms to implement an alarm clock application, perform regular network lookups, or schedule time-consuming or cost-bound operations at “off peak” times.

For timing operations that occur only during the lifetime of your applications, the Handler class in combination with Timers and Threads is a better approach as it allows Android better control over system resources.

Alarms in Android remain active while the device is in sleep mode and can optionally be set to wake the device; however, all Alarms are canceled whenever the device is rebooted.

Alarm operations are handled through the AlarmManager, a system Service accessed via getSystemService as shown below:

AlarmManager alarms = (AlarmManager)getSystemService(Context.ALARM_SERVICE);

To create a new Alarm, use the set method and specify an alarm type, trigger time, and a Pending Intent to fire when the Alarm triggers. If the Alarm you set occurs in the past, it will be triggered immediately.

There are four alarm types available. Your selection will determine if the time value passed in the set method represents a specific time or an elapsed wait:

❑RTC_WAKEUP Wakes up the device to fire the Intent at the clock time specified when setting the Alarm.

❑RTC Will fire the Intent at an explicit time, but will not wake the device.

❑ELAPSED_REALTIME The Intent will be fired based on the amount of time elapsed since the device was booted, but will not wake the device. The elapsed time includes any period of time the device was asleep. Note that the time elapsed is since it was last booted.

❑ELAPSED_REALTIME_WAKEUP Will wake up the device if necessary and fire the Intent after a specified length of time has passed since the device was booted.

The Alarm creation process is demonstrated in the snippet below:

int alarmType = AlarmManager.ELAPSED_REALTIME_WAKEUP; long timeOrLengthofWait = 10000; String ALARM_ACTION = “ALARM_ACTION”;

Intent intentToFire = new Intent(ALARM_ACTION);

PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intentToFire, 0);

alarms.set(alarmType, timeOrLengthofWait, pendingIntent);

When the Alarm goes off, the Pending Intent you specified will be fired. Setting a second Alarm using the same Pending Intent replaces the preexisting Alarm.

To cancel an Alarm, call cancel on the Alarm Manager, passing in the Pending Intent you no longer wish to trigger, as shown in the snippet below:

alarms.cancel(pendingIntent);

In the following code snippet, two Alarms are set and the first one is subsequently canceled. The first is explicitly set to a specific time and will wake up the device in order to fire. The second is set for 30 minutes of time elapsed since the device was started, but will not wake the device if it’s sleeping.

AlarmManager alarms = (AlarmManager)getSystemService(Context.ALARM_SERVICE);

String MY_RTC_ALARM = “MY_RTC_ALARM”;

String ALARM_ACTION = “MY_ELAPSED_ALARM”;

PendingIntent rtcIntent = PendingIntent.getBroadcast(this, 0,

new Intent(MY_RTC_ALARM),

1);

PendingIntent elapsedIntent = PendingIntent.getBroadcast(this, 0,

new Intent(ALARM_ACTION),

1);

Wakeup and fire intent in 5 hours.

Date t = new Date(); t.setTime(java.lang.System.currentTimeMillis() + 60*1000*5); alarms.set(AlarmManager.RTC_WAKEUP, t.getTime(), rtcIntent);

Fire intent in 30 mins if already awake.

alarms.set(AlarmManager.ELAPSED_REALTIME, 30*60*1000, elapsedIntent);

Cancel the first alarm.

alarms.cancel(rtcIntent);