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