1. 程式人生 > >iOS-使用AudioServices相關介面的連續震動

iOS-使用AudioServices相關介面的連續震動

轉自:http://www.jianshu.com/p/dded314dd920
話不多說,先上程式碼!!!喜歡就點贊

主要功能函式
/*!
    @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);
至此,就可以順利的播放聲音和震動了,而且是連續的哦!!!
別忘了! 怎麼讓他停下來
為了方便 我就寫了而一個OC的方法來做了
-(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,回撥方法就歇火了。

優化:(參考某大神的部落格,名字太長,直接附連結)
http://blog.csdn.net/openglnewbee/article/details/8494598
經過測試發現震動之間太連續,體驗不符合要求;所以我們在c回撥裡面通過單例(全域性變數性質的指標)呼叫到oc的方法進行[self performSelector:@selector(triggerShake) withObject:nil afterDelay:1](triggerShake是震動介面);在停止震動時候我們需要呼叫

[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(triggerShake)  object:nil];
停止之前可能的回撥;這兩個方法的成對使用既好用又簡便,對於需要定時呼叫的場景很適合,也免去維護定時器的麻煩。

這個時候螢幕要是常亮就更好了,不用費腦子了,用這個!!!
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];   // 設定播放時螢幕常亮