耳机插入了吗? IOS 7

时间:2014-01-22 19:51:17

标签: ios ios7 avaudioplayer avaudiosession headphones

开发适用于iPhone的应用程序,其中包含需要通过耳机收听的音频文件。

如何检查耳机是否未插入,以便我可以告诉用户插入耳机。

我有来自另一个线程的以下代码,但不推荐使用audioSessionGetProperty方法。任何人都知道如何更改以下代码以使其工作或拥有自己的代码/解决方案。

感谢。

- (BOOL)isHeadsetPluggedIn {
    UInt32 routeSize = sizeof (CFStringRef);
    CFStringRef route;


    //Maybe changing it to something like the following would work for iOS7?
    //AVAudioSession* session = [AVAudioSession sharedInstance];
    //OSStatus error = [session setCategory:kAudioSessionProperty_AudioRoute...?


    //the line below is whats giving me the warning
    OSStatus error = AudioSessionGetProperty (kAudioSessionProperty_AudioRoute,
                                              &routeSize,
                                              &route);

    /* Known values of route:
     * "Headset"
     * "Headphone"
     * "Speaker"
     * "SpeakerAndMicrophone"
     * "HeadphonesAndMicrophone"
     * "HeadsetInOut"
     * "ReceiverAndMicrophone"
     * "Lineout"
     */

    if (!error && (route != NULL)) {

        NSString* routeStr = (__bridge NSString*)route;

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

        if (headphoneRange.location != NSNotFound) return YES;

    }

    return NO;
}

8 个答案:

答案 0 :(得分:116)

这应该有效,但我现在无法测试,我会在晚上做。

- (BOOL)isHeadsetPluggedIn {
    AVAudioSessionRouteDescription* route = [[AVAudioSession sharedInstance] currentRoute];
    for (AVAudioSessionPortDescription* desc in [route outputs]) {
        if ([[desc portType] isEqualToString:AVAudioSessionPortHeadphones])
            return YES;
    }
    return NO;
}

答案 1 :(得分:59)

只是为了扩展@Antonio的回答。如果您需要检测用户是否拔出或插入了耳机。

#import <AVFoundation/AVFoundation.h>

// [AVAudioSession sharedInstance]; // @Boris edited: you may need it if there is no `AVAudioSession instance` created before. If doesn't work, uncomment this line.
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioRouteChangeListenerCallback:)
                                             name:AVAudioSessionRouteChangeNotification
                                           object:nil];
// don't forget to `removeObserver:`

// If the user pulls out he headphone jack, stop playing.
- (void)audioRouteChangeListenerCallback:(NSNotification*)notification
{
    NSDictionary *interuptionDict = notification.userInfo;

    NSInteger routeChangeReason = [[interuptionDict valueForKey:AVAudioSessionRouteChangeReasonKey] integerValue];

    switch (routeChangeReason) {

        case AVAudioSessionRouteChangeReasonNewDeviceAvailable:
            NSLog(@"AVAudioSessionRouteChangeReasonNewDeviceAvailable");
            NSLog(@"Headphone/Line plugged in");
            break;

        case AVAudioSessionRouteChangeReasonOldDeviceUnavailable:
            NSLog(@"AVAudioSessionRouteChangeReasonOldDeviceUnavailable");
            NSLog(@"Headphone/Line was pulled. Stopping player....");
            break;

        case AVAudioSessionRouteChangeReasonCategoryChange:
            // called at start - also when other audio wants to play
            NSLog(@"AVAudioSessionRouteChangeReasonCategoryChange");
            break;
    }
}

答案 2 :(得分:10)

Swift 3:

检查耳机是否已连接

extension AVAudioSession {

    static var isHeadphonesConnected: Bool {
        return sharedInstance().isHeadphonesConnected
    }

    var isHeadphonesConnected: Bool {
        return !currentRoute.outputs.filter { $0.isHeadphones }.isEmpty
    }

}

extension AVAudioSessionPortDescription {
    var isHeadphones: Bool {
        return portType == AVAudioSessionPortHeadphones
    }
}

然后你可以print("isHeadphones connected: \(AVAudioSession.isHeadphonesConnected)")

倾听变化

Swift 3 中,语法为:

