Как включить автозапуск видео с рекламой IMA во Flutter с помощью GSPlayer и Google IMA SDK?IOS

Программируем под IOS
Ответить Пред. темаСлед. тема
Anonymous
 Как включить автозапуск видео с рекламой IMA во Flutter с помощью GSPlayer и Google IMA SDK?

Сообщение Anonymous »

Я разрабатываю приложение Flutter, в котором мне нужно воспроизводить видео с рекламой с помощью GSPlayer и Google IMA SDK на iOS. Видео должно начать воспроизводиться автоматически, не требуя вмешательства пользователя. Однако у меня возникли проблемы с автовоспроизведением, особенно с интеграцией рекламы для беспрепятственного воспроизведения до начала основного контента.
Вот краткое описание моей настройки:
  • Зависимости:
  • GSPlayer для воспроизведения видео.
    < li>GoogleInteractiveMediaAds для обработки видеорекламы.
  • Цель:
    < /ol>
    • Автоматически загружать и воспроизводить рекламу перед основным видеоконтентом.
    • Автоматически начинать воспроизведение видео после завершения рекламы.
    Автоматически загружать и воспроизводить рекламу перед основным видеоконтентом.
  • Автоматически запускать воспроизведение видео после завершения показа рекламы.

    Автоматически загружать и воспроизводить рекламу перед основным видеоконтентом.
  • Автоматически начинать воспроизведение видео после завершения рекламы.

    Автоматически загружать и воспроизводить рекламу перед основным видеоконтентом.
  • Автоматически запускать воспроизведение видео после показа рекламы.

    li>
    Обеспечите плавный переход между рекламой и основным видеоконтентом.
  • Проблема:
  • Видео не запускается автоматически.
  • Рекламы нет. воспроизводите как положено перед основным контентом.

Код: Выделить всё

import Foundation
import GoogleInteractiveMediaAds
import GSPlayer
import Flutter

class NativeViewFactory : NSObject, FlutterPlatformViewFactory {
private var messenger: FlutterBinaryMessenger

init(messenger: FlutterBinaryMessenger) {
self.messenger = messenger
super.init()
}
public func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol {
return FlutterStandardMessageCodec.sharedInstance()
}
func create(
withFrame frame: CGRect,
viewIdentifier viewId: Int64,
arguments args: Any?
) -> FlutterPlatformView {
return NativeView(
frame: frame,
viewIdentifier: viewId,
arguments: args,
binaryMessenger: messenger)
}
}

public class NativeView : NSObject, FlutterPlatformView,fullScreeenDelegate, IMAAdsLoaderDelegate, IMAAdsManagerDelegate {

deinit{
stopTimer()
playerView.pause()
}

private var _view: UIView
var kTestAppContentUrl_MP4 = " "

var settings = UIButton()

var playerView =  VideoPlayerView()
var controlView =  GSPlayerControlUIView()

var paybackSlider = UISlider()

var contentPlayhead: IMAAVPlayerContentPlayhead?
var adsLoader: IMAAdsLoader!
var adsManager: IMAAdsManager!
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let controller = UIApplication.topViewController()

var item : AVPlayerItem!

var message : FlutterBinaryMessenger!
weak var timer: Timer?

static let kTestAppAdTagUrl =
"AD TAG URL HERE"
init(
frame: CGRect,
viewIdentifier viewId: Int64,
arguments args: Any?,
binaryMessenger messenger: FlutterBinaryMessenger?
) {
_view = UIView()
super.init()

if let argumentsDictionary = args as? Dictionary {
self.kTestAppContentUrl_MP4 = argumentsDictionary["videoURL"] as! String
print("test URL:", kTestAppContentUrl_MP4)
}
message = messenger

let flutterChannel = FlutterMethodChannel(name: "bms_video_player",
binaryMessenger: messenger!)

flutterChannel.setMethodCallHandler({ (call: FlutterMethodCall, result: FlutterResult) ->  Void in
switch call.method {
case "pauseVideo":
self.playerView.pause(reason: .userInteraction)
if(self.adsManager.adPlaybackInfo.isPlaying) {
self.adsManager.pause()
}
return

default:
result(FlutterMethodNotImplemented)
}
})

// iOS views can be created here

setUpContentPlayer(view: _view)
setUpAdsLoader()
createNativeView(view: _view)
startTimer()

}

func startTimer() {
timer?.invalidate()   // just in case you had existing `Timer`, `invalidate` it before we lose our reference to it
timer = Timer.scheduledTimer(withTimeInterval: 4, repeats: true) { [weak self] _ in
self?.controlView.isHidden = true
}
}

func stopTimer() {
timer?.invalidate()
self.playerView.pause()
}

// if appropriate, make sure to stop your timer in `deinit`

func fullScreenTap() {
print("fullScreen tapped!!")
let flutterChannel = FlutterMethodChannel(name: "bms_video_player",
binaryMessenger: message!)
flutterChannel.invokeMethod("fullScreen",arguments: 0)

playerView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.height, height:UIScreen.main.bounds.size.width )
controlView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.height, height: UIScreen.main.bounds.size.width)

}

