Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added UMP SDK integration to native template example #1073

Merged
merged 4 commits into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion samples/admob/native_template_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_template_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);
}
}
97 changes: 85 additions & 12 deletions samples/admob/native_template_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();
var _isMobileAdsInitializeCalled = false;
NativeAd? _nativeAd;
bool _nativeAdIsLoaded = false;
String? _versionString;

// final double _adAspectRatioSmall = (91 / 355);
final double _adAspectRatioMedium = (370 / 355);

Expand All @@ -34,8 +39,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 @@ -44,8 +60,10 @@ 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: SizedBox(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
Expand All @@ -67,14 +85,57 @@ class NativeExampleState extends State<NativeExample> {
),
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;
});
Expand Down Expand Up @@ -124,12 +185,24 @@ class NativeExampleState extends State<NativeExample> {
..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_template_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