近期处理了一个挂断电话后,莫名手机开始播放音乐的Bug。 所以顺便在这总结一下,对于IOS的AudioSession中断的几种处理情况。

一、通过C语言的init方法配置interruptionl回调。建议用这种方法,但有些细节需要注意,后续会谈到。

AudioSessionInitialize (
NULL, //
NULL, //
interruptionListenerCallback, //
userData //
);

然后在回调,实现如下逻辑代码:

void interruptionListenerCallback ( void *inUserData,  UInt32  interruptionState ) {
AudioViewController *controller = (AudioViewController *)inUserData;
if (interruptionState == kAudioSessionBeginInterruption) {
if (controller.audioRecorder) {
[controller recordOrStop: (id) controller];
} else if (controller.audioPlayer) {
[controller pausePlayback];
controller.interruptedOnPlayback = YES;
}
} else if ((interruptionState == kAudioSessionEndInterruption) && controller.interruptedOnPlayback) {
[controller resumePlayback];
controller.interruptedOnPlayback = NO;
}
}

二、使用AVAudioSessionDelegate。如果你使用的是AVAudioPlayer或AVAudioRecorder,还可以使用对应的AVAudioPlayerDelegate和 AVAudioRecorderDelegate。但AVAudioSessionDelegate在6.0后被弃用,所以使用有局限性。后者没有被弃用。

- (void) beginInterruption {
if (playing) {
playing = NO;
interruptedWhilePlaying = YES;
[self updateUserInterface];
}
}
NSError *activationError = nil;
- (void) endInterruption {
if (interruptedWhilePlaying) {
BOOL success = [[AVAudioSession sharedInstance] setActive: YES error: &activationError];
if (!success) { /* handle the error in activationError */ }
[player play];
playing = YES;
interruptedWhilePlaying = NO;
[self updateUserInterface];
}
}

三、如上所说,6.0弃用了AVAudioSessionDelegate。所以6.0之后使用AVAudioSessionInterruptionNotification来实现类似的功能。AVAudioSessionInterruptionNotification的userInfo中包括AVAudioSessionInterruptionTypeKey和AVAudioSessionInterruptionTypeEnded。

四、使用RouteChange的回调。对于音乐播放,如果当然当前是耳机模式,拔掉耳机一般是希望音乐暂停的。类似这种拔插设备,播放语音等声音设备切换,一般通过RouteChange的回调来控制。

注册RouteChange的回调:

   AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange,audioRouteChangeListenerCallback,nil);

回调处理代码:

void audioRouteChangeListenerCallback(void *inUserData, AudioSessionPropertyID inPropertyID, UInt32 inPropertyValueSize, const void *inPropertyValue) {
if (inPropertyID != kAudioSessionProperty_AudioRouteChange)
return; CFDictionaryRef routeChangeDictionary = inPropertyValue;
CFNumberRef routeChangeReasonRef = CFDictionaryGetValue (routeChangeDictionary, CFSTR(kAudioSession_AudioRouteChangeKey_Reason)); CFStringRef oldRouteRef = CFDictionaryGetValue (routeChangeDictionary,
CFSTR (kAudioSession_AudioRouteChangeKey_OldRoute));
NSString *oldRouteString = (NSString *)oldRouteRef; SInt32 routeChangeReason;
CFNumberGetValue (routeChangeReasonRef, kCFNumberSInt32Type, &routeChangeReason);
if (routeChangeReason == kAudioSessionRouteChangeReason_OldDeviceUnavailable) {
if (oldRouteStringplaying ) { //需判断不可用Route为耳机时
playing = NO;
interruptedWhilePlaying = NO; //清除中断标识,如电话中拔掉耳机挂断时,不需要继续播放
}
}
}

对于AudioSession的Route,有如下几种模式:

/* Known values of route:
*"Headset"
* "Headphone"
* "Speaker"
* "SpeakerAndMicrophone"
* "HeadphonesAndMicrophone"
* "HeadsetInOut"
* "ReceiverAndMicrophone"
* "Lineout"
*/ //ios5以后可使用的一些类型
const CFStringRef kAudioSessionOutputRoute_LineOut;
const CFStringRef kAudioSessionOutputRoute_Headphones;
const CFStringRef kAudioSessionOutputRoute_BluetoothHFP;
const CFStringRef kAudioSessionOutputRoute_BluetoothA2DP;
const CFStringRef kAudioSessionOutputRoute_BuiltInReceiver;
const CFStringRef kAudioSessionOutputRoute_BuiltInSpeaker;
const CFStringRef kAudioSessionOutputRoute_USBAudio;
const CFStringRef kAudioSessionOutputRoute_HDMI;
const CFStringRef kAudioSessionOutputRoute_AirPlay;

关于其他的一些总结:

1、对于SDK6.0,AudioSession中断是一个Bug版本。不会响应AVAudioSessionDelegate,且不响应AVAudioSessionInterruptionNotification。C语言中断,当使用AVPlayer后,不响应kAudioSessionBeginInterruption,但响应kAudioSessionEndInterruption。 这是苹果的Bug。对上这种Case,有如下处理办法:

  1)当收到kAudioSessionEndInterruption时,调用暂停播放更新UI。

  2)使用RouteChange来判断电话的接通和挂断情境。但如果是耳机模式,电话的接通和挂断,经测试,使用的是同一种Route。所以,对于SDK6.0,播放过程中未接耳机时,可通过RouteChange来恢复播放。而耳机模式播放时,来电恢复播放,目前看来无完善的处理方式。

