Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making the iPhone vibrate

From "iPhone Tutorial: Better way to check capabilities of iOS devices":

There are two seemingly similar functions that take a parameter kSystemSoundID_Vibrate:

1) AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
2) AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);

Both of the functions vibrate the iPhone. But, when you use the first function on devices that don’t support vibration, it plays a beep sound. The second function, on the other hand, does nothing on unsupported devices. So if you are going to vibrate the device continuously, as an alert, common sense says, use function 2.

First, add the AudioToolbox framework AudioToolbox.framework to your target in Build Phases.

Then, import this header file:

#import <AudioToolbox/AudioServices.h>

Swift 2.0+

AudioToolbox now presents the kSystemSoundID_Vibrate as a SystemSoundID type, so the code is:

import AudioToolbox.AudioServices

AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
AudioServicesPlayAlertSound(kSystemSoundID_Vibrate)

Instead of having to go thru the extra cast step

(Props to @Dov)

Original Answer (Swift 1.x)

And, here's how you do it on Swift (in case you ran into the same trouble as I did)

Link against AudioToolbox.framework (Go to your project, select your target, build phases, Link Binary with Libraries, add the library there)

Once that is completed:

import AudioToolbox.AudioServices

// Use either of these
AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
AudioServicesPlayAlertSound(SystemSoundID(kSystemSoundID_Vibrate))

The cheesy thing is that SystemSoundID is basically a typealias (fancy swift typedef) for a UInt32, and the kSystemSoundID_Vibrate is a regular Int. The compiler gives you an error for trying to cast from Int to UInt32, but the error reads as "Cannot convert to SystemSoundID", which is confusing. Why didn't apple just make it a Swift enum is beyond me.

@aponomarenko's goes into the details, my answer is just for the Swifters out there.


A simple way to do so is with Audio Services:

#import <AudioToolbox/AudioToolbox.h> 
...    
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);

I had great trouble with this for devices that had vibration turned off in some manner, but we needed it to work regardless, because it is critical to our application functioning, and since it is just an integer to a documented method call, it will pass validation. So I have tried some sounds that were outside of the well documented ones here: TUNER88/iOSSystemSoundsLibrary

I have then stumbled upon 1352, which is working regardless of the silent switch or the settings on the device (Settings->vibrate on ring, vibrate on silent).

- (void)vibratePhone;
{
     if([[UIDevice currentDevice].model isEqualToString:@"iPhone"])
     {
         AudioServicesPlaySystemSound (1352); //works ALWAYS as of this post
     }
     else
     {
          // Not an iPhone, so doesn't have vibrate
          // play the less annoying tick noise or one of your own
          AudioServicesPlayAlertSound (1105);
     }
}

Important Note: Alert of Future Deprecation.

As of iOS 9.0, the API functions description for:

AudioServicesPlaySystemSound(inSystemSoundID: SystemSoundID)
AudioServicesPlayAlertSound(inSystemSoundID: SystemSoundID)

includes the following note:

This function will be deprecated in a future release.
Use AudioServicesPlayAlertSoundWithCompletion or  
AudioServicesPlaySystemSoundWithCompletion instead.

The right way to go will be using any of these two:

AudioServicesPlayAlertSoundWithCompletion(kSystemSoundID_Vibrate, nil)

or

AudioServicesPlayAlertSoundWithCompletion(kSystemSoundID_Vibrate) {
 //your callback code when the vibration is done (it may not vibrate in iPod, but this callback will be always called)
}

remember to import AVFoundation