Flutter应用盈利插件refinery89_monetize_app的使用

Flutter应用盈利插件refinery89_monetize_app的使用

Refinery89 Monetize App SDK

此仓库包含用于使发布者通过Refinery89 SDK在Flutter应用中实现盈利的Refinery89 Monetize App SDK源代码。

文档

有关如何使用SDK的说明,请参阅我们官方文档站点上的开发人员指南。

下载

请访问pub.dev以获取SDK的最新版本。

支持

如果您遇到任何问题,请随时联系我们的支持团队:mobile_support@refinery89.com

许可证

此项目无许可证。


示例代码

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:refinery89_monetize_app/r89_sdk.dart';

void main() {
  runApp(const App());
}

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

  [@override](/user/override)
  State<App> createState() => _AppState();
}

class _AppState extends State<App> {
  bool _isManualInitialized = false;
  bool _isAutomaticInitialized = false;
  bool _isInitializationInProgress = false;

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      navigatorObservers: [R89SDK.routeObserver],
      home: Scaffold(
        body: Builder(
          builder: (BuildContext context) => Stack(
            children: [
              if (_isInitializationInProgress)
                const Center(
                    child: Card(
                  child: SizedBox(width: 96, height: 96, child: CircularProgressIndicator()),
                )),
              Align(
                alignment: Alignment.bottomCenter,
                child: Container(
                  width: double.infinity,
                  color: Colors.white,
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      if (!_isManualInitialized && !_isAutomaticInitialized && !_isInitializationInProgress)
                        FilledButton(
                            onPressed: () {
                              // 在调试模式下初始化SDK
                              setState(() {
                                _isInitializationInProgress = true;
                              });
                              initializeInManualMode(InitializationEvents.callbacks(
                                  onInitializationFinishedCallback: () {
                                setState(() {
                                  _isManualInitialized = true;
                                  _isInitializationInProgress = false;
                                });
                              }));
                            },
                            child: const Text('手动配置初始化')),
                      if (!_isManualInitialized && !_isAutomaticInitialized && !_isInitializationInProgress)
                        FilledButton(
                            onPressed: () {
                              // 在调试模式下初始化SDK
                              setState(() {
                                _isInitializationInProgress = true;
                              });
                              initializeInAutomaticMode(InitializationEvents.callbacks(
                                  onInitializationFinishedCallback: () {
                                setState(() {
                                  _isAutomaticInitialized = true;
                                  _isInitializationInProgress = false;
                                });
                              }));
                            },
                            child: const Text('单标签初始化')),
                      if (_isAutomaticInitialized)
                        const Flexible(child: AutomaticInitializationContent()),
                      if (_isManualInitialized)
                        const Flexible(child: ManualInitializationContent()),
                    ],
                  ),
                ),
              )
            ],
          ),
        ),
      ),
    );
  }
}

/// 在手动模式下初始化SDK,参见[R89SDK.initialize]
void initializeInManualMode(InitializationEvents listener) async {
  R89SDK.setLogLevel(LogLevel.debug);
  R89SDK.setDebug();
  R89SDK.initialize(
      publisherId: "TestRefinery89ID",
      appId: "TestDemoApp",
      singleTag: false,
      initializationEvents: listener);
}

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

  [@override](/user/override)
  State<ManualInitializationContent> createState() => _ManualInitializationContentState();
}

class _ManualInitializationContentState extends State<ManualInitializationContent> {
  int _interstitialId = -1;

  bool _isBannerEnabled = false;
  bool _isOutstreamEnabled = false;

