iOS 打开扬声器以及插入耳机的操作

Posted gavanwanggw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS 打开扬声器以及插入耳机的操作相关的知识,希望对你有一定的参考价值。

废话不多说说一下现状

网上好多关于扬声器的操作,可是问题多多。SDK7.X 和SDK7.X以上版本号有点诧异


#import <Foundation/Foundation.h>

#import <AudioToolbox/AudioToolbox.h>

#import <AVFoundation/AVFoundation.h>


@interface AudioManager : NSObject

{

    AVAudioPlayer *m_audioPlayer;

}


@property (atomic, readonly)BOOL _isSpeakerOn;

@property (atomic, readonly)BOOL _isHeadsetOn;


+(AudioManager*)shared;

// 打开扬声器

- (void)setSpeakerOn;

// 关闭扬声器

- (void)setSpeakerOff;

@end







//

//  AudioManager.m

//  AvconNetAndCallDemo

//

//  Created by zjq on 14-7-21.

//  Copyright (c) 2014 zjq. All rights reserved.

//


#import "AudioManager.h"

#import <UIKit/UIKit.h>

#define iosVersion [[UIDevice currentDevice].systemVersion floatValue]


@implementation AudioManager

@synthesize _isSpeakerOn;

@synthesize _isHeadsetOn;


- (id)init

{

    self = [super init];

    if (self) {

        _isSpeakerOn = NO;

        

        AVAudioSession *audioSession = [AVAudioSession sharedInstance];

        //默认情况下扬声器播放

        [audioSession setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers  error:nil];

        [audioSession setActive:YES error:nil];

        

        UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;

        AudioSessionSetProperty(kAudioSessionProperty_AudioCategory,

                                sizeof(sessionCategory),

                                &sessionCategory);

        

        

        UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;

        AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,

                                 sizeof (audioRouteOverride),

                                 &audioRouteOverride);

        

        AudioSessionAddPropertyListener (kAudioSessionProperty_AudioRouteChange,

                                         audioRouteChangeListenerCallback, (__bridge void *)(self));

        

    }

    return self;

}



static AudioManager *_audioManager = NULL;

+(AudioManager*)shared

{

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        _audioManager = [[AudioManager alloc] init];

    });

    return _audioManager;

}


- (void)setSpeakerOn

{

    NSLog(@"setSpeakerOn:%d",[NSThread isMainThread]);

        UInt32 doChangeDefaultRoute = kAudioSessionOverrideAudioRoute_Speaker;

        

        AudioSessionSetProperty (kAudioSessionProperty_OverrideCategoryDefaultToSpeaker,

                                 sizeof (doChangeDefaultRoute),

                                 &doChangeDefaultRoute

                                 );

        

        _isSpeakerOn = [self checkSpeakerOn];

        _isHeadsetOn = NO;

    

     //[self resetOutputTarget];

   

}


- (void)setSpeakerOff

{

    

    UInt32 doChangeDefaultRoute = kAudioSessionOverrideAudioRoute_None;

    

    AudioSessionSetProperty (kAudioSessionProperty_OverrideCategoryDefaultToSpeaker,

                             sizeof (doChangeDefaultRoute),

                             &doChangeDefaultRoute

                             );

    

    _isSpeakerOn = [self checkSpeakerOn];

}


- (BOOL)checkSpeakerOn

{

    CFStringRef route;

    UInt32 propertySize = sizeof(CFStringRef);

    AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &route);

    

    if((route == NULL) || (CFStringGetLength(route) == 0))

    {

        // Silent Mode

        NSLog(@"AudioRoute: SILENT, do nothing!");

    }

    else

    {

        NSString* routeStr = (__bridge NSString*)route;

        NSRange speakerRange = [routeStr rangeOfString : @"Speaker"];

        if (speakerRange.location != NSNotFound)

            return YES;

    }

    

    return NO;

}


- (BOOL)hasHeadset

{

    CFStringRef route;

    UInt32 propertySize = sizeof(CFStringRef);

    AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &route);

    

    if((route == NULL) || (CFStringGetLength(route) == 0))

    {

        // Silent Mode

        NSLog(@"AudioRoute: SILENT, do nothing!");

    }

    else

    {

        NSString* routeStr = (__bridge NSString*)route;

        NSLog(@"AudioRoute: %@", routeStr);

        if ([routeStr isEqualToString:@"ReceiverAndMicrophone"]) {

//            static dispatch_once_t onceToken;

//            dispatch_once(&onceToken, ^{

//                [self setSpeakerOn];

//            });

            [self setSpeakerOn];

        }

        

        NSRange headphoneRange = [routeStr rangeOfString : @"Headphone"];

        NSRange headsetRange = [routeStr rangeOfString : @"Headset"];

        if (headphoneRange.location != NSNotFound)

        {

            return YES;

        } else if(headsetRange.location != NSNotFound)

        {

            return YES;

        }

    }

    return NO;

}

