iOS AudioServices播放提示音

最近在做视频通话,在拨打/接听的时候需要响铃、震动,播放音频的方式有几种,但是最后还是选择了AudioServices来做。

1.因为我们的视频文件时长小于30S,AudioServices只能使用时长为30S之内的音频文件,目前只试过.caf是可行的
2.需求简单,只需要响铃和震动,不用监听各种属性和方法
3.实现方便快捷

实现步骤:

  • 1.创建系统声音服务
  • 2.注册铃声和震动完成的回调
  • 3.开始播放
  • 4.结束播放
  • 5.循环播放

实现方法解析

使用系统声音服务(AudioService)创建一个实例

/*!
    @functiongroup  AudioServices
*/

/*!
    @function       AudioServicesCreateSystemSoundID // 创建一个系统声音
    @abstract       Allows the application to designate an audio file for playback by the System Sound server.
//允许应用程序指定一个音频文件供系统声音服务器播放
    @discussion     Returned SystemSoundIDs are passed to AudioServicesPlayAlertSoundWithCompletion() 
                    and AudioServicesPlaySystemSoundWithCompletion() to be played.
 
                    The maximum supported duration for a system sound is 30 secs.

    @param          inFileURL
                        A CFURLRef for an AudioFile.
    @param          outSystemSoundID
                        Returns a SystemSoundID.
*/
extern OSStatus 
AudioServicesCreateSystemSoundID(   CFURLRef                    inFileURL,
                                    SystemSoundID*              outSystemSoundID)
                                                                API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0))
                                                                ;

可以看到需要的参数是一个CFURLRef类型的URL,和一个 (SystemSoundID*) ,要什么给什么:

//全局变量
static SystemSoundID sound;
//注意这里的类型,目前只测试过caf类型的可用,其他的自己去测试
NSString *path = [[NSBundle mainBundle] pathForResource:@"xxx" ofType:@"caf"];
AudioServicesCreateSystemSoundID((__bridge CFURLRef)[NSURL fileURLWithPath:path], &sound);

我们从本地获取的文件路径转成URL之后,用(__bridge CFURLRef)桥接一下,SystemSoundID* 就取&sound就行了。


注册
/*!
    This function will be deprecated in a future release. Use AudioServicesPlayAlertSoundWithCompletion 
    or AudioServicesPlaySystemSoundWithCompletion instead.
 
    @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
                        The SystemSoundID to associate with the provided completion
                        routine.
    @param          inRunLoop
                        A CFRunLoopRef indicating the desired run loop the completion routine should
                        be run on. Pass NULL to use the main run loop.
    @param          inRunLoopMode
                        A CFStringRef indicating the run loop mode for the runloop where the
                        completion routine will be executed. Pass NULL to use kCFRunLoopDefaultMode.
    @param          inCompletionRoutine
                        An AudioServicesSystemSoundCompletionProc to be called when the provided
                        SystemSoundID has completed playing in the server.
    @param          inClientData
                        A void* to pass client data to the completion routine.
*/
extern OSStatus 
AudioServicesAddSystemSoundCompletion(  SystemSoundID                                       inSystemSoundID,
                                        CFRunLoopRef __nullable                             inRunLoop,
                                        CFStringRef __nullable                              inRunLoopMode,
                                        AudioServicesSystemSoundCompletionProc              inCompletionRoutine,
                                        void * __nullable                                   inClientData)
                                                                    API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0))
                                                                    ;

inSystemSoundID 系统声音ID
** inRunLoop 一般传NULL**
** inRunLoopMode 一般传NULL**
** inCompletionRoutine 注册完成的回调**
** inClientData 一般传NULL**

//分别注册铃声和震动完后的回调
    AudioServicesAddSystemSoundCompletion(kSystemSoundID_Vibrate, NULL, NULL, vibrationCompleteCallback, NULL);
    AudioServicesAddSystemSoundCompletion(sound, NULL, NULL, soundCompleteCallback, NULL);

开始播放系统声音
/*!
    This function will be deprecated in a future release. Use AudioServicesPlaySystemSoundWithCompletion instead.
 
    @function       AudioServicesPlaySystemSound
    @abstract       Play the sound designated by the provided SystemSoundID.
    @discussion     A SystemSoundID indicating the desired System Sound to be played.
    @param          inSystemSoundID
                        A SystemSoundID for the System Sound server to play.
*/
extern void 
AudioServicesPlaySystemSound(SystemSoundID inSystemSoundID)                                         
                                                                API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0))
                                                                ;

