Skip to content

Commit

Permalink
Added swift preloading sample to APIDemo.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 689449591
  • Loading branch information
nventimigli authored and copybara-github committed Nov 4, 2024
1 parent f25aa31 commit 8ad04e7
Show file tree
Hide file tree
Showing 14 changed files with 577 additions and 6 deletions.
32 changes: 32 additions & 0 deletions Swift/advanced/APIDemo/APIDemo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
objects = {

/* Begin PBXBuildFile section */
1C04FB9F2CCACE7B00D6EEE6 /* AdmobPreloadView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1C04FB9D2CCACE7B00D6EEE6 /* AdmobPreloadView.xib */; };
1C04FBA02CCACE7B00D6EEE6 /* AdmobPreloadViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C04FB9E2CCACE7B00D6EEE6 /* AdmobPreloadViewController.swift */; };
1C04FBA12CCACE7B00D6EEE6 /* AdmobPreloadView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C04FB9C2CCACE7B00D6EEE6 /* AdmobPreloadView.swift */; };
1CD352682C9CC97200534FCC /* CustomControls.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1CD352672C9CC97200534FCC /* CustomControls.xib */; };
4A7A6CD71C76237500FB1A32 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A7A6CD61C76237500FB1A32 /* Constants.swift */; };
4AA7D6911C625A1200DFD2EB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AA7D6901C625A1200DFD2EB /* AppDelegate.swift */; };
Expand Down Expand Up @@ -34,6 +37,15 @@

/* Begin PBXFileReference section */
15CB61211C7D0256000212DE /* APIDemo-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "APIDemo-Bridging-Header.h"; sourceTree = "<group>"; };
1C04FB9C2CCACE7B00D6EEE6 /* AdmobPreloadView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdmobPreloadView.swift; sourceTree = "<group>"; };
1C04FB9D2CCACE7B00D6EEE6 /* AdmobPreloadView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AdmobPreloadView.xib; sourceTree = "<group>"; };
1C04FB9E2CCACE7B00D6EEE6 /* AdmobPreloadViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdmobPreloadViewController.swift; sourceTree = "<group>"; };
1C04FBA22CCACE8A00D6EEE6 /* GADAppOpenAd_Preview.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GADAppOpenAd_Preview.h; sourceTree = "<group>"; };
1C04FBA32CCACE8A00D6EEE6 /* GADInterstitialAd_Preview.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GADInterstitialAd_Preview.h; sourceTree = "<group>"; };
1C04FBA42CCACE8A00D6EEE6 /* GADMobileAds_Preview.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GADMobileAds_Preview.h; sourceTree = "<group>"; };
1C04FBA52CCACE8A00D6EEE6 /* GADPreloadConfiguration_Preview.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GADPreloadConfiguration_Preview.h; sourceTree = "<group>"; };
1C04FBA62CCACE8A00D6EEE6 /* GADPreloadEventDelegate_Preview.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GADPreloadEventDelegate_Preview.h; sourceTree = "<group>"; };
1C04FBA72CCACE8A00D6EEE6 /* GADRewardedAd_Preview.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GADRewardedAd_Preview.h; sourceTree = "<group>"; };
1CD352672C9CC97200534FCC /* CustomControls.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CustomControls.xib; sourceTree = "<group>"; };
4A7A6CD61C76237500FB1A32 /* Constants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
4AA7D68D1C625A1200DFD2EB /* APIDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = APIDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -120,6 +132,7 @@
4AA7D6AD1C626F2D00DFD2EB /* AdMobBannerSizesViewController.swift */,
AE3068C921221F7E006D7843 /* AdMobNativeCustomMuteThisAdViewController.swift */,
AED11115203213DF00EA4BEE /* AdManagerCustomVideoControls */,
AED11115203213DF00EA4BEC /* AdmobPreload */,
);
name = Controllers;
sourceTree = "<group>";
Expand All @@ -137,6 +150,22 @@
name = AdManagerCustomVideoControls;
sourceTree = "<group>";
};
AED11115203213DF00EA4BEC /* AdmobPreload */ = {
isa = PBXGroup;
children = (
1C04FB9C2CCACE7B00D6EEE6 /* AdmobPreloadView.swift */,
1C04FB9D2CCACE7B00D6EEE6 /* AdmobPreloadView.xib */,
1C04FB9E2CCACE7B00D6EEE6 /* AdmobPreloadViewController.swift */,
1C04FBA22CCACE8A00D6EEE6 /* GADAppOpenAd_Preview.h */,
1C04FBA32CCACE8A00D6EEE6 /* GADInterstitialAd_Preview.h */,
1C04FBA42CCACE8A00D6EEE6 /* GADMobileAds_Preview.h */,
1C04FBA52CCACE8A00D6EEE6 /* GADPreloadConfiguration_Preview.h */,
1C04FBA62CCACE8A00D6EEE6 /* GADPreloadEventDelegate_Preview.h */,
1C04FBA72CCACE8A00D6EEE6 /* GADRewardedAd_Preview.h */,
);
name = AdmobPreload;
sourceTree = "<group>";
};
E67BC192F0B0F683C00B6670 /* Pods */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -206,6 +235,7 @@
files = (
AED1111F203213FC00EA4BEE /* SimpleNativeAdView.xib in Resources */,
4AA7D69B1C625A1200DFD2EB /* LaunchScreen.storyboard in Resources */,
1C04FB9F2CCACE7B00D6EEE6 /* AdmobPreloadView.xib in Resources */,
4AA7D6981C625A1200DFD2EB /* Assets.xcassets in Resources */,
4AA7D6961C625A1200DFD2EB /* Main.storyboard in Resources */,
1CD352682C9CC97200534FCC /* CustomControls.xib in Resources */,
Expand All @@ -230,6 +260,8 @@
5038FC6F251144E300750F9C /* MainViewController.swift in Sources */,
507818F8219A418100E5A44A /* AdManagerCustomVideoControlsController.swift in Sources */,
507818FA219A418100E5A44A /* AdManagerFluidAdSizeViewController.swift in Sources */,
1C04FBA02CCACE7B00D6EEE6 /* AdmobPreloadViewController.swift in Sources */,
1C04FBA12CCACE7B00D6EEE6 /* AdmobPreloadView.swift in Sources */,
4A7A6CD71C76237500FB1A32 /* Constants.swift in Sources */,
507818F6219A418100E5A44A /* AdManagerPPIDViewController.swift in Sources */,
EFC712462AD853D80014A2BF /* CollapsibleBannerViewController.swift in Sources */,
Expand Down
7 changes: 7 additions & 0 deletions Swift/advanced/APIDemo/APIDemo/APIDemo-Bridging-Header.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,10 @@
//

#import <CommonCrypto/CommonDigest.h>

#import "GADAppOpenAd_Preview.h"
#import "GADInterstitialAd_Preview.h"
#import "GADMobileAds_Preview.h"
#import "GADPreloadConfiguration_Preview.h"
#import "GADPreloadEventDelegate_Preview.h"
#import "GADRewardedAd_Preview.h"
47 changes: 47 additions & 0 deletions Swift/advanced/APIDemo/APIDemo/AdmobPreloadView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//
// Copyright 2024 Google LLC
//
// 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 Foundation
import UIKit

class AdmobPreloadView: UIView {

var showDelegate: (() -> Void)!

@IBOutlet weak var titleText: UILabel!
@IBOutlet weak var statusText: UILabel!
@IBOutlet weak var showButton: UIButton!

@IBAction func show(_ sender: Any) {
showDelegate()
}

static func load(title: String, showDelegate: @escaping () -> Void)
-> AdmobPreloadView!
{
guard
let preloadView = Bundle.main.loadNibNamed("AdmobPreloadView", owner: self, options: nil)?
.first
as? AdmobPreloadView
else {
print("Error loading AdmobPreloadView nib file.")
return nil
}
preloadView.titleText.text = title
preloadView.showDelegate = showDelegate
return preloadView
}
}
58 changes: 58 additions & 0 deletions Swift/advanced/APIDemo/APIDemo/AdmobPreloadView.xib
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="23089" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_12" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23077"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view verifyAmbiguity="ignoreSizes" contentMode="top" verticalCompressionResistancePriority="100" insetsLayoutMarginsFromSafeArea="NO" translatesAutoresizingMaskIntoConstraints="NO" id="iN0-l3-epB" customClass="AdmobPreloadView" customModule="APIDemo" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="{Status}" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="YNv-nJ-SSa">
<rect key="frame" x="10" y="24" width="229" height="20"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="{Title}" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="uUp-HP-rTJ">
<rect key="frame" x="10" y="0.0" width="229" height="25"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="20"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" id="VIV-5R-Bjd">
<rect key="frame" x="250" y="0.0" width="113" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="filled" title="Show Ad"/>
<connections>
<action selector="show:" destination="iN0-l3-epB" eventType="touchUpInside" id="vSe-Bl-Ut7"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstAttribute="height" constant="50" id="G9L-bE-Q0n"/>
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="393" id="tIb-Wo-lHu"/>
</constraints>
<connections>
<outlet property="showButton" destination="VIV-5R-Bjd" id="xL8-Eq-gKO"/>
<outlet property="statusText" destination="YNv-nJ-SSa" id="dh2-hj-qwD"/>
<outlet property="titleText" destination="uUp-HP-rTJ" id="po3-qS-sJz"/>
</connections>
<point key="canvasLocation" x="-104.58015267175573" y="-295.77464788732397"/>
</view>
</objects>
<resources>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>
193 changes: 193 additions & 0 deletions Swift/advanced/APIDemo/APIDemo/AdmobPreloadViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
//
// Copyright 2024 Google LLC
//
// 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 GoogleMobileAds
import UIKit

class AdmobPreloadViewController: UIViewController, GADPreloadEventDelegate,
GADFullScreenContentDelegate
{

// Status messages for preload views.
private final var preloadAvailable = "Is available."
private final var preloadExhausted = "Is exhausted."

@IBOutlet weak var preloadContainer: UIStackView!

private var isMobileAdsStartCalled = false
private var interstitialView: AdmobPreloadView!
private var rewardedView: AdmobPreloadView!
private var appOpenView: AdmobPreloadView!

override func viewDidLoad() {
super.viewDidLoad()
startGoogleMobileAdsPreload()
configurePreloadViews()
}

// [START start_preload]
private func startGoogleMobileAdsPreload() {
// Define a list of PreloadConfigurations of ad units and formats you want to preload.
let interstitialConfig = GADPreloadConfiguration.init(
adUnitID: Constants.admobPreloadInterstitialAdUnitID,
adFormat: GADAdFormat.interstitial
)

let rewardedConfig = GADPreloadConfiguration.init(
adUnitID: Constants.admobPreloadRewardedAdUnitID,
adFormat: GADAdFormat.rewarded
)

let appOpenConfig = GADPreloadConfiguration.init(
adUnitID: Constants.admobPreloadAppOpenAdUnitID,
adFormat: GADAdFormat.appOpen
)

// Optionally set a custom GADRequest for each configuration.
//interstitialConfig.request = GADRequest()
//rewardedConfig.request = GADRequest()
//appOpenConfig.request = GADRequest()

// Optionally set the quantity of ads that can be cached for each ad units.
interstitialConfig.bufferSize = 2
rewardedConfig.bufferSize = 2
appOpenConfig.bufferSize = 2

// Start the preloading initialization process.
GADMobileAds.sharedInstance().preload(
with: [interstitialConfig, rewardedConfig, appOpenConfig],
delegate: self
)
}

// [END start_preload]

// [START isAdAvailable]
private func isInterstitialAvailable() -> Bool {
return GADInterstitialAd.isPreloadedAdAvailable(Constants.admobPreloadInterstitialAdUnitID)
}

// [END isAdAvailable]

private func isRewardedAvailable() -> Bool {
// Verify that an ad is available before polling.
return GADRewardedAd.isPreloadedAdAvailable(Constants.admobPreloadRewardedAdUnitID)
}

private func isAppOpenAvailable() -> Bool {
// Verify that an ad is available before polling.
return GADAppOpenAd.isPreloadedAdAvailable(Constants.admobPreloadAppOpenAdUnitID)
}

// [START pollAndShowAd]
private func showInterstitialAd() {
// Verify that the preloaded ad is available before polling.
guard isInterstitialAvailable() else {
printAndShowAlert("Preload interstitial ad is exhausted.")
return
}

// Polling returns the next available ad and load another ad in the background.
let ad = GADInterstitialAd.preloadedAd(withAdUnitID: Constants.admobPreloadInterstitialAdUnitID)
ad?.fullScreenContentDelegate = self
ad?.present(fromRootViewController: self)
}

// [END pollAndShowAd]

private func showRewardedAd() {
// Verify that the preloaded ad is available before polling.
guard isRewardedAvailable() else {
printAndShowAlert("Preloaded rewarded ad is exhausted.")
return
}

// Polling returns the next available ad and load another ad in the background.
let ad = GADRewardedAd.preloadedAd(withAdUnitID: Constants.admobPreloadRewardedAdUnitID)
ad?.fullScreenContentDelegate = self
ad?.present(fromRootViewController: self) {
if let reward = ad?.adReward {
print("User was rewarded \(reward.amount) \(reward.type)")
}
}
}

private func showAppOpenAd() {
// Verify that the preloaded ad is available before polling.
guard isAppOpenAvailable() else {
printAndShowAlert("Preload app open ad is exhausted.")
return
}

// Polling returns the next available ad and load another ad in the background.
let ad = GADAppOpenAd.preloadedAd(withAdUnitID: Constants.admobPreloadAppOpenAdUnitID)
ad?.fullScreenContentDelegate = self
ad?.present(fromRootViewController: self)
}

private func configurePreloadViews() {
interstitialView = AdmobPreloadView.load(
title: "Interstitial", showDelegate: showInterstitialAd)
preloadContainer.addArrangedSubview(interstitialView)
rewardedView = AdmobPreloadView.load(title: "Rewarded", showDelegate: showRewardedAd)
preloadContainer.addArrangedSubview(rewardedView)
appOpenView = AdmobPreloadView.load(title: "App open", showDelegate: showAppOpenAd)
preloadContainer.addArrangedSubview(appOpenView)

updatePreloadViews()
}

private func updatePreloadViews() {
updatePreloadView(preloadView: interstitialView, isAvailable: isInterstitialAvailable())
updatePreloadView(preloadView: rewardedView, isAvailable: isRewardedAvailable())
updatePreloadView(preloadView: appOpenView, isAvailable: isAppOpenAvailable())
}

private func updatePreloadView(preloadView: AdmobPreloadView, isAvailable: Bool) {
preloadView.showButton.isEnabled = isAvailable
preloadView.statusText.text = isAvailable ? preloadAvailable : preloadExhausted
preloadView.statusText.textColor = isAvailable ? UIColor.blue : UIColor.red
}

private func printAndShowAlert(_ message: String) {
let alert = UIAlertController(title: "Alert", message: message, preferredStyle: .alert)
let dismissAction = UIAlertAction(title: "Dismiss", style: .default)
alert.addAction(dismissAction)
present(alert, animated: true, completion: nil)
}

// MARK: GADPreloadEventDelegate

func adAvailable(for configuration: GADPreloadConfiguration) {
print("Ad preloaded successfully for ad unit ID: \(configuration.adUnitID)")
updatePreloadViews()
}

func adsExhausted(for configuration: GADPreloadConfiguration) {
print("Ad exhausted for ad unit ID: \(configuration.adUnitID)")
updatePreloadViews()
}

// MARK: GADFullScreenContentDelegate

func adWillPresentFullScreenContent(_ ad: GADFullScreenPresentingAd) {
print("Preloaded ad will be presented.")
}

func adDidDismissFullScreenContent(_ ad: GADFullScreenPresentingAd) {
print("Preloaded ad dismissed.")
}
}
Loading

0 comments on commit 8ad04e7

Please sign in to comment.