Skip to content

ikeno-web/flutter_admob_kit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

flutter_admob_kit

pub package CI coverage license

The missing high-level AdMob wrapper for Flutter.

Stop writing hundreds of lines of boilerplate for every ad format. flutter_admob_kit gives you banner, interstitial, rewarded, and app-open ads with a clean API, automatic UMP consent handling, and zero dependency on any state management framework.

Features

  • One-line initialization -- await adManager.initialize() sets up AdMob SDK + UMP consent in one call
  • Widget API + Imperative API -- Drop-in widgets for declarative UI, or call methods from business logic
  • Automatic test/production switching -- Debug builds use Google's test ad IDs; release builds use yours
  • UMP consent flow -- GDPR/CCPA consent handled automatically; manual trigger available for settings screens
  • Retry with exponential backoff -- Failed loads retry automatically (configurable attempts and delay)
  • Frequency capping -- Prevent interstitial ad fatigue with configurable cooldown
  • App-open ads -- Show ads on foreground resume with optional cold-start skip
  • Event streaming -- Forward ad events to Firebase Analytics or any analytics service
  • Fully testable -- Ships with FakeAdManager for unit and widget tests
  • State-management agnostic -- Works with Provider, Riverpod, Bloc, GetX, or plain Flutter

Install

Add to your pubspec.yaml:

dependencies:
  flutter_admob_kit: ^0.1.0
  google_mobile_ads: ^5.0.0  # peer dependency -- you manage the version

Platform setup

Android -- Add your AdMob App ID to AndroidManifest.xml:

<manifest>
  <application>
    <meta-data
      android:name="com.google.android.gms.ads.APPLICATION_ID"
      android:value="ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy"/>
  </application>
</manifest>

iOS -- Add your AdMob App ID to Info.plist:

<key>GADApplicationIdentifier</key>
<string>ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy</string>

Quick Start

1. Initialize

import 'package:flutter/material.dart';
import 'package:flutter_admob_kit/flutter_admob_kit.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  final adManager = AdManager(
    config: AdConfig(
      bannerId: AdUnitId(
        android: 'ca-app-pub-xxxxx/banner-android',
        ios: 'ca-app-pub-xxxxx/banner-ios',
      ),
      interstitialId: AdUnitId(
        android: 'ca-app-pub-xxxxx/interstitial-android',
        ios: 'ca-app-pub-xxxxx/interstitial-ios',
      ),
      rewardedId: AdUnitId(
        android: 'ca-app-pub-xxxxx/rewarded-android',
        ios: 'ca-app-pub-xxxxx/rewarded-ios',
      ),
      testDeviceIds: ['YOUR_TEST_DEVICE_ID'],
    ),
  );

  await adManager.initialize();

  runApp(MyApp(adManager: adManager));
}

2. Show a banner ad

// Drop into any widget tree -- that's it.
BannerAdWidget(manager: adManager)

// Or use an adaptive banner that fills the available width:
BannerAdWidget.adaptive(manager: adManager)

3. Show an interstitial ad

Widget API -- wrap any widget to show an ad on tap:

InterstitialTrigger(
  manager: adManager,
  onComplete: () => Navigator.push(context, nextRoute),
  onSkipped: () => Navigator.push(context, nextRoute),
  child: ElevatedButton(
    onPressed: null, // controlled by InterstitialTrigger
    child: Text('Next Level'),
  ),
)

Imperative API -- call from business logic:

await adManager.loadInterstitial();

// Later, when ready to show:
final shown = await adManager.showInterstitial();
if (!shown) {
  // Ad wasn't ready or frequency cap active -- proceed normally
}

4. Show a rewarded ad

await adManager.loadRewarded();

final reward = await adManager.showRewarded();
if (reward != null) {
  gameState.addCoins(reward.amount);
}

5. UMP consent (automatic)

Consent is handled automatically during initialize(). For a manual settings-screen trigger:

final result = await adManager.consent.requestConsent();

switch (result) {
  case ConsentResult.obtained:
    print('Personalized ads allowed');
  case ConsentResult.denied:
    print('Non-personalized ads only');
  case ConsentResult.error:
    print('Consent check failed, using non-personalized');
}

6. App-open ads

final adManager = AdManager(
  config: AdConfig(
    bannerId: AdUnitId(android: '...', ios: '...'),
    appOpenId: AdUnitId(
      android: 'ca-app-pub-xxxxx/appopen-android',
      ios: 'ca-app-pub-xxxxx/appopen-ios',
    ),
    skipColdStartAppOpen: true, // skip on first launch
  ),
);

await adManager.initialize();
adManager.enableAppOpenAd(); // shows on foreground resume

7. Event tracking

adManager.onAdEvent.listen((event) {
  switch (event.type) {
    case AdEventType.shown:
      analytics.logEvent(name: 'ad_shown');
    case AdEventType.rewardEarned:
      print('Earned ${event.reward!.amount} ${event.reward!.type}');
    case AdEventType.paidEvent:
      final pv = event.paidValue!;
      analytics.logRevenue(pv.valueMicros, pv.currencyCode);
    default:
      break;
  }
});

Testing

The package ships with FakeAdManager so your tests never touch real ads:

import 'package:flutter_admob_kit/flutter_admob_kit.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  test('reward is granted after watching ad', () async {
    final fake = FakeAdManager();
    fake.nextRewardedResult = const AdReward(amount: 50, type: 'gems');

    await fake.initialize();
    await fake.loadRewarded();
    final reward = await fake.showRewarded();

    expect(reward?.amount, 50);
    expect(reward?.type, 'gems');
  });
}

Configuration Reference

Parameter Default Description
bannerId required Banner ad unit ID (Android + iOS)
interstitialId null Interstitial ad unit ID (null = disabled)
rewardedId null Rewarded ad unit ID (null = disabled)
appOpenId null App-open ad unit ID (null = disabled)
testDeviceIds [] Physical device IDs for test ads
frequencyCapSeconds 60 Min seconds between interstitial impressions
maxRetryCount 3 Retry attempts on load failure
retryBaseDelayMs 1000 Base delay for exponential backoff (ms)
loadTimeoutSeconds 30 Timeout per load attempt (seconds)
skipColdStartAppOpen true Skip app-open ad on first launch

Requirements

Platform Minimum
Flutter 3.22+
Dart 3.4+
Android API 21+
iOS 14.0+

License

MIT -- see LICENSE.

About

Unified AdMob management for Flutter. Instance-based, testable, with retry, frequency cap, and FakeAdManager.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages