特点
1.限制:用于播放不超过30秒的声音
2.支持格式:CAF、AIF和使用PCM或IMA/ADPCM数据的WAV文件
3.其他:没有提供操纵声音和控制音量的功能
功能
- 声音:播放声音文件。如果手机被设置为静音,用户什么也听不到
- 提醒:播放一个声音文件且震动,如果手机被设置为静音或震动,将通过震动提醒用户
- 震动:手机震动
准备工作
导入框架:#import <AudioToolbox/AudioToolbox.h>
要实现的功能
如上图,通过上面的UISiwtch控件来控制打开或关闭对应的功能,通过下面UIButton控件来检测该功能的有效性。
这里主要实现的是四个功能:控制声音,控制震动,控制提醒,自定义提示声音
实现过程
一般在项目中,使用到通知提示,都是全局的,在工程中全局可用,所以在这里使用单例,将声音的获取方法,初始化方法,播放方法,释放方法都写在单独的类中,并把这个类写成单例。而在外部,只需要调用单例的获取,和播放/释放方法就可以了
先写单例类
先看单例类SoundControlSingle.h文件中的代码
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>//引入头框架的文件
@interface SoundControlSingle : NSObject
@property(nonatomic,assign)SystemSoundID soundID;//播放文件标识
//获取震动、声音、自定义声音对象的方法
+ (id) sharedInstanceForVibrate;
+ (id) sharedInstanceForSound;
+ (id) sharedInstanceForProjectSound;
/**
* @brief 为播放震动效果初始化
* @return self
*/
-(id)initForPlayingVibrate;
/**
* @brief 为播放系统音效初始化(无需提供音频文件)
* @param resourceName 系统音效名称
* @param type 系统音效类型
* @return self
*/
-(id)initForPlayingSystemSoundEffectWith:(NSString *)resourceName ofType:(NSString *)type;
/**
* @brief 为播放特定的音频文件初始化(需提供音频文件)
* @param filename 音频文件名(加在工程中)
* @return self
*/
-(id)initForPlayingSoundEffectWith:(NSString *)filename;
//播放声音或者震动
-(void)play;
//播放提醒
-(void)playRemind;
//取消声音
-(void)cancleSound;
在SoundControlSingle.m文件中实现个方法
#import "SoundControlSingle.h"
@implementation SoundControlSingle
static SoundControlSingle *_sharedInstance;//震动对象全局变量
static SoundControlSingle *_sharedInstanceForSound;//声音对象全局变量
static SoundControlSingle *_sharedInstanceForProjectSound;//自定义声音对象全局变量
#pragma mark -- 实现获取各对象的方法
//获取震动对象
+(id)sharedInstanceForVibrate
{
@synchronized ([SoundControlSingle class]) {
if (_sharedInstance == nil) {
_sharedInstance = [[SoundControlSingle alloc] initForPlayingVibrate];
}
}
return _sharedInstance;
}
//获取声音
+ (id)sharedInstanceForSound
{
@synchronized ([SoundControlSingle class]) {
if (_sharedInstanceForSound == nil) {
_sharedInstanceForSound = [[SoundControlSingle alloc] initForPlayingSystemSoundEffectWith:@"sms-received2" ofType:@"caf"];
}
}
return _sharedInstanceForSound;
}
//播放自定义声音
+ (id)sharedInstanceForProjectSound{
@synchronized ([SoundControlSingle class]) {
if (_sharedInstanceForProjectSound == nil) {
_sharedInstanceForProjectSound = [[SoundControlSingle alloc] initForPlayingSoundEffectWith:@"unbelievable.caf"];
}
}
return _sharedInstanceForProjectSound;
}
#pragma mark -- 各对象的初始化方法
-(id)initForPlayingVibrate {
self = [super init];
if (self) {
_soundID = kSystemSoundID_Vibrate;//震动方式
}
return self;
}
/*
初始化声音对象的方法
第一个参数:音频文件的名字 第二个参数:音频文件的后缀名字
*/
-(id)initForPlayingSystemSoundEffectWith:(NSString *)resourceName ofType:(NSString *)type{
self=[super init];
if(self){
//获取到系统文件中的声音
NSString *path = [NSString stringWithFormat:@"/System/Library/Audio/UISounds/%@.%@",resourceName,type];
if(path){//目标文件存在
//创建声音对象
SystemSoundID theSoundID;
OSStatus error =AudioServicesCreateSystemSoundID((__bridge CFURLRef)[NSURL fileURLWithPath:path],&theSoundID);
if(error == kAudioServicesNoError){//创建成功
_soundID=theSoundID;
}else{
NSLog(@"Failed to create sound");
}
}
}
return self;
}
//初始化声音对象--传入的参数为声音文件的路径
-(id)initForPlayingSoundEffectWith:(NSString *)filename {
self = [super init];
if (self) {
NSURL *fileURL = [[NSBundle mainBundle] URLForResource:filename withExtension:nil];
if (fileURL != nil){
SystemSoundID theSoundID;
OSStatus error = AudioServicesCreateSystemSoundID((__bridge CFURLRef)fileURL, &theSoundID);
if (error == kAudioServicesNoError){
_soundID = theSoundID;
}else {
NSLog(@"Failed to create sound ");
}
}
}
return self;
}
//播放系统声音或震动
-(void)play {
AudioServicesPlaySystemSound(_soundID);//播放音乐
}
//播放提醒
-(void)playRemind{
AudioServicesPlayAlertSound(_soundID);//提醒功能
}
//单例对象置为空
-(void)cancleSound
{
_sharedInstance=nil;
_sharedInstanceForSound = nil;
_sharedInstanceForProjectSound = nil;
}
//释放声音对象
-(void)dealloc{
AudioServicesDisposeSystemSoundID(_soundID);
}
使用单例类
因为是四个功能,所以创建四个BOOL值,记录四个功能的开启关闭状态
@property(nonatomic,assign)BOOL isSoundOpen;//声音打开
@property(nonatomic,assign)BOOL isProjectSoundOpen;//声音打开
@property(nonatomic,assign)BOOL isShakeOpen;//震动打开
@property(nonatomic,assign)BOOL isRemindOpen;//提醒控制
初始化四个变量
self.isShakeOpen = self.isSoundOpen = self.isProjectSoundOpen = self.isRemindOpen = YES;
获取开关的状态,并用布尔值记录
//声音控制
- (IBAction)soundControlAction:(UISwitch *)sender {
if (sender.on) {
self.isSoundOpen = YES;
} else {
self.isSoundOpen = NO;
}
}
//震动控制
- (IBAction)shakeControlAction:(UISwitch *)sender {
if (sender.on) {
self.isShakeOpen = YES;
} else {
self.isShakeOpen = NO;
}
}
//项目中的音频文件
- (IBAction)projectSound:(UISwitch *)sender {
if (sender.on) {
self.isProjectSoundOpen = YES;
} else {
self.isProjectSoundOpen = NO;
}
}
//提醒控制
- (IBAction)remindControlAction:(UISwitch *)sender {
if (sender.on) {
self.isRemindOpen = YES;
} else {
self.isRemindOpen = NO;
}
}
点击对应按钮进行播放对应的提示
//声音测试
- (IBAction)soundText:(UIButton *)sender {
SoundControlSingle * single1 = [SoundControlSingle sharedInstanceForSound];//获取声音对象
SoundControlSingle * single2 = [SoundControlSingle sharedInstanceForProjectSound];//获取自定义声音对象
if (self.isProjectSoundOpen) {//如果播放自定义提示音的开关是打开的
[single2 play];//播放
return;
}
if (self.isSoundOpen) {//播放提示音的开关是打开的
[single1 play];//播放
}
}
//震动测试
- (IBAction)shakeText:(UIButton *)sender {
SoundControlSingle * single = [SoundControlSingle sharedInstanceForVibrate];
if (self.isShakeOpen) {
[single play];
}
}
//提醒测试
- (IBAction)remindText:(UIButton *)sender {
SoundControlSingle * single = [SoundControlSingle sharedInstanceForSound];
if (self.isRemindOpen) {
[single playRemind];//播放提示
}
}
注意
1.使用自定义音频文件,则需要把音频文件拖入到工程
2.手机静音状态下,声音提示是无效的,震动有效,提醒也有效(只有震动无声音);手机正常状态下,声音提示有效,震动有效,提醒也有效(震动+声音)