flutter 添加原生IOS 播放器

发布时间 2023-12-28 13:23:25作者: vx_guanchaoguo0

定义播放器

FlutterAVPlayer.swift


import Foundation
import AVKit
import MediaPlayer
import Flutter

class FlutterAVPlayer: NSObject, FlutterPlatformView {
    private var _flutterAVPlayerViewController : AVPlayerViewController;
    
    init(frame:CGRect,
          viewIdentifier: CLongLong,
          arguments: Dictionary<String, Any>,
          binaryMessenger: FlutterBinaryMessenger) {
        _flutterAVPlayerViewController = AVPlayerViewController()
        _flutterAVPlayerViewController.viewDidLoad()
        if let urlString = arguments["url"] {
            let item = AVPlayerItem(url: URL(string: urlString as! String)!)
            _flutterAVPlayerViewController.player = AVPlayer(playerItem: item)
        } else if let filePath = arguments["file"] {
            let appDelegate = UIApplication.shared.delegate as! FlutterAppDelegate
            let vc = appDelegate.window.rootViewController as! FlutterViewController
            let lookUpKey = vc.lookupKey(forAsset: filePath as! String)
            if let path = Bundle.main.path(forResource: lookUpKey, ofType: nil) {
                let item = AVPlayerItem(url: URL(fileURLWithPath: path))
                _flutterAVPlayerViewController.player = AVPlayer(playerItem: item)
            }
        }
        _flutterAVPlayerViewController.player!.play()
    }
    func view() -> UIView {
        return _flutterAVPlayerViewController.view;
    }
    
}


选择器

FlutterRoutePickerView.swift

import Foundation
import AVKit
import MediaPlayer
import Flutter

class FlutterRoutePickerView: NSObject, FlutterPlatformView {
    private var _flutterRoutePickerView : UIView;
    private var _delegate: AVRoutePickerViewDelegate?
    
    init(
        messenger: FlutterBinaryMessenger,
        viewId: Int64,
        arguments: Dictionary<String, Any>
    ) {
        if #available(iOS 11.0, *) {
            let tempView = AVRoutePickerView(frame: .init(x: 0.0, y: 0.0, width: 44.0, height: 44.0))
            if let tintColor = arguments["tintColor"] {
                let color = tintColor as! Dictionary<String, Any>
                tempView.tintColor = FlutterRoutePickerView.mapToColor(color)
            }
            if let tintColor = arguments["activeTintColor"] {
                let color = tintColor as! Dictionary<String, Any>
                tempView.activeTintColor = FlutterRoutePickerView.mapToColor(color)
            }
            if let tintColor = arguments["backgroundColor"] {
                let color = tintColor as! Dictionary<String, Any>
                tempView.backgroundColor = FlutterRoutePickerView.mapToColor(color)
            }
            
            if #available(iOS 13.0, *) {
                tempView.prioritizesVideoDevices = arguments["prioritizesVideoDevices"] as! Bool
            }
            
            _delegate = FlutterRoutePickerDelegate(viewId: viewId, messenger: messenger)
            tempView.delegate = _delegate
            
            _flutterRoutePickerView = tempView
        } else {
            let tempView = MPVolumeView(frame: .init(x: 0.0, y: 0.0, width: 44.0, height: 44.0))
            tempView.showsVolumeSlider = false
            _flutterRoutePickerView = tempView
        }
    }
    
    func view() -> UIView {
        return _flutterRoutePickerView
    }
    
    static func mapToColor(_ map: Dictionary<String, Any>) -> UIColor {
        return  UIColor.init(red: CGFloat(map["red"] as! Int) / 255,
                             green: CGFloat(map["green"] as! Int) / 255,
                             blue: CGFloat(map["blue"] as! Int) / 255,
                             alpha: CGFloat(map["alpha"] as! Int) / 255)
    }
}

class FlutterRoutePickerDelegate : NSObject, AVRoutePickerViewDelegate {
    let _methodChannel: FlutterMethodChannel

    init(viewId: Int64, messenger: FlutterBinaryMessenger) {
        _methodChannel = FlutterMethodChannel(name: "flutter_to_airplay#\(viewId)", binaryMessenger: messenger)
    }

    func routePickerViewWillBeginPresentingRoutes(_ routePickerView: AVRoutePickerView) {
        _methodChannel.invokeMethod("onShowPickerView", arguments: nil)
    }

    func routePickerViewDidEndPresentingRoutes(_ routePickerView: AVRoutePickerView) {
        _methodChannel.invokeMethod("onClosePickerView", arguments: nil)
    }
}

共享工厂

SharePlatformViewFactory.swift

import Foundation
import Flutter

class SharePlatformViewFactory: NSObject, FlutterPlatformViewFactory {
    let _messenger : FlutterBinaryMessenger

    init(messenger: FlutterBinaryMessenger & NSObjectProtocol) {
        _messenger = messenger
    }

    func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?) -> FlutterPlatformView {
        let argumens = args as! Dictionary<String, Any>;
        if let viewClass = argumens["class"] {
            let vc = viewClass as! String
            if vc == "AirplayRoutePicker" {
                let pickerView = FlutterRoutePickerView(messenger: _messenger, viewId: viewId, arguments: argumens)
                return pickerView
            }
            else if vc == "FlutterAVPlayerView" {
                let pickerView = FlutterAVPlayer(frame: frame, viewIdentifier: viewId, arguments: argumens, binaryMessenger: _messenger)
                return pickerView
            }
        }
        
        return UIView() as! FlutterPlatformView
    }
    
    func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol {
        return FlutterStandardMessageCodec.sharedInstance()
    }
}

注册插件

SwiftFlutterToAirplayPlugin.swift

import Flutter
import UIKit

 
public class SwiftFlutterToAirplayPlugin: NSObject, FlutterPlugin {
  public static func register(with registrar: FlutterPluginRegistrar) {
    registrar.register(
        SharePlatformViewFactory(messenger: registrar.messenger()),
        withId: "airplay_route_picker_view",
        gestureRecognizersBlockingPolicy: FlutterPlatformViewGestureRecognizersBlockingPolicy(rawValue: 0))
    
    registrar.register(
        SharePlatformViewFactory(messenger: registrar.messenger()),
        withId: "flutter_avplayer_view",
        gestureRecognizersBlockingPolicy: FlutterPlatformViewGestureRecognizersBlockingPolicy(rawValue: 0))
  }
}

最后一步委派插件

AppDelegate.swift

import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)
      let registrar:FlutterPluginRegistrar = self.registrar(forPlugin: "flutter_to_airplay")!
     SwiftFlutterToAirplayPlugin.register(with: registrar)
      
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}