ads_core_flutter 0.1.0 copy "ads_core_flutter: ^0.1.0" to clipboard
ads_core_flutter: ^0.1.0 copied to clipboard

Ready-to-use Flutter ads toolkit for Android and iOS with banner, interstitial, rewarded, app open, and native template helpers.

example/lib/main.dart

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

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const AdsExampleApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Ads Core Flutter Example',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xFFDF6D14)),
        useMaterial3: true,
      ),
      home: const AdsExampleHomePage(),
    );
  }
}

class AdsExampleHomePage extends StatefulWidget {
  const AdsExampleHomePage({super.key});

  @override
  State<AdsExampleHomePage> createState() => _AdsExampleHomePageState();
}

class _AdsExampleHomePageState extends State<AdsExampleHomePage>
    with WidgetsBindingObserver {
  final AdsController _ads = AdsController(
    unitIds: const AdsPlatformUnitIds.googleTest(),
  );

  late final NativeAdPool _smallNativePool = _ads.createNativeAdPool(
    layout: AdsNativeLayout.small(),
  );
  late final NativeAdPool _mediumNativePool = _ads.createNativeAdPool(
    layout: AdsNativeLayout.medium(),
  );

  bool _adsReady = false;
  bool _isShowingAppOpen = false;
  String _rewardText = 'Reward not collected yet.';

  static const List<_RecipePreview> _recipes = [
    _RecipePreview(
      title: 'Shan Noodle Bowl',
      subtitle: 'Tomato gravy, chicken, roasted peanuts',
      minutes: '20 min',
    ),
    _RecipePreview(
      title: 'Tea Leaf Salad',
      subtitle: 'Crunchy beans, cabbage, lime dressing',
      minutes: '15 min',
    ),
    _RecipePreview(
      title: 'Mohinga',
      subtitle: 'Fish broth, rice noodles, crispy fritters',
      minutes: '35 min',
    ),
    _RecipePreview(
      title: 'Coconut Rice',
      subtitle: 'Fragrant jasmine rice with toasted sesame',
      minutes: '18 min',
    ),
    _RecipePreview(
      title: 'Spicy Tofu Curry',
      subtitle: 'Rich curry sauce with basil and garlic',
      minutes: '25 min',
    ),
    _RecipePreview(
      title: 'Palm Sugar Pancake',
      subtitle: 'Soft center, caramel edges, sesame topping',
      minutes: '22 min',
    ),
  ];

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    _initializeAds();
  }

  Future<void> _initializeAds() async {
    await _ads.initialize();
    if (!mounted) {
      return;
    }
    setState(() {
      _adsReady = true;
    });
    _smallNativePool.preloadPositions(const [0]);
    _mediumNativePool.preloadPositions(const [0]);
    await _ads.preloadInterstitial();
    await _ads.preloadRewarded();
    await _ads.preloadAppOpen();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.resumed) {
      _showAppOpen();
    }
  }

  Future<void> _showInterstitial() async {
    final shown = await _ads.showInterstitialIfReady();
    if (!shown && mounted) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('Interstitial ad is still loading.')),
      );
      await _ads.preloadInterstitial();
    }
  }

  Future<void> _showRewarded() async {
    final shown = await _ads.showRewardedIfReady(
      onRewarded: (reward) {
        if (!mounted) {
          return;
        }
        setState(() {
          _rewardText = 'Reward earned: ${reward.amount} ${reward.type}';
        });
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text('Reward earned: ${reward.amount} ${reward.type}'),
          ),
        );
      },
    );

    if (!shown && mounted) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('Rewarded ad is still loading.')),
      );
      await _ads.preloadRewarded();
    }
  }

  Future<void> _showAppOpen() async {
    if (_isShowingAppOpen || !_adsReady) {
      return;
    }

    _isShowingAppOpen = true;
    final shown = await _ads.showAppOpenIfReady();
    if (!shown) {
      await _ads.preloadAppOpen();
    }
    _isShowingAppOpen = false;
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    _smallNativePool.dispose();
    _mediumNativePool.dispose();
    _ads.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final colorScheme = Theme.of(context).colorScheme;

    return Scaffold(
      appBar: AppBar(
        title: const Text('ads_core_flutter'),
        backgroundColor: colorScheme.surface,
      ),
      bottomNavigationBar: ColoredBox(
        color: colorScheme.surface,
        child: SafeArea(
          top: false,
          child: _adsReady
              ? AdsBanner(controller: _ads)
              : const SizedBox.shrink(),
        ),
      ),
      body: ListView(
        padding: const EdgeInsets.fromLTRB(16, 16, 16, 24),
        children: [
          _HeroCard(
            rewardText: _rewardText,
            onShowInterstitial: _showInterstitial,
            onShowRewarded: _showRewarded,
            onShowAppOpen: _showAppOpen,
          ),
          const SizedBox(height: 16),
          Text('Native Layouts', style: Theme.of(context).textTheme.titleLarge),
          const SizedBox(height: 8),
          if (_adsReady) ...[
            const _SectionLabel(
              title: 'Small template',
              subtitle: 'Compact feed card with tighter height.',
            ),
            AdsNativeFeedItem(pool: _smallNativePool, position: 0),
            const _SectionLabel(
              title: 'Medium template',
              subtitle: 'Taller native template for rich media.',
            ),
            AdsNativeFeedItem(pool: _mediumNativePool, position: 0),
          ],
          const SizedBox(height: 16),
          Text('Recipe Feed', style: Theme.of(context).textTheme.titleLarge),
          const SizedBox(height: 8),
          for (int index = 0; index < _recipes.length; index++)
            _RecipeCard(recipe: _recipes[index]),
        ],
      ),
    );
  }
}

class _SectionLabel extends StatelessWidget {
  const _SectionLabel({required this.title, required this.subtitle});

  final String title;
  final String subtitle;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.fromLTRB(4, 8, 4, 2),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(title, style: Theme.of(context).textTheme.titleSmall),
          const SizedBox(height: 2),
          Text(subtitle, style: Theme.of(context).textTheme.bodySmall),
        ],
      ),
    );
  }
}

class _HeroCard extends StatelessWidget {
  const _HeroCard({
    required this.rewardText,
    required this.onShowInterstitial,
    required this.onShowRewarded,
    required this.onShowAppOpen,
  });

  final String rewardText;
  final VoidCallback onShowInterstitial;
  final VoidCallback onShowRewarded;
  final VoidCallback onShowAppOpen;

  @override
  Widget build(BuildContext context) {
    final colorScheme = Theme.of(context).colorScheme;

    return Container(
      padding: const EdgeInsets.all(20),
      decoration: BoxDecoration(
        gradient: LinearGradient(
          colors: [
            colorScheme.primaryContainer,
            colorScheme.surfaceContainerHighest,
          ],
          begin: Alignment.topLeft,
          end: Alignment.bottomRight,
        ),
        borderRadius: BorderRadius.circular(24),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(
            'Ready-to-use mobile ads package.',
            style: Theme.of(context).textTheme.headlineSmall,
          ),
          const SizedBox(height: 8),
          Text(
            'This example uses Google test IDs. Replace them with production '
            'Android and iOS unit IDs before release.',
            style: Theme.of(context).textTheme.bodyMedium,
          ),
          const SizedBox(height: 16),
          Wrap(
            spacing: 12,
            runSpacing: 12,
            children: [
              FilledButton(
                onPressed: onShowInterstitial,
                child: const Text('Show interstitial'),
              ),
              FilledButton.tonal(
                onPressed: onShowRewarded,
                child: const Text('Show rewarded'),
              ),
              OutlinedButton(
                onPressed: onShowAppOpen,
                child: const Text('Show app open'),
              ),
            ],
          ),
          const SizedBox(height: 16),
          Text(rewardText, style: Theme.of(context).textTheme.bodyLarge),
        ],
      ),
    );
  }
}

class _RecipeCard extends StatelessWidget {
  const _RecipeCard({required this.recipe});

  final _RecipePreview recipe;

  @override
  Widget build(BuildContext context) {
    final colorScheme = Theme.of(context).colorScheme;

    return Card(
      margin: const EdgeInsets.only(top: 12),
      color: colorScheme.surfaceContainerLow,
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Row(
          children: [
            Container(
              width: 56,
              height: 56,
              decoration: BoxDecoration(
                color: colorScheme.primaryContainer,
                borderRadius: BorderRadius.circular(16),
              ),
              alignment: Alignment.center,
              child: const Icon(Icons.restaurant_menu_rounded),
            ),
            const SizedBox(width: 16),
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    recipe.title,
                    style: Theme.of(context).textTheme.titleMedium,
                  ),
                  const SizedBox(height: 4),
                  Text(
                    recipe.subtitle,
                    style: Theme.of(context).textTheme.bodyMedium,
                  ),
                ],
              ),
            ),
            const SizedBox(width: 12),
            Chip(label: Text(recipe.minutes)),
          ],
        ),
      ),
    );
  }
}

class _RecipePreview {
  const _RecipePreview({
    required this.title,
    required this.subtitle,
    required this.minutes,
  });

  final String title;
  final String subtitle;
  final String minutes;
}
1
likes
160
points
55
downloads

Documentation

API reference

Publisher

verified publisherpcodermm.com

Weekly Downloads

Ready-to-use Flutter ads toolkit for Android and iOS with banner, interstitial, rewarded, app open, and native template helpers.

Homepage
Repository (GitHub)
View/report issues

Topics

#ads #admob #monetization #flutter

License

MIT (license)

Dependencies

flutter, google_mobile_ads

More

Packages that depend on ads_core_flutter