gdpr_admob 2.0.0 copy "gdpr_admob: ^2.0.0" to clipboard
gdpr_admob: ^2.0.0 copied to clipboard

A production-ready Flutter wrapper for Google UMP consent and safe Google Mobile Ads initialization.

example/lib/main.dart

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:gdpr_admob/gdpr_admob.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';

void main() => runApp(const MyApp());

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

  final GdprAdmob? gdpr;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'GDPR AdMob example',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
        useMaterial3: true,
      ),
      home: ConsentExamplePage(gdpr: gdpr),
    );
  }
}

class ConsentExamplePage extends StatefulWidget {
  const ConsentExamplePage({super.key, this.gdpr});

  final GdprAdmob? gdpr;

  @override
  State<ConsentExamplePage> createState() => _ConsentExamplePageState();
}

class _ConsentExamplePageState extends State<ConsentExamplePage> {
  late final GdprAdmob _gdpr;
  GdprConsentResult? _result;
  BannerAd? _bannerAd;
  bool _isBannerLoaded = false;
  bool _isLoading = true;
  String? _bannerError;

  bool get _isMobile =>
      defaultTargetPlatform == TargetPlatform.android ||
      defaultTargetPlatform == TargetPlatform.iOS;

  String get _bannerAdUnitId => switch (defaultTargetPlatform) {
    TargetPlatform.android => 'ca-app-pub-3940256099942544/6300978111',
    TargetPlatform.iOS => 'ca-app-pub-3940256099942544/2934735716',
    _ => '',
  };

  @override
  void initState() {
    super.initState();
    _gdpr = widget.gdpr ?? GdprAdmob();
    if (_isMobile) {
      _initialize();
    } else {
      _isLoading = false;
    }
  }

  Future<void> _initialize() async {
    _setLoading();
    final result = await _gdpr.initialize();
    if (!mounted) return;
    _applyResult(result);
  }

  Future<void> _showPrivacyOptions() async {
    _setLoading();
    var result = await _gdpr.showPrivacyOptionsForm();
    if (result.canRequestAds && !_gdpr.isMobileAdsInitialized) {
      result = await _gdpr.initialize();
    }
    if (!mounted) return;
    _applyResult(result);
  }

  void _setLoading() {
    if (mounted) {
      setState(() {
        _isLoading = true;
      });
    }
  }

  void _applyResult(GdprConsentResult result) {
    final bannerToDispose = result.canRequestAds ? null : _bannerAd;
    setState(() {
      _result = result;
      _isLoading = false;
      if (!result.canRequestAds) {
        _bannerAd = null;
        _isBannerLoaded = false;
      }
    });
    bannerToDispose?.dispose();

    if (result.canRequestAds && _bannerAd == null) {
      _loadBanner();
    }
  }

  void _loadBanner() {
    final banner = BannerAd(
      adUnitId: _bannerAdUnitId,
      size: AdSize.banner,
      request: const AdRequest(),
      listener: BannerAdListener(
        onAdLoaded: (ad) {
          if (!mounted || !identical(_bannerAd, ad)) {
            ad.dispose();
            return;
          }
          setState(() {
            _isBannerLoaded = true;
            _bannerError = null;
          });
        },
        onAdFailedToLoad: (ad, error) {
          ad.dispose();
          if (!mounted || !identical(_bannerAd, ad)) return;
          setState(() {
            _bannerAd = null;
            _isBannerLoaded = false;
            _bannerError = error.message;
          });
        },
      ),
    );

    setState(() {
      _bannerAd = banner;
      _isBannerLoaded = false;
    });
    banner.load();
  }

  @override
  Widget build(BuildContext context) {
    final result = _result;
    final banner = _bannerAd;
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: const Text('GDPR AdMob example'),
      ),
      body: !_isMobile
          ? const Center(child: Text('This example supports Android and iOS.'))
          : ListView(
              padding: const EdgeInsets.all(24),
              children: [
                if (_isLoading) const LinearProgressIndicator(),
                const SizedBox(height: 24),
                _StatusTile(
                  label: 'Consent status',
                  value: result?.status.name ?? 'loading',
                ),
                _StatusTile(
                  label: 'Can request ads',
                  value: '${result?.canRequestAds ?? false}',
                ),
                _StatusTile(
                  label: 'Mobile Ads',
                  value: result?.mobileAdsStatus.name ?? 'not initialized',
                ),
                _StatusTile(
                  label: 'Privacy options',
                  value:
                      result?.privacyOptionsRequirementStatus.name ?? 'unknown',
                ),
                const SizedBox(height: 16),
                FilledButton(
                  onPressed: _isLoading ? null : _initialize,
                  child: const Text('Refresh consent'),
                ),
                if (result?.isPrivacyOptionsRequired ?? false)
                  OutlinedButton(
                    onPressed: _isLoading ? null : _showPrivacyOptions,
                    child: const Text('Manage privacy options'),
                  ),
                for (final error in result?.errors ?? <GdprAdmobError>[])
                  Text(
                    '${error.stage.name}: ${error.message}',
                    style: TextStyle(
                      color: Theme.of(context).colorScheme.error,
                    ),
                  ),
                if (_bannerError case final error?)
                  Text(
                    'Banner: $error',
                    style: TextStyle(
                      color: Theme.of(context).colorScheme.error,
                    ),
                  ),
              ],
            ),
      bottomNavigationBar: banner == null || !_isBannerLoaded
          ? null
          : SafeArea(
              child: SizedBox(
                width: banner.size.width.toDouble(),
                height: banner.size.height.toDouble(),
                child: AdWidget(ad: banner),
              ),
            ),
    );
  }

  @override
  void dispose() {
    _bannerAd?.dispose();
    super.dispose();
  }
}

class _StatusTile extends StatelessWidget {
  const _StatusTile({required this.label, required this.value});

  final String label;
  final String value;

  @override
  Widget build(BuildContext context) => ListTile(
    contentPadding: EdgeInsets.zero,
    title: Text(label),
    trailing: Text(value),
  );
}
9
likes
160
points
80
downloads
screenshot

Documentation

API reference

Publisher

verified publisherarabflutter.com

Weekly Downloads

A production-ready Flutter wrapper for Google UMP consent and safe Google Mobile Ads initialization.

Repository (GitHub)
View/report issues
Contributing

Topics

#admob #consent #gdpr #privacy #ump

License

GPL-3.0 (license)

Dependencies

flutter, google_mobile_ads

More

Packages that depend on gdpr_admob