Skip to content

Commit

Permalink
InstreamVideo Implementation (#333)
Browse files Browse the repository at this point in the history
* instream research

* updates

* Instream code added

* added utils

* review comment fixes

* removed instream adUnit

* updated adtag url

* added adSlot size logic

* added tests for sizes

* removed unwanted changes

* Rubicon in-stream was added (#337)

* modified API name insyc with android

* adsManager.destroy was added (#338)

* included content player logic in sample

* [Not Master] Some improvements for In-Stream video (#339)

* adsManager.destroy was added

* - removed redundant `viewDidDisappear`
- fixed `Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value`
- minor refactoring
- play video if some error was occurred
- Rubicon setup was separated

Co-authored-by: Alex <[email protected]>
  • Loading branch information
ppuviarasu and yoalex5 authored Dec 3, 2020
1 parent 9ca2c2f commit fea8da4
Show file tree
Hide file tree
Showing 11 changed files with 480 additions and 47 deletions.
4 changes: 4 additions & 0 deletions Example/PrebidDemo/PrebidDemo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

/* Begin PBXBuildFile section */
357880CCDA9464E1BC8B6ACE /* Pods_PrebidDemoSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF0177D90B948D57DD24AEB9 /* Pods_PrebidDemoSwift.framework */; };
6069716C25224655000EE732 /* InstreamVideoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6069716B25224655000EE732 /* InstreamVideoViewController.swift */; };
609C52C32395F17F001FA5BD /* NativeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 609C52C22395F17F001FA5BD /* NativeViewController.swift */; };
C7A1F0B942F152B467C71A70 /* Pods_PrebidDemoObjectiveC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0B64CCFCC9D513DEAA95A372 /* Pods_PrebidDemoObjectiveC.framework */; };
DADFB9F410588613B69275BC /* Pods_PrebidDemoTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5976732304BFCF6E222040EE /* Pods_PrebidDemoTests.framework */; };
Expand Down Expand Up @@ -116,6 +117,7 @@
55EA1793258A4B187A300E8E /* Pods-PrebidDemoSwift-PrebidDemoSwiftTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PrebidDemoSwift-PrebidDemoSwiftTests.release.xcconfig"; path = "Target Support Files/Pods-PrebidDemoSwift-PrebidDemoSwiftTests/Pods-PrebidDemoSwift-PrebidDemoSwiftTests.release.xcconfig"; sourceTree = "<group>"; };
5976732304BFCF6E222040EE /* Pods_PrebidDemoTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PrebidDemoTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
5CA527E4B4E05598C6D7B462 /* Pods-PrebidDemoTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PrebidDemoTests.debug.xcconfig"; path = "Target Support Files/Pods-PrebidDemoTests/Pods-PrebidDemoTests.debug.xcconfig"; sourceTree = "<group>"; };
6069716B25224655000EE732 /* InstreamVideoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = InstreamVideoViewController.swift; path = ../../../example/PrebidDemo/PrebidDemoSwift/InstreamVideoViewController.swift; sourceTree = "<group>"; };
609C52C22395F17F001FA5BD /* NativeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = NativeViewController.swift; path = ../../../example/PrebidDemo/PrebidDemoSwift/NativeViewController.swift; sourceTree = "<group>"; };
658745FEE114707D845BCCDA /* Pods-PrebidDemoPodTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PrebidDemoPodTests.release.xcconfig"; path = "Target Support Files/Pods-PrebidDemoPodTests/Pods-PrebidDemoPodTests.release.xcconfig"; sourceTree = "<group>"; };
6CD6AD93320513F54EF922A8 /* Pods-PrebidDemoPodTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PrebidDemoPodTests.debug.xcconfig"; path = "Target Support Files/Pods-PrebidDemoPodTests/Pods-PrebidDemoPodTests.debug.xcconfig"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -272,6 +274,7 @@
FA12E4CB231EB3F000CAA05B /* InterstitialViewController.swift */,
609C52C22395F17F001FA5BD /* NativeViewController.swift */,
FA7E552F239E87FA0063B028 /* RewardedVideoController.swift */,
6069716B25224655000EE732 /* InstreamVideoViewController.swift */,
FA12E4BA231EB04100CAA05B /* Main.storyboard */,
FA12E4BD231EB04200CAA05B /* Assets.xcassets */,
FA12E4BF231EB04200CAA05B /* LaunchScreen.storyboard */,
Expand Down Expand Up @@ -583,6 +586,7 @@
buildActionMask = 2147483647;
files = (
FA12E4D0231EB3F000CAA05B /* IndexController.swift in Sources */,
6069716C25224655000EE732 /* InstreamVideoViewController.swift in Sources */,
FA12E4D1231EB3F000CAA05B /* BannerController.swift in Sources */,
FA7E5530239E87FA0063B028 /* RewardedVideoController.swift in Sources */,
FA12E4B7231EB04100CAA05B /* AppDelegate.swift in Sources */,
Expand Down
105 changes: 88 additions & 17 deletions Example/PrebidDemo/PrebidDemoSwift/Base.lproj/Main.storyboard

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions Example/PrebidDemo/PrebidDemoSwift/IndexController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ class IndexController: UIViewController {

case let vc as RewardedVideoController:
vc.adServerName = adServerName

case let vc as InstreamVideoViewController:
vc.adServerName = adServerName

default:
print("wrong controller")
Expand Down
218 changes: 218 additions & 0 deletions Example/PrebidDemo/PrebidDemoSwift/InstreamVideoViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
/* Copyright 2018-2019 Prebid.org, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import UIKit
import GoogleInteractiveMediaAds
import PrebidMobile

class InstreamVideoViewController: UIViewController, IMAAdsLoaderDelegate, IMAAdsManagerDelegate {

@IBOutlet var adServerLabel: UILabel!

@IBOutlet var appInstreamView: UIView!
@IBOutlet weak var playButton: UIButton!

var adServerName: String = ""
let parameters = VideoBaseAdUnit.Parameters()
var adUnitID: String!

private var adUnit: VideoAdUnit!

var adsLoader: IMAAdsLoader!
var adsManager: IMAAdsManager?

var contentPlayer: AVPlayer?
var playerLayer: AVPlayerLayer?

var contentPlayhead: IMAAVPlayerContentPlayhead?

static let kTestAppContentUrl_MP4 = "https://storage.googleapis.com/gvabox/media/samples/stock.mp4"

override func viewDidLoad() {
super.viewDidLoad()
playButton.layer.zPosition = CGFloat.greatestFiniteMagnitude
adServerLabel.text = adServerName
setUpContentPlayer()
}

override func viewDidDisappear(_ animated: Bool) {
playerLayer?.frame = self.appInstreamView.layer.bounds
adsManager?.destroy()
contentPlayer?.pause()
contentPlayer = nil
}

@IBAction func onPlayButtonTouch(_ sender: AnyObject) {
if (adServerName == "DFP") {
setupAndLoadAMInstreamVideo()

} else if (adServerName == "MoPub") {
contentPlayer?.play()
print("mopub not supported")
}

playButton.isHidden = true
}

func setUpContentPlayer() {
// Load AVPlayer with path to our content.
guard let contentURL = URL(string: InstreamVideoViewController.kTestAppContentUrl_MP4) else {
print("ERROR: please use a valid URL for the content URL")
return
}
contentPlayer = AVPlayer(url: contentURL)

// Create a player layer for the player.
playerLayer = AVPlayerLayer(player: contentPlayer)

// Size, position, and display the AVPlayer.
playerLayer?.frame = appInstreamView.layer.bounds
appInstreamView.layer.addSublayer(playerLayer!)

// Set up our content playhead and contentComplete callback.
contentPlayhead = IMAAVPlayerContentPlayhead(avPlayer: contentPlayer)
NotificationCenter.default.addObserver(
self,
selector: #selector(InstreamVideoViewController.contentDidFinishPlaying(_:)),
name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,
object: contentPlayer?.currentItem)
}

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

func setupAndLoadAMInstreamVideo() {
setupVideoParameters()

//AppNexus
// setupPBAppNexusInStreamVideo()
// setupAMAppNexusInstreamVideo()

//Rubicon
setupPBRubiconInStreamVideo()
setupAMRubiconInstreamVideo()

loadAMInStreamVideo()
}

func setupVideoParameters() {
parameters.mimes = ["video/mp4"]
parameters.protocols = [Signals.Protocols.VAST_2_0]
parameters.playbackMethod = [Signals.PlaybackMethod.AutoPlaySoundOn]
}

//Setup PB
func setupPBAppNexusInStreamVideo() {
setupPB(host: .Appnexus, accountId: "aecd6ef7-b992-4e99-9bb8-65e2d984e1dd", storedResponse: "")

let videoAdUnit = VideoAdUnit(configId: "2c0af852-a55d-49dc-a5ca-ef7e141f73cc", size: CGSize(width: 1,height: 1))
videoAdUnit.parameters = parameters
adUnit = videoAdUnit
}

func setupPBRubiconInStreamVideo() {
setupPB(host: .Rubicon, accountId: "1001", storedResponse: "sample_video_response")

let videoAdUnit = VideoAdUnit(configId: "1001-1", size: CGSize(width: 1, height: 1))
videoAdUnit.parameters = parameters
adUnit = videoAdUnit
}

func setupPB(host: PrebidHost, accountId: String, storedResponse: String) {
Prebid.shared.prebidServerHost = host
Prebid.shared.prebidServerAccountId = accountId
Prebid.shared.storedAuctionResponse = storedResponse
}

//Setup AdServer
func setupAMAppNexusInstreamVideo() {
adUnitID = "/19968336/Punnaghai_Instream_Video1"
}

func setupAMRubiconInstreamVideo() {
adUnitID = "/5300653/test_adunit_vast_pavliuchyk"
}

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

adUnit.fetchDemand { (ResultCode, prebidKeys: [String : String]?) in
print("prebid keys")
if (ResultCode == .prebidDemandFetchSuccess){
do {
let adServerTag = try IMAUtils.shared.generateInstreamUriForGAM(adUnitID: self.adUnitID, adSlotSizes: [.Size640x480,.Size400x300], customKeywords: prebidKeys!)
let adDisplayContainer = IMAAdDisplayContainer(adContainer: self.appInstreamView)
// Create an ad request with our ad tag, display container, and optional user context.
let request = IMAAdsRequest(adTagUrl: adServerTag, adDisplayContainer: adDisplayContainer, contentPlayhead: nil, userContext: nil)
self.adsLoader.requestAds(with: request)
} catch {
print(error)
self.contentPlayer?.play()
}
} else {
print("Error constructing IMA Tag")
self.contentPlayer?.play()
}
}
}

//MARK: - IMAAdsLoaderDelegate
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.webOpenerPresentingController = self

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

func adsLoader(_ loader: IMAAdsLoader!, failedWith adErrorData: IMAAdLoadingErrorData!) {
print("Error loading ads: \(adErrorData.adError.message ?? "nil")")
contentPlayer?.play()
}

//MARK: - IMAAdsManagerDelegate
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()
}
}

func adsManager(_ adsManager: IMAAdsManager!, didReceive error: IMAAdError!) {
print("AdsManager error: \(error.message ?? "nil")")
contentPlayer?.play()
}

func adsManagerDidRequestContentPause(_ adsManager: IMAAdsManager!) {
// The SDK is going to play ads, so pause the content.
contentPlayer?.pause()
}

func adsManagerDidRequestContentResume(_ adsManager: IMAAdsManager!) {
// The SDK is done playing ads (at least for now), so resume the content.
contentPlayer?.play()
}

}
1 change: 1 addition & 0 deletions Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ def prebid_demo_pods

pod 'Google-Mobile-Ads-SDK'
pod 'mopub-ios-sdk'
pod 'GoogleAds-IMA-iOS-SDK'
end

target 'PrebidDemoSwift' do
Expand Down
64 changes: 34 additions & 30 deletions Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,30 +1,31 @@
PODS:
- Google-Mobile-Ads-SDK (7.66.0):
- GoogleAppMeasurement (~> 6.0)
- Google-Mobile-Ads-SDK (7.68.0):
- GoogleAppMeasurement (~> 7.0)
- GoogleUserMessagingPlatform (~> 1.1)
- GoogleAppMeasurement (6.8.3):
- GoogleUtilities/AppDelegateSwizzler (~> 6.7)
- GoogleUtilities/MethodSwizzler (~> 6.7)
- GoogleUtilities/Network (~> 6.7)
- "GoogleUtilities/NSData+zlib (~> 6.7)"
- nanopb (~> 1.30906.0)
- GoogleUserMessagingPlatform (1.2.0)
- GoogleUtilities/AppDelegateSwizzler (6.7.2):
- GoogleAds-IMA-iOS-SDK (3.11.3)
- GoogleAppMeasurement (7.1.0):
- GoogleUtilities/AppDelegateSwizzler (~> 7.0)
- GoogleUtilities/MethodSwizzler (~> 7.0)
- GoogleUtilities/Network (~> 7.0)
- "GoogleUtilities/NSData+zlib (~> 7.0)"
- nanopb (~> 2.30906.0)
- GoogleUserMessagingPlatform (1.4.0)
- GoogleUtilities/AppDelegateSwizzler (7.1.1):
- GoogleUtilities/Environment
- GoogleUtilities/Logger
- GoogleUtilities/Network
- GoogleUtilities/Environment (6.7.2):
- GoogleUtilities/Environment (7.1.1):
- PromisesObjC (~> 1.2)
- GoogleUtilities/Logger (6.7.2):
- GoogleUtilities/Logger (7.1.1):
- GoogleUtilities/Environment
- GoogleUtilities/MethodSwizzler (6.7.2):
- GoogleUtilities/MethodSwizzler (7.1.1):
- GoogleUtilities/Logger
- GoogleUtilities/Network (6.7.2):
- GoogleUtilities/Network (7.1.1):
- GoogleUtilities/Logger
- "GoogleUtilities/NSData+zlib"
- GoogleUtilities/Reachability
- "GoogleUtilities/NSData+zlib (6.7.2)"
- GoogleUtilities/Reachability (6.7.2):
- "GoogleUtilities/NSData+zlib (7.1.1)"
- GoogleUtilities/Reachability (7.1.1):
- GoogleUtilities/Logger
- mopub-ios-sdk (5.12.1):
- mopub-ios-sdk/MoPubSDK (= 5.12.1)
Expand All @@ -40,20 +41,22 @@ PODS:
- mopub-ios-sdk/NativeAds
- mopub-ios-sdk/NativeAds (5.12.1):
- mopub-ios-sdk/Core
- nanopb (1.30906.0):
- nanopb/decode (= 1.30906.0)
- nanopb/encode (= 1.30906.0)
- nanopb/decode (1.30906.0)
- nanopb/encode (1.30906.0)
- PromisesObjC (1.2.10)
- nanopb (2.30906.0):
- nanopb/decode (= 2.30906.0)
- nanopb/encode (= 2.30906.0)
- nanopb/decode (2.30906.0)
- nanopb/encode (2.30906.0)
- PromisesObjC (1.2.11)

DEPENDENCIES:
- Google-Mobile-Ads-SDK
- GoogleAds-IMA-iOS-SDK
- mopub-ios-sdk

SPEC REPOS:
trunk:
- Google-Mobile-Ads-SDK
- GoogleAds-IMA-iOS-SDK
- GoogleAppMeasurement
- GoogleUserMessagingPlatform
- GoogleUtilities
Expand All @@ -62,14 +65,15 @@ SPEC REPOS:
- PromisesObjC

SPEC CHECKSUMS:
Google-Mobile-Ads-SDK: 7d7074359c040f5add4e0963bf860e14690060d0
GoogleAppMeasurement: 966e88df9d19c15715137bb2ddaf52373f111436
GoogleUserMessagingPlatform: c85530d930ba509583aa5a6d50a10aca22cf8502
GoogleUtilities: 7f2f5a07f888cdb145101d6042bc4422f57e70b3
Google-Mobile-Ads-SDK: 29bbdb182d69ff606cc0301da1590b40be8d2205
GoogleAds-IMA-iOS-SDK: 134b35758455576aaa6b3d2d3146699dcf8af4f1
GoogleAppMeasurement: 89e1a64593f968713b0506ba1b53b38a154bf9a5
GoogleUserMessagingPlatform: b168e8c46cd8f92aa3e34b584c4ca78a411ce367
GoogleUtilities: 3dc4ff0d5e4840e2fa8eef0889620e8c33d4218c
mopub-ios-sdk: d1640225b34ad74700e2acddb116cac634fc45d8
nanopb: 59317e09cf1f1a0af72f12af412d54edf52603fc
PromisesObjC: b14b1c6b68e306650688599de8a45e49fae81151
nanopb: 1bf24dd71191072e120b83dd02d08f3da0d65e53
PromisesObjC: 8c196f5a328c2cba3e74624585467a557dcb482f

PODFILE CHECKSUM: 96585ca3984eaf5fa0b84ba62e751dd02e7386aa
PODFILE CHECKSUM: 3ac6b72b8e32e6b50d5524e6bbdc3864ec850fb0

COCOAPODS: 1.9.3
COCOAPODS: 1.10.0
Loading

0 comments on commit fea8da4

Please sign in to comment.