简体   繁体   English

让iPhone振动

[英]Making the iPhone vibrate

How can the iPhone be set to vibrate once? 如何将iPhone设置为振动一次?

For example, when a player loses a life or the game is over, the iPhone should vibrate. 例如,当玩家失去生命或游戏结束时,iPhone应该振动。

From " iPhone Tutorial: Better way to check capabilities of iOS devices ": 从“ iPhone教程:检查iOS设备功能的更好方法 ”:

There are two seemingly similar functions that take a parameter kSystemSoundID_Vibrate : 有两个看似相似的函数采用参数kSystemSoundID_Vibrate

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

Both of the functions vibrate the iPhone. 这两个功能都会震动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. 因此,如果您要持续振动设备,作为警报,常识说,请使用功能2。

First, add the AudioToolbox framework AudioToolbox.framework to your target in Build Phases. 首先,在Build Phases中将AudioToolbox框架AudioToolbox.framework添加到目标。

Then, import this header file: 然后,导入此头文件:

#import <AudioToolbox/AudioServices.h>

Swift 2.0+ Swift 2.0+

AudioToolbox now presents the kSystemSoundID_Vibrate as a SystemSoundID type, so the code is: AudioToolbox现在将kSystemSoundID_VibrateSystemSoundID类型,因此代码为:

import AudioToolbox.AudioServices

AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
AudioServicesPlayAlertSound(kSystemSoundID_Vibrate)

Instead of having to go thru the extra cast step 而不是必须通过额外的演员步骤

(Props to @Dov) (@Dov的道具)

Original Answer (Swift 1.x) 原始答案(Swift 1.x)

And, here's how you do it on Swift (in case you ran into the same trouble as I did) 而且,这是你如何在Swift上做的(如果你遇到了和我一样的麻烦)

Link against AudioToolbox.framework (Go to your project, select your target, build phases, Link Binary with Libraries, add the library there) 链接到AudioToolbox.framework (转到您的项目,选择目标,构建阶段,链接二进制文件库,在那里添加库)

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 . 俗气的是, SystemSoundID基本上是UInt32typealias (花式swift typedef ),而kSystemSoundID_Vibrate是常规的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. 编译器在尝试从IntUInt32时会出错,但错误显示为“无法转换为SystemSoundID”,这令人困惑。 Why didn't apple just make it a Swift enum is beyond me. 为什么苹果不能让它成为Swift枚举超出我的范围。

@aponomarenko's goes into the details, my answer is just for the Swifters out there. @ aponomarenko's详细介绍,我的答案仅适用于那里的Swifters。

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 所以我尝试了一些声音,这些声音不在这里有详细记录的声音: 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) . 然后我偶然发现1352,无论静音开关或设备上的设置如何都可以工作(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: iOS 9.0开始API函数描述为:

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 记得import AVFoundation

如果你正在使用Xamarin(monotouch)框架,只需打电话

SystemSound.Vibrate.PlayAlertSound()

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. recorder是AVRecorder实例。

Hope this helps others that have had the same problem before. 希望这能帮助以前遇到过同样问题的其他人。

In iOS 10, and on newer iPhones, you can also use haptic API. 在iOS 10和更新的iPhone上,您还可以使用触觉API。 This haptic feedback is softer than the AudioToolbox API. 此触觉反馈比AudioToolbox API更柔和。

For your GAME OVER scenario, a heavy UI impact feedback should be suitable. 对于您的GAME OVER场景,重要的UI影响反馈应该是合适的。

UIImpactFeedbackGenerator(style: .heavy).impactOccurred()

You could use the other haptic feedback styles . 您可以使用其他触觉反馈样式

For an iPhone 7/7 Plus or newer, use these three Haptic feedback APIs. 对于iPhone 7/7 Plus或更高版本,请使用这三种Haptic反馈API。

Available APIs 可用的API

For notifications: 对于通知:

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

Available styles are .error , .success , and .warning . 可用的样式是.error.success.warning Each has its own distinctive feel. 每个人都有自己独特的感觉。
From the docs : 来自文档

A concrete UIFeedbackGenerator subclass that creates haptics to communicate successes, failures, and warnings. 一个具体的UIFeedbackGenerator子类,它创建触觉来传达成功,失败和警告。

For simple vibrations: 对于简单的振动:

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

Available styles are .heavy , .medium , and .light . 可用的样式有.heavy.medium.light These are simple vibrations with varying degrees of "hardness". 这些是具有不同程度“硬度”的简单振动。
From the docs : 来自文档

A concrete UIFeedbackGenerator subclass that creates haptics to simulate physical impacts 一个具体的UIFeedbackGenerator子类,它创建触觉来模拟物理影响

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. 一个具体的UIFeedbackGenerator子类,它创建触觉以指示选择的更改。

Notes 笔记

There are a couple of things worth remembering when using these APIs. 使用这些API时,有几件事值得记住。

Note A 注意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) 如果设备上有可能触觉(在这种情况下是否有Taptic Engine)
  • 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. 替换switch - case语句中的注释,此触觉生成代码将可移植到其他iOS设备。 It will generate the highest level of haptic possible. 它将产生最高水平的触觉。

Note B 注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. 出于这个原因,Taptic Engine API都有一个prepare()方法,使其处于准备状态。 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. 使用您的游戏结果示例:您可能知道游戏即将结束,HP的用户非常低,或者附近有危险的怪物。
  • 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) 如果您在几秒钟内未生成触觉,则Taptic Engine将返回空闲状态(以节省电池寿命)


In this case, preparing the Taptic Engine would create a higher-quality, more responsive experience. 在这种情况下,准备Taptic Engine将创造更高质量,更灵敏的体验。

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. 当用户“环视”360度时,您需要产生触觉。 Here is how you could use prepare() : 以下是使用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

} 

In Swift: 在Swift中:

import AVFoundation
...
AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))

In my case I was using the AVCaptureSession. 就我而言,我使用的是AVCaptureSession。 AudioToolbox was in project's build phases and it was imported but still didn't work. AudioToolbox处于项目的构建阶段,它已导入但仍无法正常工作。 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];
}

You can use 您可以使用

1) AudioServicesPlayAlertSound(kSystemSoundID_Vibrate); 1)AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);

for iPhone and few newer iPods. 用于iPhone和几个较新的iPod。

2) AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); 2)AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);

for iPads. 适用于iPad。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM