Skip to content

Commit

Permalink
Added UMP SDK integration to Rewarded Interstitial Objective-C & Swif…
Browse files Browse the repository at this point in the history
…t samples

PiperOrigin-RevId: 557938443
  • Loading branch information
Justin Malandruccolo authored and maddevrelgithubbot committed Aug 17, 2023
1 parent ea0aea5 commit f8f4b78
Show file tree
Hide file tree
Showing 27 changed files with 841 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
A8CC5E022A8ECECD0094B83E /* GoogleMobileAdsConsentManager.m in Sources */ = {isa = PBXBuildFile; fileRef = A8CC5E012A8ECECD0094B83E /* GoogleMobileAdsConsentManager.m */; };
CF9F261F1991396300F5C44E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = CF9F261E1991396300F5C44E /* main.m */; };
CF9F26221991396300F5C44E /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CF9F26211991396300F5C44E /* AppDelegate.m */; };
CF9F26251991396300F5C44E /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CF9F26241991396300F5C44E /* ViewController.m */; };
Expand All @@ -15,6 +16,8 @@
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
A8CC5E002A8ECECC0094B83E /* GoogleMobileAdsConsentManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GoogleMobileAdsConsentManager.h; sourceTree = "<group>"; };
A8CC5E012A8ECECD0094B83E /* GoogleMobileAdsConsentManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GoogleMobileAdsConsentManager.m; sourceTree = "<group>"; };
CF9F26191991396300F5C44E /* AdManagerRewardedInterstitialExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AdManagerRewardedInterstitialExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
CF9F261D1991396300F5C44E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
CF9F261E1991396300F5C44E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -66,6 +69,8 @@
children = (
CF9F26201991396300F5C44E /* AppDelegate.h */,
CF9F26211991396300F5C44E /* AppDelegate.m */,
A8CC5E002A8ECECC0094B83E /* GoogleMobileAdsConsentManager.h */,
A8CC5E012A8ECECD0094B83E /* GoogleMobileAdsConsentManager.m */,
CF9F26231991396300F5C44E /* ViewController.h */,
CF9F26241991396300F5C44E /* ViewController.m */,
CF9F26261991396300F5C44E /* Main.storyboard */,
Expand Down Expand Up @@ -154,6 +159,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A8CC5E022A8ECECD0094B83E /* GoogleMobileAdsConsentManager.m in Sources */,
CF9F26251991396300F5C44E /* ViewController.m in Sources */,
CF9F26221991396300F5C44E /* AppDelegate.m in Sources */,
CF9F261F1991396300F5C44E /* main.m in Sources */,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright 2023 Google LLC
// Copyright (C) 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright 2023 Google LLC
// Copyright (C) 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -16,15 +16,10 @@

#import "AppDelegate.h"

#import <GoogleMobileAds/GoogleMobileAds.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary<UIApplicationLaunchOptionsKey, id> *)launchOptions {
// Initialize Google Mobile Ads SDK
[GADMobileAds.sharedInstance startWithCompletionHandler:nil];

return YES;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="22113.1" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES" initialViewController="VCq-9h-Ghp">
<device id="retina5_9" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22089"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Navigation Controller-->
<scene sceneID="93Z-ew-WzI">
<objects>
<navigationController id="VCq-9h-Ghp" sceneMemberID="viewController">
<navigationBar key="navigationBar" contentMode="scaleToFill" id="DKe-Cq-k44">
<rect key="frame" x="0.0" y="50" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<connections>
<segue destination="BYZ-38-t0r" kind="relationship" relationship="rootViewController" id="Bjc-9Q-oYO"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="sd2-1B-A5U" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-766" y="103"/>
</scene>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
Expand Down Expand Up @@ -36,7 +52,7 @@
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="The Impossible Game" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="kBt-AA-hYj">
<rect key="frame" x="47.666666666666657" y="94" width="280" height="36"/>
<rect key="frame" x="47.666666666666657" y="144" width="280" height="36"/>
<fontDescription key="fontDescription" type="system" pointSize="30"/>
<nil key="highlightedColor"/>
</label>
Expand All @@ -59,10 +75,18 @@
<constraint firstItem="728-cg-9BF" firstAttribute="top" secondItem="K63-xT-qpW" secondAttribute="bottom" constant="20" id="mxq-iL-0N5"/>
</constraints>
</view>
<navigationItem key="navigationItem" id="Itz-Jw-Nh2">
<barButtonItem key="rightBarButtonItem" enabled="NO" title="Privacy Settings" id="04C-Fc-x4d">
<connections>
<action selector="privacySettingsTapped:" destination="BYZ-38-t0r" id="o0a-Ga-IOJ"/>
</connections>
</barButtonItem>
</navigationItem>
<connections>
<outlet property="coinCountLabel" destination="K63-xT-qpW" id="cAl-QK-AAy"/>
<outlet property="gameText" destination="hNG-Yh-paY" id="EaJ-Mh-Htn"/>
<outlet property="playAgainButton" destination="YbK-8l-i8l" id="SKB-fc-Knv"/>
<outlet property="privacySettingsButton" destination="04C-Fc-x4d" id="fdg-ho-Dx8"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// Copyright (C) 2023 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 <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

/// The Google Mobile Ads SDK provides the User Messaging Platform (Google's
/// IAB Certified consent management platform) as one solution to capture
/// consent for users in GDPR impacted countries. This is an example and
/// you can choose another consent management platform to capture consent.
@interface GoogleMobileAdsConsentManager : NSObject

@property(class, atomic, readonly, strong, nonnull) GoogleMobileAdsConsentManager *sharedInstance;
@property(nonatomic, readonly) BOOL canRequestAds;
@property(nonatomic, readonly) BOOL isPrivacyOptionsRequired;

/// Helper method to call the UMP SDK methods to request consent information and load/present a
/// consent form if necessary.
- (void)gatherConsentFromConsentPresentationViewController:(UIViewController *)viewController
consentGatheringComplete:
(void (^)(NSError *_Nullable error))completionHandler;

/// Helper method to call the UMP SDK method to present the privacy options form.
- (void)presentPrivacyOptionsFormFromViewController:(UIViewController *)viewController
completionHandler:
(void (^)(NSError *_Nullable error))completionHandler;

@end

NS_ASSUME_NONNULL_END
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//
// Copyright (C) 2023 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 "GoogleMobileAdsConsentManager.h"

#import <GoogleMobileAds/GoogleMobileAds.h>
#import <UserMessagingPlatform/UserMessagingPlatform.h>


@implementation GoogleMobileAdsConsentManager

+ (instancetype)sharedInstance {
static GoogleMobileAdsConsentManager *shared;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
shared = [[GoogleMobileAdsConsentManager alloc] init];
});
return shared;
}

- (BOOL)canRequestAds {
return UMPConsentInformation.sharedInstance.canRequestAds;
}

- (BOOL)isPrivacyOptionsRequired {
return UMPConsentInformation.sharedInstance.privacyOptionsRequirementStatus ==
UMPPrivacyOptionsRequirementStatusRequired;
}

- (void)gatherConsentFromConsentPresentationViewController:(UIViewController *)viewController
consentGatheringComplete:
(void (^)(NSError *_Nullable))consentGatheringComplete {
UMPRequestParameters *parameters = [[UMPRequestParameters alloc] init];

// For testing purposes, you can force a UMPDebugGeography of EEA or not EEA.
UMPDebugSettings *debugSettings = [[UMPDebugSettings alloc] init];
// debugSettings.geography = UMPDebugGeographyEEA;
parameters.debugSettings = debugSettings;

// Requesting an update to consent information should be called on every app launch.
[UMPConsentInformation.sharedInstance
requestConsentInfoUpdateWithParameters:parameters
completionHandler:^(NSError *_Nullable requestConsentError) {
if (requestConsentError) {
consentGatheringComplete(requestConsentError);
} else {
[UMPConsentForm
loadAndPresentIfRequiredFromViewController:viewController
completionHandler:^(
NSError
*_Nullable loadAndPresentError) {
// Consent has been gathered.
consentGatheringComplete(
loadAndPresentError);
}];
}
}];
}

- (void)presentPrivacyOptionsFormFromViewController:(UIViewController *)viewController
completionHandler:
(void (^)(NSError *_Nullable))completionHandler {
[UMPConsentForm presentPrivacyOptionsFormFromViewController:viewController
completionHandler:completionHandler];
}

@end
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright 2023 Google LLC
// Copyright (C) 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -18,6 +18,9 @@

@interface ViewController : UIViewController

/// The privacy settings button.
@property (weak, nonatomic) IBOutlet UIBarButtonItem *privacySettingsButton;

/// The game text.
@property(nonatomic, weak) IBOutlet UILabel *gameText;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright 2023 Google LLC
// Copyright (C) 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -18,6 +18,8 @@

#import <GoogleMobileAds/GoogleMobileAds.h>

#import "GoogleMobileAdsConsentManager.h"

/// GameState indicates the progress of the game.
typedef NS_ENUM(NSUInteger, GameState) {
/** Game has not started. */
Expand Down Expand Up @@ -72,16 +74,51 @@ - (void)viewDidLoad {
name:UIApplicationDidBecomeActiveNotification
object:nil];

[self startNewGame];
__weak __typeof__(self) weakSelf = self;
[GoogleMobileAdsConsentManager.sharedInstance
gatherConsentFromConsentPresentationViewController:self
consentGatheringComplete:^(NSError *_Nullable consentError) {
__strong __typeof__(self) strongSelf = weakSelf;
if (!strongSelf) {
return;
}

[strongSelf startNewGame];

if (consentError) {
// Consent gathering failed.
NSLog(@"Error: %@", consentError.localizedDescription);
}

if (GoogleMobileAdsConsentManager.sharedInstance.canRequestAds) {
[strongSelf startGoogleMobileAdsSDK];
}

strongSelf.privacySettingsButton.enabled =
GoogleMobileAdsConsentManager.sharedInstance
.isPrivacyOptionsRequired;
}];

// This sample attempts to load ads using consent obtained in the previous session.
if (GoogleMobileAdsConsentManager.sharedInstance.canRequestAds) {
[self startGoogleMobileAdsSDK];
}
}

#pragma mark Game logic
- (void)startGoogleMobileAdsSDK {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// Initialize the Google Mobile Ads SDK.
[GADMobileAds.sharedInstance startWithCompletionHandler:nil];

- (void)startNewGame {
if (!self.rewardedInterstitialAd) {
// Request an ad.
[self loadRewardedInterstitialAd];
}
});
}

#pragma mark Game logic

- (void)startNewGame {
self.gameState = GameStatePlaying;
self.playAgainButton.hidden = YES;
self.timeLeft = kGameLength;
Expand All @@ -94,6 +131,10 @@ - (void)startNewGame {
}

- (void)loadRewardedInterstitialAd {
if (self.rewardedInterstitialAd) {
return;
}

GAMRequest *request = [GAMRequest request];
[GADRewardedInterstitialAd loadWithAdUnitID:@"/21775744923/example/rewarded_interstitial"
request:request
Expand Down Expand Up @@ -237,8 +278,39 @@ - (void)adDidDismissFullScreenContent:(id)ad {

#pragma Rewarded Interstitial button actions

- (IBAction)privacySettingsTapped:(UIBarButtonItem *)sender {
[self pauseGame];

[GoogleMobileAdsConsentManager.sharedInstance
presentPrivacyOptionsFormFromViewController:self
completionHandler:^(NSError *_Nullable formError) {
if (formError) {
UIAlertController *alertController = [UIAlertController
alertControllerWithTitle:formError.localizedDescription
message:@"Please try again later."
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *defaultAction =
[UIAlertAction actionWithTitle:@"OK"
style:UIAlertActionStyleCancel
handler:^(UIAlertAction *action) {
[self resumeGame];
}];

[alertController addAction:defaultAction];
[self presentViewController:alertController
animated:YES
completion:nil];
} else {
[self resumeGame];
}
}];
}

- (IBAction)playAgain:(id)sender {
[self startNewGame];
if (GoogleMobileAdsConsentManager.sharedInstance.canRequestAds) {
[self loadRewardedInterstitialAd];
}
}

@end
Loading

0 comments on commit f8f4b78

Please sign in to comment.