You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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异常。

正确的做法是:

  1. 初始化时加载第一个广告
  2. 在广告播放完成、加载失败、展示失败的回调里,立即加载下一个广告,保证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

火山引擎 最新活动