inSystemSoundID 系统声音ID

//开始震动
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
//开始播放铃声
AudioServicesPlaySystemSound(sound);

移除回调
/*!
    This function will be deprecated in a future release. Use AudioServicesPlayAlertSoundWithCompletion
    or AudioServicesPlaySystemSoundWithCompletion instead.
 
    @function       AudioServicesRemoveSystemSoundCompletion
    @abstract       Disassociate any completion proc for the specified SystemSoundID
    @discussion     Tells the SystemSound client to remove any completion proc associated with the
                    provided SystemSoundID
    @param          inSystemSoundID
                        The SystemSoundID for which completion routines should be
                        removed.
*/
extern void 
AudioServicesRemoveSystemSoundCompletion(SystemSoundID inSystemSoundID)                             
                                                                    API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0))
                                                                    ;

inSystemSoundID 需要移除的系统声音ID

//移除震动回调
AudioServicesRemoveSystemSoundCompletion(kSystemSoundID_Vibrate);
//移除声音回调
AudioServicesRemoveSystemSoundCompletion(sound);

清除铃声和震动
/*!
    @function       AudioServicesDisposeSystemSoundID
    @abstract       Allows the System Sound server to dispose any resources needed for the provided
                    SystemSoundID.
    @discussion     Allows the application to tell the System Sound server that the resources for the
                    associated audio file are no longer required.
    @param          inSystemSoundID
                        A SystemSoundID that the application no longer needs to use.
*/
extern OSStatus 
AudioServicesDisposeSystemSoundID(SystemSoundID inSystemSoundID)                                    
                                                                API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0))
                                                                ;

inSystemSoundID 需要清除的系统声音ID

//清除震动
AudioServicesDisposeSystemSoundID(kSystemSoundID_Vibrate);
//清除铃声
AudioServicesDisposeSystemSoundID(sound);

AudioServices基本上使用就这个流程,更加全面的使用没有尝试过,还请大神指教。

下面放上代码:

#import 

NS_ASSUME_NONNULL_BEGIN

@interface AudioServicesPlaySounds : NSObject
- (void)startAudioToolWork;
- (void)stopAudioToolWork;
@end

NS_ASSUME_NONNULL_END
#import "AudioServicesTool.h"

@implementation AudioServicesTool
//全局变量
static SystemSoundID sound;
//开始播放的时候调用
- (void)startAudioToolWork {
    NSString *path = [[NSBundle mainBundle] pathForResource:@"music1" ofType:@"caf"];
    AudioServicesCreateSystemSoundID((__bridge CFURLRef)[NSURL fileURLWithPath:path], &sound);
    AudioServicesAddSystemSoundCompletion(kSystemSoundID_Vibrate, NULL, NULL, vibrationCompleteCallback, NULL);
    AudioServicesAddSystemSoundCompletion(sound, NULL, NULL, soundCompleteCallback, NULL);
    AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
    AudioServicesPlaySystemSound(sound);
}

- (void)stopAudioToolWork {
    stopRingAndVibration();
}

void stopRingAndVibration() {
    AudioServicesRemoveSystemSoundCompletion(kSystemSoundID_Vibrate);
    AudioServicesRemoveSystemSoundCompletion(sound);
    AudioServicesDisposeSystemSoundID(kSystemSoundID_Vibrate);
    AudioServicesDisposeSystemSoundID(sound);
}

void vibrationCompleteCallback(SystemSoundID sound,void * clientData) {
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(800 * NSEC_PER_MSEC)), dispatch_get_global_queue(0, 0), ^{
        AudioServicesPlaySystemSound(sound);
    });
}

void soundCompleteCallback(SystemSoundID sound,void * clientData) {
//    单次播放
//    stopRingAndVibration();
//循环播放
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
AudioServicesPlaySystemSound(sound);
}

@end

使用方式

@interface ViewController()
@property (nonatomic, strong) AudioServicesTool *playSound;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.playSound startAudioToolWork];
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    [self.playSound stopAudioToolWork];
}

#pragma mark - Getter
- (AudioServicesTool *)playSound {
    if (!_playSound) {
        _playSound = ({
            AudioServicesTool *sound = [[AudioServicesTool alloc] init];
            sound;
        });
    }
    return _playSound;
}
@end

如有错误,请指正。本文仅记录工作

你可能感兴趣的:(iOS AudioServices播放提示音)