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

PlatformiOS

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.6

Then run:

flutter pub get

Platform setup #

Follow the official setup for each SDK your app will use and apply the additional configuration below.

Android configuration #

  1. Project-level Gradle (android/build.gradle)

    Add the AppLovin repository and configure dependencies with version alignment:

    buildscript {
        repositories {
            google()
            mavenCentral()
            maven { url = uri("https://artifacts.applovin.com/android") }
        }
        dependencies {
            classpath 'com.android.tools.build:gradle:8.1.2' // Use your current version
            classpath 'com.google.gms:google-services:4.3.15' // Add this line for Google Services
        }
    }
    
    allprojects {
        repositories {
            google()
            mavenCentral()
            maven { url = uri("https://artifacts.applovin.com/android") }
        }
        configurations.all {
            resolutionStrategy {
                force(
                        "com.google.android.gms:play-services-ads:24.7.0",
                        "com.applovin.mediation:google-adapter:24.7.0.0"
                )
            }
        }
    }
    

    Note: Adapt versions to the latest recommended by google_mobile_ads and applovin_max packages.

  2. App-level Gradle (android/app/build.gradle)

    Add the mediation adapter dependencies to the dependencies block:

    dependencies {
        // Align Google Mobile Ads SDK with AppLovin Google adapter
        implementation("com.google.android.gms:play-services-ads:24.7.0")
        implementation("com.applovin.mediation:google-adapter:24.7.0.0")
    }
    
  3. AndroidManifest (android/app/src/main/AndroidManifest.xml)

    Add required permissions, AdMob application ID, and AppLovin MAX activities:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools">
    
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    
        <application
            android:name="${applicationName}"
            android:icon="@mipmap/launcher_icon"
            android:label="YOUR_APP_NAME">
               
            <!-- Your main activity configuration -->
            <activity
                android:name=".MainActivity"
                android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
                android:exported="true"
                android:hardwareAccelerated="true"
                android:launchMode="singleTask"
                android:taskAffinity="${applicationId}"
                android:theme="@style/LaunchTheme"
                android:windowSoftInputMode="adjustResize">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
    
            <!-- AdMob App ID required for Google Mobile Ads SDK initialization -->
            <meta-data
                android:name="com.google.android.gms.ads.APPLICATION_ID"
                android:value="YOUR_ADMOB_APP_ID_ANDROID" />
                   
            <!-- AppLovin MAX Ad Activities - Force them to use our task -->
            <activity
                android:name="com.applovin.adview.AppLovinInterstitialActivity"
                android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
                android:excludeFromRecents="true"
                android:taskAffinity="${applicationId}"
                tools:replace="android:configChanges,android:taskAffinity" />
            <activity
                android:name="com.applovin.adview.AppLovinFullscreenActivity"
                android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
                android:excludeFromRecents="true"
                android:taskAffinity="${applicationId}"
                tools:replace="android:configChanges,android:taskAffinity" />
            <!-- Optional: For webview-based ads or browsers -->
            <activity
                android:name="com.applovin.sdk.AppLovinWebViewActivity"
                android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
                android:excludeFromRecents="true"
                android:taskAffinity="${applicationId}"
                tools:replace="android:configChanges,android:taskAffinity" />
            <!-- Optional: If using the mediation debugger -->
            <!-- REMOVE THIS IN PRODUCTION -->
    <!--        <activity-->
    <!--            android:name="com.applovin.mediation.MaxDebuggerActivity"-->
    <!--            android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"-->
    <!--            android:excludeFromRecents="true"-->
    <!--            android:taskAffinity="${applicationId}"-->
    <!--            tools:replace="android:configChanges,android:taskAffinity" />-->
               
            <meta-data
                android:name="flutterEmbedding"
                android:value="2" />
        </application>
           
        <queries>
            <intent>
                <action android:name="android.intent.action.PROCESS_TEXT" />
                <data android:mimeType="text/plain" />
            </intent>
        </queries>
    </manifest>
    

    Important:

    • Replace YOUR_ADMOB_APP_ID_ANDROID with your real AdMob app ID
    • Replace YOUR_APP_NAME with your app name
    • The AppLovin MAX activities ensure ads stay within your app's task
    • Uncomment the debugger activity only during development
    • The <queries> tag is required for some ad networks to work properly

iOS configuration #

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