Skip to content

Commit

Permalink
Updating exapmle iOS SDK and Adapter to show the use of native video.
Browse files Browse the repository at this point in the history
  • Loading branch information
maninomula committed May 8, 2018
1 parent 1f8c375 commit 541df5c
Show file tree
Hide file tree
Showing 15 changed files with 242 additions and 62 deletions.
2 changes: 1 addition & 1 deletion example/Adapter/SampleAdapter.m
Expand Up @@ -216,7 +216,7 @@ - (GADNativeAdViewAdOptions *)nativeAdViewAdOptions {

/// Initializes and returns a sample adapter with a reward based video ad connector.
- (instancetype)initWithRewardBasedVideoAdNetworkConnector:
(id<GADMRewardBasedVideoAdNetworkConnector>)connector {
(id<GADMRewardBasedVideoAdNetworkConnector>)connector {
if (!connector) {
return nil;
}
Expand Down
14 changes: 13 additions & 1 deletion example/Adapter/SampleAdapterMediatedNativeAd.m
Expand Up @@ -47,6 +47,7 @@ @interface SampleAdapterMediatedNativeAd () <GADMediatedNativeAdDelegate>
@property(nonatomic, copy) NSDictionary *extras;
@property(nonatomic, strong) GADNativeAdViewAdOptions *nativeAdViewAdOptions;
@property(nonatomic, strong) SampleAdInfoView *adInfoView;
@property(nonatomic, strong) SampleMediaView *mediaView;

@end

Expand Down Expand Up @@ -77,7 +78,7 @@ - (instancetype)initWithSampleNativeAd:(SampleNativeAd *)sampleNativeAd
NSURL *iconURL = [[NSURL alloc] initFileURLWithPath:_sampleAd.iconURL];
_mappedIcon = [[GADNativeAdImage alloc] initWithURL:iconURL scale:_sampleAd.iconScale];
}

_mediaView = _sampleAd.mediaView;
_nativeAdViewAdOptions = nativeAdViewAdOptions;

// The sample SDK provides an AdChoices view (SampleAdInfoView). If your SDK provides image
Expand All @@ -88,6 +89,14 @@ - (instancetype)initWithSampleNativeAd:(SampleNativeAd *)sampleNativeAd
return self;
}

- (BOOL)hasVideoContent {
return self.sampleAd.mediaView != nil;
}

- (UIView *)mediaView {
return _mediaView;
}

- (NSString *)advertiser {
return self.sampleAd.advertiser;
}
Expand Down Expand Up @@ -180,6 +189,9 @@ - (void)didRenderInView:(UIView *)view
viewController:(UIViewController *)viewController {
// This method is called when the native ad view is rendered. Here you would pass the UIView back
// to the mediated network's SDK.

// Playing video using SampleMediaView's playVideo method
[_sampleAd playVideo];
}

- (void)didUntrackView:(UIView *)view {
Expand Down
13 changes: 12 additions & 1 deletion example/CustomEvent/SampleMediatedNativeAd.m
Expand Up @@ -45,6 +45,7 @@ @interface SampleMediatedNativeAd ()
@property(nonatomic, copy) NSDictionary *extras;
@property(nonatomic, strong) GADNativeAdViewAdOptions *nativeAdViewAdOptions;
@property(nonatomic, strong) SampleAdInfoView *adInfoView;
@property(nonatomic, strong) SampleMediaView *mediaView;

@end

Expand Down Expand Up @@ -75,7 +76,7 @@ - (instancetype)initWithSampleNativeAd:(SampleNativeAd *)sampleNativeAd
NSURL *iconURL = [[NSURL alloc] initFileURLWithPath:_sampleAd.iconURL];
_mappedIcon = [[GADNativeAdImage alloc] initWithURL:iconURL scale:_sampleAd.iconScale];
}

_mediaView = _sampleAd.mediaView;
_nativeAdViewAdOptions = nativeAdViewAdOptions;

// The sample SDK provides an AdChoices view (SampleAdInfoView). If your SDK provides image
Expand All @@ -86,6 +87,14 @@ - (instancetype)initWithSampleNativeAd:(SampleNativeAd *)sampleNativeAd
return self;
}

- (BOOL)hasVideoContent {
return self.sampleAd.mediaView != nil;
}