func normalScreenTap() {
print("normalScreen tapped!!")
let flutterChannel = FlutterMethodChannel(name: "bms_video_player",
binaryMessenger: message!)
flutterChannel.invokeMethod("normalScreen",arguments: 0)

playerView.frame = CGRect(x: 0, y: 0, width:UIScreen.main.bounds.size.height, height: 400)
controlView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.height, height: 400)

}

func backButtonTap() {
print("backButton tapped!!")
// Handle back button action
controlView.onClicked_FullScreen(self)
let flutterChannel = FlutterMethodChannel(name: "bms_video_player", binaryMessenger: message!)
flutterChannel.invokeMethod("onBackButtonClicked", arguments: nil)
}

func setUpContentPlayer(view _view: UIView) {
// Load AVPlayer with path to our content.
print("test URL1:", kTestAppContentUrl_MP4)

guard let contentURL = URL(string: kTestAppContentUrl_MP4) else {
print("ERROR: please use a valid URL for the content URL")
return
}

let controller = AVPlayerViewController()
let player = AVPlayer(url: URL(string: kTestAppContentUrl_MP4)!)

controller.player = player

playerView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 400)
controlView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 400)

playerView.contentMode = .scaleAspectFill
playerView.play(for: contentURL)

controlView.delegate = self
controlView.populate(with: playerView)

// Size, position, and display the AVPlayer.
_view.addSubview(playerView)
_view.addSubview(controlView)

playerView.pause(reason: .userInteraction)
controlView.isHidden = true
controlView.bringSubviewToFront(_view)

let tap = UITapGestureRecognizer(target: self, action: #selector(self.touchHappen(_:)))
playerView.addGestureRecognizer(tap)
playerView.isUserInteractionEnabled = true
//_view.layer.addSublayer(playerLayer!)

// Set up our content playhead and contentComplete callback.
contentPlayhead = IMAAVPlayerContentPlayhead(avPlayer: playerView.player!)
}

@objc func touchHappen(_ sender:  UITapGestureRecognizer) {
print("touchHappen")
self.controlView.isHidden = false
}

@objc func applicationDidEnterBackground(_ notification: NSNotification) {
playerView.pause(reason: .userInteraction)
}

@objc func contentDidFinishPlaying(_ notification: Notification) {
// Make sure we don't call contentComplete as a result of an ad completing.
// if (notification.object as! AVPlayerItem) == playerView.playerLayer.player?.currentItem {
//    adsLoader.contentComplete()
// }
}

func setUpAdsLoader() {
adsLoader = IMAAdsLoader(settings: nil)
adsLoader.delegate = self
}

func requestAds(view _view: UIView) {
// Create ad display container for ad rendering.
let adDisplayContainer = IMAAdDisplayContainer(
adContainer: _view, viewController: controller, companionSlots: nil)
// Create an ad request with our ad tag, display container, and optional user context.
let request = IMAAdsRequest(
adTagUrl: NativeView.kTestAppAdTagUrl,
adDisplayContainer: adDisplayContainer,
contentPlayhead: contentPlayhead,
userContext: controlView)

adsLoader.requestAds(with: request)

}
public func view() ->  UIView {
return _view
}

