iOS 系统声音和振动控制SystemSoundServices的使用

特点

1.限制:用于播放不超过30秒的声音
2.支持格式:CAF、AIF和使用PCM或IMA/ADPCM数据的WAV文件
3.其他:没有提供操纵声音和控制音量的功能

功能

  1. 声音:播放声音文件。如果手机被设置为静音,用户什么也听不到
  2. 提醒:播放一个声音文件且震动,如果手机被设置为静音或震动,将通过震动提醒用户
  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.手机静音状态下,声音提示是无效的,震动有效,提醒也有效(只有震动无声音);手机正常状态下,声音提示有效,震动有效,提醒也有效(震动+声音)

Demo下载
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,039评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,223评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,916评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,009评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,030评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,011评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,934评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,754评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,202评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,433评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,590评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,321评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,917评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,568评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,738评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,583评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,482评论 2 352

推荐阅读更多精彩内容