聊聊iOS开发中耳机的那点事(监听耳机拔插、耳机线控)-b
如果说一个项目出现的最重大的事故,那无疑就是开发人员使用了不可控的元素.
前言
iOS开发当中有关于视音频播放的开发不在少数,用户时常会使用到一种输出设备,那就是"耳机",这一篇博客写的就是关于耳机的一些开发相关的技术点.
检测耳机是否插入
看到上面的标题的时候一定要注意,这里说的是"检测耳机是否插入",这里只是一次性的检测,不是实时监控耳机的拔插,但是有一些时候,下面的这个方法已经足够满足我们的开发需求了.
首先,我们需要导入AVFoundation.framework这个框架如下图.
导入AVFoundation.framework框架
然后导入头文件,实现下面的方法
#import <AVFoundation/AVFoundation.h> //导入头文件
- (BOOL)isHeadsetPluggedIn {
AVAudioSessionRouteDescription* route = [[AVAudioSession sharedInstance] currentRoute];
for (AVAudioSessionPortDescription* desc in [route outputs]) {
if ([[desc portType] isEqualToString:AVAudioSessionPortHeadphones])
return YES;
}
return NO;
}
监听耳机的拔插 (iOS6.0的实现)
其实这几天一直在看网上的相关的资料,发现监听耳机拔插大多数是一些iOS6.0左右的老方法,我们就先抛砖引玉一下,先看看iOS6.0是如何监听耳机拔插事件.
首先,我们需要导入AVFoundation.framework这个框架如下图.
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkJDQzA1MTVGNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkJDQzA1MTYwNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QkNDMDUxNUQ2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QkNDMDUxNUU2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6p+a6fAAAAD0lEQVR42mJ89/Y1QIABAAWXAsgVS/hWAAAAAElFTkSuQmCC" alt="" data-ratio="0.5472473294987674" data-src="http://mmbiz.qpic.cn/mmbiz_jpg/g4uoJOMA38LZxYD1pIRhWO3Ak65c1rZicXEdEB3wgHdJGSazQqZev7wtkkTjNpDmhwruChrTLbyWc0Oc385kbBg/0?wx_fmt=jpeg" data-type="jpeg" data-w="1217" />
导入AVFoundation.framework框架
iOS6.0的监听耳机拔插主要是对AVAudioSession单例对象中的AudioSessionAddPropertyListener 这个 block函数的实现完成的,这个函数在耳机拔插的时候调用才会调用.这里的监听耳机拔插事件我直接写在了AppDelegate中- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions,我们看一下具体的代码实现.
#import "AppDelegate.h"
#import <AVFoundation/AVFoundation.h>//导入头文件
@interface AppDelegate ()<AVAudioSessionDelegate>
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[AVAudioSession sharedInstance] setDelegate:self];//初始化单例设置代理
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];//设置AVAudioSession单例对象的类型
AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange,audioRouteChangeListenerCallback, (__bridge void *)(self));//调用block函数
return YES;
}//对block函数其中的方法进行实现
void audioRouteChangeListenerCallback (void *inUserData, AudioSessionPropertyID inPropertyID, UInt32 inPropertyValueSize,const void *inPropertyValue ) { // ensure that this callback was invoked for a route change
if (inPropertyID != kAudioSessionProperty_AudioRouteChange) return; {
// Determines the reason for the route change, to ensure that it is not
// because of a category change.
CFDictionaryRef routeChangeDictionary = (CFDictionaryRef)inPropertyValue; CFNumberRef routeChangeReasonRef = (CFNumberRef)CFDictionaryGetValue (routeChangeDictionary, CFSTR (kAudioSession_AudioRouteChangeKey_Reason) );
SInt32 routeChangeReason;
CFNumberGetValue (routeChangeReasonRef, kCFNumberSInt32Type, &routeChangeReason); if (routeChangeReason == kAudioSessionRouteChangeReason_OldDeviceUnavailable) { //Handle Headset Unplugged
NSLog(@"没有耳机!");
} else if (routeChangeReason == kAudioSessionRouteChangeReason_NewDeviceAvailable) { //Handle Headset plugged in
NSLog(@"有耳机!");
} } }
监听耳机的拔插 (iOS6.0之后的实现)
其实,如果不是一个有警告情结的程序猿,上面的监听耳机拔插实现已经完全能满足工作需求,但是对于我这么一个有警告情结的程序猿,心中对上面的程序运行过程出现的警告十分的反感,在上面的AVAudioSession很多方法被弃用之后,我们需要使用通知来实现监听耳机的拔插.所以就出现了下面的方法.
下面的方法我为了方便,就直接下载Demo的ViewController中,和上面一样,我们需要导入AVFoundation.framework这个框架.然后我们在ViewController导入头文件.然后我们需要监听的通知名称如下.
AVAudioSessionRouteChangeNotification //需要监听的通知名称
具体的代码实现,如下.
#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[[AVAudioSession sharedInstance] setActive:YES error:nil];//创建单例对象并且使其设置为活跃状态.
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioRouteChangeListenerCallback:) name:AVAudioSessionRouteChangeNotification object:nil];//设置通知
}//通知方法的实现
- (void)audioRouteChangeListenerCallback:(NSNotification*)notification {
NSDictionary *interuptionDict = notification.userInfo;
NSInteger routeChangeReason = [[interuptionDict valueForKey:AVAudioSessionRouteChangeReasonKey] integerValue];
switch (routeChangeReason) {
case AVAudioSessionRouteChangeReasonNewDeviceAvailable:
NSLog(@"AVAudioSessionRouteChangeReasonNewDeviceAvailable");
tipWithMessage(@"耳机插入");
break;
case AVAudioSessionRouteChangeReasonOldDeviceUnavailable:
NSLog(@"AVAudioSessionRouteChangeReasonOldDeviceUnavailable"); tipWithMessage(@"耳机拔出,停止播放操作");
break;
case AVAudioSessionRouteChangeReasonCategoryChange: // called at start - also when other audio wants to play
tipWithMessage(@"AVAudioSessionRouteChangeReasonCategoryChange");
break;
}
}//不管何时,只要有通知中心的出现,在dealloc的方法中都要移除所有观察者.
-(void)dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
//自定提醒窗口
NS_INLINE void tipWithMessage(NSString *message){
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView *alerView = [[UIAlertView alloc] initWithTitle:@"提示" message:message delegate:nil cancelButtonTitle:nil otherButtonTitles:nil, nil];
[alerView show];
[alerView performSelector:@selector(dismissWithClickedButtonIndex:animated:) withObject:@[@0, @1] afterDelay:0.9];
});
}
监听耳机的拔插的注意事项(必看部分)
1.开发人员测试监听耳机的拔插的代码的时候,要使用真机测试.模拟器是没有耳机插孔的,除非你给电脑凿一个孔.
聊聊iOS开发中耳机的那点事(监听耳机拔插、耳机线控)-b的更多相关文章
- 聊聊 iOS 开发中的协议
前言 何为协议,简单来说在OC中我们使用关键字@protocol可以声明一个协议,并在协议中添加多个属性.方法供于遵循者实现,从某个角度上来说,这是一种不同于category机制的category.在 ...
- iOS开发中的错误整理,(百思项目,指示器位置)设置控件尺寸和点坐标,先设置尺寸,再设置点坐标
之前对控件的尺寸和点的坐标的设置从来都是想到什么写什么,从来没有关心过顺序.然后就有了这次的血的教训!!!!! 下面是错误的截图,先设置的中心点,然后设置的宽度.程序运行就这样了,点别的没有毛病!!! ...
- [转载]对iOS开发中内存管理的一点总结与理解
对iOS开发中内存管理的一点总结与理解 做iOS开发也已经有两年的时间,觉得有必要沉下心去整理一些东西了,特别是一些基础的东西,虽然现在有ARC这种东西,但是我一直也没有去用过,个人觉得对内存操作 ...
- 总结iOS开发中的断点续传那些事儿
前言 断点续传概述 断点续传就是从文件赏赐中断的地方重新开始下载或者上传数据,而不是从头文件开始.当下载大文件的时候,如果没有实现断点续传功能,那么每次出现异常或者用户主动的暂停,都会从头下载,这样很 ...
- iOS开发中静态库之".framework静态库"的制作及使用篇
iOS开发中静态库之".framework静态库"的制作及使用篇 .framework静态库支持OC和swift .a静态库如何制作可参照上一篇: iOS开发中静态库之" ...
- iOS开发中静态库制作 之.a静态库制作及使用篇
iOS开发中静态库之".a静态库"的制作及使用篇 一.库的简介 1.什么是库? 库是程序代码的集合,是共享程序代码的一种方式 2.库的类型? 根据源代码的公开情况,库可以分为2种类 ...
- ios开发中的小技巧
在这里总结一些iOS开发中的小技巧,能大大方便我们的开发,持续更新. UITableView的Group样式下顶部空白处理 //分组列表头部空白处理 UIView *view = [[UIViewal ...
- IOS 开发中 Whose view is not in the window hierarchy 错误的解决办法
在 IOS 开发当中经常碰到 whose view is not in the window hierarchy 的错误,该错误简单的说,是由于 "ViewController" ...
- [转]iOS开发中的火星坐标系及各种坐标系转换算法
iOS开发中的火星坐标系及各种坐标系转换算法 源:https://my.oschina.net/u/2607703/blog/619183 其原理是这样的:保密局开发了一个系统,能将实际的坐标转 ...
随机推荐
- Android_Notification
xml文件: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns ...
- C语言枚举
应该是 各种语言都支持枚举的. 所以这个 之前在我们java案例里面就出现过的季节代码再次出现了. 枚举帮我们起到一个变量值,在某一范围内的限定,用来避免一些非法值的键入. 值得注意的是,这里面的枚举 ...
- 关于Eclipse插件开发-----加入首选项(preferencePages)
选择主菜单"窗口---->首选项"命令打开"首选项"窗口.此窗口是Eclipse设置项的集中营, 修改plugin.xml文件,设置首选项的扩展点: pl ...
- 关于JFace中的输入值(InputDialog)对话框类
格式: InputDialog(Shell parentShell, String dialogTitle, String dialogMessage, String initialValue, In ...
- 基于ARM的RealView MDK开发环境
RealView MDK可以对各种嵌入式处理器的软件开发工具.这么高端,着实很吸引我,ADS12还不知道怎么搞,居然还有这么高端的,但是还是得了解一下唉.洗这个自动配 置启动代码,集成Flash烧写模 ...
- mount命令详解
http://tutu.spaces.eepw.com.cn/articles/article/item/70737 挂接命令(mount) 首先,介绍一下挂接(mount)命令的使用方法,mount ...
- 用Java socket (TCP通信模型)实现一个简单的web 服务器
package cn.magicdu.think.socket; import java.io.OutputStream; import java.io.PrintWriter; import jav ...
- jenkins离线安装git插件
jenkins没有默认安装git,当jenkins无法连接外网的话,安装git插件就是一件很麻烦的事,需要自己去下载插件: 往下拉 这边的插件就是需要自己去下载了,在bing下搜索jenkins gi ...
- Apache Rewrite url重定向功能的简单配置
http://www.jb51.net/article/24435.htm 1.Apache Rewrite的主要功能 就是实现URL的跳转和隐藏真实地址,基于Perl语言的正则表达式规范.平时帮助我 ...
- OC班级类
// // MyClass.h // OC2_班级类 // // Created by zhangxueming on 15/6/12. // Copyright (c) 2015年 zhangxue ...