1. kazuhiro4949

    Posted

    kazuhiro4949
Changes in title
+iOS11から搭載されるスクリーンレコーディングでの録画を防ぐ方法
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,74 @@
+iOS11から**Screen Recording**という機能が追加されました。
+
+- [発見! iOS 11から、iPhone単体で動画キャプチャが撮れるように](https://www.gizmodo.jp/2017/06/ios-11-screen-recorder.html)
+
+とても素敵な機能で、簡単に画面の録画が実現できるようになりました。(超便利!)
+しかしアプリによっては「この画面を録画されると都合が悪い」といったケースもあるでしょう。
+そこで、アプリの中で録画の検知をする方法をTipsとしてまとめます。
+
+# アプリ内で録画を検知するためのプロパティ
+iOS11からUIScreenに以下のAPIが追加されました。
+
+- [isCaptured - UIScreen | Apple Developer Documentation](https://developer.apple.com/documentation/uikit/uiscreen/2921651-iscaptured)
+
+このプロパティは、**「スクリーンのキャプチャ」**が行われている間はtrueを返します。
+
+```swift
+UIScreen.main.isCaptured
+```
+
+ここでいう「スクリーンのキャプチャ」にはScreen Recordingも含まれます。
+レコードを開始した上でプロパティの値を確認してみるとわかるのですが、確かにレコード中はtrueを返して、やめるとfalseを返します。
+注意点として、「含まれます」というのが曲者で、AirPlayやミラーリング中でも同じくtrueを返す仕様となっています。
+従って、AirPlayをサポートしている映像サービスだと、AirPlayのケースを取り除かないとならないでしょう。
+
+AVPlayerを使って映像を再生しているケースであれば、以下のAPIを組み合わせることで**Screen Recording中であるがAirPlayではない**というのを判定できるかと思います。
+
+- [isExternalPlaybackActive - AVPlayer | Apple Developer Documentation](https://developer.apple.com/documentation/avfoundation/avplayer/1388982-isexternalplaybackactive)
+
+Screen Recordingもしくはミラーリング中であるかどうかは上記2つのプロパティを使って判定します。
+
+```swift
+// player: AVPlayer
+UIScreen.main.isCaptured && !player.isExternalPlaybackActive
+```
+
+残念ながらミラーリングかどうかを判定するためのプロパティは見つけられませんでした。。。(もしご存知のかたがいたら教えてください)
+
+# アプリ内で録画を検知するためのNotification
+
+前述のプロパティを使い、UIのライフサイクルイベントや通信完了ハンドラなどで検知できるようになりました。
+
+ただしこのままだと不十分です。映像の再生中にコントロールセンターを開き、再生を開始したときにはどうすればいいでしょうか。(寧ろそういうパターンのほうが多いでしょう。)
+そういった場合でも対応できるよう、Notificationにも新たな通知が追加されました。
+
+- [UIScreenDidConnectNotification - UIKit | Apple Developer Documentation](https://developer.apple.com/documentation/uikit/uiscreendidconnectnotification)
+
+リファレンスを見る限り、通知を受け取ってもuserInfoには何も入っていないようです。通知の中で先程のisCapturedを呼んで、判定をしましょう。
+
+```swift
+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を使う
+
+以上です。
+
+# 参考資料
+
+- [iOS 11 Screen Recording - Copyright Risks | Apple Developer Forums](https://forums.developer.apple.com/thread/86521)
+- [発見! iOS 11から、iPhone単体で動画キャプチャが撮れるように](https://www.gizmodo.jp/2017/06/ios-11-screen-recorder.html)
+- [isCaptured - UIScreen | Apple Developer Documentation](https://developer.apple.com/documentation/uikit/uiscreen/2921651-iscaptured)
+- [isExternalPlaybackActive - AVPlayer | Apple Developer Documentation](https://developer.apple.com/documentation/avfoundation/avplayer/1388982-isexternalplaybackactive)
+
+