From a1ef9f5ca2e560e3c01ddab2b20c297186571e97 Mon Sep 17 00:00:00 2001 From: Justin Malandruccolo Date: Tue, 16 Jul 2024 10:55:22 -0400 Subject: [PATCH] Add Ad Inspector button to Banner Example (#1125) * Added ad inspector to app bar * removed changes * removed * new line * no changes * no changes pt 2 * Updated minimum to iOS 12 --------- Co-authored-by: Justin Malandruccolo --- .../ios/Flutter/AppFrameworkInfo.plist | 2 +- .../ios/Runner.xcodeproj/project.pbxproj | 29 +++---- .../banner_example/lib/app_bar_item.dart | 9 ++ samples/admob/banner_example/lib/main.dart | 86 +++++++++++-------- 4 files changed, 72 insertions(+), 54 deletions(-) create mode 100644 samples/admob/banner_example/lib/app_bar_item.dart diff --git a/samples/admob/banner_example/ios/Flutter/AppFrameworkInfo.plist b/samples/admob/banner_example/ios/Flutter/AppFrameworkInfo.plist index 9625e105d..7c5696400 100644 --- a/samples/admob/banner_example/ios/Flutter/AppFrameworkInfo.plist +++ b/samples/admob/banner_example/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 11.0 + 12.0 diff --git a/samples/admob/banner_example/ios/Runner.xcodeproj/project.pbxproj b/samples/admob/banner_example/ios/Runner.xcodeproj/project.pbxproj index d9c210628..1917bf7db 100644 --- a/samples/admob/banner_example/ios/Runner.xcodeproj/project.pbxproj +++ b/samples/admob/banner_example/ios/Runner.xcodeproj/project.pbxproj @@ -8,12 +8,12 @@ /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; - 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -42,6 +42,8 @@ /* Begin PBXFileReference section */ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -53,8 +55,6 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; - 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -68,6 +68,14 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( @@ -79,14 +87,6 @@ name = Flutter; sourceTree = ""; }; - 331C8082294A63A400263BE5 /* RunnerTests */ = { - isa = PBXGroup; - children = ( - 331C807B294A618700263BE5 /* RunnerTests.swift */, - ); - path = RunnerTests; - sourceTree = ""; - }; 97C146E51CF9000F007C117D = { isa = PBXGroup; children = ( @@ -129,7 +129,6 @@ buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( 331C807D294A63A400263BE5 /* Sources */, - 331C807E294A63A400263BE5 /* Frameworks */, 331C807F294A63A400263BE5 /* Resources */, ); buildRules = ( @@ -363,6 +362,7 @@ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -377,7 +377,6 @@ }; 331C8088294A63A400263BE5 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = AE0B7B92F70575B8D7E0D07E /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -395,7 +394,6 @@ }; 331C8089294A63A400263BE5 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 89B67EB44CE7B6631473024E /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -411,7 +409,6 @@ }; 331C808A294A63A400263BE5 /* Profile */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 640959BDD8F10B91D80A66BE /* Pods-RunnerTests.profile.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -541,6 +538,7 @@ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -563,6 +561,7 @@ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", diff --git a/samples/admob/banner_example/lib/app_bar_item.dart b/samples/admob/banner_example/lib/app_bar_item.dart new file mode 100644 index 000000000..e77175cee --- /dev/null +++ b/samples/admob/banner_example/lib/app_bar_item.dart @@ -0,0 +1,9 @@ +class AppBarItem { + static const adInpsectorText = 'Ad Inspector'; + static const privacySettingsText = 'Privacy Settings'; + + final String label; + final int value; + + AppBarItem(this.label, this.value); +} diff --git a/samples/admob/banner_example/lib/main.dart b/samples/admob/banner_example/lib/main.dart index 3b28efa10..845f0c3cc 100644 --- a/samples/admob/banner_example/lib/main.dart +++ b/samples/admob/banner_example/lib/main.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:google_mobile_ads/google_mobile_ads.dart'; +import 'app_bar_item.dart'; import 'consent_manager.dart'; void main() { @@ -12,7 +13,7 @@ void main() { )); } -/// A simple app that loads a banner ad. +/// An example app that loads a banner ad. class BannerExample extends StatefulWidget { const BannerExample({super.key}); @@ -21,10 +22,9 @@ class BannerExample extends StatefulWidget { } class BannerExampleState extends State { - static const privacySettingsText = 'Privacy Settings'; - final _consentManager = ConsentManager(); var _isMobileAdsInitializeCalled = false; + var _isPrivacyOptionsRequired = false; BannerAd? _bannerAd; bool _isLoaded = false; Orientation? _currentOrientation; @@ -44,6 +44,9 @@ class BannerExampleState extends State { "${consentGatheringError.errorCode}: ${consentGatheringError.message}"); } + // Check if a privacy options entry point is required. + _getIsPrivacyOptionsRequired(); + // Attempt to initialize the Mobile Ads SDK. _initializeMobileAdsSDK(); }); @@ -58,10 +61,7 @@ class BannerExampleState extends State { title: 'Banner Example', home: Scaffold( appBar: AppBar( - title: const Text('Banner Example'), - actions: _isMobileAdsInitializeCalled - ? _privacySettingsAppBarAction() - : null), + title: const Text('Banner Example'), actions: _appBarActions()), body: OrientationBuilder( builder: (context, orientation) { if (_currentOrientation != orientation) { @@ -88,33 +88,36 @@ class BannerExampleState extends State { ))); } - List _privacySettingsAppBarAction() { + List _appBarActions() { + var array = [AppBarItem(AppBarItem.adInpsectorText, 0)]; + + if (_isPrivacyOptionsRequired) { + array.add(AppBarItem(AppBarItem.privacySettingsText, 1)); + } + return [ - // 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( - onSelected: (String result) { - if (result == privacySettingsText) { - _consentManager.showPrivacyOptionsForm((formError) { - if (formError != null) { - debugPrint( - "${formError.errorCode}: ${formError.message}"); - } - }); - } - }, - itemBuilder: (BuildContext context) => - >[ - const PopupMenuItem( - value: privacySettingsText, - child: Text(privacySettingsText)) - ], - )); + PopupMenuButton( + itemBuilder: (context) => array + .map((item) => PopupMenuItem( + value: item, + child: Text( + item.label, + ), + )) + .toList(), + onSelected: (item) { + switch (item.value) { + case 0: + MobileAds.instance.openAdInspector((error) { + // Error will be non-null if ad inspector closed due to an error. + }); + case 1: + _consentManager.showPrivacyOptionsForm((formError) { + if (formError != null) { + debugPrint("${formError.errorCode}: ${formError.message}"); + } + }); + } }) ]; } @@ -169,6 +172,15 @@ class BannerExampleState extends State { ).load(); } + /// Redraw the app bar actions if a privacy options entry point is required. + void _getIsPrivacyOptionsRequired() async { + if (await _consentManager.isPrivacyOptionsRequired()) { + setState(() { + _isPrivacyOptionsRequired = true; + }); + } + } + /// Initialize the Mobile Ads SDK if the SDK has gathered consent aligned with /// the app's configured messages. void _initializeMobileAdsSDK() async { @@ -176,14 +188,12 @@ class BannerExampleState extends State { return; } - var canRequestAds = await _consentManager.canRequestAds(); - if (canRequestAds) { - setState(() { - _isMobileAdsInitializeCalled = true; - }); + if (await _consentManager.canRequestAds()) { + _isMobileAdsInitializeCalled = true; // Initialize the Mobile Ads SDK. MobileAds.instance.initialize(); + // Load an ad. _loadAd(); }