  [@override](/user/override)
  Widget build(BuildContext context) => StreamBuilder<Object>(
      stream: null,
      builder: (context, snapshot) {
        return Stack(
          alignment: Alignment.bottomCenter,
          children: [
            Align(
              alignment: Alignment.topCenter,
              child: ListView(
                padding: EdgeInsets.only(
                    left: 24, right: 24, bottom: MediaQuery.of(context).size.height / 2),
                children: [
                  const SizedBox(
                    height: 48,
                  ),
                  FilledButton(
                      onPressed: () => _showAddOnAdFor(banner: true),
                      child: const Text('显示横幅广告')),
                  FilledButton(
                      onPressed: () => _showAddOnAdFor(outstream: true),
                      child: const Text('显示视频横幅广告')),
                  const SizedBox(
                    height: 48,
                  ),
                  FilledButton(
                      onPressed: () {
                        final int infiniteScrollId = R89SDK.adFactory.createInfiniteScroll(
                            configurationId: ConfigBuilder.infiniteScrollTestR89ConfigId);
                        Navigator.of(context).push(MaterialPageRoute(
                          builder: (context) => Scaffold(
                            appBar: AppBar(
                              title: const Text('无限滚动'),
                            ),
                            body: _infiniteScroll(context, infiniteScrollId),
                          ),
                        ));
                      },
                      child: const Text('显示无限滚动')),
                  const SizedBox(
                    height: 48,
                  ),
                  FilledButton(
                      onPressed: () async {
                        _interstitialId = await R89SDK.adFactory.createInterstitial(
                            configurationId: ConfigBuilder.interstitialTestR89ConfigId,
                            lifecycleCallbacks: InterstitialEventListener.callbacks(
                              onLoadedCallback: () =>
                                  R89SDK.adFactory.showInterstitial(_interstitialId),
                            ));
                      },
                      child: const Text('显示横幅插屏广告')),
                  FilledButton(
                      onPressed: () async {
                        _interstitialId = await R89SDK.adFactory.createInterstitial(
                            configurationId: ConfigBuilder.videoInterstitialTestR89ConfigId,
                            lifecycleCallbacks: InterstitialEventListener.callbacks(
                              onLoadedCallback: () =>
                                  R89SDK.adFactory.showInterstitial(_interstitialId),
                            ));
                      },
                      child: const Text('显示视频插屏广告')),
                  const SizedBox(
                    height: 48,
                  ),
                  FilledButton(
                      style: ButtonStyle(
                          backgroundColor: WidgetStateProperty.all(Colors.redAccent)),
                      onPressed: () => R89SDK.resetConsent(),
                      child: const Text('重置同意')),
                  FilledButton(
                      style: ButtonStyle(
                          backgroundColor: WidgetStateProperty.all(Colors.redAccent)),
                      onPressed: () => R89SDK.reOpenConsent(),
                      child: const Text('重新打开同意')),
                  FilledButton(
                      style: ButtonStyle(
                          backgroundColor: WidgetStateProperty.all(Colors.redAccent)),
                      onPressed: () async {
                        String cmpString = await R89SDK.exportCmpString();
                        // 显示CMP字符串在一个弹出对话框中
                        if(context.mounted){
                          showDialog(
                            context: context,
                            builder: (BuildContext context) {
                              return AlertDialog(
                                content: SingleChildScrollView(child: SelectableText(cmpString)),
                                actions: <Widget>[
                                  TextButton(
                                    onPressed: () => Navigator.of(context).pop(),
                                    child: const Text('关闭'),
                                  ),
                                ],
                              );
                            },
                          );
                        }
                      },
                      child: const Text('导出CMP字符串')),
                  FilledButton(
                      style: ButtonStyle(
                          backgroundColor: WidgetStateProperty.all(Colors.redAccent)),
                      onPressed: () => _showAddOnAdFor(),
                      child: const Text('重置广告')),
                ],
              ),
            ),
            if (_isOutstreamEnabled)
              const R89OutStream(
                configurationId: ConfigBuilder.videoOutStreamTestR89ConfigId,
              ),
            if (_isBannerEnabled)
              const R89Banner(
                configurationId: ConfigBuilder.bannerTestR89ConfigId,
              ),
          ],
        );
      });

  Widget _infiniteScroll(BuildContext context, int infiniteScrollId) => ListView.separated(
        itemCount: 100,
        separatorBuilder: (context, index) => const Divider(),
        itemBuilder: (context, index) => Column(
          children: [
            ListTile(
              leading: const Icon(
                Icons.star_rounded,
                color: Colors.amber,
              ),
              title: Text(features[index % features.length]),
            ),
            R89InfiniteScrollAd(infiniteScrollId: infiniteScrollId, itemIndex: index)
          ],
        ),
      );

  void _showAddOnAdFor({bool banner = false, bool outstream = false}) => setState(() {
        _isOutstreamEnabled = outstream;
        _isBannerEnabled = banner;
      });
}

/// 在自动模式下初始化SDK,参见[R89SDK.initialize],
/// 初始化后SDK将使用R89Tag小部件来替换广告。
void initializeInAutomaticMode(InitializationEvents listener) async {
  R89SDK.singleTagConfiguration
    ..initialRouteName = '/'
    ..addAdScreenConfig(
        adScreenConfig: AdScreenConfig(screenName: '/')
          // 这个配置了一个横幅广告,在所有地方(因为getAllWithTag:true)被替换
          // 其中R89Tag带有'tag'被指定在'BannerTagsScreen'中
          ..addBanner(
              tag: 'banner_tag', getAllWithTag: true, wrapperRelativePositionAfter: true)
          // 这个配置了一个outstream广告作为第一个(因为getAllWithTag:false)
          // 其中R89Tag带有'tag'被指定。
          ..addOutStream(
              tag: 'outstream_tag', getAllWithTag: false, wrapperRelativePositionAfter: true)
          // 这个配置了BannerTagsScreen的关闭按钮在执行关闭操作前显示一个插屏广告
          // 需要将关闭按钮包装在带有'tag'的R89Tag中
          ..addInterstitial(eventToTrackButton: 'button_tag')
          // 这个配置了一个插屏广告当从根'/'屏幕导航到BannerTagsScreen时。
          ..addInterstitial(eventToTrack: 'FeaturesList'))
    ..addAdScreenConfig(
      adScreenConfig: AdScreenConfig(screenName: 'FeaturesList')
        ..addInfiniteScroll(tag: 'scroll_tag')
        ..addInterstitial(eventToTrack: '/'),
    );

  R89SDK.setLogLevel(LogLevel.debug);
  R89SDK.setDebug();
  R89SDK.initialize(
      publisherId: "TestRefinery89ID",
      appId: "TestDemoApp",
      singleTag: true,
      initializationEvents: listener);
}

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

  [@override](/user/override)
  State<AutomaticInitializationContent> createState() => _AutomaticInitializationContentState();
}

class _AutomaticInitializationContentState extends State<AutomaticInitializationContent> {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView(
        children: [
          const SizedBox(
            height: 24,
          ),
          R89Tag(
            tag: 'banner_tag',
            child: Padding(
              padding: const EdgeInsets.all(8.0),
              child: Text(
                '单标签:所有一体化\n广告管理解决方案为发布者',
                textAlign: TextAlign.center,
                style: TextStyle(
                  fontSize: 18,
                  fontWeight: FontWeight.w600,
                  color: Colors.grey[800],
                ),
              ),
            ),
          ),
          const Divider(),
          ListTile(
            leading: const Icon(
              Icons.arrow_circle_right_outlined,
              color: Colors.amber,
            ),
            title: const Text('导航时显示插屏广告'),
            trailing: const Icon(Icons.chevron_right),
            subtitle: const Text('导航并显示插屏广告'),
            onTap: () {
              Navigator.of(context).push(MaterialPageRoute(
                  builder: (context) => const FeaturesList(),
                  settings: const RouteSettings(name: 'FeaturesList')));
            },
          ),
          R89Tag(
            tag: 'button_tag',
            child: ListTile(
              leading: const Icon(
                Icons.touch_app_outlined,
                color: Colors.amber,
              ),
              title: const Text('点击事件显示插屏广告'),
              subtitle: const Text('显示插屏广告后运行点击操作'),
              trailing: const Icon(Icons.chevron_right),
              onTap: () {
                ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
                    content:
                        Text('此SnackBar在插屏广告关闭后显示')));
              },
            ),
          ),
          const Divider(),
          const SizedBox(
            height: 8,
          ),
          const R89Tag(tag: 'banner_tag'),
          R89Tag(
            tag: 'outstream_tag',
            child: Padding(
              padding: const EdgeInsets.all(8.0),
              child: Text(
                """Monetize App SDK 的创建旨在使应用盈利变得像Web盈利一样简单灵活,解决App开发者和出版商最常遇到的问题""",
                textAlign: TextAlign.center,
                style: TextStyle(
                  fontSize: 16,
                  color: Colors.grey[800],
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

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

  [@override](/user/override)
  Widget build(BuildContext context) => Scaffold(
        body: Column(
          mainAxisAlignment: MainAxisAlignment.end,
          children: [
            Flexible(
              child: ListView.separated(
                itemCount: 100,
                shrinkWrap: true,
                separatorBuilder: (context, index) => const Divider(),
                itemBuilder: (context, index) => R89Tag(
                  tag: 'scroll_tag',
                  itemIndex: index,
                  child: ListTile(
                    leading: const Icon(
                      Icons.star_rounded,
                      color: Colors.amber,
                    ),
                    title: Text(features[index % features.length]),
                  ),
                ),
              ),
            ),
            ListTile(
              tileColor: Colors.yellowAccent,
              leading: const Icon(
                Icons.arrow_back_rounded,
                color: Colors.amber,
              ),
              title: const Text('导航回时显示插屏广告'),
              subtitle: const Text('导航回并显示插屏广告'),
              onTap: () {
                Navigator.of(context).pop();
              },
            ),
          ],
        ),
      );
}

const features = [
  "All-In-One Ad Monetization",
  "Performance Dashboard",
  "No More App Updates Required",
  "Fully GDPR Compliant CMP"
];

更多关于Flutter应用盈利插件refinery89_monetize_app的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter应用盈利插件refinery89_monetize_app的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter应用中使用refinery89_monetize_app插件的一个基本代码示例。这个插件通常用于在应用内展示广告以实现盈利。

首先,确保你已经在pubspec.yaml文件中添加了该插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  refinery89_monetize_app: ^最新版本号 # 请替换为实际的最新版本号

然后,运行flutter pub get来安装依赖。

接下来,在你的Flutter应用中初始化并使用该插件。以下是一个简单的示例,展示了如何初始化插件并在应用中展示一个广告横幅(Banner Ad)。

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  BannerAd? _bannerAd;
  bool _isAdLoaded = false;

  @override
  void initState() {
    super.initState();
    _loadBannerAd();
  }

  void _loadBannerAd() {
    // 假设你已经有了一个广告单元ID
    String bannerAdUnitId = '你的广告单元ID';

    // 初始化广告横幅
    _bannerAd = BannerAd(
      adUnitId: bannerAdUnitId,
      size: AdSize.banner, // 或者使用其他尺寸,如AdSize.largeBanner, AdSize.mediumRectangle等
      listener: (AdStatusEvent event) {
        if (event.ad!.status == AdStatus.loaded) {
          setState(() {
            _isAdLoaded = true;
          });
        }
      },
    )..load();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter盈利插件示例'),
      ),
      body: Center(
        child: _isAdLoaded
            ? Container(
                height: 50, // 根据你的广告横幅尺寸调整
                child: AdWidget(ad: _bannerAd!),
              )
            : CircularProgressIndicator(), // 广告加载中的指示器
      ),
    );
  }

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

在这个示例中,我们:

  1. pubspec.yaml中添加了refinery89_monetize_app依赖。
  2. 创建了一个简单的Flutter应用,其中包含一个广告横幅。
  3. initState方法中加载了广告横幅。
  4. 使用AdWidget来展示广告横幅。
  5. dispose方法中释放了广告横幅资源。

请注意,你需要将你的广告单元ID替换为你实际从广告平台(如AdMob)获取的广告单元ID。此外,根据广告平台的要求,你可能还需要在应用级别进行一些额外的配置,例如添加广告平台的SDK等。

这个示例仅展示了基本的广告横幅加载和展示。根据插件的文档和广告平台的要求,你还可以实现更多功能,如插屏广告、视频广告等。务必参考refinery89_monetize_app插件的官方文档和广告平台的指南,以确保正确实现和应用内广告的最佳实践。

回到顶部