### Troubleshoot GroMore Ads SDK Initialization Failures (Flutter) Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/02-quick-start Provides a code example for handling potential exceptions during GroMore Ads SDK initialization and outlines common reasons for initialization failures, such as incorrect appId, network issues, duplicate initialization, or incorrect platform configurations. ```dart try { final success = await GromoreAds.initAd( 'your_app_id', useMediation: true, debugMode: true, ); if (!success) { // 初始化失败,检查以下问题: // 1. appId是否正确(在穿山甲平台复制完整ID) // 2. 网络连接是否正常 // 3. 是否在测试环境使用了生产appId print('SDK初始化失败'); } } catch (e) { // 捕获异常情况 print('SDK初始化异常: $e'); } ``` -------------------------------- ### 初始化 GroMore Ads SDK Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/02-quick-start 初始化 GroMore Ads SDK 的主要方法。首次调用时执行初始化,后续调用根据配置复用实例或返回错误。建议在应用启动时调用一次。 ```dart final success = await GromoreAds.initAd( 'your_app_id', useMediation: true, debugMode: true, ); if (success) { print('SDK初始化成功,可以加载广告了'); // 继续预加载广告或展示广告 await GromoreAds.preload(configs: [...]); } else { print('SDK初始化失败,请检查配置'); } ``` ```dart Future main() async { WidgetsFlutterBinding.ensureInitialized(); try { await GromoreAds.initAd( 'app_id', useMediation: true, debugMode: true, ); } catch (e) { debugPrint('SDK初始化失败: $e'); } runApp( const MaterialApp( home: Scaffold( body: Center( child: Text('GroMore ready'), ), ), ), ); } ``` -------------------------------- ### Install Flutter Dependencies Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/01-installation Execute the `flutter pub get` command to download and install all the project dependencies, including the newly added GroMore Ads plugin. ```bash flutter pub get ``` -------------------------------- ### 启用 GroMore Ads SDK 调试日志 Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/02-quick-start 通过设置 `debugMode: true` 来启用 GroMore Ads SDK 的调试模式。在调试模式下,SDK 会在控制台输出详细的运行日志,包括初始化状态、广告加载过程和错误信息。请注意,生产环境必须关闭此模式。 ```dart await GromoreAds.initAd( 'your_app_id', useMediation: true, debugMode: true, // ✅ 开启调试模式 ); ``` -------------------------------- ### 配置 GroMore Ads SDK 初始化 Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/02-quick-start 通过 `config` 参数为 GroMore Ads SDK 提供初始化配置。支持多种格式,包括 Flutter 资源路径、绝对路径、JSON 字符串和 Map 对象,方便离线或动态配置。 ```dart // 方式1:Flutter资源路径 await GromoreAds.initAd( 'your_app_id', useMediation: true, debugMode: true, config: 'assets/gromore_config.json', ); ``` ```dart // 方式2:绝对路径 await GromoreAds.initAd( 'your_app_id', useMediation: true, debugMode: true, config: '/data/user/0/com.example.app/files/config.json', ); ``` ```dart // 方式3:JSON字符串 await GromoreAds.initAd( 'your_app_id', useMediation: true, debugMode: true, config: '{"key": "value"}', ); ``` ```dart // 方式4:Map对象 await GromoreAds.initAd( 'your_app_id', useMediation: true, debugMode: true, config: {'key': 'value'}, ); ``` -------------------------------- ### Flutter GroMore Ads: Basic Preload Example Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/11-preload A minimal Flutter example demonstrating how to preload reward video and interstitial ads using the GroMore Ads SDK. This snippet is useful for quickly integrating the basic preloading functionality. ```dart import 'package:gromore_ads/gromore_ads.dart'; // 预加载激励视频和插屏广告 await GromoreAds.preload( configs: [ PreloadConfig.rewardVideo(['your_reward_video_ad_id']), PreloadConfig.interstitial(['your_interstitial_ad_id']), ], ); ``` -------------------------------- ### 监听 GroMore Ads SDK 事件 Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/02-quick-start 使用订阅模式监听 GroMore Ads SDK 的各种事件,包括通用事件、特定广告位事件以及类型化的事件(如激励视频)。支持多个并发订阅,并通过 `cancel()` 方法取消订阅。基础用法需要一个 `AdEventSubscription` 对象来管理订阅。 ```dart class _MyPageState extends State { AdEventSubscription? _subscription; @override void initState() { super.initState(); // 创建事件订阅 _subscription = GromoreAds.onEvent( onEvent: (event) { debugPrint('📌 ${event.action} (posId: ${event.posId})'); }, onError: (event) { debugPrint('❌ 错误 ${event.code}: ${event.message}'); }, onReward: (event) { if (event.verified) { debugPrint('✅ 奖励: ${event.rewardType} x${event.rewardAmount}'); } }, ); } @override void dispose() { _subscription?.cancel(); // 取消订阅 super.dispose(); } } ``` ```dart // 只监听特定 posId 的事件 _subscription = GromoreAds.onAdEvents( 'reward_video_001', onEvent: (event) { // 只会收到 reward_video_001 的事件 debugPrint('事件: ${event.action}'); }, ); ``` ```dart // 激励视频专用监听 _subscription = GromoreAds.onRewardVideoEvents( 'reward_video_001', onLoaded: (event) => debugPrint('✅ 加载成功'), onRewarded: (event) => _grantReward(event.rewardAmount), onCompleted: (event) => debugPrint('✅ 播放完成'), onError: (event) => debugPrint('❌ 错误: ${event.message}'), ); ``` -------------------------------- ### Full Example: Test Tools Page UI (Flutter) Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/10-test-tools A comprehensive Flutter example showcasing a UI page to launch the GroMore Ads test tools. This includes state management for loading indicators, user feedback via SnackBars, and a button to trigger the tool. This example is intended for development phases and should be conditionally included. ```dart import 'package:flutter/material.dart'; import 'package:gromore_ads/gromore_ads.dart'; class TestToolsPage extends StatefulWidget { @override _TestToolsPageState createState() => _TestToolsPageState(); } class _TestToolsPageState extends State { bool _isLoading = false; // 启动测试工具 Future _launchTestTools() async { setState(() => _isLoading = true); try { final success = await GromoreAds.launchTestTools(); if (!mounted) return; if (success) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('测试工具已启动'), backgroundColor: Colors.green, ), ); } else { throw Exception('启动返回false'); } } catch (e) { if (!mounted) return; ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('启动失败: $e'), backgroundColor: Colors.red, ), ); } finally { if (mounted) { setState(() => _isLoading = false); } } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('广告测试工具'), backgroundColor: Colors.blue, ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.bug_report, size: 80, color: Colors.blue, ), SizedBox(height: 20), Text( '点击按钮启动测试工具', style: TextStyle(fontSize: 16), ), SizedBox(height: 40), ElevatedButton.icon( onPressed: _isLoading ? null : _launchTestTools, icon: _isLoading ? SizedBox( width: 20, height: 20, child: CircularProgressIndicator( strokeWidth: 2, color: Colors.white, ), ) : Icon(Icons.play_arrow), label: Text(_isLoading ? '启动中...' : '启动测试工具'), style: ElevatedButton.styleFrom( padding: EdgeInsets.symmetric(horizontal: 30, vertical: 15), ), ), ], ), ), ); } } ``` -------------------------------- ### Initialize GroMore Ads SDK with Various Configurations (Flutter) Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/02-quick-start Demonstrates different ways to initialize the GroMore Ads SDK using various combinations of required and optional parameters. This includes minimal configuration, full configuration with a local config file, GDPR compliance settings, and teen mode. ```dart // 最简配置(仅必填参数) await GromoreAds.initAd( 'your_app_id', useMediation: true, debugMode: true, ); // 完整配置(包含所有可选参数) await GromoreAds.initAd( 'your_app_id', useMediation: true, debugMode: true, config: 'assets/gromore_config.json', // 本地配置文件 limitPersonalAds: 1, // 限制个性化广告 limitProgrammaticAds: 1, // 限制程序化广告 themeStatus: 0, // 正常主题 ageGroup: 0, // 成人用户 supportMultiProcess: true, // @android 多进程支持 ); // GDPR合规场景 await GromoreAds.initAd( 'your_app_id', useMediation: true, debugMode: false, limitPersonalAds: 1, // 欧盟用户限制个性化 limitProgrammaticAds: 1, // 限制程序化广告 ); // 青少年模式 await GromoreAds.initAd( 'your_app_id', useMediation: true, debugMode: false, ageGroup: 1, // 青少年模式,会自动限制部分功能 ); ``` -------------------------------- ### Verify GroMore Ads SDK Installation (Flutter) Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/01-installation After completing the integration steps, import the `gromore_ads` plugin into your Dart code to verify that the installation was successful. An import without errors indicates a correct setup. ```dart import 'package:gromore_ads/gromore_ads.dart'; ``` -------------------------------- ### Initialize GroMore Ads SDK and Handle Events (Flutter) Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/02-quick-start Initializes the GroMore Ads SDK, requests necessary permissions (IDFA on iOS, general permission on Android), sets up event listeners for ad events (onEvent, onError, onReward), and optionally preloads ad units. This function should be called during application startup. ```dart import 'dart:io'; import 'package:flutter/material.dart'; import 'package:gromore_ads/gromore_ads.dart'; class MyApp extends StatefulWidget { const MyApp({super.key}); @override State createState() => _MyAppState(); } class _MyAppState extends State { AdEventSubscription? _adEventSubscription; @override void initState() { super.initState(); _bootstrapAds(); } Future _bootstrapAds() async { try { // 1) 可选隐私权限 if (Platform.isIOS) { await GromoreAds.requestIDFA; } else if (Platform.isAndroid) { await GromoreAds.requestPermissionIfNecessary; } // 2) 注册事件监听器 _adEventSubscription = GromoreAds.onEvent( onEvent: (event) { debugPrint('📌 广告事件: ${event.action} (posId: ${event.posId})'); }, onError: (event) { debugPrint('❌ 广告错误 ${event.code}: ${event.message}'); }, onReward: (event) { if (event.verified) { debugPrint('✅ 奖励验证成功: ${event.rewardType ?? ''} x${event.rewardAmount ?? 0}'); } }, ); // 3) 初始化 SDK final success = await GromoreAds.initAd( 'your_app_id', useMediation: true, debugMode: true, ); if (success) { // 4) 可选:预加载常用广告位 await GromoreAds.preload( configs: const [ PreloadConfig.rewardVideo(['reward_pos_id']), PreloadConfig.interstitial(['interstitial_pos_id']), PreloadConfig.feed(['feed_pos_id']), PreloadConfig.banner(['banner_pos_id']), ], ); } else { debugPrint('SDK初始化失败,请检查配置'); } } catch (e) { debugPrint('广告SDK启动异常: $e'); } } @override void dispose() { _adEventSubscription?.cancel(); super.dispose(); } @override Widget build(BuildContext context) { return const MaterialApp(home: Placeholder()); } } ``` -------------------------------- ### Asynchronous Ad Preloading During App Startup in Dart Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/11-preload Demonstrates how to initiate ad preloading asynchronously after the main application logic has started. This approach ensures that ad preloading does not block the UI thread during application startup, leading to a faster perceived launch time. The preloading happens in the background without awaiting its completion. ```dart // ✅ 推荐: 不阻塞应用启动 void main() async { WidgetsFlutterBinding.ensureInitialized(); await GromoreAds.init(/* ... */); // 先启动应用 runApp(MyApp()); // 后台预加载(不await) GromoreAds.preload(configs: [/* ... */]); } ``` -------------------------------- ### Flutter GroMore Ads: Preload Error Handling Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/11-preload Example of error handling for the `preload` method in the GroMore Ads Flutter SDK, specifically addressing the case where the `configs` list is empty. This demonstrates how to use a try-catch block to manage potential exceptions during ad preloading. ```dart // 异常处理 try { await GromoreAds.preload(configs: []); } catch (e) { // ❌ 抛出 ArgumentError: configs cannot be empty when calling preload print('configs不能为空: $e'); } ``` -------------------------------- ### Flutter Game Ad Preloading with Gromore Ads SDK Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/11-preload This Dart code snippet demonstrates how to implement dynamic ad preloading strategies for a game application using the Gromore Ads SDK. It defines a `GameAdManager` class with methods to preload ads on app start, level start, and refresh them periodically. Key features include preloading different ad types (rewarded video, banner, interstitial) with specific configurations and options tailored to game scenarios. Dependencies include the Gromore Ads SDK and Flutter's `WidgetsFlutterBinding`. It assumes the existence of utility functions like `getCurrentUserId()`, `getCurrentLevel()`, and `MyGameApp`. ```dart class GameAdManager { /// 应用启动时 - 预加载高频广告 static Future preloadOnAppStart() async { await GromoreAds.preload( configs: [ // 激励视频 - 复活、奖励等高频场景 PreloadConfig.rewardVideo( ['reward_revive', 'reward_coin'], options: { 'userId': 'player_${getCurrentUserId()}', 'mutedIfCan': false, // 保持声音增强吸引力 }, ), // Banner - 主界面底部常驻 PreloadConfig.banner( ['banner_main'], options: { 'width': 600, 'height': 100, }, ), ], parallelNum: 2, requestIntervalS: 2, ); print('✅ 游戏启动预加载完成'); } /// 关卡开始前 - 预加载关卡相关广告 static Future preloadOnLevelStart() async { await GromoreAds.preload( configs: [ // 插屏广告 - 关卡暂停、失败时展示 PreloadConfig.interstitial( ['interstitial_pause', 'interstitial_fail'], options: { 'orientation': 1, // 竖屏游戏 'scenarioId': 'level_${getCurrentLevel()}', }, ), // 激励视频 - 跳过关卡、额外道具 PreloadConfig.rewardVideo( ['reward_skip', 'reward_power_up'], options: { 'userId': 'player_${getCurrentUserId()}', 'rewardName': '金币', 'rewardAmount': 50, 'scenarioId': 'level_reward', }, ), ], parallelNum: 2, requestIntervalS: 1, // 关卡间歇快速加载 ); } /// 长时间游戏后 - 刷新广告缓存 static Future refreshAds() async { // 先清理过期的信息流广告 await GromoreAds.clearFeedAd(); // 重新预加载 await preloadOnAppStart(); } } // 使用示例 void main() async { WidgetsFlutterBinding.ensureInitialized(); await GromoreAds.init(/* ... */); // 应用启动时预加载 await GameAdManager.preloadOnAppStart(); runApp(MyGameApp()); } // 关卡开始时 void onLevelStart() { GameAdManager.preloadOnLevelStart(); } // 每30分钟刷新一次广告 Timer.periodic(Duration(minutes: 30), (_) { GameAdManager.refreshAds(); }); ``` -------------------------------- ### Configuring Concurrency for Ad Preloading in Dart Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/11-preload Provides guidelines for setting the `parallelNum` and `requestIntervalS` parameters in `GromoreAds.preload`. It shows examples of using default values for few ads, increasing concurrency for multiple ads, and avoiding excessive concurrency that can lead to errors. ```dart // ✅ 推荐: 少量广告用默认值 await GromoreAds.preload( configs: [ PreloadConfig.rewardVideo(['id1']), PreloadConfig.banner(['id2']), ], // 不传parallelNum和requestIntervalS,使用默认值(2, 2) ); // ✅ 推荐: 多个广告适当提高并发 await GromoreAds.preload( configs: [ PreloadConfig.rewardVideo(['id1', 'id2']), PreloadConfig.interstitial(['id3']), PreloadConfig.feed(['id4']), PreloadConfig.banner(['id5']), ], parallelNum: 3, // 提高到3 requestIntervalS: 2, ); // ❌ 不推荐: 并发过高导致资源竞争 await GromoreAds.preload( configs: [/* 很多广告位 */], parallelNum: 20, // 太高!会导致部分请求失败 requestIntervalS: 0, // 无间隔!会被SDK限流 ); ``` -------------------------------- ### Flutter GroMore Ads: Preload with Custom Concurrency Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/11-preload An example demonstrating how to use the `preload` method with custom `parallelNum` and `requestIntervalS` parameters in the GroMore Ads Flutter SDK. This snippet shows how to adjust the concurrency and timing of ad preloading requests to optimize resource usage and loading speed. ```dart // 完整配置 - 自定义并发参数 await GromoreAds.preload( configs: [ PreloadConfig.rewardVideo(['reward_id_1', 'reward_id_2']), PreloadConfig.interstitial(['interstitial_id']), PreloadConfig.feed(['feed_id']), ], parallelNum: 3, // 同时加载3个 requestIntervalS: 2, // 间隔2秒 ); ``` -------------------------------- ### Flutter GroMore Ads: Advanced Preload Configuration Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/11-preload An advanced Flutter example showcasing comprehensive preloading of various ad types (reward video, interstitial, feed, draw feed, banner) with custom options and parameters. This illustrates how to configure preloading for different ad formats and scenarios, including user ID, reward information, orientation, and dimensions. ```dart import 'package:gromore_ads/gromore_ads.dart'; class AdPreloadManager { /// 在应用启动时调用 static Future preloadAdsOnAppStart() async { try { await GromoreAds.preload( configs: [ // 激励视频广告 - 带奖励信息 PreloadConfig.rewardVideo( ['reward_pos_id_1', 'reward_pos_id_2'], options: { 'userId': 'user_123', 'rewardName': '金币', 'rewardAmount': 50, 'mutedIfCan': true, }, ), // 插屏广告 - 竖屏模式 PreloadConfig.interstitial( ['interstitial_pos_id'], options: { 'orientation': 1, // 1=竖屏, 2=横屏 'scenarioId': 'home_page', }, ), // 信息流广告 - 指定宽高 PreloadConfig.feed( ['feed_pos_id'], options: { 'width': 320, // 单位: px 'height': 180, // 单位: px 'count': 3, // 预加载3条 }, ), // Draw信息流广告 PreloadConfig.drawFeed(['draw_pos_id']), // Banner横幅广告 PreloadConfig.banner( ['banner_pos_id'], options: { 'width': 600, 'height': 100, }, ), ], parallelNum: 2, // 并发数: 同时加载2个广告 requestIntervalS: 2, // 请求间隔: 每个请求间隔2秒 ); print('✅ 广告预加载完成'); } catch (e) { print('❌ 广告预加载失败: $e'); } } } // 在应用启动时调用 void main() async { WidgetsFlutterBinding.ensureInitialized(); // 初始化GroMore SDK await GromoreAds.init(/* ... */); // 预加载广告 await AdPreloadManager.preloadAdsOnAppStart(); runApp(MyApp()); } ``` -------------------------------- ### Server-Side Reward Verification Setup in Flutter Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/07-reward-video-ad Configures reward video ad loading to include parameters necessary for server-side verification. This involves passing user ID and custom data, which will be forwarded to your backend for validation. Essential for critical rewards. ```dart await GromoreAds.loadRewardVideoAd( 'reward_ad_id', userId: 'user_123', // 用户唯一标识 customData: { 'order_id': generateOrderId(), 'timestamp': DateTime.now().millisecondsSinceEpoch.toString(), 'signature': calculateSignature(), // 签名防篡改 }, ); ``` -------------------------------- ### Preloading Splash Ads with Consistent Parameters (Dart) Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/04-splash-ads This example shows how to use the preload feature for splash ads. It highlights that to successfully reuse a preloaded ad, the parameters of subsequent `showSplashAd` calls must exactly match the initial preload request. Mismatched parameters, like `timeout`, will result in a new ad load instead of using the preloaded one. ```dart // Preload await GromoreAds.showSplashAd( SplashAdRequest(posId: 'id1', preload: true, timeout: Duration(seconds: 4)), ); // ✅ Correct: Parameters match, preloaded ad will be used await GromoreAds.showSplashAd( SplashAdRequest(posId: 'id1', timeout: Duration(seconds: 4)), ); // ❌ Incorrect: timeout differs, will reload await GromoreAds.showSplashAd( SplashAdRequest(posId: 'id1', timeout: Duration(seconds: 5)), ); ``` -------------------------------- ### Ad Event Monitoring and Metrics Collection (Flutter) Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/12-best-practices An example implementation of an `OnAdEventListener` to monitor ad events and collect metrics such as loaded, shown, clicked, and failed counts. This class helps in tracking ad performance and diagnosing issues. The `snapshot` method provides a way to get the current metrics. ```dart class AdMonitor extends OnAdEventListener { final _metrics = {}; @override void onAdEvent(AdEvent event) { final record = _metrics.putIfAbsent(event.posId, () => _Record()); if (event.action.endsWith('_loaded')) record.loaded++; if (event.action.endsWith('_showed')) record.shown++; if (event.action.endsWith('_clicked')) record.clicked++; } @override void onAdError(AdErrorEvent event) { final record = _metrics.putIfAbsent(event.posId, () => _Record()); record.failed++; } Map> snapshot() { return _metrics.map((posId, record) => MapEntry(posId, record.toJson())); } } class _Record { int loaded = 0; int shown = 0; int clicked = 0; int failed = 0; Map toJson() => { 'loaded': loaded, 'shown': shown, 'clicked': clicked, 'failed': failed, }; } ``` -------------------------------- ### Responsive Banner Implementation Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/06-banner-ads Example of creating a responsive banner that adjusts its size based on the available screen width. ```APIDOC ## Responsive Banner Widget ### Description Implement a responsive banner that dynamically adjusts its width based on the parent constraints, ensuring optimal display across different screen sizes. ### Method Widget Component with `LayoutBuilder` ### Endpoint N/A (Widget Integration) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body N/A ### Request Example ```dart class ResponsiveBanner extends StatelessWidget { @override Widget build(BuildContext context) { return LayoutBuilder( builder: (context, constraints) { // Adjust banner width based on available screen width double bannerWidth = constraints.maxWidth; double bannerHeight = 60; // Cap max width if necessary if (bannerWidth > 375) { bannerWidth = 375; } return Center( child: AdBannerWidget( posId: 'your_banner_ad_id', width: bannerWidth, height: bannerHeight, onAdLoaded: () => print('Responsive banner loaded'), onAdError: (error) => print('Responsive banner load error: $error'), ), ); }, ); } } ``` ### Response #### Success Response (Widget Rendered) - The banner ad is displayed and resizes according to the parent's constraints. #### Response Example N/A (Visual Component) ``` -------------------------------- ### Basic PreloadConfig Usage in Flutter Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/11-preload Demonstrates the basic usage of the PreloadConfig class for pre-loading ads without options, and with options for different ad types like reward video and feed ads. It also shows how to extend to custom ad types. ```dart import 'package:gromore_ads/gromore_ads.dart'; // Basic usage - without options PreloadConfig.rewardVideo(['reward_id']); // With options - configure parameters during pre-loading PreloadConfig.rewardVideo( ['reward_id'], options: { 'userId': 'user_123', 'rewardName': '金币', 'rewardAmount': 50, }, ); // Multiple ad slots PreloadConfig.feed( ['feed_id_1', 'feed_id_2', 'feed_id_3'], options: { 'width': 320, 'height': 180, 'count': 2, }, ); // Extend new types (if needed) PreloadConfig( adType: 'custom_ad_type', adIds: ['custom_id'], ); ``` -------------------------------- ### Prompt User Before Showing Ads Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/07-reward-video-ad Clearly communicate the rewards users can obtain before they decide to watch an ad. This example shows a dialog prompting the user and confirming their intent to watch. ```dart void _showRewardPrompt() { showDialog( context: context, builder: (context) => AlertDialog( title: Text('观看视频获得奖励'), content: Text('观看完整视频可获得50金币\n您确定要观看吗?'), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: Text('取消'), ), TextButton( onPressed: () { Navigator.pop(context); _showAd(); }, child: Text('观看视频'), ), ], ), ); } ``` -------------------------------- ### Listen for Reward Video Ad Events in Dart Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/11-preload Demonstrates how to listen for reward video ad loading events, including success and failure. This allows for real-time feedback on the ad's status, which is crucial for managing user experience and displaying ads only when they are ready. Requires GromoreAds to be initialized. ```dart _subscription = GromoreAds.onRewardVideoEvents( 'reward_video_pos_id', onLoaded: (event) { print('✅ 激励视频预加载成功: ${event.posId}'); }, onError: (event) { print('❌ 激励视频预加载失败: ${event.posId}'); print('错误信息: ${event.message} (${event.code})'); }, ); ``` -------------------------------- ### Display Loading State for Ads Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/07-reward-video-ad Provide visual feedback to the user about the ad's loading status. This example uses a `CircularProgressIndicator` when the ad is loading and changes the button text accordingly. ```dart ElevatedButton.icon( onPressed: _isLoaded ? _showAd : _loadAd, icon: _isLoading ? SizedBox( width: 16, height: 16, child: CircularProgressIndicator(strokeWidth: 2), ) : Icon(Icons.play_circle), label: Text(_isLoaded ? '观看视频' : '加载中...'), ) ``` -------------------------------- ### Recommended Ad Cache Refresh Strategy in Dart Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/11-preload Illustrates the recommended approach for refreshing ad caches to avoid unnecessary waste. It shows how to preload an ad and then refresh it after a significant interval (e.g., 30 minutes), contrasting it with the anti-pattern of frequent, redundant preloading of the same ad unit. ```dart // ❌ 不推荐: 短时间内重复预加载 await GromoreAds.preload(configs: [PreloadConfig.rewardVideo(['id'])]); await Future.delayed(Duration(seconds: 5)); await GromoreAds.preload(configs: [PreloadConfig.rewardVideo(['id'])]); // 浪费 // ✅ 推荐: 合理的刷新策略 await GromoreAds.preload(configs: [PreloadConfig.rewardVideo(['id'])]); // ... 30分钟后 await GromoreAds.preload(configs: [PreloadConfig.rewardVideo(['id'])]); // 刷新 ``` -------------------------------- ### Recommended Ad Preloading Timing in Dart Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/11-preload Demonstrates optimal moments for initiating ad preloading within a Flutter application lifecycle. It contrasts recommended practices like app startup and page initialization with a less effective approach of preloading only upon user interaction. ```dart // ✅ 推荐: 应用启动后预加载 void main() async { WidgetsFlutterBinding.ensureInitialized(); await GromoreAds.init(/* ... */); // 在用户看到首页前完成预加载 await GromoreAds.preload(configs: [/* ... */]); runApp(MyApp()); } // ✅ 推荐: 页面初始化时预加载 @override void initState() { super.initState(); _preloadAds(); } // ❌ 不推荐: 用户点击时才预加载(失去了预加载的意义) void onButtonClick() { await GromoreAds.preload(configs: [/* ... */]); // 太晚了! await GromoreAds.showRewardVideoAd('reward_id'); } ``` -------------------------------- ### AdBannerWidget with Full Callbacks Example Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/06-banner-ads Demonstrates how to use the AdBannerWidget with all available callback functions. This includes handling ad loading, errors, clicks, closes, and specific events like render success and ECPM information. ```dart AdBannerWidget( posId: 'your_banner_ad_id', width: 320, height: 100, onAdLoaded: () { print('Banner广告加载成功'); }, onAdError: (error) { print('Banner广告加载失败: $error'); }, onRenderSuccess: (width, height) { print('Banner广告渲染成功: ${width}x$height'); }, onRenderFail: (error) { print('Banner广告渲染失败: $error'); }, onEcpmInfo: (ecpmData) { print('Banner ECPM信息: $ecpmData'); final ecpm = ecpmData['ecpm'] ?? '0'; final platform = ecpmData['platform'] ?? ''; print('价格: $ecpm分, 平台: $platform'); }, onMixedLayout: () { print('Banner混出信息流布局触发'); }, onAdClicked: () { print('Banner广告被点击'); }, onAdClosed: () { print('Banner广告被关闭'); }, ) ``` -------------------------------- ### Splash Screen Widget with Ad Integration (Flutter) Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/04-splash-ads An example of a Flutter `StatefulWidget` for a splash screen that integrates splash ads. It loads the ad in `initState` and navigates to the home page after the ad is shown or a delay has passed. ```dart import 'package:flutter/material.dart'; import 'package:gromore_ads/gromore_ads.dart'; // Assume HomePage is defined elsewhere class HomePage extends StatelessWidget { const HomePage({super.key}); @override Widget build(BuildContext context) { return const Scaffold(body: Center(child: Text('Home Page'))); } } class SplashScreen extends StatefulWidget { const SplashScreen({super.key}); @override State createState() => _SplashScreenState(); } class _SplashScreenState extends State { @override void initState() { super.initState(); _loadAndEnter(); } Future _loadAndEnter() async { await GromoreAds.showSplashAd( SplashAdRequest( posId: 'your_splash_ad_id', timeout: const Duration(seconds: 5), logo: SplashAdLogo.asset('assets/logo.png'), ), ); // 按需延迟进入首页 await Future.delayed(const Duration(milliseconds: 600)); if (mounted) { Navigator.of(context).pushReplacement( MaterialPageRoute(builder: (_) => const HomePage()), ); } } @override Widget build(BuildContext context) { return const Scaffold( body: Center(child: CircularProgressIndicator()), ); } } ``` -------------------------------- ### Initialize SDK and Launch Test Tools (Dart) Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/10-test-tools Demonstrates how to initialize the Gromore Ads SDK and then launch the test tools. Initialization must be completed before launching the test tools. This is typically done during application startup. ```dart await GromoreAds.initAd( 'your_app_id', useMediation: true, debugMode: true, ); // Initialize after completing the SDK initialization await GromoreAds.launchTestTools(); ``` -------------------------------- ### Embedding Banner within a Scrollable List Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/06-banner-ads Demonstrates how to insert AdBannerWidgets into a Flutter ListView. This example shows how to conditionally render an ad banner every few list items using the mixed mode for better ad fill rates. ```dart class NewsListWithBanner extends StatelessWidget { final List newsItems = List.generate(20, (i) => '新闻 ${i + 1}'); @override Widget build(BuildContext context) { return ListView.builder( itemCount: newsItems.length, itemBuilder: (context, index) { // 每5条新闻后插入一个Banner if (index > 0 && index % 5 == 0) { return Container( margin: EdgeInsets.symmetric(vertical: 8), child: AdBannerWidget( posId: 'your_banner_ad_id', width: MediaQuery.of(context).size.width - 32, height: 60, enableMixedMode: true, // 启用混出模式,提高填充率 mutedIfCan: true, scenarioId: 'news_feed', onAdLoaded: () => print('列表Banner-$index加载成功'), onEcpmInfo: (data) { print('Banner-$index ECPM: ${data['ecpm']}'); }, ), ); } // 普通新闻列表项 return ListTile( leading: Icon(Icons.article), title: Text(newsItems[index]), ); }, ); } } ``` -------------------------------- ### Displaying Reward Video Ad After Successful Load in Dart Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/11-preload Shows the correct sequence for displaying a reward video ad. It involves preloading the ad, listening for the 'loaded' event to confirm readiness, and then conditionally calling the show method. This ensures that the application only attempts to show ads that have been successfully loaded, preventing errors. ```dart bool _isRewardLoaded = false; // 1. 预加载 await GromoreAds.preload( configs: [PreloadConfig.rewardVideo(['reward_id'])], ); // 2. 监听加载成功事件 _subscription = GromoreAds.onRewardVideoEvents( 'reward_id', onLoaded: (event) { _isRewardLoaded = true; print('✅ 广告加载成功'); }, ); // 3. 展示前检查 if (_isRewardLoaded) { await GromoreAds.showRewardVideoAd('reward_id'); } else { print('⚠️ 广告尚未加载完成'); } ``` -------------------------------- ### Show Reward Video Ad in Flutter Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/07-reward-video-ad Displays a previously loaded reward video ad. The 'posId' must match the ID used when loading the ad. Returns a Future indicating if the ad started to show. ```dart Future showRewardVideoAd(String posId) { // Implementation details... return GromoreAds.showRewardVideoAd(posId); } // 展示广告 await GromoreAds.showRewardVideoAd('reward_ad_id'); ``` -------------------------------- ### Launch GroMore Test Tools in Flutter Source: https://zhecent.com/sdks/flutter-gromore-ads/docs/10-test-helper This Dart code demonstrates how to create a helper class `AdTestHelper` to launch the GroMore test tools. It includes error handling for cases where the SDK might not be ready or dependencies are missing. The `launchTestTools` function returns a `Future` and prints debug messages based on the result. ```dart class AdTestHelper { // 启动GroMore测试工具 static Future launchTestTools() async { try { final bool result = await GromoreAds.launchTestTools(); if (!result) { debugPrint('GroMore测试工具启动失败:SDK未就绪或依赖缺失'); } } catch (e) { debugPrint('测试工具启动异常: $e'); } } } ```