Skip to content

Commit

Permalink
Added UMP SDK integration to Native Platform Example (#1072)
Browse files Browse the repository at this point in the history
* Added UMP integration to native platform example

* comment out debug

* explicit widget

* 5.1.0

---------

Co-authored-by: Justin Malandruccolo <[email protected]>
  • Loading branch information
malandr2 and Justin Malandruccolo authored May 9, 2024
1 parent 74f7aed commit 020a5dd
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 47 deletions.
2 changes: 1 addition & 1 deletion samples/admob/native_platform_example/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ subprojects {
project.evaluationDependsOn(':app')
}

task clean(type: Delete) {
tasks.register("clean", Delete) {
delete rootProject.buildDir
}
51 changes: 51 additions & 0 deletions samples/admob/native_platform_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);
}
}
163 changes: 118 additions & 45 deletions samples/admob/native_platform_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: NativeExample(),
));
Expand All @@ -20,9 +21,13 @@ class NativeExample extends StatefulWidget {
}

class NativeExampleState extends State<NativeExample> {
static const privacySettingsText = 'Privacy Settings';

final _consentManager = ConsentManager();
final double _nativeAdHeight = Platform.isAndroid ? 320 : 300;
var _isMobileAdsInitializeCalled = false;
NativeAd? _nativeAd;
bool _nativeAdIsLoaded = false;
String? _versionString;

final String _adUnitId = Platform.isAndroid
? 'ca-app-pub-3940256099942544/2247696110'
Expand All @@ -32,8 +37,19 @@ class NativeExampleState extends State<NativeExample> {
void initState() {
super.initState();

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

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

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

@override
Expand All @@ -42,68 +58,125 @@ class NativeExampleState extends State<NativeExample> {
title: 'Native Example',
home: Scaffold(
appBar: AppBar(
title: const Text('Native Example'),
),
title: const Text('Native Example'),
actions: _isMobileAdsInitializeCalled
? _privacySettingsAppBarAction()
: null),
body: Center(
child: Column(
children: [
Stack(
children: [
Stack(children: [
SizedBox(
height: 300,
width: MediaQuery.of(context).size.width),
height: _nativeAdHeight,
width: MediaQuery.of(context).size.width),
if (_nativeAdIsLoaded && _nativeAd != null)
SizedBox(
height: 300,
width: MediaQuery.of(context).size.width,
child: AdWidget(ad: _nativeAd!))]),
SizedBox(
height: _nativeAdHeight,
width: MediaQuery.of(context).size.width,
child: AdWidget(ad: _nativeAd!))
]),
TextButton(
onPressed: _loadAd, child: const Text("Refresh Ad")),
if (_versionString != null) Text(_versionString!)],
FutureBuilder(
future: MobileAds.instance.getVersionString(),
builder: (context, snapshot) {
var versionString = snapshot.data ?? "";
return Text(versionString);
})
],
),
)
));
)));
}

List<Widget> _privacySettingsAppBarAction() {
return <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) {
_consentManager.showPrivacyOptionsForm((formError) {
if (formError != null) {
debugPrint(
"${formError.errorCode}: ${formError.message}");
}
});
}
},
itemBuilder: (BuildContext context) =>
<PopupMenuEntry<String>>[
const PopupMenuItem<String>(
value: privacySettingsText,
child: Text(privacySettingsText))
],
));
})
];
}

/// Loads a native 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;
}

setState(() {
_nativeAdIsLoaded = false;
});

_nativeAd = NativeAd(
adUnitId: _adUnitId,
factoryId: 'adFactoryExample',
listener: NativeAdListener(
onAdLoaded: (ad) {
// ignore: avoid_print
print('$NativeAd loaded.');
setState(() {
_nativeAdIsLoaded = true;
});
},
onAdFailedToLoad: (ad, error) {
// ignore: avoid_print
print('$NativeAd failedToLoad: $error');
ad.dispose();
},
onAdClicked: (ad) {},
onAdImpression: (ad) {},
onAdClosed: (ad) {},
onAdOpened: (ad) {},
onAdWillDismissScreen: (ad) {},
onPaidEvent: (ad, valueMicros, precision, currencyCode) {},
),
request: const AdRequest(),
adUnitId: _adUnitId,
factoryId: 'adFactoryExample',
listener: NativeAdListener(
onAdLoaded: (ad) {
// ignore: avoid_print
print('$NativeAd loaded.');
setState(() {
_nativeAdIsLoaded = true;
});
},
onAdFailedToLoad: (ad, error) {
// ignore: avoid_print
print('$NativeAd failedToLoad: $error');
ad.dispose();
},
onAdClicked: (ad) {},
onAdImpression: (ad) {},
onAdClosed: (ad) {},
onAdOpened: (ad) {},
onAdWillDismissScreen: (ad) {},
onPaidEvent: (ad, valueMicros, precision, currencyCode) {},
),
request: const AdRequest(),
)..load();
}

void _loadVersionString() {
MobileAds.instance.getVersionString().then((value) {
/// 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) {
setState(() {
_versionString = value;
_isMobileAdsInitializeCalled = true;
});
});

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

@override
Expand Down
2 changes: 1 addition & 1 deletion samples/admob/native_platform_example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ environment:
dependencies:
flutter:
sdk: flutter
google_mobile_ads: ^5.0.0
google_mobile_ads: ^5.1.0

# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
Expand Down

0 comments on commit 020a5dd

Please sign in to comment.