发布于:2014-07-17 09:39阅读数:3667
在实施前一篇中所述的7个步骤步之前还必须面对一个麻烦的问题,AudioSession。AudioSession主要功能包括以下几点:1.确定你的app如何使用音频;2.为你的app选择合适的输入输出设备……
“”(本文转自码农人生)
前言
- extern OSStatus AudioSessionInitialize(CFRunLoopRef inRunLoop,
- CFStringRef inRunLoopMode,
- AudioSessionInterruptionListener inInterruptionListener,
- void *inClientData);
- typedef void (*AudioSessionInterruptionListener)(void * inClientData, UInt32 inInterruptionState);
- extern OSStatus AudioSessionAddPropertyListener(AudioSessionPropertyID inID,
- AudioSessionPropertyListener inProc,
- void *inClientData);
- typedef void (*AudioSessionPropertyListener)(void * inClientData,
- AudioSessionPropertyID inID,
- UInt32 inDataSize,
- const void * inData);
- //AudioSession的AudioRouteChangeReason枚举
- enum {
- kAudioSessionRouteChangeReason_Unknown = 0,
- kAudioSessionRouteChangeReason_NewDeviceAvailable = 1,
- kAudioSessionRouteChangeReason_OldDeviceUnavailable = 2,
- kAudioSessionRouteChangeReason_CategoryChange = 3,
- kAudioSessionRouteChangeReason_Override = 4,
- kAudioSessionRouteChangeReason_WakeFromSleep = 6,
- kAudioSessionRouteChangeReason_NoSuitableRouteForCategory = 7,
- kAudioSessionRouteChangeReason_RouteConfigurationChange = 8
- };
- //AVAudioSession的AudioRouteChangeReason枚举
- typedef NS_ENUM(NSUInteger, AVAudioSessionRouteChangeReason)
- {
- AVAudioSessionRouteChangeReasonUnknown = 0,
- AVAudioSessionRouteChangeReasonNewDeviceAvailable = 1,
- AVAudioSessionRouteChangeReasonOldDeviceUnavailable = 2,
- AVAudioSessionRouteChangeReasonCategoryChange = 3,
- AVAudioSessionRouteChangeReasonOverride = 4,
- AVAudioSessionRouteChangeReasonWakeFromSleep = 6,
- AVAudioSessionRouteChangeReasonNoSuitableRouteForCategory = 7,
- AVAudioSessionRouteChangeReasonRouteConfigurationChange NS_ENUM_AVAILABLE_IOS(7_0) = 8
- }
- + (BOOL)usingHeadset
- {
- #if TARGET_IPHONE_SIMULATOR
- return NO;
- #endif
- CFStringRef route;
- UInt32 propertySize = sizeof(CFStringRef);
- AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &route);
- BOOL hasHeadset = NO;
- if((route == NULL) || (CFStringGetLength(route) == 0))
- {
- // Silent Mode
- }
- else
- {
- /* Known values of route:
- * "Headset"
- * "Headphone"
- * "Speaker"
- * "SpeakerAndMicrophone"
- * "HeadphonesAndMicrophone"
- * "HeadsetInOut"
- * "ReceiverAndMicrophone"
- * "Lineout"
- */
- NSString* routeStr = (__bridge NSString*)route;
- NSRange headphoneRange = [routeStr rangeOfString : @"Headphone"];
- NSRange headsetRange = [routeStr rangeOfString : @"Headset"];
- if (headphoneRange.location != NSNotFound)
- {
- hasHeadset = YES;
- }
- else if(headsetRange.location != NSNotFound)
- {
- hasHeadset = YES;
- }
- }
- if (route)
- {
- CFRelease(route);
- }
- return hasHeadset;
- }
- + (BOOL)isAirplayActived
- {
- CFDictionaryRef currentRouteDescriptionDictionary = nil;
- UInt32 dataSize = sizeof(currentRouteDescriptionDictionary);
- AudioSessionGetProperty(kAudioSessionProperty_AudioRouteDescription, &dataSize, ¤tRouteDescriptionDictionary);
- BOOL airplayActived = NO;
- if (currentRouteDescriptionDictionary)
- {
- CFArrayRef outputs = CFDictionaryGetValue(currentRouteDescriptionDictionary, kAudioSession_AudioRouteKey_Outputs);
- if(outputs != NULL && CFArrayGetCount(outputs) > 0)
- {
- CFDictionaryRef currentOutput = CFArrayGetValueAtIndex(outputs, 0);
- //Get the output type (will show airplay / hdmi etc
- CFStringRef outputType = CFDictionaryGetValue(currentOutput, kAudioSession_AudioRouteKey_Type);
- airplayActived = (CFStringCompare(outputType, kAudioSessionOutputRoute_AirPlay, 0) == kCFCompareEqualTo);
- }
- CFRelease(currentRouteDescriptionDictionary);
- }
- return airplayActived;
- }
- extern OSStatus AudioSessionSetProperty(AudioSessionPropertyID inID,
- UInt32 inDataSize,
- const void *inData);
- UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;
- AudioSessionSetProperty (kAudioSessionProperty_AudioCategory,
- sizeof(sessionCategory),
- &sessionCategory);
- /* set session category */
- - (BOOL)setCategory:(NSString *)category error:(NSError **)outError;
- /* set session category with options */
- - (BOOL)setCategory:(NSString *)category withOptions: (AVAudioSessionCategoryOptions)options error:(NSError **)outError NS_AVAILABLE_IOS(6_0);
- //AudioSession的AudioSessionCategory枚举
- enum {
- kAudioSessionCategory_AmbientSound = 'ambi',
- kAudioSessionCategory_SoloAmbientSound = 'solo',
- kAudioSessionCategory_MediaPlayback = 'medi',
- kAudioSessionCategory_RecordAudio = 'reca',
- kAudioSessionCategory_PlayAndRecord = 'plar',
- kAudioSessionCategory_AudioProcessing = 'proc'
- };
- //AudioSession的AudioSessionCategory字符串
- /* Use this category for background sounds such as rain, car engine noise, etc.
- Mixes with other music. */
- AVF_EXPORT NSString *const AVAudioSessionCategoryAmbient;
- /* Use this category for background sounds. Other music will stop playing. */
- AVF_EXPORT NSString *const AVAudioSessionCategorySoloAmbient;
- /* Use this category for music tracks.*/
- AVF_EXPORT NSString *const AVAudioSessionCategoryPlayback;
- /* Use this category when recording audio. */
- AVF_EXPORT NSString *const AVAudioSessionCategoryRecord;
- /* Use this category when recording and playing back audio. */
- AVF_EXPORT NSString *const AVAudioSessionCategoryPlayAndRecord;
- /* Use this category when using a hardware codec or signal processor while
- not playing or recording audio. */
- AVF_EXPORT NSString *const AVAudioSessionCategoryAudioProcessing;
- //AudioSession的启动方法
- extern OSStatus AudioSessionSetActive(Boolean active);
- extern OSStatus AudioSessionSetActiveWithFlags(Boolean active, UInt32 inFlags);
- //AVAudioSession的启动方法
- - (BOOL)setActive:(BOOL)active error:(NSError **)outError;
- - (BOOL)setActive:(BOOL)active withFlags:(NSInteger)flags error:(NSError **)outError NS_DEPRECATED_IOS(4_0, 6_0);
- - (BOOL)setActive:(BOOL)active withOptions:(AVAudioSessionSetActiveOptions)options error:(NSError **)outError NS_AVAILABLE_IOS(6_0);
- #import <Endian.h>
- NSString * OSStatusToString(OSStatus status)
- {
- size_t len = sizeof(UInt32);
- long addr = (unsigned long)&status;
- char cstring[5];
- len = (status >> 24) == 0 ? len - 1 : len;
- len = (status >> 16) == 0 ? len - 1 : len;
- len = (status >> 8) == 0 ? len - 1 : len;
- len = (status >> 0) == 0 ? len - 1 : len;
- addr += (4 - len);
- status = EndianU32_NtoB(status); // strings are big endian
- strncpy(cstring, (char *)addr, len);
- cstring[len] = 0;
- return [NSString stringWithCString:(char *)cstring encoding:NSMacOSRomanStringEncoding];
- }
- static void MyAudioSessionInterruptionListener(void *inClientData, UInt32 inInterruptionState)
- {
- AudioSessionInterruptionType interruptionType = kAudioSessionInterruptionType_ShouldNotResume;
- UInt32 interruptionTypeSize = sizeof(interruptionType);
- AudioSessionGetProperty(kAudioSessionProperty_InterruptionType,
- &interruptionTypeSize,
- &interruptionType);
- NSDictionary *userInfo = @{MyAudioInterruptionStateKey:@(inInterruptionState),
- MyAudioInterruptionTypeKey:@(interruptionType)};
- [[NSNotificationCenter defaultCenter] postNotificationName:MyAudioInterruptionNotification object:nil userInfo:userInfo];
- }
- - (void)interruptionNotificationReceived:(NSNotification *)notification
- {
- UInt32 interruptionState = [notification.userInfo[MyAudioInterruptionStateKey] unsignedIntValue];
- AudioSessionInterruptionType interruptionType = [notification.userInfo[MyAudioInterruptionTypeKey] unsignedIntValue];
- [self handleAudioSessionInterruptionWithState:interruptionState type:interruptionType];
- }
- - (void)handleAudioSessionInterruptionWithState:(UInt32)interruptionState type:(AudioSessionInterruptionType)interruptionType
- {
- if (interruptionState == kAudioSessionBeginInterruption)
- {
- //控制UI,暂停播放
- }
- else if (interruptionState == kAudioSessionEndInterruption)
- {
- if (interruptionType == kAudioSessionInterruptionType_ShouldResume)
- {
- OSStatus status = AudioSessionSetActive(true);
- if (status == noErr)
- {
- //控制UI,继续播放
- }
- }
- }
- }
联系客服