diff --git a/ios/Video/Features/RCTPictureInPicture.swift b/ios/Video/Features/RCTPictureInPicture.swift index 4525df0b..da6a9d8c 100644 --- a/ios/Video/Features/RCTPictureInPicture.swift +++ b/ios/Video/Features/RCTPictureInPicture.swift @@ -4,15 +4,15 @@ import MediaAccessibility import React import Foundation -#if TARGET_OS_IOS +#if os(iOS) class RCTPictureInPicture: NSObject, AVPictureInPictureControllerDelegate { - private var _onPictureInPictureStatusChanged: RCTDirectEventBlock? - private var _onRestoreUserInterfaceForPictureInPictureStop: RCTDirectEventBlock? + private var _onPictureInPictureStatusChanged: (() -> Void)? = nil + private var _onRestoreUserInterfaceForPictureInPictureStop: (() -> Void)? = nil private var _restoreUserInterfaceForPIPStopCompletionHandler:((Bool) -> Void)? = nil private var _pipController:AVPictureInPictureController? private var _isActive:Bool = false - init(_ onPictureInPictureStatusChanged: @escaping RCTDirectEventBlock, _ onRestoreUserInterfaceForPictureInPictureStop: @escaping RCTDirectEventBlock) { + init(_ onPictureInPictureStatusChanged: (() -> Void)? = nil, _ onRestoreUserInterfaceForPictureInPictureStop: (() -> Void)? = nil) { _onPictureInPictureStatusChanged = onPictureInPictureStatusChanged _onRestoreUserInterfaceForPictureInPictureStop = onRestoreUserInterfaceForPictureInPictureStop } @@ -20,22 +20,20 @@ class RCTPictureInPicture: NSObject, AVPictureInPictureControllerDelegate { func pictureInPictureControllerDidStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) { guard let _onPictureInPictureStatusChanged = _onPictureInPictureStatusChanged else { return } - _onPictureInPictureStatusChanged([ "isActive": NSNumber(value: true)]) + _onPictureInPictureStatusChanged() } func pictureInPictureControllerDidStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) { guard let _onPictureInPictureStatusChanged = _onPictureInPictureStatusChanged else { return } - _onPictureInPictureStatusChanged([ "isActive": NSNumber(value: false)]) + _onPictureInPictureStatusChanged() } func pictureInPictureController(_ pictureInPictureController: AVPictureInPictureController, restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void) { - - assert(_restoreUserInterfaceForPIPStopCompletionHandler == nil, "restoreUserInterfaceForPIPStopCompletionHandler was not called after picture in picture was exited.") - + guard let _onRestoreUserInterfaceForPictureInPictureStop = _onRestoreUserInterfaceForPictureInPictureStop else { return } - _onRestoreUserInterfaceForPictureInPictureStop([:]) + _onRestoreUserInterfaceForPictureInPictureStop() _restoreUserInterfaceForPIPStopCompletionHandler = completionHandler } @@ -47,7 +45,6 @@ class RCTPictureInPicture: NSObject, AVPictureInPictureControllerDelegate { } func setupPipController(_ playerLayer: AVPlayerLayer?) { - guard playerLayer != nil && AVPictureInPictureController.isPictureInPictureSupported() && _isActive else { return } // Create new controller passing reference to the AVPlayerLayer _pipController = AVPictureInPictureController(playerLayer:playerLayer!) _pipController?.delegate = self diff --git a/ios/Video/RCTVideo.swift b/ios/Video/RCTVideo.swift index e40a0c9f..03ae306d 100644 --- a/ios/Video/RCTVideo.swift +++ b/ios/Video/RCTVideo.swift @@ -82,8 +82,8 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH private let _videoCache:RCTVideoCachingHandler = RCTVideoCachingHandler() #endif -#if TARGET_OS_IOS - private let _pip:RCTPictureInPicture = RCTPictureInPicture(self.onPictureInPictureStatusChanged, self.onRestoreUserInterfaceForPictureInPictureStop) +#if os(iOS) + private var _pip:RCTPictureInPicture? = nil #endif // Events @@ -110,6 +110,14 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH @objc var onRestoreUserInterfaceForPictureInPictureStop: RCTDirectEventBlock? @objc var onGetLicense: RCTDirectEventBlock? @objc var onReceiveAdEvent: RCTDirectEventBlock? + + @objc func _onPictureInPictureStatusChanged() { + onPictureInPictureStatusChanged?([ "isActive": NSNumber(value: true)]) + } + + @objc func _onRestoreUserInterfaceForPictureInPictureStop() { + onPictureInPictureStatusChanged?([ "isActive": NSNumber(value: false)]) + } init(eventDispatcher:RCTEventDispatcher!) { super.init(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) @@ -119,6 +127,10 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH _eventDispatcher = eventDispatcher +#if os(iOS) + _pip = RCTPictureInPicture(self._onPictureInPictureStatusChanged, self._onRestoreUserInterfaceForPictureInPictureStop) +#endif + NotificationCenter.default.addObserver( self, selector: #selector(applicationWillResignActive(notification:)), @@ -175,7 +187,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH } @objc func applicationDidEnterBackground(notification:NSNotification!) { - if _playInBackground { + if !_playInBackground { // Needed to play sound in background. See https://developer.apple.com/library/ios/qa/qa1668/_index.html _playerLayer?.player = nil _playerViewController?.player = nil @@ -411,15 +423,21 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH @objc func setPictureInPicture(_ pictureInPicture:Bool) { -#if TARGET_OS_IOS - _pip.setPictureInPicture(pictureInPicture) +#if os(iOS) + let audioSession = AVAudioSession.sharedInstance() + do { + try audioSession.setCategory(.playback) + try audioSession.setActive(true, options: []) + } catch { + } + _pip?.setPictureInPicture(pictureInPicture) #endif } @objc func setRestoreUserInterfaceForPIPStopCompletionHandler(_ restore:Bool) { -#if TARGET_OS_IOS - _pip.setRestoreUserInterfaceForPIPStopCompletionHandler(restore) +#if os(iOS) + _pip?.setRestoreUserInterfaceForPIPStopCompletionHandler(restore) #endif } @@ -753,6 +771,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH viewController.view.frame = self.bounds viewController.player = player + viewController.allowsPictureInPicturePlayback = true return viewController } @@ -771,8 +790,8 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH self.layer.addSublayer(_playerLayer) } self.layer.needsDisplayOnBoundsChange = true -#if TARGET_OS_IOS - _pip.setupPipController(_playerLayer) +#if os(iOS) + _pip?.setupPipController(_playerLayer) #endif } }