From f8230b36b3431cd7c05b04cb13dc2d2390ca69e6 Mon Sep 17 00:00:00 2001 From: jeffrey0606 Date: Mon, 22 Aug 2022 02:40:04 +0100 Subject: [PATCH] implemented banner ads and setup app for first release --- .gitignore | 2 + android/app/build.gradle | 23 +++- android/app/src/debug/AndroidManifest.xml | 8 -- android/app/src/main/AndroidManifest.xml | 4 + android/app/src/profile/AndroidManifest.xml | 8 -- lib/core/ads/ads_state.dart | 19 +++ lib/core/app/app_layout.dart | 6 + lib/core/widgets/my_banner_ad.dart | 108 ++++++++++++++++++ .../pages/pokemon_details_page.dart | 3 + lib/injection_container.dart | 10 +- lib/main.dart | 2 + pubspec.lock | 14 +++ pubspec.yaml | 1 + 13 files changed, 184 insertions(+), 24 deletions(-) delete mode 100644 android/app/src/debug/AndroidManifest.xml delete mode 100644 android/app/src/profile/AndroidManifest.xml create mode 100644 lib/core/ads/ads_state.dart create mode 100644 lib/core/widgets/my_banner_ad.dart diff --git a/.gitignore b/.gitignore index a8e938c..731a873 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,5 @@ app.*.map.json /android/app/debug /android/app/profile /android/app/release + +/android/key.properties diff --git a/android/app/build.gradle b/android/app/build.gradle index eb9fca0..a94cf02 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -25,6 +25,13 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" +def keystoreProperties = new Properties() +def keystorePropertiesFile = rootProject.file('key.properties') +if (keystorePropertiesFile.exists()) { + keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) +} + + android { compileSdkVersion flutter.compileSdkVersion ndkVersion flutter.ndkVersion @@ -44,20 +51,27 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.example.pokemondo" + applicationId "com.hooreo.pokemondo" // You can update the following values to match your application needs. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. minSdkVersion flutter.minSdkVersion targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() versionName flutterVersionName + multiDexEnabled true } + signingConfigs { + release { + keyAlias keystoreProperties['keyAlias'] + keyPassword keystoreProperties['keyPassword'] + storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null + storePassword keystoreProperties['storePassword'] + } + } buildTypes { release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig signingConfigs.debug + signingConfig signingConfigs.release } } } @@ -68,4 +82,5 @@ flutter { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation "androidx.multidex:multidex:2.0.1" } diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml deleted file mode 100644 index 8199616..0000000 --- a/android/app/src/debug/AndroidManifest.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 3b8a0ff..164802e 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -30,5 +30,9 @@ + + diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml deleted file mode 100644 index 8199616..0000000 --- a/android/app/src/profile/AndroidManifest.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - diff --git a/lib/core/ads/ads_state.dart b/lib/core/ads/ads_state.dart new file mode 100644 index 0000000..f277c47 --- /dev/null +++ b/lib/core/ads/ads_state.dart @@ -0,0 +1,19 @@ +import 'dart:io'; + +class AdState { + static bool appInDevMode = false; + + static String get appId => "ca-app-pub-7101902781826262~1954409331"; + + static String get homePageAdUnitId => Platform.isAndroid + ? appInDevMode + ? "ca-app-pub-3940256099942544/6300978111" + : "ca-app-pub-7101902781826262/7662031583" + : ""; + + static String get detailsPageAdUnitId => Platform.isAndroid + ? appInDevMode + ? "ca-app-pub-3940256099942544/6300978111" + : "ca-app-pub-7101902781826262/6529462058" + : ""; +} diff --git a/lib/core/app/app_layout.dart b/lib/core/app/app_layout.dart index de2d77a..e648439 100644 --- a/lib/core/app/app_layout.dart +++ b/lib/core/app/app_layout.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:pokemondo/core/ads/ads_state.dart'; +import 'package:pokemondo/core/widgets/my_banner_ad.dart'; import 'package:pokemondo/features/pokemon/presentation/widgets/show_dialog.dart'; import '../../features/pokemon/presentation/favourites_bloc/bloc/favourites_bloc.dart'; @@ -155,6 +157,10 @@ class AppLayoutState extends State ), ), ), + // bottomSheet: Container( + // height: 50, + // ), + bottomNavigationBar: MyBannarAd(adUnit: AdState.homePageAdUnitId), floatingActionButton: Material( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(50), diff --git a/lib/core/widgets/my_banner_ad.dart b/lib/core/widgets/my_banner_ad.dart new file mode 100644 index 0000000..f1677ba --- /dev/null +++ b/lib/core/widgets/my_banner_ad.dart @@ -0,0 +1,108 @@ +import 'dart:developer'; + +import 'package:flutter/material.dart'; +import 'package:google_mobile_ads/google_mobile_ads.dart'; + +class MyBannarAd extends StatefulWidget { + final String adUnit; + const MyBannarAd({ + Key? key, + required this.adUnit, + }) : super(key: key); + + @override + MyBannarAdState createState() => MyBannarAdState(); +} + +class MyBannarAdState extends State { + BannerAd? _anchoredAdaptiveAd; + bool _isLoaded = false; + late Orientation _currentOrientation; + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + _currentOrientation = MediaQuery.of(context).orientation; + _loadAd(); + } + + /// Load another ad, disposing of the current ad if there is one. + Future _loadAd() async { + await _anchoredAdaptiveAd?.dispose(); + setState(() { + _anchoredAdaptiveAd = null; + _isLoaded = false; + }); + + final AnchoredAdaptiveBannerAdSize? size = + await AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize( + MediaQuery.of(context).size.width.truncate()); + + if (size == null) { + print('Unable to get height of anchored banner.'); + return; + } + + _anchoredAdaptiveAd = BannerAd( + adUnitId: widget.adUnit, + size: size, + request: AdRequest(), + listener: BannerAdListener( + onAdLoaded: (Ad ad) { + log('$ad loaded: ${ad.responseInfo}'); + setState(() { + // When the ad is loaded, get the ad size and use it to set + // the height of the ad container. + _anchoredAdaptiveAd = ad as BannerAd; + _isLoaded = true; + }); + }, + onAdFailedToLoad: (Ad ad, LoadAdError error) { + log('Anchored adaptive banner failedToLoad: $error'); + ad.dispose(); + }, + ), + ); + return _anchoredAdaptiveAd!.load(); + } + + /// Gets a widget containing the ad, if one is loaded. + /// + /// Returns an empty container if no ad is loaded, or the orientation + /// has changed. Also loads a new ad if the orientation changes. + Widget _getAdWidget() { + return OrientationBuilder( + builder: (context, orientation) { + if (_currentOrientation == orientation && + _anchoredAdaptiveAd != null && + _isLoaded) { + return SizedBox( + // color: Colors.green, + width: _anchoredAdaptiveAd!.size.width.toDouble(), + height: _anchoredAdaptiveAd!.size.height.toDouble(), + child: AdWidget(ad: _anchoredAdaptiveAd!), + ); + } + // Reload the ad if the orientation changes. + if (_currentOrientation != orientation) { + _currentOrientation = orientation; + _loadAd(); + } + return Container( + height: 0, + ); + }, + ); + } + + @override + void dispose() { + super.dispose(); + _anchoredAdaptiveAd?.dispose(); + } + + @override + Widget build(BuildContext context) { + return _getAdWidget(); + } +} diff --git a/lib/features/pokemon/presentation/pages/pokemon_details_page.dart b/lib/features/pokemon/presentation/pages/pokemon_details_page.dart index 57bebd6..7536eb3 100644 --- a/lib/features/pokemon/presentation/pages/pokemon_details_page.dart +++ b/lib/features/pokemon/presentation/pages/pokemon_details_page.dart @@ -1,5 +1,7 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; +import 'package:pokemondo/core/ads/ads_state.dart'; +import 'package:pokemondo/core/widgets/my_banner_ad.dart'; import '../widgets/base_stats_title.dart'; import '../widgets/display_pokemon_property.dart'; import '../widgets/favourite_button.dart'; @@ -59,6 +61,7 @@ class PokemonDetailsPage extends StatelessWidget { ), ), floatingActionButton: FavouriteButton(pokemon: pokemon), + bottomNavigationBar: MyBannarAd(adUnit: AdState.detailsPageAdUnitId), ); } diff --git a/lib/injection_container.dart b/lib/injection_container.dart index 1ba74ea..fdc9599 100644 --- a/lib/injection_container.dart +++ b/lib/injection_container.dart @@ -1,6 +1,7 @@ import 'package:get_it/get_it.dart'; import 'package:http/http.dart' as http; import 'package:internet_connection_checker/internet_connection_checker.dart'; +import 'package:pokemondo/core/ads/ads_state.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'core/network/network_info.dart'; @@ -103,8 +104,9 @@ Future initServices() async { serviceLocator.registerLazySingleton(() => http.Client()); - serviceLocator.registerLazySingleton(() => InternetConnectionChecker.createInstance( - checkTimeout: const Duration(seconds: 1), - checkInterval: const Duration(seconds: 1), - )); + serviceLocator + .registerLazySingleton(() => InternetConnectionChecker.createInstance( + checkTimeout: const Duration(seconds: 1), + checkInterval: const Duration(seconds: 1), + )); } diff --git a/lib/main.dart b/lib/main.dart index fd8d87d..5138e95 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_native_splash/flutter_native_splash.dart'; +import 'package:google_mobile_ads/google_mobile_ads.dart'; import 'core/app/app.dart'; import 'core/app_lang/app_lang_widget.dart'; @@ -17,6 +18,7 @@ void main() async { FlutterNativeSplash.remove(); await initServices(); await StoredConfigs.initBeforeRunApp(); + MobileAds.instance.initialize(); runApp( const SplashScreen( myApp: MyApp(), diff --git a/pubspec.lock b/pubspec.lock index 6fe9cba..e136c3d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -336,6 +336,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.0.1" + google_mobile_ads: + dependency: "direct main" + description: + name: google_mobile_ads + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" graphs: dependency: transitive description: @@ -803,6 +810,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.2" + visibility_detector: + dependency: transitive + description: + name: visibility_detector + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.3" watcher: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 720352e..e5bff5b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -47,6 +47,7 @@ dependencies: intl: ^0.17.0 palette_generator: ^0.3.3+1 shared_preferences: ^2.0.15 + google_mobile_ads: ^2.0.1 dev_dependencies: build_runner: ^2.2.0