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
更多关于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();
}
}
在这个示例中,我们:
- 在
pubspec.yaml
中添加了refinery89_monetize_app
依赖。 - 创建了一个简单的Flutter应用,其中包含一个广告横幅。
- 在
initState
方法中加载了广告横幅。 - 使用
AdWidget
来展示广告横幅。 - 在
dispose
方法中释放了广告横幅资源。
请注意,你需要将你的广告单元ID
替换为你实际从广告平台(如AdMob)获取的广告单元ID。此外,根据广告平台的要求,你可能还需要在应用级别进行一些额外的配置,例如添加广告平台的SDK等。
这个示例仅展示了基本的广告横幅加载和展示。根据插件的文档和广告平台的要求,你还可以实现更多功能,如插屏广告、视频广告等。务必参考refinery89_monetize_app
插件的官方文档和广告平台的指南,以确保正确实现和应用内广告的最佳实践。