美文网首页iOS开发经验总结iOSiOS技巧学习_JM
iOS-使用AudioServices相关接口的连续震动

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

作者: 煜寒了 | 来源:发表于2015-07-25 13:25 被阅读10397次
    震动的手机

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

    参考链接

    使用AudioServices相关接口(底层c接口)的连续震动实现

    相关文章

      网友评论

      • _敏哥哥_:AudioServicesPlayAlertSound(sound)
        alert本身就有震动,然后加上callback就可以实现了
      • 七秀儿:求demo
      • 阿兹尔:demo 有没有啊
      • 3fda77b6cb66:你好大神, 我想问一下 我得用了自定义的声音后 为什么不震动了, 以前用系统默认的震动是可以的, 但是换自定义声音 震动就不行了。
      • zyg:希望能有个详细的demo
      • 0e2192df4ee5: :+1: :+1: :+1: 厉害,我就想问下,这个震动怎么调,怎么自定义啊
      • 6eeebdf65572:虽然排版看得有点累,但是有帮助点个赞!
        PS: inClientData 这个参数是类似于context的东西,你在注册回调的时候填的是什么,在回调里就会当一个参数跟着传过去,就像通知里面的userInfo一样的东西,至于runloop就是指定runloop = =
        煜寒了:@MonsterSong 恩 后来我是知道了,排版无力啊
      • 6a53b918bd3c:我想问一下 程序退到后台 怎么不能播放声音震动
        煜寒了:@秦夜 这个不是调用播放器的,而是使用系统提示音,需要的话你可以使用音频播放,但是震动只能在前台。。
      • b4f7aa45114d:太好了,刚好用的到!给力 :+1:
        煜寒了:@CocoaCxx 能用就行,哈哈
      • 北海有鱼w:经过测试发现震动之间太连续,体验不符合要求;所以我们在c回调里面通过单例(全局变量性质的指针)调用到oc的方法进行[self performSelector:@selector(triggerShake) withObject:nil afterDelay:1](triggerShake是震动接口);在停止震动时候我们需要调用

        [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(triggerShake) object:nil];

        这怎么调用
        煜寒了:@394e6f841540 其实苹果关于这块的设计都是由用户来决定的,他可以设置静音模式下不允许震动,所以我觉得开发者不用考虑是否处于静音模式。
        在你开发的时候,首个震动应该也是你调用的,应该不存在和系统震动重合的问题。
        那个取消震动的方法,就是在延时后调用停止震动的方法就好了~
        北海有鱼w:@煜寒了 我的手机调成静音模式,然后就会连续震动,是那种一秒都不到一直震震震... ,我想了下可能是系统静音模式下会有一个震动,然后我们的代码里也有一个震动,这2个震动重合了就会一直没有时间间隔的震动,这样的话我还的判断手机是不是处于静音模式再去停止震动?这不科学
        煜寒了:@394e6f841540 调用取消的方法应该可以的
      • 北海有鱼w:最后一段什么意思啊 在哪里调用?
      • 帅可儿妞:Mark一下,经常就是这些小东西闹心
      • 低调_哲:没看懂 咋用 小白一个
        煜寒了:@低调_哲 回头有时间我写个demo吧,😄
        低调_哲:@煜寒了 我试了 不太懂 复制我都不知道怎么复制 有demo吗 ?
        煜寒了:@低调_哲 试试看就知道咯
      • 煜寒了:@lifution 相互学习,一起来进步啊

      本文标题:iOS-使用AudioServices相关接口的连续震动

      本文链接:https://www.haomeiwen.com/subject/adkmqttx.html