233

How can the iPhone be set to vibrate once?

For example, when a player loses a life or the game is over, the iPhone should vibrate.

Juan Boero
  • 6,281
  • 1
  • 44
  • 62
some_id
  • 29,466
  • 62
  • 182
  • 304
  • 9
    Shake gesture is completely different than vibration. One is human-initiated, one device-initiated. – Eiko Jan 18 '11 at 14:15

12 Answers12

407

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>
DDPWNAGE
  • 1,423
  • 10
  • 37
linuxbuild
  • 15,843
  • 6
  • 60
  • 87
  • Is this the only way to vibrate the phone? Why did they run it through AudioServices? – some_id Jan 18 '11 at 14:34
  • 3
    #import is not required. – Raptor Sep 30 '11 at 04:33
  • 10
    Is there a way to reduce the vibration time to less than 1 sec? – George Asda Jan 23 '13 at 16:13
  • 11
    I would like to add, that if vibration is off in Settings of iOS, user will not get vibration even if you use these commands. – Denis Kutlubaev Mar 07 '13 at 14:10
  • Any info on general stance from Apple on vibration? Any case where they turned an app down because of improper vibration use? – Jonny Apr 08 '13 at 03:39
  • 7
    In Swift: `AudioServicesPlayAlertSound(UInt32(kSystemSoundID_Vibrate))` (at least as of beta 2) – Sam Soffes Jun 18 '14 at 23:25
  • 1
    AudioServicesPlayAlertSound(kSystemSoundID_Vibrate); Vibarate on iPhone proerly but it doesn't make any beep sound on iPad. – Mangesh Jul 05 '14 at 06:40
  • this works great when your app is in foreground state but what when in background state like, bgTask = [application beginBackgroundTaskWithExpirationHandler:^{ function 1 or function 2 for vibration }]; this is not working. can you explain? – Vatsal Shukla Sep 22 '15 at 07:05
  • This functions are going to be deprecated in a future release of iOS. – Hugo Alonso Feb 17 '16 at 15:21
  • 1
    Keep in mind that the device does not vibrate if your app’s audio session is configured with the AVAudioSessionCategoryPlayAndRecord or AVAudioSessionCategoryRecord audio session category. This ensures that vibration doesn’t interfere with audio recording. – FedeH Oct 30 '18 at 11:13
  • how to increase/Decrease Vibration time. – Bhavesh.iosDev Nov 16 '18 at 09:56
  • Hello @FedeHenze How can we achieve vibration with the recording? Is there another way to achieve vibration wile recording? – Diken Shah Aug 05 '20 at 07:39
46

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.

Community
  • 1
  • 1
Can
  • 8,502
  • 48
  • 57
  • This seems to be fixed in Swift 2/iOS 9/Xcode 7. I used `AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)` and it compiled fine – Dov Oct 01 '15 at 15:17
35

A simple way to do so is with Audio Services:

#import <AudioToolbox/AudioToolbox.h> 
...    
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
fsaint
  • 8,759
  • 3
  • 36
  • 48
34

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);
     }
}
soumya
  • 3,801
  • 9
  • 35
  • 69
Joel Teply
  • 3,260
  • 1
  • 31
  • 21
  • 7
    It's always better to use named aliases instead of magic constants, like kSystemSoundID_Vibrate instead 1352. I encourage you to update your answer. – nalexn Jan 21 '15 at 06:24
  • Looks like he's not going to update it - why not edit the answer yourself? – Grimxn Feb 06 '15 at 19:25
  • 3
    I would agree using this magic 1352 is not ideal, but I can't find any other way to force a vibration even when the vibrate switch is off on the device. This seems to be the only way. – marcshilling Apr 29 '15 at 14:14
  • @JoelTeply I confirm, `kSystemSoundID_Vibrate` not worked for me, but `1352` did. Where did you find this constant? – medvedNick Apr 30 '15 at 11:01
  • 4
    I wrote a for loop with integers starting past the published constants and figured out which one caused a vibrate – Joel Teply May 02 '15 at 19:14
  • 2
    I can confirm that the iPhone vibrates even if the silent mode is activated on the iPhone. Great answer! – John May 17 '15 at 09:59
  • What I mean to say is that I hacked the Gibson – Joel Teply May 18 '15 at 16:16
  • 2
    AudioServicesPlaySystemSound (1352) still works for iPhones regardless of silent switch position as of Jan 2016 – JustAnotherCoder Jan 21 '16 at 02:20
  • 1
    AudioServicesPlaySystemSound (1352) works with target 9.3 in iOS 11 beta 2 even with vibration disabled + night mode. – Jano Jun 25 '17 at 21:01
26

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

Hugo Alonso
  • 6,684
  • 2
  • 34
  • 65
12

For an iPhone 7/7 Plus or newer, use these three Haptic feedback APIs.

Available APIs

For notifications:

let generator = UINotificationFeedbackGenerator()
generator.notificationOccured(style: .error)

Available styles are .error, .success, and .warning. Each has its own distinctive feel.
From the docs:

A concrete UIFeedbackGenerator subclass that creates haptics to communicate successes, failures, and warnings.

For simple vibrations:

let generator = UIImpactFeedbackGenerator(style: .medium)
generator.impactOccured()

Available styles are .heavy, .medium, and .light. These are simple vibrations with varying degrees of "hardness".
From the docs:

A concrete UIFeedbackGenerator subclass that creates haptics to simulate physical impacts

For when the user selected an item

let generator = UISelectionFeedbackGenerator()
generator.selectionChanged()

