flutter_prakash_ads 0.0.3
flutter_prakash_ads: ^0.0.3 copied to clipboard
A policy-compliant Google Mobile Ads (AdMob) suite for Flutter with offline fallbacks, reactive ad-free mode, and zero DI lock-in.
Flutter Prakash Ads (flutter_prakash_ads) #
An enterprise-grade, policy-compliant, standalone Google Mobile Ads package for Flutter applications. Built with zero dependency-injection lock-in, reactive "Remove Ads" toggles, offline fallback house ads, unified analytics telemetry, and ready-to-use Agent Skills for autonomous AI integration.
πΈ Showcase & Interactive Previews #
| 1. Feed Integration & Banners | 2. Rich Native Ad Templates | 3. Rewarded Content & Medium Ads |
|---|---|---|
| [Clean Feed with In-line Native Ad and Bottom Anchored Adaptive Banner] | [Large Fluid Medium Native Ad Card with Policy Badge and Install CTA] | [Gated Rewarded Video Ad Unlock Trigger and Sponsored Ad Unit] |
| Anchored Adaptive Banner & Small Native Ad | Fluid Medium Native Ad Template (350px) | Gated Rewarded Video Trigger & Inline 300x250 |
π₯ Watch Full Video Demonstration (MP4)
The video walk-through demonstrates:
- β‘ Instant App Open Ad cold-start transition without UI freezing.
- π Smooth Adaptive Banner & Native Ad Rendering inline within scrollable feed lists.
- π Rewarded Video Ad Flow unlocking gated content with coin/reward callbacks.
- π« Instant "Remove Ads" (Ad-Free Mode) hiding all mounted banners and native ads in real-time.
- π Automatic Offline House Ad Fallback when connectivity is lost or fill fails.
β¨ Features #
- π‘οΈ Zero DI Lock-in: Fully standalone. Works out of the box with Riverpod, BLoC/Cubit, Provider, GetX, or vanilla Flutter without requiring
injectableorget_it. - β‘ Zero-Latency Conditional Network Architecture: If custom ads are not configured (
AdsManager.setupCustomAds(...)), the package completely skips all network/internet checks for banner, native, and full-screen adsβeliminating DNS lookups, latency, and socket pings. AdMob ads request immediately. - βοΈ One-Line Production/Test Switching: Switch seamlessly between official Google test ads and production AdMob units using
AdManager.setRealAds(...). - π Reactive "Remove Ads" (IAP): Instantly hide and dispose all mounted banner and native ads across the widget tree with
AdManager.setAdsEnabled(false). - π¨ Custom / House Ads & Offline Fallbacks: Render promotional or offline ads (
CustomAdModel) with asset/network images, custom badges, and centralized click routing (AdManager.onCustomAdClicked). If custom ads are not configured, widgets cleanly collapse without showing unwanted placeholder ads. - π Unified Analytics Telemetry: Capture all lifecycle events (Loaded, Failed, Showed, Dismissed, Clicked, Impression, Paid / ILRD, Reward Earned) via
AdManager.onAdEventorAdManager.adEventStreamfor logging to Firebase Analytics, Adjust, AppsFlyer, etc. - π€ Agentic Coding Ready (
SKILL.md): Includes official agent skill instructions in.agents/skills/flutter-prakash-ads/SKILL.mdfor AI pair programmers and autonomous coding assistants. - π Anchored Adaptive Banners: Built-in
SmartBannerAdView.getAnchoredAdaptiveAdSize(context)to maximize fill rates and eCPMs. - πΆ COPPA & Google Play Families Policy Ready: Configure child-directed treatment, age of consent, and content rating tags with
AdManager.updateRequestConfiguration(...). - π GDPR / UMP Consent Ready: Built-in
ConsentManagerfor EEA/UK GDPR compliance and privacy options revocation forms with local caching resilience. - β±οΈ AdMob & Play Policy Guardrails:
- Anti-Stacking Collision: Prevents App Open, Interstitial, and Rewarded ads from ever presenting simultaneously.
- 4-Hour Max-Age Expiration: Automatically evicts stale cached impressions.
- 30s Interstitial Throttling: Prevents rapid ad spam and user fatigue.
- App Open Cold-Start & Background Guards: 4-second timeout deadline and 15-second background threshold.
- CLS Prevention: Fixed dimensional bounding prevents Cumulative Layout Shifts and accidental clicks without distracting spinners.
π± Supported Ad Formats #
| Format | Widget / Service | Description |
|---|---|---|
| Banner | SmartBannerAdView |
Adaptive / fixed banners with offline fallback and CLS protection |
| Native | SmartNativeAdView |
Small (90px) & Medium (350px) native templates with fallback |
| Interstitial | AdsService.showInterstitialAd |
Full-screen interstitial with 30s throttling & collision prevention |
| Rewarded Video | AdsService.showRewardedAd |
Rewarded ad with verified server/client reward callbacks |
| Rewarded Interstitial | AdsService.showRewardedInterstitialAd |
Rewarded interstitial format with reward completion callbacks |
| App Open | AppOpenAdManager |
Policy-compliant cold-start & resume app open ads |
π Getting Started #
1. Add Dependency #
Add flutter_prakash_ads to your pubspec.yaml:
dependencies:
flutter_prakash_ads: ^0.0.3
2. Platform Setup #
Android (android/app/src/main/AndroidManifest.xml)
Add your Google AdMob App ID inside the <application> tag:
<manifest>
<!-- Recommended Permissions -->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="com.google.android.gms.permission.AD_ID"/>
<application>
<!-- AdMob App ID (Replace with your real Android App ID in production) -->
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-3940256099942544~3347511713"/>
<!-- Optional: AdMob initialization and loading optimizations -->
<meta-data
android:name="com.google.android.gms.ads.flag.OPTIMIZE_INITIALIZATION"
android:value="true"/>
<meta-data
android:name="com.google.android.gms.ads.flag.OPTIMIZE_AD_LOADING"
android:value="true"/>
</application>
</manifest>
iOS (ios/Runner/Info.plist)
Add GADApplicationIdentifier and recommended SKAdNetworkItems:
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-3940256099942544~1458002511</string>
<key>SKAdNetworkItems</key>
<array>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>cstr6suwn9.skadnetwork</string>
</dict>
</array>
π‘ Quick Start & Usage Examples #
1. Initialize SDK & Consent in main() #
import 'package:flutter/material.dart';
import 'package:flutter_prakash_ads/fp_ads.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// (Optional) Configure Production Ad Units:
// AdManager.setRealAds(
// androidAppId: 'ca-app-pub-XXX~XXX',
// iosAppId: 'ca-app-pub-XXX~XXX',
// androidBanner: 'ca-app-pub-XXX/XXX',
// iosBanner: 'ca-app-pub-XXX/XXX',
// androidInterstitial: 'ca-app-pub-XXX/XXX',
// iosInterstitial: 'ca-app-pub-XXX/XXX',
// androidRewarded: 'ca-app-pub-XXX/XXX',
// iosRewarded: 'ca-app-pub-XXX/XXX',
// androidNative: 'ca-app-pub-XXX/XXX',
// iosNative: 'ca-app-pub-XXX/XXX',
// androidAppOpen: 'ca-app-pub-XXX/XXX',
// iosAppOpen: 'ca-app-pub-XXX/XXX',
// );
// 1. Request GDPR/UMP Consent
final consentResult = await AdManager.requestConsent();
// 2. Initialize AdMob and App Open Ads if allowed by consent
if (consentResult.canRequestAds) {
await AdManager.instance.initialize();
await AdManager.instance.initializeAppOpenAd();
}
runApp(const MyApp());
}
2. Display Adaptive / Standard Banner Ads #
import 'package:flutter/material.dart';
import 'package:flutter_prakash_ads/fp_ads.dart';
class MyBannerPage extends StatelessWidget {
const MyBannerPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Banner Ad Example')),
body: const Center(child: Text('Content Area')),
bottomNavigationBar: const SafeArea(
child: SmartBannerAdView(
adSize: AdSize.banner, // or use default anchored adaptive
showOfflineFallback: true,
),
),
);
}
}
3. Display Native Ads (Small & Medium Templates) #
import 'package:flutter/material.dart';
import 'package:flutter_prakash_ads/fp_ads.dart';
// Small Native Ad (90px height)
const SmartNativeAdView(
templateType: TemplateType.small,
cornerRadius: 12.0,
);
// Medium Native Ad (350px height)
const SmartNativeAdView(
templateType: TemplateType.medium,
cornerRadius: 12.0,
);
4. Full-Screen Interstitial & Rewarded Ads #
final adsService = AdsServiceImpl();
// 1. Preload Interstitial
adsService.loadInterstitialAd();
// 2. Show Interstitial (with 30s policy throttling & collision lock)
adsService.showInterstitialAd(
onAdDismissedFullScreenContent: () {
// Navigate to next screen
},
);
// 3. Show Rewarded Video Ad
adsService.showRewardedAd(
onUserEarnedReward: (ad, reward) {
print('User earned ${reward.amount} ${reward.type}');
},
);
5. π Rewarded Interstitial Ad (with AdMob Policy Opt-Out) #
β οΈ Google AdMob Policy Requirement: Unlike rewarded video (which users explicitly click to view), Rewarded Interstitials appear contextually. Therefore, Google AdMob strictly mandates showing an introductory prompt or countdown giving users an explicit option to skip or opt-out before presenting the ad.
// 1. Show user an introductory prompt allowing them to opt out
showDialog(
context: context,
builder: (ctx) => AlertDialog(
title: const Text('Bonus Reward Offer! π'),
content: const Text('Watch a short sponsored message to unlock +100 Coins?'),
actions: [
TextButton(
onPressed: () => Navigator.of(ctx).pop(),
child: const Text('Skip / No Thanks'), // Explicit opt-out per AdMob Policy
),
ElevatedButton(
onPressed: () {
Navigator.of(ctx).pop();
// 2. Play Rewarded Interstitial upon user confirmation
adsService.showRewardedInterstitialAd(
onUserEarnedReward: (ad, reward) {
print('Earned ${reward.amount} ${reward.type}!');
},
);
},
child: const Text('Watch & Unlock (+100)'),
),
],
),
);
6. π Impression-Level Ad Revenue (ILRD / tROAS) Telemetry #
Capture exact impression revenue values for analytics and attribution providers (Firebase Analytics, Adjust, AppsFlyer, Singular):
AdManager.onAdEvent((event) {
if (event.isPaid) {
// π΅ ILRD telemetry with micro precision
print('Paid Event: ${event.format.name} earned ${event.revenueValue} ${event.currencyCode}');
print('Value in Micros: ${event.valueMicros} | Precision: ${event.precision?.name}');
}
});
7. π Reactive In-App Purchase ("Remove Ads") Toggle #
When a user purchases an ad-free subscription or lifetime unlock:
// π« Globally hide and dispose all mounted banners and native ads instantly
AdManager.setAdsEnabled(false);
π‘οΈ AdMob Policy & Invalid Traffic (IVT) Compliance #
flutter_prakash_ads is engineered specifically to prevent Google Play policy violations, Invalid Ad Traffic, and accidental clicks:
| Policy Area | Protection Mechanism | Built-in Guardrail |
|---|---|---|
| π« Accidental Clicks & CLS | Cumulative Layout Shift protection | Rigid bounding containers without jarring spinners; widgets smoothly collapse to zero height on failure when no fallback is configured. |
| π Ad Stacking & Collision | Presentation Lock | AdsManager.instance.isShowingFullScreenAd prevents full-screen ads from ever appearing on top of each other. |
| β³ Stale Ad Impressions | 4-Hour Invalidation | Preloaded full-screen ads are timestamped and discarded after 4 hours per AdMob cache freshness policies. |
| β±οΈ Ad Fatigue & Spamming | Frequency Throttling | Interstitial ads enforce a minimum 30-second interval between presentations. |
| πͺ App Open Cold Starts | 4-Second Timeout | Cold-start app open ads enforce a strict 4-second deadline to avoid popping up over user interface interactions. |
| βΈοΈ Background Resume Guard | 15-Second Threshold | App Open ads will not trigger unless the application has been backgrounded for at least 15 seconds. |
| πΆ COPPA / Families Policy | Tag For Child Treatment | AdManager.updateRequestConfiguration(...) provides one-line compliance with COPPA and age-appropriate ratings. |
| πͺπΊ GDPR / UMP Regulations | Consent Management | Native Google UMP SDK integration with cached consent resilience and privacy options revocation support. |
| π·οΈ Clear Ad Attribution | Offline Fallback Badging | Offline house ads feature prominent, high-contrast AD badges so users are never misled. |
| π Non-Blocking UI Fallback | Navigation Freeze Protection | All full-screen ad show failures, dismissals, and early skips safely invoke dismissal callbacks so app navigation never freezes. |
π± Example Application #
A complete showcase application demonstrating Clean Architecture, BLoC/Cubit, Injectable DI, offline fallback promotions, and every ad format is located in the example/ directory:
cd example
flutter pub get
dart run build_runner build --delete-conflicting-outputs
flutter run
For full details, see example/README.md.
π¨βπ» Author & Publisher #
Developed and published by Prakash Bahadur Chand:
- π Website: prakashbahadurchand.com.np
- βοΈ Email: prakashbahadurchand@gmail.com
- π GitHub: @prakashbahadurchand
π License #
This project is licensed under the MIT License - see the LICENSE file for details.