// 推断麦克风是否实用

- (BOOL)hasMicphone

{

    return [[AVAudioSession sharedInstance] isInputAvailable];

}


- (void)erjiOutPutTarget

{

    BOOL hasHeadset = [self hasHeadset];

    

    if (hasHeadset) {

        _isHeadsetOn = YES;

    }

    NSLog (@"Will Set output target is_headset = %@ .", hasHeadset?@"YES":@"NO");

    UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_None;

    AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute, sizeof(audioRouteOverride), &audioRouteOverride);

}


- (void)resetOutputTarget

{

    BOOL hasHeadset = [self hasHeadset];

    NSLog (@"Will Set output target is_headset = %@ .", hasHeadset?@"YES":@"NO");

    UInt32 audioRouteOverride =  kAudioSessionOverrideAudioRoute_Speaker;

    AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute, sizeof(audioRouteOverride), &audioRouteOverride);

    _isHeadsetOn = NO;

}


void audioRouteChangeListenerCallback (void *inUserData, AudioSessionPropertyID inPropertyID, UInt32 inPropertyValueS, const void *inPropertyValue)

{

    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);

    NSLog(@"<<<RouteChangeReason: %d",(int)routeChangeReason);

    NSLog(@"[=======%@",inUserData);

    

    AudioManager *pMgr = (__bridge AudioManager *)inUserData;

    //没有耳机

    if (routeChangeReason == kAudioSessionRouteChangeReason_OldDeviceUnavailable)

    {

        [pMgr setSpeakerOn];

        [pMgr resetOutputTarget];

    }

    else if (routeChangeReason == kAudioSessionRouteChangeReason_NewDeviceAvailable)

    {

        [pMgr erjiOutPutTarget];

    }else if (routeChangeReason == kAudioSessionRouteChangeReason_Override){

        [pMgr setSpeakerOn];

        [pMgr resetOutputTarget];

    }

    NSLog(@"-------->%f",IOSVersion);

    //if (IOSVersion >= 8.0) {

        if (routeChangeReason==8) {

            [pMgr hasHeadset];

        }

    //}

}


//- (BOOL)isAirplayActived

//{

//    CFDictionaryRef currentRouteDescriptionDictionary = nil;

//    UInt32 dataSize = sizeof(currentRouteDescriptionDictionary);

//    AudioSessionGetProperty(kAudioSessionProperty_AudioRouteDescription, &dataSize, &currentRouteDescriptionDictionary);

//

//    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;

//}


/*

 - (void)openloudspeaker{

 //初始化播放器的时候例如以下设置

 UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;

 AudioSessionSetProperty(kAudioSessionProperty_AudioCategory,

 sizeof(sessionCategory),

 &sessionCategory);

 

 UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;

 AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,

 sizeof (audioRouteOverride),

 &audioRouteOverride);

 

 AVAudioSession *audioSession = [AVAudioSession sharedInstance];

 //默认情况下扬声器播放

 [audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];

 [audioSession setActive:YES error:nil];

 [self handleNotification:YES];

 

 }

 #pragma mark - 监听听筒or扬声器

 - (void) handleNotification:(BOOL)state

 {

 [[UIDevice currentDevice] setProximityMonitoringEnabled:state]; //建议在播放之前设置yes。播放结束设置NO,这个功能是开启红外感应

 

 if(state)//加入监听

 [[NSNotificationCenter defaultCenter] addObserver:self

 selector:@selector(sensorStateChange:) name:@"UIDeviceProximityStateDidChangeNotification"

 object:nil];

 else//移除监听

 [[NSNotificationCenter defaultCenter] removeObserver:self name:@"UIDeviceProximityStateDidChangeNotification" object:nil];

 }

 

 //处理监听触发事件

 -(void)sensorStateChange:(NSNotificationCenter *)notification;

 {

 //假设此时手机靠近面部放在耳朵旁,那么声音将通过听筒输出,并将屏幕变暗(省电啊)

 if ([[UIDevice currentDevice] proximityState] == YES)

 {

 NSLog(@"Device is close to user");

 [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];

 }

 else

 {

 NSLog(@"Device is not close to user");

 [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];

 }

 }

 */

@end





























以上是关于iOS 打开扬声器以及插入耳机的操作的主要内容,如果未能解决你的问题,请参考以下文章

iOS耳机监听

插入耳机时强制音频到扬声器?

Android蓝牙耳机/扬声器音频切换

Android蓝牙耳机/扬声器音频切换

win7无声音显示“未插入扬声器或耳机” 怎么解决

电脑显示未插入扬声器和耳机?