Я хочу реализовать функцию «Картинка в картинке» (PiP) на iOS.
Flutter не обеспечивает встроенную поддержку PiP напрямую для iOS, поэтому я реализовал ее с использованием собственного кода Swift через собственный плагин.
Проблема, с которой я сталкиваюсь, заключается в следующем:
Когда я вручную нажимаю на свой собственный плагин Кнопка PiP, PiP успешно запускается и работает нормально.
Но когда я перевожу приложение в фоновый режим (кнопка «Домой» / прокручиваю вверх) и пытаюсь запустить PiP автоматически, PiP не появляется — хотя кажется, что он запускается внутри.
Это мой IosPipManager(swift)
import Foundation
import AVKit
import Flutter
public class IosPipManager: NSObject, FlutterPlugin {
private var pipController: AVPictureInPictureController?
private var playerLayer: AVPlayerLayer?
private var methodChannel: FlutterMethodChannel?
public static func register(with registrar: FlutterPluginRegistrar) {
let instance = IosPipManager()
let channel = FlutterMethodChannel(name: "ios_pip_manager", binaryMessenger: registrar.messenger())
instance.methodChannel = channel
registrar.addMethodCallDelegate(instance, channel: channel)
NotificationCenter.default.addObserver(
instance,
selector: #selector(instance.appDidEnterBackground),
name: UIApplication.didEnterBackgroundNotification,
object: nil
)
}
@objc private func appDidEnterBackground() {
guard let controller = pipController else {
print("
return
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
if !controller.isPictureInPictureActive {
print("
controller.startPictureInPicture()
}
}
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
switch call.method {
case "initializePip":
print("
guard let viewController = UIApplication.shared.delegate?.window??.rootViewController else {
result(FlutterError(code: "NO_VIEW", message: "No root view controller", details: nil))
return
}
if let playerLayer = findPlayerLayer(in: viewController.view.layer) {
print("
self.playerLayer = playerLayer
self.pipController = AVPictureInPictureController(playerLayer: playerLayer)
result(true)
} else {
print("
result(FlutterError(code: "NO_PLAYER_LAYER", message: "Couldn't find AVPlayerLayer from Flutter video player", details: nil))
}
case "startPip":
print("
startPip(result: result)
case "stopPip":
print("⏹ stopPip called")
stopPip(result: result)
default:
result(FlutterMethodNotImplemented)
}
}
private func startPip(result: @escaping FlutterResult) {
guard let controller = pipController else {
result(FlutterError(code: "NOT_INITIALIZED", message: "PiP controller not initialized", details: nil))
return
}
if !controller.isPictureInPictureActive {
controller.startPictureInPicture()
}
result(true)
}
private func stopPip(result: @escaping FlutterResult) {
guard let controller = pipController else {
result(FlutterError(code: "NOT_INITIALIZED", message: "PiP controller not initialized", details: nil))
return
}
if controller.isPictureInPictureActive {
controller.stopPictureInPicture()
}
result(true)
}
private func findPlayerLayer(in layer: CALayer) -> AVPlayerLayer? {
if let playerLayer = layer as? AVPlayerLayer {
return playerLayer
}
for sublayer in layer.sublayers ?? [] {
if let found = findPlayerLayer(in: sublayer) {
return found
}
}
return nil
}
}
extension IosPipManager: AVPictureInPictureControllerDelegate {
public func pictureInPictureControllerDidStartPictureInPicture(\_ pictureInPictureController: AVPictureInPictureController) {
methodChannel?.invokeMethod("onPipStarted", arguments: nil)
}
public func pictureInPictureControllerDidStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
methodChannel?.invokeMethod("onPipStopped", arguments: nil)
}
public func pictureInPictureController(_ pictureInPictureController: AVPictureInPictureController, failedToStartPictureInPictureWithError error: Error) {
methodChannel?.invokeMethod("onPipError", arguments: error.localizedDescription)
}
}
Подробнее здесь: https://stackoverflow.com/questions/797 ... d-works-on
Мобильная версия