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

Helper blocs for handling common in-app-purchase & admob flow

example/lib/main.dart

import 'package:example/ad_manager.dart';
import 'package:flutter/material.dart';
import 'package:knt_base_monetized/knt_base_monetized.dart';

import 'flavors.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Flavors.init();
  MobileAds.instance.initialize();
  runApp(const MyApp());
}

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

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Knt Monetized Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Knt Monetized Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  // This widget is the home page of your application. It is stateful, meaning
  // that it has a State object (defined below) that contains fields that affect
  // how it looks.

  // This class is the configuration for the state. It holds the values (in this
  // case the title) provided by the parent (in this case the App widget) and
  // used by the build method of the State. Fields in a Widget subclass are
  // always marked "final".

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  AppOpenAdBloc? _appOpenAdBloc;
  InterstitialAdBloc? _interstitialAdBloc;
  BannerAdBloc? _bannerAdBloc;
  NativeAdBloc? _nativeAdBloc;
  bool _blocLoaded = false;

  @override
  void initState() {
    super.initState();
    Future.delayed(Duration.zero, () {
      _init();
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: couldShowView
            ? MultiBlocProvider(
                providers: [
                  BlocProvider(
                    create: (_) => _appOpenAdBloc!,
                  ),
                  BlocProvider(
                    create: (_) => _interstitialAdBloc!,
                  ),
                  BlocProvider(
                    create: (_) => _bannerAdBloc!,
                  ),
                  BlocProvider(
                    create: (_) => _nativeAdBloc!,
                  ),
                ],
                child: const _ContentPage(),
              )
            : const CircularProgressIndicator(
                color: Colors.orange,
              ),
      ),
    );
  }

  void _init() async {
    _blocLoaded = false;
    _appOpenAdBloc = await appOpenAdBloc;
    _interstitialAdBloc = await interstitialAdBloc;
    _bannerAdBloc = await bannerAdBloc;
    _nativeAdBloc = await nativeAdBloc;

    setState(() {
      _blocLoaded = true;
    });
    _appOpenAdBloc!.add(PrepareAdWithoutViewEvent());
    _interstitialAdBloc!.add(PrepareAdWithoutViewEvent());
    _bannerAdBloc!.add(PrepareAdWithViewEvent());
    _nativeAdBloc!.add(PrepareAdWithViewEvent());
  }

  bool get couldShowView =>
      _blocLoaded &&
      _appOpenAdBloc != null &&
      _interstitialAdBloc != null &&
      _bannerAdBloc != null &&
      _nativeAdBloc != null;
}

class _ContentPage extends StatelessWidget {
  const _ContentPage({Key? key}) : super(key: key);

  final _adTag = 'MyHomePage';

  @override
  Widget build(BuildContext context) {
    return MultiBlocListener(
      listeners: [
        BlocListener<AppOpenAdBloc, BaseState>(
          listener: (context, state) {
            if (state is ClosedAdWithoutViewState) {
              context.showInSnackBar('AppOpenAd closed!');
            }
          },
        ),
        BlocListener<InterstitialAdBloc, BaseState>(
          listener: (context, state) {
            if (state is ClosedAdWithoutViewState) {
              context.showInSnackBar('InterstitialAd closed!');
            }
          },
        ),
      ],
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          ElevatedButton(
            onPressed: () {
              context.read<AppOpenAdBloc>().add(ShowAdWithoutViewEvent(_adTag));
            },
            child: const Text('Show App Open Ads'),
          ),
          const SizedBox(height: 16),
          ElevatedButton(
            onPressed: () {
              context
                  .read<InterstitialAdBloc>()
                  .add(ShowAdWithoutViewEvent(_adTag));
            },
            child: const Text('Show Interstitial Ads'),
          ),
          const SizedBox(height: 16),
          BlocBuilder<BannerAdBloc, BaseState>(
            builder: (context, state) =>
                (state is LoadedAdWithViewState && state.ad != null)
                    ? Container(
                        alignment: Alignment.center,
                        width: MediaQuery.of(context).size.width,
                        height: 50,
                        child: AdWidget(ad: state.ad!),
                      )
                    : const SizedBox(),
          ),
          const SizedBox(height: 16),
          BlocBuilder<NativeAdBloc, BaseState>(
            builder: (context, state) =>
                (state is LoadedAdWithViewState && state.ad != null)
                    ? Container(
                        width: MediaQuery.of(context).size.width,
                        height: 360,
                        padding: const EdgeInsets.symmetric(horizontal: 4),
                        color: Colors.white,
                        alignment: Alignment.center,
                        child: AdWidget(ad: state.ad!),
                      )
                    : const SizedBox(),
          ),
        ],
      ),
    );
  }
}

extension on BuildContext {
  void showInSnackBar(String message) {
    ScaffoldMessenger.of(this).removeCurrentSnackBar();
    ScaffoldMessenger.of(this).showSnackBar(SnackBar(
      duration: const Duration(milliseconds: 3000),
      content: Text(message),
    ));
  }
}