🎶

【Flutter】AudioCache で BGM を再生するときに iPhone だとマナーモードを貫通してくる

2021/05/10に公開

AudioCache とは

AudioCache とは Flutter 製のオーディオフレームワーク audioplayers で音声再生を行うときに使うオブジェクトです。

詳しくはこちらの公式ページをご覧ください。

今回は普通に使う話はスルーさせて頂きます🙇‍♂️

iPhone だとマナーモードでも再生される

本題です。 AudioCahce で BGM をそのまま再生するとマナーモード(サイレントスイッチをオン)にしても音楽が再生されてしまいます。

AudioCache _bgmCache = AudioCache(fixedPlayer: new AudioPlayer());
_bgmCache.loop(sound.filePath, volume: volume);    // マナーモード貫通.

結論を先に書くと isNotificationtrue にすればマナーモードではサイレントになります。

AudioCache _bgmCache = AudioCache(fixedPlayer: new AudioPlayer());
_bgmCache.loop(sound.filePath, volume: volume, isNotification: true);

めでたしめでたし(╹◡╹)

なんでなん?

そもそも iPhone でマナーモードはなぜ貫通するのかというと AVAudioSession.Categoryplayback が設定されているからです。

audioplayers パッケージでは SwiftAudioplayersPlugin#configureAudioSession で設定されているようです。

    private func configureAudioSession(
        category: AVAudioSession.Category? = nil,
        options: AVAudioSession.CategoryOptions = [],
        active: Bool? = nil
    ) {
        do {
            let session = AVAudioSession.sharedInstance()
            if let category = category {
                try session.setCategory(category, options: options)
            }
            if let active = active {
                try session.setActive(active)
            }
        } catch {
            log("Error configuring audio session: %@", error)
        }
    }

さらに configureAudioSessionupdateCategory で呼ばれております。

    func updateCategory(
        recordingActive: Bool,
        isNotification: Bool,
        playingRoute: String,
        duckAudio: Bool
    ) {
        #if os(iOS)
        // When using AVAudioSessionCategoryPlayback, by default, this implies that your app’s audio is nonmixable—activating your session
        // will interrupt any other audio sessions which are also nonmixable. AVAudioSessionCategoryPlayback should not be used with
        // AVAudioSessionCategoryOptionMixWithOthers option. If so, it prevents infoCenter from working correctly.
        let category = (playingRoute == "earpiece" || recordingActive) ? AVAudioSession.Category.playAndRecord : (
            isNotification ? AVAudioSession.Category.ambient : AVAudioSession.Category.playback
        )
        let options = isNotification || duckAudio ? AVAudioSession.CategoryOptions.mixWithOthers : []
        
        configureAudioSession(category: category, options: options)
        if isNotification {
            UIApplication.shared.beginReceivingRemoteControlEvents()
        }
        #endif
    }

以下の部分が非常に気になります。というか答えです。

let category = (playingRoute == "earpiece" || recordingActive) ? AVAudioSession.Category.playAndRecord : (
            isNotification ? AVAudioSession.Category.ambient : AVAudioSession.Category.playback
        )

AVAudioSession.Category.playback を設定しているとバックグランドでも再生し続け、かつさサイレントモードでも再生されます
参考:https://qiita.com/pandapanda/items/1c87fa0115a8bcba51a6#マナーモード下で音を鳴らす

なので、 isNotificationtrue にして裏で ambient を指定させる感じですね。

アプリの都合によっては soloAmbient にするようにしてもいいかもしれません。

てか、普通デフォルトではマナーモード貫通して欲しくないでしょ・・・と思ったのは私だけでしょうか?w

皆さんのお役に立てると幸いです(╹◡╹)

Discussion