Visual notifications are great
for providing feedback to a user and getting critical input. There are
other senses, however, that can be just as useful for getting a user’s
attention. Sounds, for example, play an important role on nearly every
computer system (regardless of platform or purpose). They tell us when
an error has occurred or an action has been completed. Sounds free a
user’s visual focus and still provide feedback about what an application
is doing.
Vibrations take alerts one
step further. When a device has the ability to vibrate, it can
communicate with users even if they can’t see or hear it. For the
iPhone, vibration means that an app can notify users of events even when
stowed in a pocket or resting on a nearby
table. The best news of all? iPhone sounds and vibrations are both
handled through the same simple code, so you’ll be able to implement
them relatively easily within your applications.
System Sound Services
To enable sound playback
and vibration, we will take advantage of System Sound Services. System
Sound Services provides an interface for playing back sounds that are 30
seconds or less in length. It supports a limited number of file formats
(specifically CAF, AIF, and WAV files using PCM or IMA/ADPCM data). The
functions provide no manipulation of the sound, nor control of the
volume, so you won’t want to use System Sound Services to create the
soundtrack for your latest and greatest iPhone game.
Unlike most of the other
development functionality we’ve discussed in this book, the System Sound
Services functionality is not implemented as a class. Instead, you will
be using more traditional C-style function calls to trigger playback.
iOS supports three different
notifications using this API:
Sound: A simple sound file is played back immediately. If
the device is muted, the user will hear nothing.
Alert: Again, a sound file is played, but if the device is muted and
set to vibrate, the user is alerted through vibration.
Vibrate: The device
is vibrated, regardless of any other settings.
Playing Sounds and
Alerts
To play a sound file, you first
need to make the file available as a resource to your application.
Let’s continue to expand the GettingAttention project to include sound
playback:
1. | With your
project open in Xcode, return to the Finder and navigate to the
“sounds” directory within this hour’s project folder.
|
2. | Drag the soundeffect.wav and alertsound.wav files into
your Xcode project’s Resources folder. Choose to copy the files when
prompted.
|
You should see the files
listed as resources, as shown in Figure 1.
Adding the AudioToolbox
Framework
The
AudioToolbox framework must be added to our project before we can use
any of the playback functions. To add this framework, complete the
following steps:
1. | Right-click
the Frameworks group in Xcode and choose Add Existing Framework.
|
2. | Navigate to AudioToolbox.framework and click Add.
|
3. | Open the GettingAttentionViewController.h file and
import the interface file necessary to access the sound functions
(AudioToolbox/AudioToolbox.h). This edit should fall directly after the
existing import line:
#import <AudioToolbox/AudioToolbox.h>
|
Creating and Playing
System Sounds
With the prep work out of the
way, we’re ready to add some sounds to our project. The two functions
that we’ll need to use are AudioServicesCreateSystemSoundID and
AudioServicesPlaySystemSound. We’ll
also need to declare a variable of the type SystemSoundID. This will represent the sound file that we are
working with.
Edit
GettingAttentionViewController.m and add the implementation for the doSound
method shown in Listing 1.
Listing 1.
1: -(IBAction)doSound:(id)sender { 2: SystemSoundID soundID; 3: NSString *soundFile = [[NSBundle mainBundle] 4: pathForResource:@"soundeffect" ofType:@"wav"]; 5: 6: AudioServicesCreateSystemSoundID((CFURLRef) 7: [NSURL fileURLWithPath:soundFile] 8: , &soundID); 9: AudioServicesPlaySystemSound(soundID); 10: [soundFile release]; 11: }
|
The code to play a system sound
might look a bit alien after all the Objective-C we’ve been using. Let’s
take a look at the functional pieces.
Line 2 starts things off
by declaring a variable, soundID, that
we will use to refer to the sound file. (Note that this is not declared as a
pointer, as pointers begin with a *!)
Next, in line 3, we declare and assign a string (soundFile) to the path of the sound file “soundeffect.wav.”
This works by first using the NSBundle class method mainBundle
to return an NSBundle object that
corresponds to the directory containing the current application’s
executable binary. The NSBundle object’s pathForResource:ofType: method is then used to identify the specific
sound file by name and extension.
Once a path has been
identified for the sound file, we must use the AudioServicesCreateSystemSoundID
function in lines 6–8 to create a SystemSoundID that will represent this file for the functions that
will actually play the sound. This function takes two parameters: a CFURLRef object that points to the location of the file and a
pointer to the SystemSoundID variable that
we want to be set. For the first parameter, we use the NSURL
fileURLWithPath class method to return an NSURLCFURLRef) to cast the NSURL
object to the CFURLRef type expected
by the system. The second parameter is satisfied by passing &soundID
to the function. object from the sound file path. We preface this
with (
By
the Way
Recall that &<variable> returns a reference (pointer) to the named variable. This is
rarely needed when working with the Objective-C classes because nearly
everything is already a pointer!
After soundID has
been properly set up, all that remains is playing it. Pass the soundID
variable to the AudioServicesPlaySystemSound function, as shown in line 9, then release the soundFile
string, and we’re done.
Build and test the
application. Pressing the Play Sound button should now play back the
sound-effect WAV file.
Playing Alert Sounds
with Vibrations
The difference between an “alert sound” and a “system sound” is that an
alert sound, if muted, will automatically trigger a phone vibration. The
setup and use of an alert sound is identical to a system sound. In
fact, to implement the doAlertSound
method stub in GettingAttentionViewController.m, use the same code as doSound
method in list 1 of this article, substituting the sound file
alertsound.wav and using the function AudioServicesPlayAlertSound
rather than AudioServicesPlaySystemSound:
AudioServicesPlayAlertSound(soundID);
After implementing the
new method, build and test the application. Pressing the Play Alert
Sound button will play the sound, and muting the phone will cause the
phone to vibrate when the button is pressed.
Vibrating the iPhone
For our grand finale, we’ll
implement the final method in our GettingAttention application: doVibration. As you’ve already learned, the same System
Sound Services that enabled us to play sounds and alert sounds will also
create vibrations. The magic we need here is the kSystemSoundID_Vibrate constant. When this value is substituted for
the SystemSoundID and AudioServicesPlaySystemSound is called, the phone vibrates. It’s as simple as
that! Implement the doVibration method as follows:
-(IBAction)doVibration:(id)sender {
AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);
}
That’s all there is to it.
You’ve now explored seven different ways of getting a user’s attention.
These are techniques that you can use in any application to make sure
that your user is alerted to changes that may require interaction and
can respond if needed.