首页 文章

路由 iPhone 音频声音

提问于
浏览
5

我有一个应用程序,可以同时收听和播放声音。默认情况下,声音输出通过耳机。所以我使用以下代码通过扬声器进行路由:

UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute, sizeof(audioRouteOverride), &audioRouteOverride);

这很好用。但现在,我想在连接耳机或外接扬声器时通过耳机传送声音。我怎么做到这一点?

理想情况下,所有其他声音(i.e.音乐 etc.)应该在应用程序启动时静音。

谢谢!

3 回答

  • 11

    为此,您必须在设置音频会话时添加属性侦听器:

    AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, audioSessionPropertyListener, nil);
    

    哪里

    void audioSessionPropertyListener(void* inClientData, AudioSessionPropertyID inID,
                                              UInt32 inDataSize, const void* inData) {
              UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
    
              if (!isHeadsetPluggedIn()) 
                AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,sizeof (audioRouteOverride),&audioRouteOverride);
            }
    
    BOOL isHeadsetPluggedIn() {
      UInt32 routeSize = sizeof (CFStringRef);
      CFStringRef route;
    
      OSStatus error = AudioSessionGetProperty (kAudioSessionProperty_AudioRoute,
                                                &routeSize,
                                                &route
                                                );
    
         if (!error && (route != NULL) && ([(NSString*)route rangeOfString:@"Head"].location != NSNotFound)) {
            NSLog(@"HeadsetPluggedIn");
            return YES;
          }
          NSLog(@"Headset_NOT_PluggedIn");
          return NO;
        }
    

    因此,当耳机插入或拔出时,您会收到通知并更改音频输出方向。

  • 1

    这是一种快速而肮脏的方式,似乎对我有用:

    
    

    void sessionPropertyListener(void * inClientData,
    AudioSessionPropertyID inID,
    UInt32 inDataSize,
    const void * inData){

    if(inID == kAudioSessionProperty_AudioRouteChange)
    {
    CFStringRef newRoute;
    UInt32 size = sizeof(CFStringRef);
    AudioSessionGetProperty(kAudioSessionProperty_AudioRoute,&size,&newRoute);
    if(newRoute)
    {
    CFShow(newRoute);
    if(CFStringCompare(newRoute,CFSTR(“ReceiverAndMicrophone”),
    (UInt32)NULL)== kCFCompareEqualTo)//if 接收器,通过扬声器播放
    {
    UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
    AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute,
    sizeof(audioRouteOverride)
    &audioRouteOverride);
    }
    否则 if(CFStringCompare(newRoute,CFSTR(“HeadsetInOut”),
    (UInt32)NULL)== kCFCompareEqualTo)//headset
    {
    UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_None;
    AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute,
    sizeof(audioRouteOverride)
    &audioRouteOverride);
    }
    }
    }
    }

  • 0

    With AudioSessionSetProperty deprecated since iOS 7 we should be using AVFoundation AVAudioSession. Since the desired action is to allow a user action to override the route through the speaker you might consider the difference between AVAudioSessionPortOverrideSpeaker and AVAudioSessionCategoryOptionDefaultToSpeaker.

    According to Technical bulletin Q&A QA1754: "When using AVAudioSessionCategoryOptionDefaultToSpeaker, user gestures will be honored. For example, plugging in a headset will cause the route to change to headset mic/headphones and unplugging the headset will cause the route to change to built-in mic/speaker".

    Note that the technical bulletin explains that AVAudioSessionPortOverrideSpeaker would be more appropriate for use with a speakerphone button for example, which is not what the original post was asking for.

    https://developer.apple.com/library/ios/qa/qa1754/_index.html

    My own implementation is called before I invoke the player as follows:

    NSError *error;
    AVAudioSession* audioSession   = [AVAudioSession sharedInstance];
    [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:&error];
    // handle any error
    // initiate the player or recorder
    [_player play];
    

    此问题类似于在另一个相关帖子中提到的问题。

    根据这里提到的相同技术公告“想想使用 overrideOutputAudioPort:就你可能用来实现一个扬声器按钮而言,你希望能够在扬声器(AVAudioSessionPortOverrideSpeaker)和正常输出路径(AVAudioSessionPortOverrideNone)之间切换。 “

    如果您正在寻找实现扬声器覆盖 overrideOutputPort 类别,请参阅该帖子:如何在不使用 AudioSessionSetProperty 的情况下将音频路由到扬声器?

相关问题