50

iOS-使用AudioServices相关接口的连续震动

 5 years ago
source link: http://www.10tiao.com/html/605/201807/2654251855/2.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

点击上方“程序员大咖”,选择“置顶公众号”

关键时刻,第一时间送达!


作者:煜寒了  來源:简书

文:https://www.jianshu.com/p/dded314dd920

程序员大咖整理发布,转载请联系作者获得授权


本文使用底层接口,实现 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


【点击成为源码大神】


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK