Skip to content

Commit

Permalink
Added UMP SDK integration to Rewarded sample
Browse files Browse the repository at this point in the history
  • Loading branch information
Justin Malandruccolo committed May 3, 2024
1 parent d4071e1 commit 09afc14
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 9 deletions.
51 changes: 51 additions & 0 deletions samples/admob/rewarded_example/lib/consent_manager.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import 'dart:async';

import 'package:google_mobile_ads/google_mobile_ads.dart';

typedef OnConsentGatheringCompleteListener = void Function(FormError? error);

/// 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.
class ConsentManager {
/// Helper variable to determine if the app can request ads.
Future<bool> canRequestAds() async {
return await ConsentInformation.instance.canRequestAds();
}

/// Helper variable to determine if the privacy options form is required.
Future<bool> isPrivacyOptionsRequired() async {
return await ConsentInformation.instance
.getPrivacyOptionsRequirementStatus() ==
PrivacyOptionsRequirementStatus.required;
}

/// Helper method to call the Mobile Ads SDK to request consent information
/// and load/show a consent form if necessary.
void gatherConsent(
OnConsentGatheringCompleteListener onConsentGatheringCompleteListener) {
// For testing purposes, you can force a DebugGeography of Eea or NotEea.
ConsentDebugSettings debugSettings = ConsentDebugSettings(
debugGeography: DebugGeography.debugGeographyEea,
);
ConsentRequestParameters params =
ConsentRequestParameters(consentDebugSettings: debugSettings);

// Requesting an update to consent information should be called on every app launch.
ConsentInformation.instance.requestConsentInfoUpdate(params, () async {
ConsentForm.loadAndShowConsentFormIfRequired((loadAndShowError) {
// Consent has been gathered.
onConsentGatheringCompleteListener(loadAndShowError);
});
}, (FormError formError) {
onConsentGatheringCompleteListener(formError);
});
}

/// Helper method to call the Mobile Ads SDK method to show the privacy options form.
void showPrivacyOptionsForm(
OnConsentFormDismissedListener onConsentFormDismissedListener) {
ConsentForm.showPrivacyOptionsForm(onConsentFormDismissedListener);
}
}
23 changes: 19 additions & 4 deletions samples/admob/rewarded_example/lib/countdown_timer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,42 @@ import 'package:flutter/material.dart';
enum CountdownState {
notStarted,
active,
paused,
ended,
}

/// A simple class that keeps track of a decrementing timer.
class CountdownTimer extends ChangeNotifier {
final _countdownTime = 10;
final _countdownTime = 5;
late var timeLeft = _countdownTime;
var _countdownState = CountdownState.notStarted;
Timer? _timer;

bool get isComplete => _countdownState == CountdownState.ended;

void start() {
timeLeft = _countdownTime;
_resumeTimer();
_startTimer();
_countdownState = CountdownState.active;

notifyListeners();
}

void _resumeTimer() {
Timer.periodic(const Duration(seconds: 1), (timer) {
void resume() {
_startTimer();
_countdownState = CountdownState.active;
}

void pause() {
if (_countdownState != CountdownState.active) {
return;
}
_timer?.cancel();
_countdownState = CountdownState.paused;
}

void _startTimer() {
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
timeLeft--;

if (timeLeft == 0) {
Expand Down
107 changes: 103 additions & 4 deletions samples/admob/rewarded_example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';

import 'consent_manager.dart';

void main() {
WidgetsFlutterBinding.ensureInitialized();
MobileAds.instance.initialize();
runApp(const MaterialApp(
home: RewardedExample(),
));
Expand All @@ -20,8 +21,14 @@ class RewardedExample extends StatefulWidget {
}

class RewardedExampleState extends State<RewardedExample> {
static const privacySettingsText = 'Privacy Settings';

final _consentManager = ConsentManager();
final CountdownTimer _countdownTimer = CountdownTimer();
var _showWatchVideoButton = false;
var _gamePaused = false;
var _gameOver = false;
var _isMobileAdsInitializeCalled = false;
var _coins = 0;
RewardedAd? _rewardedAd;

Expand All @@ -33,20 +40,55 @@ class RewardedExampleState extends State<RewardedExample> {
void initState() {
super.initState();

_consentManager.gatherConsent((consentGatheringError) {
if (consentGatheringError != null) {
// Consent not obtained in current session.
debugPrint(
"${consentGatheringError.errorCode}: ${consentGatheringError.message}");
}

// Kick off the first play of the "game".
_startNewGame();

// Attempt to initialize the Mobile Ads SDK.
_initializeMobileAdsSDK();
});

// This sample attempts to load ads using consent obtained in the previous session.
_initializeMobileAdsSDK();

// Show the "Watch video" button when the timer reaches zero.
_countdownTimer.addListener(() => setState(() {
if (_countdownTimer.isComplete) {
_gameOver = true;
_showWatchVideoButton = true;
_coins += 1;
} else {
_showWatchVideoButton = false;
}
}));
_startNewGame();
}

void _startNewGame() {
_loadAd();
_countdownTimer.start();
_gameOver = false;
_gamePaused = false;
}

void _pauseGame() {
if (_gameOver || _gamePaused) {
return;
}
_countdownTimer.pause();
_gamePaused = true;
}

void _resumeGame() {
if (_gameOver || !_gamePaused) {
return;
}
_countdownTimer.resume();
_gamePaused = false;
}

@override
Expand All @@ -56,6 +98,37 @@ class RewardedExampleState extends State<RewardedExample> {
home: Scaffold(
appBar: AppBar(
title: const Text('Rewarded Example'),
actions: <Widget>[
// Regenerate the options menu to include a privacy setting.
FutureBuilder(
future: _consentManager.isPrivacyOptionsRequired(),
builder: (context, snapshot) {
final bool visibility = snapshot.data ?? false;
return Visibility(
visible: visibility,
child: PopupMenuButton<String>(
onSelected: (String result) {
if (result == privacySettingsText) {
_pauseGame();
_consentManager
.showPrivacyOptionsForm((formError) {
if (formError != null) {
debugPrint(
"${formError.errorCode}: ${formError.message}");
}
_resumeGame();
});
}
},
itemBuilder: (BuildContext context) =>
<PopupMenuEntry<String>>[
const PopupMenuItem<String>(
value: privacySettingsText,
child: Text(privacySettingsText))
],
));
})
],
),
body: Stack(
children: [
Expand All @@ -82,6 +155,7 @@ class RewardedExampleState extends State<RewardedExample> {
child: TextButton(
onPressed: () {
_startNewGame();
_loadAd();
},
child: const Text('Play Again'),
),
Expand Down Expand Up @@ -117,7 +191,14 @@ class RewardedExampleState extends State<RewardedExample> {
}

/// Loads a rewarded ad.
void _loadAd() {
void _loadAd() async {
// Only load an ad if the Mobile Ads SDK has gathered consent aligned with
// the app's configured messages.
var canRequestAds = await _consentManager.canRequestAds();
if (!canRequestAds) {
return;
}

RewardedAd.load(
adUnitId: _adUnitId,
request: const AdRequest(),
Expand Down Expand Up @@ -146,6 +227,24 @@ class RewardedExampleState extends State<RewardedExample> {
}));
}

/// Initialize the Mobile Ads SDK if the SDK has gathered consent aligned with
/// the app's configured messages.
void _initializeMobileAdsSDK() async {
if (_isMobileAdsInitializeCalled) {
return;
}

var canRequestAds = await _consentManager.canRequestAds();
if (canRequestAds) {
_isMobileAdsInitializeCalled = true;

// Initialize the Mobile Ads SDK.
MobileAds.instance.initialize();
// Load an ad.
_loadAd();
}
}

@override
void dispose() {
_rewardedAd?.dispose();
Expand Down
6 changes: 5 additions & 1 deletion samples/admob/rewarded_example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@ environment:
sdk: '>=3.2.0 <4.0.0'

dependencies:
google_mobile_ads:
git:
url: https://github.com/googleads/googleads-mobile-flutter/
path: ./packages/google_mobile_ads

flutter:
sdk: flutter
google_mobile_ads: ^5.0.0

dev_dependencies:
flutter_test:
Expand Down

0 comments on commit 09afc14

Please sign in to comment.