vie_app_ads_manager 1.0.0 copy "vie_app_ads_manager: ^1.0.0" to clipboard
vie_app_ads_manager: ^1.0.0 copied to clipboard

Simple ads manager for admob and applovin ads

vie_app_ads_manager #

A lightweight, opinionated ads manager for Flutter that unifies AdMob (Google Mobile Ads) and AppLovin MAX into a single, simple API.

Features #

  • Full Ad Format Support: Interstitial, Rewarded, Rewarded-Interstitial (AdMob), App Open, Banner, Native
  • Smart Fallback System: Automatic fallback from AdMob to AppLovin MAX when configured
  • Remote Config Driven Providers: Select AdMob/MAX and enable flags via Firebase Remote Config
  • Widget-Based Ads: Banner and Native ad widgets that auto-select provider via RC
  • Event Streaming: Real-time ad lifecycle events for UI state management
  • Test Mode Support: Built-in AppLovin MAX mediation debugger and AdMob test ads
  • Robust Error Handling: Comprehensive logging and state management

Works with: google_mobile_ads, applovin_max.

Installation #

Add to your pubspec.yaml:

dependencies:
  vie_app_ads_manager: ^1.0.0

Then run:

flutter pub get

Platform setup #

Follow the official setup for each SDK your app will use.

Make sure you use your own ad unit IDs in production. Use test IDs during development.

Getting started #

Import the package:

import 'package:vie_app_ads_manager/ads_manager.dart';

Initialize as early as possible (e.g., in main or first page load). You must initialize Firebase and the provided AnalyticsManager to fetch Remote Config before initializing AdsManager:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(home: const Home());
  }
}

class Home extends StatefulWidget {
  const Home({super.key});
  @override
  State<Home> createState() => _HomeState();
}

class _HomeState extends State<Home> {
  bool _initializing = true;

  @override
  void initState() {
    super.initState();
    _initAds();
  }

  Future<void> _initAds() async {
    // 1) Initialize Analytics + Remote Config
    await AnalyticsManager.instance.init(
      options: /* Your DefaultFirebaseOptions.currentPlatform */, 
      minimumFetchInterval: Duration.zero,
    );

    // 2) Provide your AdMob and (optionally) AppLovin MAX IDs
    final admobIds = AdmobIds(
      appIdAndroid: 'YOUR_ADMOB_APP_ID_ANDROID',
      appIdIos: 'YOUR_ADMOB_APP_ID_IOS',
      bannerId: 'YOUR_ADMOB_BANNER_ID',
      interstitialId: 'YOUR_ADMOB_INTERSTITIAL_ID',
      rewardedId: 'YOUR_ADMOB_REWARDED_ID',
      rewardedInterstitialId: 'YOUR_ADMOB_REWARDED_INTERSTITIAL_ID',
      nativeId: 'YOUR_ADMOB_NATIVE_ID',
      appOpenId: 'YOUR_ADMOB_APPOPEN_ID',
    );

    // Optional: provide AppLovin MAX IDs to enable fallback or to force MAX
    final maxIds = MaxIds(
      sdkKey: 'YOUR_MAX_SDK_KEY',
      bannerId: 'YOUR_MAX_BANNER_ID',
      interstitialId: 'YOUR_MAX_INTERSTITIAL_ID',
      rewardedId: 'YOUR_MAX_REWARDED_ID',
      nativeId: 'YOUR_MAX_NATIVE_ID',
      appOpenId: 'YOUR_MAX_APPOPEN_ID',
    );

    // 3) Initialize AdsManager (it will read provider flags from Remote Config)
    await AdsManager.instance.initialize(
      admobIds: admobIds,
      maxIds: maxIds,
      adjustAppToken: 'YOUR_ADJUST_APP_TOKEN',
    );
    if (!mounted) return;
    setState(() => _initializing = false);
  }
}

## Remote Config Provider Control

Provider selection and feature flags are controlled via Firebase Remote Config (RC). Configure these keys in RC:

