15
A
回答
18
请参阅音频会话编程指南中的Responding to Route Changes。
-Marc
1
这里是全面落实我最终用于当插入耳机(和不插电)发送事件。
我需要处理一些相当复杂的事情,以确保应用程序从后台返回后仍能正常工作。
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
5
这改变与iOS 7,你只需要听命名AVAudioSessionRouteChangeNotification
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioRouteChanged:) name:AVAudioSessionRouteChangeNotification object:nil];
+0
这可以用于视频播放器,但只有当你使用'AVAudioSession'。 – Legoless 2016-07-31 16:11:46
2
斯威夫特的通知3.0 @ snakeoil的解决方案:
NotificationCenter.default.addObserver(self, selector: #selector(YourViewController.yourMethodThatShouldBeCalledOnChange), name: NSNotification.Name.AVAudioSessionRouteChange, object: nil)
+0
太棒了!非常感谢! – 2017-04-18 01:25:31
相关问题
- 1. BroadcastReceiver用于拔掉耳机
- 2. iOS应用程序在耳机插入或拔出时崩溃
- 3. 按耳机按钮并触发事件?
- 4. 是否有太多事件发生?
- 5. 您能否告诉耳机/耳机是否插入WP8
- 6. 在wp7中检测插入/拔出耳机
- 7. DragDrop事件发生后是否有事件?
- 8. 当TextView失效时是否有事件发生?
- 9. wp7 mediaelement在拔下耳机时会停止
- 10. MPMoviePlayerViewController在拔下耳机时停止播放
- 11. 检查耳机是否在Android手机
- 12. 视图退出时是否有事件被触发?
- 13. 是否有'产生发电机的所有输出'的简写?
- 14. 是否可以通过带耳机的耳机播放音调?
- 15. 发生MySQL事件时出错
- 16. [Android]耳机插入时只有耳机声音
- 17. 检测耳机是否插入iPhone
- 18. Android:检查是否插入了耳机
- 19. 检测耳机是否插入iPhone/iPod
- 20. 在jQuery中测试一段时间后是否发生事件
- 21. EJB应用程序启动时是否发生任何事件?
- 22. 在.NET中发生垃圾回收时是否存在事件?
- 23. 是否有可能找出RowChanging事件中发生了什么变化?
- 24. 在Rails中,随机事件发生在随机时间随机事件的随机事件
- 25. 是否有可能在javascript变量上发生更改事件?
- 26. 确定组内是否有最近发生的事件
- 27. 是否有触发生成ANDROID_ID的事件?
- 28. URL更改时是否触发事件
- 29. 如何找出外接耳机是否连接到iPhone?
- 30. 有线耳机插入和插出
谢谢!此页面从此链接,http://developer.apple.com/library/ios/#documentation/Audio/Conceptual/AudioSessionProgrammingGuide/Cookbook/Cookbook.html#//apple_ref/doc/uid/TP40007875-CH6-SW8。有'用户插入或拔出耳机,或停靠或取消锁定设备,从而添加或删除音频连接时调用回调'的示例代码。还没有尝试过,但看起来很完美。欢呼的单挑。 – 2010-12-15 17:06:00
真棒:)。没有头痛的回调 – iEinstein 2014-06-04 15:14:43