Flutter集成Google Admob激励视频广告PlatformException未捕获问题求助
解决Flutter AdMob激励视频广告的PlatformException问题
嘿,我之前帮不少开发者排查过类似的AdMob广告问题,咱们先拆解下你遇到的两个核心痛点:try-catch抓不到异常,以及广告播完后二次点击报错,一步步来解决。
一、先搞定try-catch无法捕获异常的问题
你之所以抓不到这个PlatformException,大概率是因为调用广告展示方法的姿势不对。AdMob的激励广告展示方法是异步的,如果你的代码没有用async/await配合try-catch完整包裹,异常就会“逃逸”到全局,自然抓不到。
给你个正确的示例:
ElevatedButton( onPressed: () async { try { await RewardedAd.instance.show( onUserEarnedReward: (AdWithoutView ad, RewardItem reward) { // 处理用户获得奖励的逻辑 ad.dispose(); }, ); } on PlatformException catch (e) { print("广告展示失败: ${e.message}"); // 这里可以做重试加载或者提示用户的操作 await loadRewardedAd(); } catch (e) { print("其他异常: $e"); } }, child: const Text("观看广告得奖励"), )
关键是把onPressed设为异步函数,用await等待show方法执行完成,这样try-catch才能捕获到异步抛出的异常。
二、解决广告播放完成后无可用广告的问题
这才是根源问题——你只在初始化时加载了一次广告,播放完成后没有重新加载新的广告,第二次点击时自然没有可用广告,触发ad_not_loaded异常。
正确的做法是:
- 初始化时加载第一个广告
- 在广告播放完成、加载失败、展示失败的回调里,立即加载下一个广告,保证App里随时有可用广告
完整的实现示例
RewardedAd? _rewardedAd; // 封装加载广告的方法 Future<void> loadRewardedAd() async { try { _rewardedAd = RewardedAd( adUnitId: "你的广告单元ID", // 测试环境建议用官方测试ID request: const AdRequest(), listener: RewardedAdListener( onAdLoaded: (Ad ad) => print("广告加载成功"), onAdFailedToLoad: (Ad ad, LoadAdError error) { print("广告加载失败: ${error.message}"); ad.dispose(); // 加载失败后延迟几秒重试,避免频繁请求触发限制 Future.delayed(const Duration(seconds: 3), () => loadRewardedAd()); }, onAdClosed: (Ad ad) { print("广告关闭"); ad.dispose(); // 广告关闭后立即加载下一个,保证下次点击有广告可用 loadRewardedAd(); }, onUserEarnedReward: (AdWithoutView ad, RewardItem reward) { print("用户获得奖励: ${reward.amount} ${reward.type}"); // 这里处理给用户发奖励的逻辑,比如加金币、解锁功能 }, ), ); await _rewardedAd!.load(); } catch (e) { print("加载广告时出错: $e"); } } // 在页面初始化时加载第一个广告 @override void initState() { super.initState(); loadRewardedAd(); } // 按钮点击的展示逻辑 void _showRewardedAd() async { if (_rewardedAd != null) { try { await _rewardedAd!.show( onUserEarnedReward: (AdWithoutView ad, RewardItem reward) { print("用户获得奖励: ${reward.amount}"); }, ); } on PlatformException catch (e) { print("广告展示失败: ${e.message}"); // 展示失败后立即加载新广告 loadRewardedAd(); } catch (e) { print("其他异常: $e"); } } else { // 如果当前没有可用广告,提示用户并触发加载 print("暂无可用广告,请稍后再试"); loadRewardedAd(); } } // 页面销毁时记得销毁广告实例,避免内存泄漏 @override void dispose() { _rewardedAd?.dispose(); super.dispose(); }
三、额外的注意事项
- 测试环境建议用AdMob官方提供的测试ID(比如Android测试ID:
ca-app-pub-3940256099942544/5224354917),避免因为账号审核、额度问题导致广告加载失败 - 不要频繁调用加载广告的方法,AdMob有请求频率限制,加载失败后设置3-5秒的延迟重试比较合适
- 每次广告使用完成后,一定要调用
dispose()销毁旧实例,再加载新广告,避免内存泄漏
内容的提问来源于stack exchange,提问作者nigale




