本文使用底层接口,实现 iOS
设备上的连续震动,以及连续播放系统声音(不是音乐播放器)
主要功能函数
/*!
@function AudioServicesAddSystemSoundCompletion
@abstract Call the provided Completion Routine when provided SystemSoundID
finishes playing.
@discussion Once set, the System Sound server will send a message to the System Sound client
indicating which SystemSoundID has finished playing.
@param inSystemSoundID
systemSoundID 自定义的sound(1007系统默认提示音)或者kSystemSoundID_Vibrate(震动)
@param inRunLoop
没有研究 一般写NULL 有兴趣可以自己研究一下跟大家共享
@param inRunLoopMode
同上个属性
@param inCompletionRoutine
这个是指某次震动播放完成后的回调 注意是C的函数 一般我们会在回调中写播放震动的函数 来实现连续震动
@param inClientData
没有研究啦!!!NULL就行啦
*/
extern OSStatus
AudioServicesAddSystemSoundCompletion( SystemSoundID inSystemSoundID,
CFRunLoopRef inRunLoop,
CFStringRef inRunLoopMode,
AudioServicesSystemSoundCompletionProc inCompletionRoutine,
void* inClientData)
__OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_2_0);
- 首先实现上述函数中的回调函数(注意是C)
void soundCompleteCallback(SystemSoundID sound,void * clientData) {
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); //震动
AudioServicesPlaySystemSound(sound); // 播放系统声音 这里的sound是我自定义的,不要 copy 哈,没有的
}
- 实现播放声音或震动的代码
SystemSoundID sound;
NSString *path = [[NSBundle mainBundle] pathForResource:soundName ofType:nil];
AudioServicesCreateSystemSoundID((__bridge CFURLRef)[NSURL fileURLWithPath:path], &_sound);
AudioServicesAddSystemSoundCompletion(_soundID, NULL, NULL, soundCompleteCallback, NULL);
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
AudioServicesPlaySystemSound(_sound);
- 至此,就可以顺利的播放声音和震动了,而且是连续的!!!
别忘了! 怎么让他停下来
为了方便 我就写了而一个 ObjC
的方法来做了
-(void)stopAlertSoundWithSoundID:(SystemSoundID)sound {
AudioServicesDisposeSystemSoundID(kSystemSoundID_Vibrate);
AudioServicesDisposeSystemSoundID(sound);
AudioServicesRemoveSystemSoundCompletion(sound);
}
这里要详细解说一下需要注意的事项:
AudioServicesAddSystemSoundCompletion(kSystemSoundID_Vibrate, NULL, NULL, systemAudioCallback, NULL);
AudioServicesRemoveSystemSoundCompletion(kSystemSoundID_Vibrate);
这两个接口的用途是绑定和取消指定 soundID
对应的回调方法;kSystemSoundID_Vibrate为soundID
类型,其回调方法认准的也是这个 soundID
,在任何地方使用这个id去执行 AudioServicesPlaySystemSound(xxxSoundID)
都会调用到该回调方法。而一旦调用 remove
方法取消回调,同样的在任何地方使用这个 id
去执行 AudioServicesPlaySystemSound(xxxSoundID)
都不会调用到这个回调。说的这么绕,其实就是说这俩接口的影响是全局的,威力很大。
我们只要在回调方法里面再调用 AudioServicesPlaySystemSound
接口,就可以实现连续震动了;当我们想要停止震动时,调用 remove
接口,ok
,回调方法就停止。
经过测试发现震动之间太连续,体验不符合要求;所以我们在 C
回调里面通过单例(全局变量性质的指针)调用到 ObjC
的方法进行
[self performSelector:@selector(triggerShake) withObject:nil afterDelay:1]
triggerShake
是震动接口,在停止震动时候我们需要调用下面的方法
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(triggerShake) object:nil];
停止之前可能存在的回调;这两个方法的成对使用既好用又简便,对于需要定时调用的场景很适合,也免去维护定时器的麻烦。
这个时候屏幕要是常亮就更好了
[[UIApplication sharedApplication] setIdleTimerDisabled:YES]; // 设置播放时屏幕常亮
同样,别忘了结束的时候设置为 NO
网友评论
alert本身就有震动,然后加上callback就可以实现了
PS: inClientData 这个参数是类似于context的东西,你在注册回调的时候填的是什么,在回调里就会当一个参数跟着传过去,就像通知里面的userInfo一样的东西,至于runloop就是指定runloop = =
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(triggerShake) object:nil];
这怎么调用
在你开发的时候,首个震动应该也是你调用的,应该不存在和系统震动重合的问题。
那个取消震动的方法,就是在延时后调用停止震动的方法就好了~