Mirrativ Tech Blog

株式会社ミラティブの開発者(バックエンド,iOS,Android,Unity,機械学習,インフラ, etc.)によるブログです

Android 15 QPR1 におけるMediaProjectionの変更点とMirrativの対応

こんにちは、Androidエンジニアの藤原です。

Android 15が配信されてから数ヶ月が経ちました。
Android ベータプログラムに参加しているとPixel端末にてQPR版のOSが入手できますが、そのAndroid 15 QPR1のバージョンでMirrativ Android版に影響のある変更があったので紹介します。

Android 15 QPR1での変更点とMirrativへの影響

developer.android.com

公式にも記載されていますが、アプリ内で画面共有を行っている際に、ステータスバーに画面共有中であることを示すチップが表示されるようになります。

画面共有中であることがひと目で判断できる、とてもありがたい変更です。

このチップをタップすることでシステム側から画面共有を停止できるのですが、Mirrativでそれを行うと画面共有だけが終了し配信画面だけが残る状態となりました。
下記のGIF動画は、どちらも配信者さんの画面ですが左はMirrativ内の配信メニューから「配信停止」をタップしたもの、右はステータスバーから画面共有停止を行ったものです。左は期待通り配信終了画面に遷移しているのに対し、右は配信画面に居続けています。

配信メニューから終了 ステータスバーから終了


また、視聴者さんの画面では本来なら配信終了時に視聴画面は自動で閉じられますが、ステータスバーから画面共有を停止した場合には視聴者さんに配信が終わったことが伝わらず映像が停止したままの状態となってしまいます。

これはさすがに体験としてよろしくないので対応していきます。

原因と対応内容

原因はMediaProjectionを利用し画面共有の停止を検知する際に、MediaProjection.Callback#onStop()を利用していないことが原因でした。

APIレベル34からMediaProjectionのcreateVirtualDisplayを呼び出す際に、事前にMediaProjection.Callbackを登録する必要があります。 未登録でcreateVirtualDisplayを実行するとIllegalStateExceptionがthrowされます。
そして、MediaProjection.Callback#onStop()のコメントには

Called when the MediaProjection session is no longer valid. Once a MediaProjection has been stopped, it's up to the application to release any resources it may be holding (e. g. releasing the VirtualDisplay and Surface).

とあります。 「MediaProjectionが止まったらonStop()が呼ばれるので、あとはアプリ側でVirtualDisplayなど開放してください」 といったことだと考えられます。
MirrativではもともとMediaProjection.Callbackを使わず、アプリ内の配信終了処理をトリガーにVirtualDisplayの開放を行っていました。
APIレベル34対応時にも形式上MediaProjection.Callbackの登録だけを行い、Callbackの中では何も行っていませんでした。

val callback = object : MediaProjection.Callback() {}
mediaProjection.registerCallback(callback, null)

これによりステータスバーから画面共有を終了した場合に発生したイベントを受け取ることができず本事象へと繋がりました。

よって、MediaProjection.Callback内でonStop()をオーバーライドし

val callback = object : MediaProjection.Callback() {
    override fun onStop() {
        // 配信終了処理を実行し、VirtualDisplayなどを開放する
    }
}
mediaProjection.registerCallback(callback, null)

とすることで、解決することができました。

ステータスバーから画面共有を終了した場合でも、期待通り配信結果画面に遷移するようになっています。

補足

また、以前までは画面ロック状態でも画面共有が維持されていましたが、Android 15 QPR1からは画面ロック状態になった場合でも画面共有が停止します。
こちらも同様にMediaProjection.Callback#onStop()が呼ばれるため上記の対応で解決できます。

まとめ

Android 15 QPR1以降でMediaProjectionを利用して画面共有する場合には、MediaProjection.Callback#onStop()を利用して終了処理を行う必要があります。 MediaProjectionを使う場合はご注意ください。

We are hiring!

ミラティブでは一緒に開発してくれるエンジニアを募集しています!

hrmos.co

www.mirrativ.co.jp

mirrativ.notion.site

speakerdeck.com