func createNativeView(view _view: UIView){
_view.backgroundColor = UIColor.black

settings.addTarget(self, action: #selector(touchedSet), for: .touchUpInside)
settings.setImage(UIImage(named: "play_48px"), for: .normal)
settings.frame = CGRect(x: 200, y:200 , width: 50, height: 50)
_view.addSubview(settings)
_view.bringSubviewToFront(controlView)
_view.bringSubviewToFront(settings)

}

@objc func touchedSet(sender: UIButton!) {
print("You tapped the button")

requestAds(view: _view)
settings.isHidden = true
}

// MARK: - IMAAdsLoaderDelegate

public func adsLoader(_ loader: IMAAdsLoader, adsLoadedWith adsLoadedData: IMAAdsLoadedData) {
// Grab the instance of the IMAAdsManager and set ourselves as the delegate.
adsManager = adsLoadedData.adsManager
adsManager.delegate = self

// Create ads rendering settings and tell the SDK to use the in-app browser.
let adsRenderingSettings = IMAAdsRenderingSettings()
adsRenderingSettings.linkOpenerPresentingController = controller

// Initialize the ads manager.
adsManager.initialize(with: adsRenderingSettings)

//touchedSet(sender: UIButton())
//controlView.onClicked_FullScreen(self)
}

public func adsLoader(_ loader: IMAAdsLoader, failedWith adErrorData: IMAAdLoadingErrorData) {
playerView.resume()
controlView.isHidden = false

}

// MARK: - IMAAdsManagerDelegate

public func adsManager(_ adsManager: IMAAdsManager, didReceive event: IMAAdEvent) {
if event.type == IMAAdEventType.LOADED {
// When the SDK notifies us that ads have been loaded, play them.
adsManager.start()
}
if event.type == IMAAdEventType.RESUME {

settings.addTarget(self, action: #selector(touchedSet), for: .touchUpInside)
settings.setImage(UIImage(named: "play_48px"), for: .normal)
settings.frame = CGRect(x: 200, y:200 , width: 50, height: 50)
_view.addSubview(settings)
}

if event.type == IMAAdEventType.PAUSE {

if(adsManager.adPlaybackInfo.isPlaying) {
adsManager.pause()
}
settings.addTarget(self, action: #selector(touchedSet), for: .touchUpInside)
settings.setImage(UIImage(named: "play_48px"), for: .normal)
settings.frame = CGRect(x:200, y:200 , width: 50, height: 50)
_view.addSubview(settings)
}

if event.type == IMAAdEventType.TAPPED {
// You can also add allow the user to tap anywhere on the Ad to resume play
if(!adsManager.adPlaybackInfo.isPlaying) {
adsManager.resume()
}
}

}

public func adsManager(_ adsManager: IMAAdsManager, didReceive error: IMAAdError) {
// Something went wrong with the ads manager after ads were loaded.  Log the error and play the
// content.
print("AdsManager error: \(error.message ?? "nil")")
playerView.resume()
controlView.isHidden = false

}

public func adsManagerDidRequestContentPause(_ adsManager: IMAAdsManager) {
// The SDK is going to play ads, so pause the content.
playerView.pause(reason: .userInteraction)
controlView.isHidden = true

}

public func adsManagerDidRequestContentResume(_ adsManager: IMAAdsManager) {
// The SDK is done playing ads (at least for now), so resume the content.
print("AdsManager resume: \("nil")")
playerView.resume()
controlView.isHidden = false

}
}

extension UIApplication {
class func topViewController(controller: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
if let navigationController = controller as? UINavigationController {
return topViewController(controller: navigationController.visibleViewController)
}
if let tabController = controller as? UITabBarController {
if let selected = tabController.selectedViewController {
return topViewController(controller: selected)
}
}
if let presented = controller?.presentedViewController {
return topViewController(controller: presented)
}
return controller
}
}
и
GSPlayerControlUIView.swift:

Код: Выделить всё

import UIKit
import CoreMedia
import GSPlayer
import Flutter
import MediaPlayer

protocol fullScreeenDelegate: class {
func fullScreenTap()
func normalScreenTap()
func backButtonTap()

}

@IBDesignable
class GSPlayerControlUIView: UIView {

// MARK: IBOutlet
@IBOutlet weak var play_Button: UIButton!
@IBOutlet weak var duration_Slider: UISlider!
@IBOutlet weak var currentDuration_Label: UILabel!
@IBOutlet weak var totalDuration_Label: UILabel!
@IBOutlet weak var fullscreen_Button : UIButton!
@IBOutlet weak var backButton: UIButton!
@IBOutlet weak var volume_Slider: UISlider!
@IBOutlet weak var brightness_Slider: UISlider!

weak var delegate: fullScreeenDelegate?
var isFullScreen = false

// MARK: Variables
private var videoPlayer: VideoPlayerView!

// MARK: Listeners
var onStateDidChanged: ((VideoPlayerView.State) ->  Void)?

override init(frame: CGRect) {
super.init(frame: frame)
self.commonInit()
}

required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.commonInit()
}

override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
self.commonInit()
}

func commonInit() {
guard let view = Bundle(for: GSPlayerControlUIView.self).loadNibNamed("GSPlayerControlUIView", owner: self, options: nil)?.first as? UIView else { return }

view.frame = self.bounds
view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.isUserInteractionEnabled = false

self.addSubview(view)
// Set the image for the back button
backButton.setImage(UIImage(named: "backbutton"), for: .normal)
}
}

// MARK: Functions
extension GSPlayerControlUIView {

func populate(with videoPlayer: VideoPlayerView) {
self.videoPlayer = videoPlayer
self.isUserInteractionEnabled = true

setPeriodicTimer()
setOnClicked_VideoPlayer()
setStateDidChangedListener()

duration_Slider.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tapSlider(_:))))
}

