我正在 iOS 上实现画中画。我添加了后台模式功能。当我调用 isPictureInPicturePossible 时,它返回 false 并出现错误:
pictureInPictureController failedToStartPictureInPictureWithError Error Domain=AVKitErrorDomain Code=-1001 "Failed to start picture in picture." UserInfo={NSLocalizedDescription=Failed to start picture in picture., NSLocalizedFailureReason=The UIScene for the content source has an activation state other than UISceneActivationStateForegroundActive, which is not allowed.}
但是当我记录activationState时,我可以看到它实际上是foregroundActive。知道可能是什么原因吗?
(在此之前 isPictureInPictureActive 返回 true,isPictureInPictureSuspished 返回 false,isPictureInPictureActive 返回 false。)
不知道你是否还需要这个。但我遇到了同样的问题,我设法用
AVPlayerLayer
解决了它。
这是我的代码(在
AVPlayerViewController
内,但也可以在普通的 UIViewController 中使用):
extension PlayerContainerViewController: AVPictureInPictureControllerDelegate {
func setupPictureInPicture() {
if AVPictureInPictureController.isPictureInPictureSupported() {
let playerLayer: AVPlayerLayer = AVPlayerLayer()
playerLayer.player = player // player is your AVPlayer
self.view.layer.addSublayer(playerLayer) // <-- Very important
playerLayer.videoGravity = .resizeAspect
playerLayer.frame = self.view.bounds
pipController = AVPictureInPictureController(playerLayer: playerLayer)
pipController?.delegate = self
}
}
func pictureInPictureController(
_ pictureInPictureController: AVPictureInPictureController,
restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void
) {
completionHandler(true)
}
func pictureInPictureControllerWillStartPictureInPicture(
_ pictureInPictureController: AVPictureInPictureController) {
// Pip starting
}
func pictureInPictureControllerDidStopPictureInPicture(
_ pictureInPictureController: AVPictureInPictureController) {
// Pip stopped
}
func pictureInPictureController(_ pictureInPictureController: AVPictureInPictureController, failedToStartPictureInPictureWithError error: Error) {
print("[PIP] \(error)")
}
func startPip() {
pipController?.startPictureInPicture()
}
func stopPip() {
pipController?.stopPictureInPicture()
}
}
希望这有帮助。
在无法访问代码且不了解版本的情况下发表意见有点困难。
我的建议:
检查应用程序是否确实位于前台。您可以通过查看内容源的 UIScene 的activationState 来验证这一点。如果不是foregroundActive,则无法启动图像中的图像。如果您使用的是 UISceneDelegate,则可以在 sceneWillEnterForeground: 方法中检查场景的激活状态。如果使用 AppDelegate,您可以在 applicationDidBecomeActive: 方法中检查场景的激活状态。
如果您使用 UISceneDelegate 而不是 AppDelegate。将其更改为 AppDelegate。
在AppDelegate.swift文件中将sceneActivationState设置为foregroundActive:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if #available(iOS 13.0, *) {
let scene = UIApplication.shared.connectedScenes.first
if let sceneDelegate = scene?.delegate as? SceneDelegate {
sceneDelegate.window?.windowScene?.activationState = .foregroundActive
}
}
return true
}
如果没有选项进行验证。我们将为您提供有关该问题的更多信息。
在我的例子中,这些错误是由于我为一个播放器层(
AVPictureInPictureController
)创建了AVPlayerLayer
,但尝试为另一个播放器层启动画中画(当更改项目中的项目时,播放器层在我的代码中发生了更改)玩家)。
因此,如果您遇到此类错误,请检查 AVPictureInPictureController 的播放器层是否正确。