This is the least noticeable of all the haptics, and so is the most suitable for when haptics should not be taking over the app experience.
From the docs:

A concrete UIFeedbackGenerator subclass that creates haptics to indicate a change in selection.

Notes

There are a couple of things worth remembering when using these APIs.

Note A

You do not actually create the haptic. You request the system generate a haptic. The system will decide based on the below:

  • If haptics are possible on the device (whether it has a Taptic Engine in this case)
  • Whether the app may record audio (haptics do not generate during recording to prevent unwanted interference)
  • Whether haptics are enabled in system Settings.

Therefore, the system will silently ignore your request for a haptic if it is not possible. If this is due to an unsupported device, you could try this:

func haptic() {
    // Get whether the device can generate haptics or not
    // If feedbackSupportLevel is nil, will assign 0
    let feedbackSupportLevel = UIDevice.current.value(forKey: "_feedbackSupportLevel") as? Int ?? 0

    switch feedbackSupportLevel { 
    case 2:
        // 2 means the device has a Taptic Engine
        // Put Taptic Engine code here, using the APIs explained above

    case 1: 
    // 1 means no Taptic Engine, but will support AudioToolbox
    // AudioToolbox code from the myriad of other answers!

    default: // 0
        // No haptic support
        // Do something else, like a beeping noise or LED flash instead of haptics
    }

Substitute the comments in the switch-case statements, and this haptic generation code will be portable to other iOS devices. It will generate the highest level of haptic possible.

Note B

  • Due to the fact that generating haptics is a hardware-level task, there may be latency between when you call the haptic-generation code, and when it actually happens. For this reason, the Taptic Engine APIs all have a prepare() method, to put it in a state of readiness. Using your Game Over example: You may know that the game is about to end, by the user having very low HP, or a dangerous monster being near them.
  • If you don't generate a haptic within a few seconds, the Taptic Engine will go back into an idle state (to save battery life)


In this case, preparing the Taptic Engine would create a higher-quality, more responsive experience.

For example, let's say your app uses a pan gesture recogniser to change the portion of the world visible. You want a haptic to generate when the user 'looks' round 360 degrees. Here is how you could use prepare():

@IBAction func userChangedViewablePortionOfWorld(_ gesture: UIPanGestureRecogniser!) {

    haptic = UIImpactFeedbackGenerator(style: .heavy)

    switch gesture.state {
        case .began:
            // The user started dragging the screen.
            haptic.prepare()

        case .changed:
            // The user trying to 'look' in another direction
            // Code to change viewable portion of the virtual world

            if virtualWorldViewpointDegreeMiddle = 360.0 { 
                haptic.impactOccured()
            }
        
        default:
            break

} 
Community
  • 1
  • 1
Benj
  • 736
  • 7
  • 21
  • Just remember to `import UIKit`! – Benj May 02 '19 at 11:03
  • You don't want to create a new instance of `haptic` inside this method. You are not calling `impactOccured` on the same instance that you call `prepare`. – rmaddy Jun 25 '19 at 03:58
  • Hello @Benj I want to implement vibration with audio recording and haptic does not work while recording. – Diken Shah Aug 05 '20 at 08:14
  • @DikenShah as stated, I believe I read somewhere this is a deliberate move to minimise microphone interference. As microphones detect vibrations, and the Taptic Engine **makes** vibrations, this would clearly be an issue. – Div Aug 06 '20 at 19:39
  • @Div I found the solution. Thanks for your answer – Diken Shah Aug 28 '20 at 06:24
5

And if you're using Xamarin (monotouch) framework, simply call

SystemSound.Vibrate.PlayAlertSound()
Wheelie
  • 3,866
  • 2
  • 33
  • 39
5

In my travels I have found that if you try either of the following while you are recording audio, the device will not vibrate even if it is enabled.

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

My method was called at a specific time in the measurement of the devices movements. I had to stop the recording and then restart it after the vibration had occurred.

It looked like this.

-(void)vibrate {
    [recorder stop];
    AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);
    [recorder start];
}

recorder is an AVRecorder instance.

Hope this helps others that have had the same problem before.

Sebastien Peek
  • 2,528
  • 2
  • 23
  • 32
5

In iOS 10, and on newer iPhones, you can also use haptic API. This haptic feedback is softer than the AudioToolbox API.

For your GAME OVER scenario, a heavy UI impact feedback should be suitable.

UIImpactFeedbackGenerator(style: .heavy).impactOccurred()

You could use the other haptic feedback styles.

samwize
  • 25,675
  • 15
  • 141
  • 186
1

In my case I was using the AVCaptureSession. AudioToolbox was in project's build phases and it was imported but still didn't work. In order to make it work I stopped the session before vibration and continued on after that.

#import <AudioToolbox/AudioToolbox.h>
...
@property (nonatomic) AVCaptureSession *session;
...
- (void)vibratePhone;
{
  [self.session stopRunning];
     NSLog(@"vibratePhone %@",@"here");
    if([[UIDevice currentDevice].model isEqualToString:@"iPhone"])
    {
        AudioServicesPlaySystemSound (kSystemSoundID_Vibrate); 
    }
    else
    {
        AudioServicesPlayAlertSound (kSystemSoundID_Vibrate);
    }
  [self.session startRunning];
}
Caner
  • 1,448
  • 23
  • 38
1

In Swift:

import AVFoundation
...
AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
Eric
  • 16,003
  • 15
  • 87
  • 139
-5

You can use

1) AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);

for iPhone and few newer iPods.

2) AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);

for iPads.

swathy krishnan
  • 916
  • 9
  • 22