diff --git a/packages/firebase_admob/CHANGELOG.md b/packages/firebase_admob/CHANGELOG.md index 9b16c5e7c762..f8ee9733c879 100644 --- a/packages/firebase_admob/CHANGELOG.md +++ b/packages/firebase_admob/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.9.0+8 + +* Handle exception in `BannerAd.dispose()` call for `no_ad_for_id` scenario. + ## 0.9.0+7 * Update Android gradle plugin, gradle, and Admob versions. diff --git a/packages/firebase_admob/lib/firebase_admob.dart b/packages/firebase_admob/lib/firebase_admob.dart index 70289b2b5dc2..17211e07de57 100644 --- a/packages/firebase_admob/lib/firebase_admob.dart +++ b/packages/firebase_admob/lib/firebase_admob.dart @@ -238,7 +238,7 @@ abstract class MobileAd { /// Disposing a banner ad that's been shown removes it from the screen. /// Interstitial ads can't be programmatically removed from view. Future dispose() { - assert(_allAds[id] != null); + if (_allAds[id] == null) return Future.value(true); _allAds[id] = null; return _invokeBooleanMethod("disposeAd", {'id': id}); } @@ -520,9 +520,19 @@ class FirebaseAdMob { } Future _invokeBooleanMethod(String method, [dynamic arguments]) async { - final bool result = await FirebaseAdMob.instance._channel.invokeMethod( - method, - arguments, - ); + bool result = false; + try { + result = await FirebaseAdMob.instance._channel.invokeMethod( + method, + arguments, + ); + } on PlatformException catch (e) { + if (e.code == "no_ad_for_id") { + result = false; + return result; + } + rethrow; + } + return result; } diff --git a/packages/firebase_admob/pubspec.yaml b/packages/firebase_admob/pubspec.yaml index d741765b358a..f719fe72d82c 100644 --- a/packages/firebase_admob/pubspec.yaml +++ b/packages/firebase_admob/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase AdMob, supporting banner, interstitial (full-screen), and rewarded video ads author: Flutter Team homepage: https://github.com/FirebaseExtended/flutterfire/tree/master/packages/firebase_admob -version: 0.9.0+7 +version: 0.9.0+8 flutter: plugin: diff --git a/packages/firebase_admob/test/firebase_admob_test.dart b/packages/firebase_admob/test/firebase_admob_test.dart index e2a8bc5a6fba..0b46908395be 100644 --- a/packages/firebase_admob/test/firebase_admob_test.dart +++ b/packages/firebase_admob/test/firebase_admob_test.dart @@ -18,6 +18,8 @@ void main() { final List log = []; final FirebaseAdMob admob = FirebaseAdMob.private(channel); + int invalidAdId; + setUp(() async { channel.setMockMethodCallHandler((MethodCall methodCall) async { log.add(methodCall); @@ -29,6 +31,15 @@ void main() { case 'showAd': case 'showRewardedVideoAd': case 'disposeAd': + if (methodCall.arguments != null) { + if (methodCall.arguments.containsKey('id') && + (invalidAdId != null)) { + if (invalidAdId == methodCall.arguments['id']) { + invalidAdId = null; + throw PlatformException(code: 'no_ad_for_id'); + } + } + } return Future.value(true); default: assert(false); @@ -138,5 +149,24 @@ void main() { isMethodCall('showRewardedVideoAd', arguments: null), ]); }); + + test('noAdForId', () async { + log.clear(); + + final BannerAd banner = BannerAd( + adUnitId: BannerAd.testAdUnitId, + size: AdSize.banner, + ); + final int id = banner.id; + invalidAdId = banner.id; + + expect(await banner.dispose(), false); + + expect(log, [ + isMethodCall('disposeAd', arguments: { + 'id': id, + }), + ]); + }); }); }