On this page14 sections
  1. Prerequisites
  2. Connection With Previous Lectures
  3. Learning Objectives
  4. Lesson
  5. 1. The Helper
  6. 2. The Screen
  7. 3. Be Clear Before the Ad
  8. Code Examples
  9. Common Beginner Mistakes
  10. Best Practices
  11. Mini Challenge
  12. Practice Questions
  13. Practice Answers
  14. Key Takeaways

Lecture 008 — Rewarded Ads

Category3 — Native & Rewarded Ads
Lecture008 of 010
Estimated video length22 min
TargetFlutter 3.44 · Dart 3.12 · google_mobile_ads 9
LevelBeginner
Source codeGitHub — urraan_admob_final

A rewarded ad is the user's choice: watch a short ad, get something — coins, an extra try, an unlocked file. Because the user chose it, it is the best-liked ad format.

Contents

Prerequisites · Connection · Objectives · Lesson · Code Examples · Common Mistakes · Best Practices · Mini Challenge · Practice Questions · Answers · Takeaways


Prerequisites

Lectures 001–005.


Connection With Previous Lectures

Interstitials interrupt the user. Rewarded ads let the user say yes first — that is why the button text matters.


Learning Objectives

By the end of this lecture you will be able to:

  • Load and show a RewardedAd
  • Receive the reward in onUserEarnedReward
  • Handle "not ready" gracefully
  • Explain the flow before the ad

Lesson

1. The Helper

dart
// lib/admob/rewarded_ad_helper.dart
import 'package:flutter/foundation.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';

import 'admob_manager.dart';

class RewardedAdHelper {
  bool isAdLoaded = false;
  RewardedAd? _rewardedAd;

  void loadRewardedAd({
    required VoidCallback onAdShowFullScreen,
    required VoidCallback onAdDismissed,
  }) {
    RewardedAd.load(
      adUnitId: AdmobManager.rewardedId,
      request: const AdRequest(),
      rewardedAdLoadCallback: RewardedAdLoadCallback(
        onAdLoaded: (ad) {
          isAdLoaded = true;
          _rewardedAd = ad;

          ad.fullScreenContentCallback = FullScreenContentCallback(
            onAdShowedFullScreenContent: (_) => onAdShowFullScreen(),
            onAdDismissedFullScreenContent: (ad) {
              ad.dispose();
              isAdLoaded = false;
              _rewardedAd = null;
              onAdDismissed();
              loadRewardedAd(
                onAdShowFullScreen: onAdShowFullScreen,
                onAdDismissed: onAdDismissed,
              );
            },
            onAdFailedToShowFullScreenContent: (ad, error) {
              ad.dispose();
              isAdLoaded = false;
              _rewardedAd = null;
            },
          );
        },
        onAdFailedToLoad: (error) {
          isAdLoaded = false;
          debugPrint('Rewarded failed: ${error.code} ${error.message}');
        },
      ),
    );
  }

  /// Returns false when no ad is ready, so the screen can tell the user.
  bool showAdIfAvailable(void Function(RewardItem reward) onEarnedReward) {
    if (_rewardedAd == null || !isAdLoaded) return false;
    _rewardedAd!.show(
      onUserEarnedReward: (_, reward) => onEarnedReward(reward),
    );
    return true;
  }

  void dispose() => _rewardedAd?.dispose();
}
  • showAdIfAvailable returns true if it showed the ad, false if none was ready.
  • The reward arrives in onUserEarnedReward — grant it there, not when the ad closes, because a user who skips early gets no reward.
  • After dismissal we load the next ad.

2. The Screen

dart
// lib/screen_rewarded_ads.dart
import 'package:flutter/material.dart';

import 'admob/ad_state.dart';
import 'admob/rewarded_ad_helper.dart';

class ScreenRewardedAds extends StatefulWidget {
  const ScreenRewardedAds({super.key});

  @override
  State<ScreenRewardedAds> createState() => _ScreenRewardedAdsState();
}

class _ScreenRewardedAdsState extends State<ScreenRewardedAds> {
  final rewardedAdHelper = RewardedAdHelper();
  int _coins = 0;

  @override
  void initState() {
    super.initState();
    rewardedAdHelper.loadRewardedAd(
      onAdShowFullScreen: () => AdState().disableAppOpenAds(),
      onAdDismissed: () => AdState().enableAppOpenAdsAfterCooldown(),
    );
  }

  @override
  void dispose() {
    rewardedAdHelper.dispose();
    super.dispose();
  }

  void _watchAd() {
    final shown = rewardedAdHelper.showAdIfAvailable((reward) {
      setState(() => _coins += reward.amount.toInt());
    });
    if (!shown) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('Ad is not ready yet, try again')),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Rewarded Ads')),
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Text('Coins: $_coins', style: const TextStyle(fontSize: 24)),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: _watchAd,
              child: const Text('Watch an ad to earn coins'),
            ),
          ],
        ),
      ),
    );
  }
}
  • _coins += reward.amount runs only when the reward is earned.
  • If no ad is ready, a SnackBar explains; the user is never silently ignored.

3. Be Clear Before the Ad

The button text should say what happens: "Watch an ad to earn coins". If the text is not clear, show a short dialog first (see the next lecture).


Code Examples

Example 1 — The Reward Item

RewardItem has an amount and a type set in the AdMob dashboard when you create the ad unit (for example coins / 10). Test ads return a small default value.


Common Beginner Mistakes

1. Giving the reward on dismiss — users who close early would be rewarded unfairly.

2. Showing a rewarded ad without a clear button — users feel tricked; policy risk.

3. Ignoring "not ready" — the button seems broken.

4. Not disposing.


Best Practices

  • Make the reward obvious in the button text
  • Grant the reward only in onUserEarnedReward
  • Handle a not-ready ad with a message

Mini Challenge

Disable the button until rewardedAdHelper.isAdLoaded is true (use setState from the load callback).


Practice Questions

  1. Where is the reward granted?
  2. What does showAdIfAvailable return?
  3. Why a clear button?
  4. What dashboard value defines the reward?

Practice Answers

  1. onUserEarnedReward.
  2. Whether the ad was shown.
  3. So users know they are choosing to watch.
  4. The reward amount and type on the ad unit.

Key Takeaways

  • Rewarded = user choice + reward callback
  • Always handle not-ready
  • Clear text beats surprise