- (UIView *)mediaView {
return _mediaView;
}

- (NSString *)advertiser {
return self.sampleAd.advertiser;
}
Expand Down Expand Up @@ -146,6 +155,8 @@ - (void)didRenderInView:(UIView *)view
viewController:(UIViewController *)viewController {
// This method is called when the native ad view is rendered. Here you would pass the UIView back
// to the mediated network's SDK.
// Playing video using SampleNativeAd's playVideo method
[_sampleAd playVideo];
}

- (void)didUntrackView:(UIView *)view {
Expand Down
71 changes: 33 additions & 38 deletions example/CustomEventSwift/SampleCustomEventNativeAdSwift.swift
Expand Up @@ -21,19 +21,19 @@ import GoogleMobileAds
import SampleAdSDK

/// Constant for Sample Ad Network custom event error domain.
private let customEventErrorDomain: String = "com.google.CustomEvent"
private let customEventErrorDomain : String = "com.google.CustomEvent"

class SampleCustomEventNativeAdSwift: NSObject, GADCustomEventNativeAd {
class SampleCustomEventNativeAdSwift : NSObject, GADCustomEventNativeAd {
/// Native ad view options.
fileprivate var nativeAdViewAdOptions: GADNativeAdViewAdOptions?

var delegate: GADCustomEventNativeAdDelegate?

func request(withParameter serverParameter: String, request: GADCustomEventRequest,
adTypes: [Any], options: [Any], rootViewController: UIViewController) {

fileprivate var nativeAdViewAdOptions : GADNativeAdViewAdOptions?
var delegate : GADCustomEventNativeAdDelegate?
func request(withParameter serverParameter : String,
request : GADCustomEventRequest,
adTypes : [Any],
options : [Any],
rootViewController : UIViewController) {
let requestedUnified: Bool =
adTypes.contains(where: { $0 as? GADAdLoaderAdType == .unifiedNative})
adTypes.contains(where: { $0 as? GADAdLoaderAdType == .unifiedNative})

// This custom event assumes you have implemented unified native advanced in your app as is done
// in this sample. If you have implemented app install and content ad formats in your app,
Expand All @@ -50,7 +50,6 @@ class SampleCustomEventNativeAdSwift: NSObject, GADCustomEventNativeAd {
delegate?.customEventNativeAd(self, didFailToLoadWithError: error)
return
}

let adLoader = SampleNativeAdLoader()
let sampleRequest = SampleNativeAdRequest()

Expand All @@ -65,56 +64,52 @@ class SampleCustomEventNativeAdSwift: NSObject, GADCustomEventNativeAd {
sampleRequest.preferredImageOrientation = NativeAdImageOrientation.any
sampleRequest.shouldRequestMultipleImages = false
if let options = options as? [GADAdLoaderOptions] {
for loaderOptions: GADAdLoaderOptions in options {
for loaderOptions:GADAdLoaderOptions in options {
if let imageOptions = loaderOptions as? GADNativeAdImageAdLoaderOptions {
switch imageOptions.preferredImageOrientation {
case GADNativeAdImageAdLoaderOptionsOrientation.landscape:
sampleRequest.preferredImageOrientation = NativeAdImageOrientation.landscape
case GADNativeAdImageAdLoaderOptionsOrientation.portrait:
sampleRequest.preferredImageOrientation = NativeAdImageOrientation.portrait
default:
sampleRequest.preferredImageOrientation = NativeAdImageOrientation.any
switch imageOptions.preferredImageOrientation{
case GADNativeAdImageAdLoaderOptionsOrientation.landscape:
sampleRequest.preferredImageOrientation = NativeAdImageOrientation.landscape
case GADNativeAdImageAdLoaderOptionsOrientation.portrait :
sampleRequest.preferredImageOrientation = NativeAdImageOrientation.portrait
default:
sampleRequest.preferredImageOrientation = NativeAdImageOrientation.any
}
sampleRequest.shouldRequestMultipleImages = imageOptions.shouldRequestMultipleImages
// If the GADNativeAdImageAdLoaderOptions' disableImageLoading property is YES, the
// adapter should send just the URLs for the images.
// If the GADNativeAdImageAdLoaderOptions' disableImageLoading property is
// YES, the adapter should send just the URLs for the images.
sampleRequest.shouldDownloadImages = !imageOptions.disableImageLoading
}
else if let options = loaderOptions as? GADNativeAdViewAdOptions {
nativeAdViewAdOptions = options
}
}
}

// This custom event uses the server parameter to carry an ad unit ID, which is the most common
// use case.
adLoader.adUnitID = serverParameter
adLoader.delegate = self
adLoader.fetchAd(sampleRequest)
}
// This custom event uses the server parameter to carry an ad unit ID, which is the most common
// use case.
adLoader.adUnitID = serverParameter
adLoader.delegate = self
adLoader.fetchAd(sampleRequest)
}

// Indicates if the custom event handles user clicks. Return YES if the custom event should handle
// user clicks.
func handlesUserClicks() -> Bool {
func handlesUserClicks() -> Bool{
return true
}

func handlesUserImpressions() -> Bool {
return false
}
}

extension SampleCustomEventNativeAdSwift: SampleNativeAdLoaderDelegate {

func adLoader(_ adLoader: SampleNativeAdLoader, didReceive nativeAd: SampleNativeAd) {
extension SampleCustomEventNativeAdSwift : SampleNativeAdLoaderDelegate {
func adLoader(_ adLoader : SampleNativeAdLoader, didReceive nativeAd : SampleNativeAd){
let mediatedAd = SampleMediatedUnifiedNativeAdSwift(
sampleNativeAd:nativeAd,nativeAdViewAdOptions: nativeAdViewAdOptions)
delegate?.customEventNativeAd(self, didReceive: mediatedAd)
sampleNativeAd : nativeAd, nativeAdViewAdOptions : nativeAdViewAdOptions)
delegate?.customEventNativeAd(self, didReceive : mediatedAd)
}

func adLoader(_ adLoader: SampleNativeAdLoader, didFailToLoadAdWith errorCode: SampleErrorCode) {
let error = NSError(domain: customEventErrorDomain, code: errorCode.rawValue, userInfo: nil)
func adLoader(_ adLoader : SampleNativeAdLoader, didFailToLoadAdWith errorCode : SampleErrorCode) {
let error = NSError(domain : customEventErrorDomain, code : errorCode.rawValue, userInfo : nil)
delegate?.customEventNativeAd(self, didFailToLoadWithError: error)
}

}
39 changes: 24 additions & 15 deletions example/CustomEventSwift/SampleMediatedNativeAdSwift.swift
Expand Up @@ -25,7 +25,7 @@ import SampleAdSDK
/// by a mediated network don't always line up with the ones expected by the Google
/// Mobile Ads SDK (one might have "title" while the other expects "headline," for
/// example). It's the job of this "mapper" class to smooth out those wrinkles.
class SampleMediatedUnifiedNativeAdSwift: NSObject {
class SampleMediatedUnifiedNativeAdSwift : NSObject {
// You may notice that this class and the Mediation Adapter's
// SampleAdapterMediatedNativeAd class look an awful lot alike. That's not
// by accident. They're the same class, with the same methods and properties,
Expand All @@ -43,41 +43,39 @@ class SampleMediatedUnifiedNativeAdSwift: NSObject {
// share code between them), they each get their own copies of this class,
// with slightly different names.

var sampleAd: SampleNativeAd
var sampleAd : SampleNativeAd
var mappedImages = [GADNativeAdImage]()
var mappedIcon: GADNativeAdImage?
var extras = [String: Any]()
var extras = [String:Any]()
var nativeAdViewAdOptions: GADNativeAdViewAdOptions?
let adInfoView = SampleAdInfoView()

init(sampleNativeAd: SampleNativeAd, nativeAdViewAdOptions: GADNativeAdViewAdOptions?) {

var sampleMediaView : SampleMediaView?
init(sampleNativeAd : SampleNativeAd, nativeAdViewAdOptions : GADNativeAdViewAdOptions?) {
sampleAd = sampleNativeAd
super.init()

extras = [SampleCustomEventConstantsSwift.awesomenessKey: sampleAd.degreeOfAwesomeness ?? ""]
if let image = sampleAd.image {
mappedImages = [GADNativeAdImage(image: image)]
mappedImages = [GADNativeAdImage(image : image)]
}
else {
let imageUrl = URL(fileURLWithPath: sampleAd.imageURL)
mappedImages = [GADNativeAdImage(url: imageUrl, scale: sampleAd.imageScale)]
let imageUrl = URL(fileURLWithPath : sampleAd.imageURL)
mappedImages = [GADNativeAdImage(url : imageUrl, scale : sampleAd.imageScale)]
}
if let icon = sampleAd.icon {
mappedIcon = GADNativeAdImage(image: icon)
mappedIcon = GADNativeAdImage(image : icon)
}
else {
let iconURL = URL(fileURLWithPath: sampleNativeAd.iconURL)
mappedIcon = GADNativeAdImage(url: iconURL, scale: sampleAd.iconScale)
let iconURL = URL(fileURLWithPath : sampleNativeAd.iconURL)
mappedIcon = GADNativeAdImage(url : iconURL, scale : sampleAd.iconScale)
}
self.nativeAdViewAdOptions = nativeAdViewAdOptions
self.sampleMediaView = self.sampleAd.mediaView
}

}

/// This is a concrete implementation for the GADMediatedUnifiedNativeAd protocol.
extension SampleMediatedUnifiedNativeAdSwift : GADMediatedUnifiedNativeAd {

var advertiser : String? {
return sampleAd.advertiser
}
Expand Down Expand Up @@ -122,6 +120,14 @@ extension SampleMediatedUnifiedNativeAdSwift : GADMediatedUnifiedNativeAd {
return extras
}

var mediaView : UIView?{
return self.sampleMediaView!
}

var hasVideoContent : Bool {
return self.sampleAd.mediaView != nil
}

func didRecordImpression() {
sampleAd.recordImpression()
}
Expand All @@ -134,9 +140,12 @@ extension SampleMediatedUnifiedNativeAdSwift : GADMediatedUnifiedNativeAd {
// one.
// You can also access the clickable and non-clickable views by asset key if the mediation network
// needs this information.
func didRender(in view: UIView, clickableAssetViews: [GADUnifiedNativeAssetIdentifier : UIView], nonclickableAssetViews: [GADUnifiedNativeAssetIdentifier : UIView], viewController: UIViewController) {
func didRender(in view: UIView, clickableAssetViews: [GADUnifiedNativeAssetIdentifier : UIView],
nonclickableAssetViews: [GADUnifiedNativeAssetIdentifier : UIView],
viewController: UIViewController) {
// This method is called when the native ad view is rendered. Here you would pass the UIView
// back to the mediated network's SDK.
self.sampleAd.mediaView.playMedia()
}

func didRecordClickOnAsset(withName assetName: GADUnifiedNativeAssetIdentifier, view: UIView, viewController: UIViewController) {
Expand Down
15 changes: 13 additions & 2 deletions example/MediationExample/Base.lproj/ExampleUnifiedNativeAdView.xib
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="13529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13527"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
Expand Down Expand Up @@ -36,6 +36,13 @@
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Hda-Ug-PYB" customClass="GADMediaView">
<rect key="frame" x="139" y="113" width="125" height="190"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="width" constant="125" id="rit-OI-xCL"/>
</constraints>
</view>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="749" translatesAutoresizingMaskIntoConstraints="NO" id="5Jr-ya-pzP">
<rect key="frame" x="77" y="113" width="250" height="191.5"/>
<constraints>
Expand Down Expand Up @@ -82,15 +89,18 @@
</subviews>
<color key="backgroundColor" red="1" green="0.98303861469999998" blue="0.92887652860000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="535-ao-Wpn" firstAttribute="top" secondItem="Hda-Ug-PYB" secondAttribute="bottom" constant="14" id="3gm-NU-3I4"/>
<constraint firstItem="YvW-AW-TS7" firstAttribute="centerY" secondItem="535-ao-Wpn" secondAttribute="centerY" id="5xC-dh-i9m"/>
<constraint firstItem="535-ao-Wpn" firstAttribute="leading" secondItem="YvW-AW-TS7" secondAttribute="trailing" constant="10" id="5xT-tW-Osy"/>
<constraint firstItem="5Jr-ya-pzP" firstAttribute="top" secondItem="u7E-wE-IMf" secondAttribute="bottom" constant="5" id="65W-xU-AH1"/>
<constraint firstItem="xyD-2P-hRw" firstAttribute="leading" secondItem="ugI-Xx-RYZ" secondAttribute="trailing" id="8AZ-wo-Hzt"/>
<constraint firstItem="LNP-UZ-QTS" firstAttribute="leading" secondItem="u7E-wE-IMf" secondAttribute="leading" id="8ZB-fn-ueW"/>
<constraint firstItem="Hda-Ug-PYB" firstAttribute="centerX" secondItem="Bh8-Dc-RmY" secondAttribute="centerX" id="Bx2-XQ-Ssr"/>
<constraint firstItem="u7E-wE-IMf" firstAttribute="top" secondItem="LNP-UZ-QTS" secondAttribute="bottom" constant="8" symbolic="YES" id="E1U-ka-9x2"/>
<constraint firstAttribute="centerX" secondItem="w2N-Br-VLs" secondAttribute="centerX" id="Fat-Ub-qsX"/>
<constraint firstItem="YvW-AW-TS7" firstAttribute="top" secondItem="5Jr-ya-pzP" secondAttribute="bottom" constant="12.5" id="JTf-JU-kmF"/>
<constraint firstItem="w2N-Br-VLs" firstAttribute="top" secondItem="oCo-Xo-px8" secondAttribute="bottom" constant="-2" id="Je7-ZP-ZkL"/>
<constraint firstItem="Hda-Ug-PYB" firstAttribute="top" secondItem="u7E-wE-IMf" secondAttribute="bottom" constant="4.5" id="NEV-d3-CUC"/>
<constraint firstAttribute="bottom" secondItem="w2N-Br-VLs" secondAttribute="bottom" constant="20" symbolic="YES" id="NWy-ru-SNd"/>
<constraint firstItem="oCo-Xo-px8" firstAttribute="centerY" secondItem="535-ao-Wpn" secondAttribute="centerY" id="Rew-8u-f5C"/>
<constraint firstItem="oCo-Xo-px8" firstAttribute="leading" secondItem="535-ao-Wpn" secondAttribute="trailing" constant="10" id="WKw-NK-6Aj"/>
Expand All @@ -116,6 +126,7 @@
<outlet property="headlineView" destination="D79-55-6Yx" id="XNd-ZR-1Ra"/>
<outlet property="iconView" destination="LNP-UZ-QTS" id="6de-cc-ROY"/>
<outlet property="imageView" destination="5Jr-ya-pzP" id="NZh-vs-Sqf"/>
<outlet property="mediaView" destination="Hda-Ug-PYB" id="YFn-6z-8wQ"/>
<outlet property="priceView" destination="YvW-AW-TS7" id="Fr8-QF-yeG"/>
<outlet property="starRatingView" destination="xyD-2P-hRw" id="JzO-tB-4a6"/>
<outlet property="storeView" destination="535-ao-Wpn" id="Y6B-L6-Le1"/>
Expand Down
17 changes: 15 additions & 2 deletions example/MediationExample/ViewController.m
Expand Up @@ -171,12 +171,25 @@ - (void)adLoader:(GADAdLoader *)adLoader didReceiveUnifiedNativeAd:(GADUnifiedNa

[self replaceNativeAdView:nativeAdView inPlaceholder:placeholder];

if (nativeAd.videoController.hasVideoContent) {
nativeAdView.imageView.hidden = YES;
nativeAdView.mediaView.contentMode = UIViewContentModeScaleAspectFit;
nativeAdView.mediaView.hidden = NO;
} else {
nativeAdView.imageView.hidden = NO;
nativeAdView.mediaView.hidden = YES;
GADNativeAdImage *image = nativeAd.images.firstObject;
if (image != nil) {
((UIImageView *)nativeAdView.imageView).image = image.image;
}
}

// Populate the native ad view with the native ad assets.
// Some assets are guaranteed to be present in every native ad.
((UILabel *)nativeAdView.headlineView).text = nativeAd.headline;
((UILabel *)nativeAdView.bodyView).text = nativeAd.body;
[((UIButton *)nativeAdView.callToActionView)setTitle:nativeAd.callToAction
forState:UIControlStateNormal];
[((UIButton *)nativeAdView.callToActionView) setTitle:nativeAd.callToAction
forState:UIControlStateNormal];

GADNativeAdImage *image = nativeAd.images.firstObject;
if (image != nil) {
Expand Down

0 comments on commit 541df5c

Please sign in to comment.