- `show_banner` (bool): enable/disable banner widget
- `native_ad_enabled` (bool): enable/disable native widget
- `show_app_open` (bool): enable/disable app open button/flow
- `banner_provider` (int): 0=off, 1=AdMob only, 2=MAX only
- `interstitial_provider` (int): 0=off, 1=AdMob only, 2=MAX only
- `reward_provider` (int): 0=off, 1=AdMob only, 2=MAX only
- `app_open_provider` (int): 0=off, 1=AdMob only, 2=MAX only
- `native_ad_provider` (int): 0=off, 1=AdMob only, 2=MAX only

AdsManager reads these values during `initialize()` via `AnalyticsManager`.

### How selection works

- `0` → No-Op: show methods return false; widgets render nothing
- `1` → AdMob only (no MAX fallback)
- `2` → MAX only
- Otherwise: default logic attempts AdMob first, with MAX as fallback when available

### Interstitial
```dart
// Provider is selected via RC
final shown = await AdsManager.instance.showInterstitial();

Rewarded #

final shown = await AdsManager.instance.showRewarded(
  onEarnedReward: (amount) {
    // grant reward
  },
);

App Open #

final shown = await AdsManager.instance.showAppOpen();

Widgets #

A banner widget that auto-selects provider via Remote Config, with automatic fallback when allowed.

// Default behavior (provider sourced from RC)
const BannerAdManager()

// Custom size
const BannerAdManager(adSize: AdSize.largeBanner)

Note: AdSize is re-exported by this package. You only need:

import 'package:ads_manager/ads_manager.dart';

No direct import from google_mobile_ads is required just to use AdSize.

Native #

A native ad widget that auto-selects provider via Remote Config, with automatic fallback when allowed.

// Default behavior (provider sourced from RC)
const NativeAdManager(height: 300)

// Custom styling
NativeAdManager(
  height: 300,
  style: NativeTemplateStyle(templateType: TemplateType.medium),
)

Events #

Listen to the stream for ad lifecycle events to drive UI state (e.g., loading spinners):

final sub = AdsManager.instance.onEvent.listen((event) {
  final type = event.keys.first;  // AdUnitType
  final ev = event.values.first;  // AdEventType
  // handle
});

AdUnitType: banner, interstitial, rewarded, rewardedInterstitial, native, appOpen

AdEventType: loading, loaded, failedToLoad, showed, dismissed, failedToShow, earnedReward

Testing & Debugging #

AppLovin MAX Test Mode #

The ads manager automatically enables AppLovin MAX mediation debugger during initialization for testing purposes. This provides:

  • Real-time mediation waterfall information
  • Network adapter status
  • Test ad controls
  • Revenue and performance metrics

AdMob Test Ads Helper #

You can switch to AdMob test IDs at runtime and preload again:

await AdsManager.instance.showTestAds();

This is handy to validate your integration without touching your production IDs.

Provider-Based Testing #

Use the helper to switch to AdMob test IDs. To simulate networks, change RC provider keys at runtime and call AnalyticsManager().refreshRemoteConfig() before showing again.

// Switch to AdMob test IDs and preload test ads
await AdsManager.instance.showTestAds();

// Change RC: banner_provider / interstitial_provider / reward_provider / app_open_provider
await AnalyticsManager().refreshRemoteConfig();

Example #

See the example/ app for a full usage demo with buttons for interstitial, rewarded, app open, banner, and native ads plus event-handling.

Notes & Tips #

General #

  • Always use Google's test IDs or your own test placements during development to avoid policy violations.
  • AppLovin MAX requires your real SDK key and ad unit IDs. Ensure network permissions and platform setup are complete.
  • If you prefer not to use MAX, initialize without max: and the manager will work with AdMob only.

Provider Behavior #

  • Provider 0 (no ads): All show methods return false. Banner/Native widgets render nothing and do not load.
  • Provider 1 (AdMob only): No fallback to MAX, even if MAX is configured. Use this for pure AdMob testing.
  • Provider 2 (MAX only): Direct MAX ad loading, bypasses AdMob entirely.
  • Default (null provider): Smart fallback system - tries AdMob first, falls back to MAX on failure.
  • Widgets: Banner and Native widgets respect provider settings and handle fallbacks accordingly.

Performance #

  • MAX mediation debugger adds overhead - disable in production builds if needed.
  • Provider selection allows you to test individual networks without interference.
  • Event streaming helps optimize UI responsiveness during ad loading.

License #

MIT