拔下耳机时是不是有事件?
Posted
技术标签:
【中文标题】拔下耳机时是不是有事件?【英文标题】:Is there an event for when the headphones are unplugged?拔下耳机时是否有事件? 【发布时间】:2011-05-26 01:04:17 【问题描述】:在测试期间,一位客户注意到拔下耳机时 iPhone 中的视频播放会暂停。他想要类似的音频播放功能,或许还有弹出消息的能力。
有谁知道我是否可以参与某种活动来实现这一切?
【问题讨论】:
【参考方案1】:请参阅音频会话编程指南中的 Responding to Route Changes。
【讨论】:
谢谢!这个页面,从那里链接,developer.apple.com/library/ios/#documentation/Audio/Conceptual/…。也有示例代码“当用户插入或拔出耳机时,系统调用回调,或者对接或取消对接设备 - 从而添加或删除音频连接”。还没试过,但看起来很完美。为单挑干杯。 太棒了:)。回调不用头疼【参考方案2】:这是我最终用于在耳机插入(和拔出)时发送事件的完整实现。
我需要处理相当多的复杂性,以确保在应用从后台返回后仍能正常工作。
CVAudioSession.h 文件
#import <Foundation/Foundation.h>
#define kCVAudioInputChangedNotification @"kCVAudioInputChangedNotification"
#define kCVAudioInterruptionEnded @"kCVAudioInterruptionEnded"
@interface CVAudioSession : NSObject
+(void) setup;
+(void) destroy;
+(NSString*) currentAudioRoute;
+(BOOL) interrupted;
@end
CVAudioSession.m 文件
#import "CVAudioSession.h"
#import <AudioToolbox/AudioToolbox.h>
@implementation CVAudioSession
static BOOL _isInterrupted = NO;
+(void) setup
NSLog(@"CVAudioSession setup");
// Set up the audio session for recording
OSStatus error = AudioSessionInitialize(NULL, NULL, interruptionListener, (__bridge void*)self);
if (error) NSLog(@"ERROR INITIALIZING AUDIO SESSION! %ld\n", error);
if (!error)
UInt32 category = kAudioSessionCategory_RecordAudio; // NOTE CANT PLAY BACK WITH THIS
error = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(category), &category);
if (error) NSLog(@"couldn't set audio category!");
error = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, propListener, (__bridge void*) self);
if (error) NSLog(@"ERROR ADDING AUDIO SESSION PROP LISTENER! %ld\n", error);
UInt32 inputAvailable = 0;
UInt32 size = sizeof(inputAvailable);
// we do not want to allow recording if input is not available
error = AudioSessionGetProperty(kAudioSessionProperty_AudioInputAvailable, &size, &inputAvailable);
if (error) NSLog(@"ERROR GETTING INPUT AVAILABILITY! %ld\n", error);
// we also need to listen to see if input availability changes
error = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioInputAvailable, propListener, (__bridge void*) self);
if (error) NSLog(@"ERROR ADDING AUDIO SESSION PROP LISTENER! %ld\n", error);
error = AudioSessionSetActive(true);
if (error) NSLog(@"CVAudioSession: AudioSessionSetActive (true) failed");
+ (NSString*) currentAudioRoute
UInt32 routeSize = sizeof (CFStringRef);
CFStringRef route;
AudioSessionGetProperty (kAudioSessionProperty_AudioRoute,
&routeSize,
&route);
NSString* routeStr = (__bridge NSString*)route;
return routeStr;
+(void) destroy
NSLog(@"CVAudioSession destroy");
// Very important - remove the listeners, or we'll crash when audio routes etc change when we're no longer on screen
OSStatus stat = AudioSessionRemovePropertyListenerWithUserData(kAudioSessionProperty_AudioRouteChange, propListener, (__bridge void*)self);
NSLog(@".. AudioSessionRemovePropertyListener kAudioSessionProperty_AudioRouteChange returned %ld", stat);
stat = AudioSessionRemovePropertyListenerWithUserData(kAudioSessionProperty_AudioInputAvailable, propListener, (__bridge void*)self);
NSLog(@".. AudioSessionRemovePropertyListener kAudioSessionProperty_AudioInputAvailable returned %ld", stat);
AudioSessionSetActive(false); // disable audio session.
NSLog(@"AudioSession is now inactive");
+(BOOL) interrupted
return _isInterrupted;
// Called when audio is interrupted for whatever reason. NOTE: doesn't always call the END one..
void interruptionListener( void * inClientData,
UInt32 inInterruptionState)
if (inInterruptionState == kAudioSessionBeginInterruption)
_isInterrupted = YES;
NSLog(@"CVAudioSession: interruptionListener kAudioSessionBeginInterruption. Disable audio session..");
// Try just deactivating the audiosession..
OSStatus rc = AudioSessionSetActive(false);
if (rc)
NSLog(@"CVAudioSession: interruptionListener kAudioSessionBeginInterruption - AudioSessionSetActive(false) returned %.ld", rc);
else
NSLog(@"CVAudioSession: interruptionListener kAudioSessionBeginInterruption - AudioSessionSetActive(false) ok.");
else if (inInterruptionState == kAudioSessionEndInterruption)
_isInterrupted = NO;
// Reactivate the audiosession
OSStatus rc = AudioSessionSetActive(true);
if (rc)
NSLog(@"CVAudioSession: interruptionListener kAudioSessionEndInterruption - AudioSessionSetActive(true) returned %.ld", rc);
else
NSLog(@"CVAudioSession: interruptionListener kAudioSessionEndInterruption - AudioSessionSetActive(true) ok.");
[[NSNotificationCenter defaultCenter] postNotificationName:kCVAudioInterruptionEnded object:(__bridge NSObject*)inClientData userInfo:nil];
// This is called when microphone or other audio devices are plugged in and out. Is on the main thread
void propListener( void * inClientData,
AudioSessionPropertyID inID,
UInt32 inDataSize,
const void * inData)
if (inID == kAudioSessionProperty_AudioRouteChange)
CFDictionaryRef routeDictionary = (CFDictionaryRef)inData;
CFNumberRef reason = (CFNumberRef)CFDictionaryGetValue(routeDictionary, CFSTR(kAudioSession_AudioRouteChangeKey_Reason));
SInt32 reasonVal;
CFNumberGetValue(reason, kCFNumberSInt32Type, &reasonVal);
if (reasonVal != kAudioSessionRouteChangeReason_CategoryChange)
NSLog(@"CVAudioSession: input changed");
[[NSNotificationCenter defaultCenter] postNotificationName:kCVAudioInputChangedNotification object:(__bridge NSObject*)inClientData userInfo:nil];
else if (inID == kAudioSessionProperty_AudioInputAvailable)
if (inDataSize == sizeof(UInt32))
UInt32 isAvailable = *(UInt32*)inData;
if (isAvailable == 0)
NSLog(@"AUDIO RECORDING IS NOT AVAILABLE");
@end
【讨论】:
【参考方案3】:iOS 7 改变了这一点,你只需要收听名为AVAudioSessionRouteChangeNotification
的通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioRouteChanged:) name:AVAudioSessionRouteChangeNotification object:nil];
【讨论】:
这确实适用于视频播放器,但前提是您使用AVAudioSession
。【参考方案4】:
Swift 3.0 @snakeoil 的解决方案:
NotificationCenter.default.addObserver(self, selector: #selector(YourViewController.yourMethodThatShouldBeCalledOnChange), name: NSNotification.Name.AVAudioSessionRouteChange, object: nil)
【讨论】:
太棒了!非常感谢!以上是关于拔下耳机时是不是有事件?的主要内容,如果未能解决你的问题,请参考以下文章