背景:
近期的项目中有提醒这项功能,在一定条件下,app需要播放音频并振动来完成提醒事项。用户可以在app中设置提醒方式:1、声音 2、振动 3、声音加振动 4、无
技术选型:
经过查找比较,发现音效播放(<AudioToolbox/AudioToolbox.h>
)完全可以满足需求,在此记录相关用法。
使用限制:
1、播放声音不能超过30秒。
2、数据必须是PCM或IMA4格式。
3、音频文件必须打包成.caf、.aif、.wav中的一种(官方文档说法,实际测试发现一些.mp3也可以)。
函数方法说明:
AudioServicesCreateSystemSoundID( CFURLRef inFileURL, SystemSoundID* outSystemSoundID) ;
获取声音ID
inFileURL
为自定义的声音文件的url
outSystemSoundID
为声音文件对应的ID(播放、回调都需要用到)AudioServicesAddSystemSoundCompletion( SystemSoundID inSystemSoundID, CFRunLoopRef __nullable inRunLoop, CFStringRef __nullable inRunLoopMode, AudioServicesSystemSoundCompletionProc inCompletionRoutine, void * __nullable inClientData) ;
监听播放操作AudioServicesPlaySystemSound(SystemSoundID inSystemSoundID)
播放音效(不带振动)AudioServicesPlayAlertSound(SystemSoundID inSystemSoundID)
播放音效(带振动),如果手机静音但开启了静音模式振动,虽然播放不出声音但是振动还会执行。
代码说明:
考虑到会在多处进行调用,把它封装成一个单例。
.h文件
#import <Foundation/Foundation.h>
//导入系统框架
#import <AudioToolbox/AudioToolbox.h>
@interface AlertWayClass : NSObject
//停止标志
@property (nonatomic,assign) BOOL stop;
//声音ID
@property (nonatomic) SystemSoundID crash;
+ (AlertWayClass *)sharedInstance;
//播放
-(void)playAlert;
//停止
-(void)stopAlert;
@end
.m文件
#import "AlertWayClass.h"
@implementation AlertWayClass
+ (AlertWayClass *)sharedInstance
{
static AlertWayClass *alertWay;
static dispatch_once_t once;
dispatch_once(&once, ^{
alertWay = [[AlertWayClass alloc] init];
});
return alertWay;
}
- (instancetype)init
{
if (self = [super init]) {
SystemSoundID crash;
NSURL* crashUrl = [[NSBundle mainBundle]
URLForResource:@"high_alarm" withExtension:@"mp3"];
// 加载音效文件
AudioServicesCreateSystemSoundID((__bridge CFURLRef)crashUrl , &crash);
// 为crash播放完成绑定回调函数
AudioServicesAddSystemSoundCompletion(crash, NULL, NULL,
(void*)completionCallback ,NULL);
// 为震动完成绑定回调函数
AudioServicesAddSystemSoundCompletion(kSystemSoundID_Vibrate, NULL, NULL,
(void*)completionVibrateCallback ,NULL);
self.crash = crash;
self.stop = NO;
}
return self;
}
//振动完成的回调(继续振动)
static void completionVibrateCallback(SystemSoundID mySSID)
{
if ([AlertWayClass sharedInstance].stop) {
return;
}
CGMSetting *setting = [CGMSetting isExist];
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
}
//音频播放完成的回调(继续播放)
static void completionCallback(SystemSoundID mySSID)
{
// 播放完毕之后,再次播放
if ([AlertWayClass sharedInstance].stop) {
return;
}
//响铃
//AudioServicesPlaySystemSound([AlertWayClass sharedInstance].crash);
//响铃加振动
AudioServicesPlayAlertSound([AlertWayClass sharedInstance].crash);
}
-(void)playAlert
{
self.stop = NO;
//响铃
//AudioServicesPlaySystemSound(self.crash);
//振动
//AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
//响铃加振动
AudioServicesPlayAlertSound(self.crash);
[NSTimer scheduledTimerWithTimeInterval:20 repeats:NO block:^(NSTimer * _Nonnull timer) {
[[AlertWayClass sharedInstance] stopAlert];
}];
}
-(void)stopAlert
{
self.stop = YES;
}
@end
注意事项
振动的ID为kSystemSoundID_Vibrate
开发时一开始没有单独为振动对应的ID添加回调函数,发现每次振动一次就结束了。所以需要监听哪个ID结束事件,就一定要添加对应的回调函数。