美文网首页iOSDev程序员
AVAudioSession踩坑

AVAudioSession踩坑

作者: 低调的魅力 | 来源:发表于2021-01-19 14:30 被阅读0次

    事情是这样的,我们应用里有视频播放,测试发现在播放视频过程中切换到后台,打开网易云音乐后播放一首歌曲,返回到我们的应用中播放视频的时候网易云音乐的音频并没有被关闭。

    于是就在AppDelegate中的加入了如下代码:

    - (void)applicationDidBecomeActive:(UIApplication *)application{
        // 激活音频回话,正常来说就可以关闭其他APP的音频了
        AVAudioSession *audioSession = [AVAudioSession sharedInstance];
        [audioSession setActive:YES error:nil];
    }
    

    发现可以正常关闭掉网易云音乐的声音的。

    于是兴冲冲地打包给测试测:
    结果发现再网易云音乐播放1分钟后再返回到我们的APP播放视频,发现网易云音乐的声音并没有被关闭。

    这就奇怪了,于是翻看了代码,发现在进入后台为了保活APP,在进入后台一定时间后就加入了播放无声音频的代码,并设置了音频会话的AVAudioSessionCategoryOptions为AVAudioSessionCategoryOptionMixWithOthers

    /// 设置活可以汇合其他APP的声音一起播放
    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:NULL];
    

    终于找到原因了,那怎么解决?

    • 1.删除掉保活的代码,嗯,能解决问题,但是应用在后台很快被kill掉,显然不行
    • 2.通过设置AVAudioSessionCategoryOptions来解决呗,看了AVAudioSessionCategoryOptions的枚举值后,发现没有可以用来设置的类型,傻眼了。。。
    typedef NS_OPTIONS(NSUInteger, AVAudioSessionCategoryOptions) {
        AVAudioSessionCategoryOptionMixWithOthers            = 0x1,
        AVAudioSessionCategoryOptionDuckOthers               = 0x2,
        AVAudioSessionCategoryOptionAllowBluetooth API_UNAVAILABLE(tvos, watchos, macos) = 0x4,
        AVAudioSessionCategoryOptionDefaultToSpeaker API_UNAVAILABLE(tvos, watchos, macos) = 0x8,
        AVAudioSessionCategoryOptionInterruptSpokenAudioAndMixWithOthers API_AVAILABLE(ios(9.0), watchos(2.0), tvos(9.0)) API_UNAVAILABLE(macos) = 0x11,
        AVAudioSessionCategoryOptionAllowBluetoothA2DP API_AVAILABLE(ios(10.0), watchos(3.0), tvos(10.0)) API_UNAVAILABLE(macos) = 0x20,
        AVAudioSessionCategoryOptionAllowAirPlay API_AVAILABLE(ios(10.0), tvos(10.0)) API_UNAVAILABLE(watchos, macos) = 0x40,
    };
    

    心里暗想,这也太奇葩了吧,苹果居然没给取消掉AVAudioSessionCategoryOptionMixWithOthers的选项。

    于是开始翻看苹果官方文档,并没有发现有用的东西,这就尴尬了,于是去翻看了AVAudioSession的头文件,找到了

    /// Get the current set of AVAudioSessionCategoryOptions.
    @property (readonly) AVAudioSessionCategoryOptions categoryOptions
    

    获取当前设置过的categoryOptions,于是就打断点看了一下,通过最初设置的[audioSession setActive:YES error:nil];并没有改变AVAudioSessionCategoryOptionMixWithOthers的类型,于是就打印了默认未设置过categoryOptions的值,发现是0,哦,恍然大悟,于是便有了下面的最终解决方案:把categoryOptions参数设置成0就可以啊

        // 激活音频回话,关闭掉其他应用的声音播放
        AVAudioSession *audioSession = [AVAudioSession sharedInstance];
        // AVAudioSessionCategoryOptions 设置为默认类型(取消在后台默认播放无声音乐的AVAudioSessionCategoryOptionMixWithOthers)
        [audioSession setCategory:AVAudioSessionCategoryPlayback withOptions:0 error:nil];
        [audioSession setActive:YES error:nil];
    

    最后,完美解决问题!

    PS:为啥我要写这篇文章呢?因为我发现百度或者Google都没有搜索到相关的问题。所以想分享一下,避免大家踩坑。

    相关文章

      网友评论

        本文标题:AVAudioSession踩坑

        本文链接:https://www.haomeiwen.com/subject/nciqzktx.html