2、当后台播放歌曲时,打开游戏之类APP,声道会被其APP占用。这种Case会有kAudioSessionBeginInterruption。但返回时不会有kAudioSessionEndInterruption。所以,这种Case在回到APP时,需要interruptedWhilePlaying这个变量重置。

Audio Session Interruption的更多相关文章

  1. IOS Audio session

    iOS实现长时间后台的两种方法:Audio session和VOIP socket 十二月 04 我们知道 iOS 开启后台任务后可以获得最多 600 秒的执行时间,而一些需要在后台下载或者与服务器保 ...

  2. AVAudioSession(2):定义一个 Audio Session

    本文转自:AVAudioSession(2):定义一个 Audio Session | www.samirchen.com 本文内容主要来源于 Defining an Audio Session. A ...

  3. audio session config

    #pragma mark - #pragma mark - audio session config - (void)setAudioSessionConfig { NSError *error; A ...

  4. AVAudioSession(3):定制 Audio Session 的 Category

    本文转自:AVAudioSession(3):定制 Audio Session 的 Category | www.samirchen.com 本文内容主要来源于 Working with Catego ...

  5. AVAudioSession(1):iOS Audio Session 概览

    本文转自:AVAudioSession(1):iOS Audio Session 概览 | www.samirchen.com 本文内容主要来源于 Audio Session Programming ...

  6. Audio Session Programming Guide

    http://www.cocoachina.com/ios/20150615/12119.html

  7. iOS播放器 - AVAudioPlayer

    今天记录一下AVAudioPlayer,这个播放器类苹果提供了一些代理方法,主要用来播放本地音频. 其实也可以用来播放网络音频,只不过是将整个网络文件下载下来而已,在实际开发中会比较耗费流量不做推荐. ...

  8. iOS -- AVAudioPlayer播放音乐

    一. AVAudioPlayer:                          声明音乐控件AVAudioPlayer,必须声明为全局属性变量,否则可能不会播放,AVAudioPlayer只能播 ...

  9. AVFoundation 框架初探究(一)

    夜深时动笔 前面一篇文章写了视频播放的几种基本的方式,算是给这个系列开了一个头,这里面最想说和探究的就是AVFoundation框架,很想把这个框架不敢说是完全理解,但至少想把它弄明白它里面到底有什么 ...

随机推荐

  1. 《DON'T MAKE ME THINK》/《点石成金访客至上的网页设计秘笈》 读书笔记

    1.web页面要尽可能简单,让用户不用思考就能知道页面的功能,如果要进行一些崭新的.开拓性的或者非常复杂的页面设计时, 此时要利用页面元素的外观.精心选择的名称.页面布局以及少量仔细斟酌过的文字,使页 ...

  2. ACM: HDU 2544 最短路-Dijkstra算法

    HDU 2544最短路 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Descrip ...

  3. [题解+总结]动态规划大合集II

    1.前言 大合集总共14道题,出自江哥之手(这就没什么好戏了),做得让人花枝乱颤.虽说大部分是NOIP难度,也有简单的几道题目,但是还是做的很辛苦,有几道题几乎没思路,下面一道道边看边分析一下. 2. ...

  4. 『备忘』HttpWebRequest 在 POST 提交时, 标头(Headers)丢失原因

    近来研究 HttpWebRequest —— 辅助类完成时,POST JSON数据 总会 丢失标头(Headers). HttpWebRequest POST JSON数据,分如下几步: > 将 ...

  5. 10秒钟安装 Vim编辑器,5分钟浏览常用命令 2015.10.25

    首先我想说,vim与vi的命令几乎相同,,所以学习编辑命令时很轻松,排除扩展相关,以及自动补全等配置的使用在外30秒钟安装 Vim编辑器,5分钟浏览常用命令环境:虚拟机Ubuntu:安装vim并浏览命 ...

  6. 【BZOJ】2795: [Poi2012]A Horrible Poem

    题意 一个长度为\(n(n \le 500000)\)的字符串\(s\),给\(q(q \le 2000000)\)个询问,每个询问给一个区间\([l, r]\),求这个区间内最短的循环节. 分析 分 ...

  7. Redis_Spring与Jedis的集成

    首先不得不服Spring这个宇宙无敌的开源框架,几乎整合了所有流行的其它框架,http://projects.spring.io/spring-data/从这上面看,当下流行的redis.solr.h ...

  8. 前端自动化工具 -- grunt 使用简介

    grunt作为一个前端构建工具,有资源压缩,代码检查,文件合并等功能. 下面就简单了解grunt的使用. 一.环境配置 grunt是基于nodejs的,所以需要一个 nodejs 环境,未了解的可以  ...

  9. POJ3903:Stock Exchange(LIS)

    题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=87125#problem/E 题目: Description The world ...

  10. [转]AS3的垃圾回收

    GC和内存泄露无关 垃圾回收,这次是一个被无数人讨论过的传统话题. Action Script使用的是和Java相似的内存管理机制,并不会即时回收废弃对象的内存,而是在特定时间统一执行一次GC(Gab ...