iOS中是否有用于自定义振动的API?

74

iOS 5及以上版本用户可以为警告和铃声创建自定义振动模式。下面的截图显示了创建一个自定义振动模式的UI(iOS 6中的联系人应用程序):

iOS 6中创建自定义振动的UI截图

我一直在搜寻相关资料,包括文档,但是我无法找到任何公共API来暴露自定义振动的创建或播放。最接近的方法是使用AudioToolbox框架来播放短暂、持续的振动:

AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);

有没有人知道是否有自定义震动的API?不一定要公共API。我好奇Contacts应用程序使用了什么。有人知道吗?

P.S. 其他人建议在CoreTelephony中使用_CTServerConnectionCreate示例)。我尝试过,但由于某些原因无法使振动起作用。

2015年10月更新:

iOS 9中有新的私有API可与Taptic Engine兼容的设备交互。更多信息请参见iOS 9中的Taptic


1
Core Haptics将在iOS 13中推出!目前仍处于测试阶段。请在此处查看“创建自定义触觉模式”以获取更多信息:https://developer.apple.com/design/human-interface-guidelines/ios/user-interaction/haptics/。 - peacetype
2个回答

105

在联系人应用程序中挖掘了几个小时后,我已经弄清楚了它是如何工作的。

ABNewPersonViewController调用ToneLibrary框架中的一些类来完成此操作。

调用堆栈看起来像这样:

0   CoreFoundation                  0x3359a1d4 CFGetTypeID + 0
1   CoreFoundation                  0x33596396 __CFPropertyListIsValidAux + 46
2   CoreFoundation                  0x33517090 CFPropertyListCreateData + 124
3   AudioToolbox                    0x38ac255a AudioServicesPlaySystemSoundWithVibration + 158
5   ToneLibrary                     0x35a7811a -[TLVibrationRecorderView vibrationComponentDidStartForVibrationRecorderTouchSurface:] + 38
6   ToneLibrary                     0x35a772b2 -[TLVibrationRecorderTouchSurface touchesBegan:withEvent:] + 342
7   UIKit                           0x3610f526 -[UIWindow _sendTouchesForEvent:] + 314
8   UIKit                           0x360fc804 -[UIApplication sendEvent:] + 376

在网上搜索“AudioServicesPlaySystemSoundWithVibration”后,我没有找到任何信息。

所以我决定自己研究一下。它是AudioToolbox框架中的私有函数。

该函数的声明如下:

void AudioServicesPlaySystemSoundWithVibration(SystemSoundID inSystemSoundID,id arg,NSDictionary* vibratePattern)

"inSystemSoundID"是SystemSoundID,就像"AudioServicesPlaySystemSound"一样,传入"kSystemSoundID_Vibrate"。

"arg"不重要,将其传入nil,一切仍将正常工作。

"vibratePattern"是一个指向"NSDictionary"的指针,联系人应用程序传入{Intensity = 1; OffDuration = 1; OnDuration = 10;}来记录用户输入。

但只调用此函数将使振动永远不停止。所以我必须找到一些函数来停止它。

答案是"AudioServicesStopSystemSound"。它也是AudioToolbox框架中的私有函数。

函数的声明如下:

void AudioServicesStopSystemSound(SystemSoundID inSystemSoundID)

我猜联系人应用程序在touchesBegan方法中使用AudioServicesPlaySystemSoundWithVibration,而在touchEnd方法中使用AudioServicesStopSystemSound来实现此效果。

TLVibrationController将管理器一个振动模式对象以记录您输入的过程。

最后,它会生成一个字典传递给AudioServicesPlaySystemSoundWithVibration,以像下面这样重新播放整个过程:

NSMutableDictionary* dict = [NSMutableDictionary dictionary];
NSMutableArray* arr = [NSMutableArray array ];

[arr addObject:[NSNumber numberWithBool:YES]]; //vibrate for 2000ms
[arr addObject:[NSNumber numberWithInt:2000]];

[arr addObject:[NSNumber numberWithBool:NO]];  //stop for 1000ms
[arr addObject:[NSNumber numberWithInt:1000]];

[arr addObject:[NSNumber numberWithBool:YES]];  //vibrate for 1000ms
[arr addObject:[NSNumber numberWithInt:1000]];

[arr addObject:[NSNumber numberWithBool:NO]];    //stop for 500ms
[arr addObject:[NSNumber numberWithInt:500]];

[dict setObject:arr forKey:@"VibePattern"];
[dict setObject:[NSNumber numberWithInt:1] forKey:@"Intensity"];


AudioServicesPlaySystemSoundWithVibration(4095,nil,dict);

如果您想在iOS上自定义振动,请使用AudioServicesPlaySystemSoundWithVibration和AudioServicesStopSystemSound。


5
注意:AudioServicesPlaySystemSoundWithVibration 只适用于 iOS6。 - Kevin Cao
2
@Jonny FOUNDATION_EXTERN "AudioServicesPlaySystemSoundWithVibration(unsigned long, objc_object*, NSDictionary*)会解决问题。别忘了还要链接AudioToolbox.framework。 - JonasG
9
现在,苹果在提交应用时拒绝使用AudioServicesPlaySystemSoundWithVibration。 - Max Tymchii
3
有没有办法实现自定义震动而不被苹果拒绝应用程序? - bobsacameno
2
这将只会让您收到类似于以下内容的友好邮件:**我们发现了您最近提交的“Appname”应用程序中存在一个或多个问题。为了处理您的提交,必须纠正以下问题:非公共API使用: 该应用程序在Appname中引用了非公共符号:_AudioServicesPlaySystemSoundWithVibration** - Edoardo
显示剩余7条评论

4
有一个名为HapticKeyboard的项目可以实现这个功能。请参见:http://code.google.com/p/zataangstuff/source/browse/trunk/HapticKeyboard/Classes/HapticKeyboard.m?r=93。具体来说,请查看最后一组函数。
_CTServerConnectionSetVibratorState(&x, connection, 0, 0, 0, 0, 0);

这里有两个问题:

  1. 我怀疑你的应用程序不会被允许进入应用商店。苹果公司认为这会对用户造成电池损耗,他们对用户体验非常严格。
  2. 这可能需要越狱。自从上次我尝试过之后,已经发布了几个新版本的iOS,所以很难确定。

谢谢你的回答。在我提问之前,我确实已经看过了HapticKeyboard(它已经有4年历史了)。我尝试按照代码中描述的方式触发振动,但是对我来说并没有起作用。我正在寻找苹果用于在联系人中实现自定义振动的API,就像屏幕截图中所示。 - Andrew
1
Apple的HapticEngine和其他设备上的所有振动响应实际上都会消耗电池。顺便说一句,代码链接已经失效了。 - kelin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接