func handleRouteChange(_ notification: Notification) {
    guard
    let userInfo = notification.userInfo,
    let reasonRaw = userInfo[AVAudioSessionRouteChangeReasonKey] as? NSNumber,
    let reason = AVAudioSessionRouteChangeReason(rawValue: reasonRaw.uintValue)
    else { fatalError("Strange... could not get routeChange") }
    switch reason {
    case .oldDeviceUnavailable:
        print("oldDeviceUnavailable")
    case .newDeviceAvailable:
        print("newDeviceAvailable") 
        if AVAudioSession.isHeadphonesConnected {
             print("Just connected headphones")
        } 
    case .routeConfigurationChange:
        print("routeConfigurationChange")
    case .categoryChange:
        print("categoryChange")
    default:
        print("not handling reason")
    }
}

func listenForNotifications() {
    NotificationCenter.default.addObserver(self, selector: #selector(handleRouteChange(_:)), name: NSNotification.Name.AVAudioSessionRouteChange, object: nil)
}

请注意使用:

 if AVAudioSession.isHeadphonesConnected {
    print("Just connected headphones")
 }

答案 3 :(得分:4)

@ Warif在 Swift 2.0 中的代码,但几乎没有变化......

values-...

:d

答案 4 :(得分:3)

在Swift(截至1.2)中:

    func headsetPluggedIn() -> Bool {
    let route = AVAudioSession.sharedInstance().currentRoute
    return (route.outputs as! [AVAudioSessionPortDescription]).filter({ $0.portType == AVAudioSessionPortHeadphones }).count > 0
}

答案 5 :(得分:3)

Swift 3.0版

  • 检查耳机是否插入的方法或连接了音频输出的任何蓝牙设备
    func bluetoothOrHeadphonesConnected() -> Bool {

        let outputs = AVAudioSession.sharedInstance().currentRoute.outputs

        for output in outputs{

            if output.portType == AVAudioSessionPortBluetoothA2DP ||
               output.portType == AVAudioSessionPortBluetoothHFP ||
               output.portType == AVAudioSessionPortBluetoothLE ||
               output.portType == AVAudioSessionPortHeadphones {
                return true
            }

        }

        return false 
    }
  • 在收听任何音频时检查耳机是否已拔出是非常重要的。
 
    private func setupObservers() {

        NotificationCenter.default.addObserver(self, selector: #selector(self.audioRouteChangeListener), name: .AVAudioSessionRouteChange, object: nil)

    }

    func audioRouteChangeListener(notification: Notification) {

        guard let audioRouteChangeReason = notification.userInfo![AVAudioSessionRouteChangeReasonKey] as? Int else { return }

        switch audioRouteChangeReason {

            case AVAudioSessionRouteChangeReason.oldDeviceUnavailable.hashValue:
                //plugged out

            default:
                break

        }

    }

答案 6 :(得分:0)

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(plugout:) name:AVAudioSessionRouteChangeNotification object:nil];
-(void)plugout:(NSNotification*)notification
{
    isRemovedHeadset = YES;
}

并使用

中的isRemovedHeadset布尔值处理代码
if (moviePlayer.playbackState == MPMoviePlaybackStatePaused) 
{
    if(isRemovedHeadset)
    {
        isRemovedHeadset = NO;
        [moviePlayer prepareToPlay];
        [moviePlayer play];
        return;
    }
}

答案 7 :(得分:0)

使用RxSwift在Swift 5上使用@Sajjon解决方案

func handleRouteChange(_ notification: Notification) {
    guard
        let userInfo = notification.userInfo,
        let reasonRaw = userInfo[AVAudioSessionRouteChangeReasonKey] as? NSNumber,
        let reason = AVAudioSession.RouteChangeReason(rawValue: reasonRaw.uintValue)
        else { fatalError("Strange... could not get routeChange") }
    switch reason {
    case .oldDeviceUnavailable:
        print("oldDeviceUnavailable")
    case .newDeviceAvailable:
        print("newDeviceAvailable")
        if AVAudioSession.isHeadphonesConnected {
            print("Just connected headphones")
        }
    case .routeConfigurationChange:
        print("routeConfigurationChange")
    case .categoryChange:
        print("categoryChange")
    default:
        print("not handling reason")
    }
}

func listenForNotifications() {
    NotificationCenter.default.rx
        .notification(AVAudioSession.routeChangeNotification)
        .subscribe(onNext: { (n) in
            self.handleRouteChange(n)
        })
        .disposed(by: disposeBag)
}