1. kazuhiro4949

    No comment

    kazuhiro4949
Changes in body
Source | HTML | Preview

iOS11の新機能の一つにScreen Recordingというものがあります。

とても素敵な機能で、簡単に画面の録画が実現できるようになりました。(超便利!)
しかしアプリによっては「この画面を録画されると都合が悪い」といったケースもあるでしょう。
そこで、アプリの中で録画の検知をする方法をTipsとしてまとめます。

アプリ内で録画を検知するためのプロパティ

Screen Recordingへ合わせる形で、iOS11からUIScreenに以下のAPIが追加されました。

このプロパティは、「スクリーンのキャプチャ」が行われている間はtrueを返します。

UIScreen.main.isCaptured

ここでいう「スクリーンのキャプチャ」にはScreen Recordingも含まれます。
レコードを開始した上でプロパティの値を確認してみるとわかるのですが、確かにレコード中はtrueを返して、やめるとfalseを返します。
注意点として、「含まれます」というのが曲者で、AirPlayやミラーリング中でも同じくtrueを返す仕様となっています。
従って、AirPlayをサポートしている映像サービスだと、AirPlayのケースを取り除かないとならないでしょう。

AVPlayerを使って映像を再生しているケースであれば、以下のAPIを組み合わせることでScreen Recording中であるがAirPlayではないというのを判定できるかと思います。

Screen Recordingもしくはミラーリング中であるかどうかは上記2つのプロパティを使って判定します。

// player: AVPlayer
UIScreen.main.isCaptured && !player.isExternalPlaybackActive

残念ながらミラーリングかどうかを判定するためのプロパティは見つけられませんでした。。。(もしご存知のかたがいたら教えてください)

アプリ内で録画を検知するためのNotification

前述のプロパティを使い、UIのライフサイクルイベントや通信完了ハンドラなどで検知できるようになりました。

ただしこのままだと不十分です。映像の再生中にコントロールセンターを開き、再生を開始したときにはどうすればいいでしょうか。(寧ろそういうパターンのほうが多いでしょう。)
そういった場合でも対応できるよう、Notificationにも新たな通知が追加されました。

リファレンスを見る限り、通知を受け取ってもuserInfoには何も入っていないようです。通知の中で先程のisCapturedを呼んで、判定をしましょう。

let obserber = NotificationCenter
            .default
            .addObserver(forName: .UIScreenCapturedDidChange, object: nil, queue: .main) { [weak self] (notif) in
                if let player = self?.player, !player.isExternalPlaybackActive, UIScreen.main.isCaptured {
                    // ここで何とかする
                }
        }

まとめ

  1. 画面遷移してデータを取ってきたタイミングで検知したいのであればUIScreenのisCapturedを呼ぶ
  2. ただし1.のみだとAirPlayやミラーリングも検知してしまうので、AVPlayerのisExternalPlaybackActiveなども適宜組み合わせる
  3. レコーディング開始のタイミングを検知したければUIScreenCapturedDidChangeを使う

以上です。

参考資料