private func setStateDidChangedListener()  {
videoPlayer.stateDidChanged = { [weak self] state in
guard let self = self else { return }

if case .playing = state {
self.setOnStartPlaying()
}

switch state {
case .playing, .paused: self.duration_Slider.isEnabled = true
default: self.duration_Slider.isEnabled = false
}

self.play_Button.setImage(state == .playing ? UIImage(named: "pause_48px") : UIImage(named: "play_48px"), for: .normal)

if let listener = self.onStateDidChanged { listener(state) }
}

videoPlayer.replay = { [weak self] in
if self != nil
{
self!.currentDuration_Label.text = "00:00"
self!.duration_Slider.setValue(0, animated: false)
}
}
}

private func setOnStartPlaying() {
let totalDuration = videoPlayer.totalDuration

duration_Slider.maximumValue = Float(totalDuration)
totalDuration_Label.text = getTimeString(seconds: Int(totalDuration))
}

private func setPeriodicTimer() {
videoPlayer.addPeriodicTimeObserver(forInterval: CMTime(seconds: 1, preferredTimescale: 60), using: { [weak self] _ in
if self != nil
{
let currentDuration = self!.videoPlayer.currentDuration
self!.currentDuration_Label.text = self!.getTimeString(seconds: Int(currentDuration))
self!.duration_Slider.setValue(Float(currentDuration), animated: true)
}
})
}

private func getTimeString(seconds: Int) ->  String {
String(format: "%02d:%02d", seconds / 60, seconds % 60)
}

}

// MARK: onClicked
extension GSPlayerControlUIView {
@IBAction func backButtonTapped(_ sender: UIButton) {
delegate?.backButtonTap()
}

@IBAction func onClicked_Play(_ sender: Any) {
if (videoPlayer.state == .playing) {
videoPlayer.pause(reason: .userInteraction)
} else {
videoPlayer.resume()
}
}

@IBAction func onClicked_Backward(_ sender: Any) {
videoPlayer.seek(to: CMTime(seconds: Double(max(videoPlayer.currentDuration - 10, 0)), preferredTimescale: 60))
}

@IBAction func onClicked_Forward(_ sender: Any) {
videoPlayer.seek(to: CMTime(seconds: Double(min(videoPlayer.currentDuration + 10, videoPlayer.totalDuration)), preferredTimescale: 60))
}

@IBAction func onClicked_FullScreen(_ sender: Any) {

if isFullScreen == false{
delegate?.fullScreenTap()
isFullScreen = true
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.myOrientation = .landscapeLeft
UIDevice.current.setValue(UIInterfaceOrientation.landscapeLeft.rawValue, forKey: "orientation")
UIView.setAnimationsEnabled(true)
self.fullscreen_Button.setImage(UIImage(named: "normal_screen"), for: .normal)
}else{
isFullScreen = false
delegate?.normalScreenTap()
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.myOrientation = .portrait
self.fullscreen_Button.setImage(UIImage(named: "full_screen"), for: .normal)
}

}

private func setOnClicked_VideoPlayer() {
videoPlayer.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(onClicked_Video(_:))))
}

@IBAction func onClicked_Video(_ sender: Any) {
UIView.animate(withDuration: 0.2) {
self.alpha = self.alpha == 0 ? 1 : 0
}
}

@IBAction func tapSlider(_ gestureRecognizer: UIGestureRecognizer) {
let pointTapped: CGPoint = gestureRecognizer.location(in: self)

let positionOfSlider: CGPoint = duration_Slider.frame.origin
let widthOfSlider: CGFloat = duration_Slider.frame.size.width
let newValue = ((pointTapped.x - positionOfSlider.x) * CGFloat(duration_Slider.maximumValue) / widthOfSlider)

duration_Slider.setValue(Float(newValue), animated: false)
onValueChanged_DurationSlider(duration_Slider)
}

@IBAction func onValueChanged_DurationSlider(_ sender: UISlider) {
videoPlayer.seek(to: CMTime(seconds: Double(sender.value), preferredTimescale: 60))
}
}
Проблема:
Видео не запускается автоматически, а реклама не воспроизводится должным образом перед основным контентом. Хотя если пользователь нажимает кнопку воспроизведения, все работает как положено.
Я пробовал много вещей, но ничего не работает.
  • Убедились, что URL-адреса видео и объявлений действительны.
  • Проверили настройкуadsLoader иadsManager.


Подробнее здесь: https://stackoverflow.com/questions/785 ... r-and-goog
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «IOS»