### Quick Start: Interact with Short Stories Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/14-story-info Demonstrates how to quickly get started with the short story module by fetching lists, searching stories, and managing favorites. Assumes the 'pangrowth_content' SDK is imported. ```dart import 'package:pangrowth_content/pangrowth_content.dart'; // 获取短故事列表 final stories = await PangrowthContent.getStoryList( page: 1, count: 20, categoryId: 1, ); // 搜索短故事 final results = await PangrowthContent.searchStory( '言情', page: 1, count: 20, ); // 收藏短故事 await PangrowthContent.favoriteStory( 'story_123', isFavorite: true, ); ``` -------------------------------- ### Install Flutter Dependencies Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/01-installation After adding the dependency to your pubspec.yaml file, run this command in your project's root directory to download and install all project dependencies, including the pangrowth_content plugin. ```bash flutter pub get ``` -------------------------------- ### VideoController API Usage Example Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/20-video-native-view Provides a concise example of interacting with the VideoController API for controlling video playback, checking its ready state, and properly disposing of the controller. This demonstrates the core methods available for video management. ```dart final controller = VideoController(); // 检查状态 if (controller.isReady) { // 控制播放 await controller.pause(); await controller.resume(); } // 销毁(通常在 dispose 中调用) await controller.dispose(); ``` -------------------------------- ### Android VideoConfig Customization Example (Flutter) Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/20-video-native-view Demonstrates how to configure video playback settings for Android using the VideoConfig class in Flutter. This example showcases common and Android-specific parameters. ```dart final config = VideoConfig( drawChannelType: 1, // Android specific configuration isShowActionBar: true, actionBarBackgroundColor: '#FF6200EE', fontSize: 16, isBold: true, topMargin: 20, // Common configuration progressBarStyle: 1, enableRefresh: true, ); ``` -------------------------------- ### iOS VideoConfig Customization Example (Flutter) Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/20-video-native-view Illustrates how to customize video player settings for iOS using the VideoConfig class in Flutter. This example includes general and iOS-specific parameters. ```dart final config = VideoConfig( drawChannelType: 1, // iOS specific configuration isShowNavigationBar: true, navigationBarBackgroundColor: '#FFFFFF', navigationBarTitleColor: '#000000', statusBarStyle: 'darkContent', allowPanBack: true, // Common configuration progressBarStyle: 2, enableRefresh: true, ); ``` -------------------------------- ### Flutter Ad Placement Best Practices Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/25-custom-ads Code examples demonstrating recommended and not recommended ad placement strategies for 'draw ads' and 'middle page ads' to optimize user experience. ```dart // ✅ 推荐:合理间隔,避免影响用户体验 drawAdPositions: [5, 10, 15, 20] // ❌ 不推荐:过于频繁 drawAdPositions: [1, 2, 3, 4, 5] ``` ```dart // ✅ 推荐:每3-5章插入一次 middlePageInterval: 5 // ❌ 不推荐:每章都插入 middlePageInterval: 1 ``` -------------------------------- ### Custom Banner Ad Widget Example (Flutter) Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/25-custom-ads A simple Flutter widget example demonstrating how a custom Banner ad might be implemented. This widget is intended to be used with the `customBannerAdViewId` configuration. ```dart class MyBannerAdWidget extends StatelessWidget { const MyBannerAdWidget({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Container( height: 50, color: Colors.blue, child: Center( child: Text( '自定义Banner广告', style: TextStyle(color: Colors.white), ), ), ); } } ``` -------------------------------- ### Watch Together VideoConfig Configuration Example (Flutter) Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/20-video-native-view Shows how to configure VideoConfig for the 'Watch Together' feature in Flutter, demonstrating settings for both host and user roles. ```dart // Host configuration final hostConfig = VideoConfig( drawChannelType: 1, watchTogetherRole: 'HOST', hostGroupId: 12345, customCategory: '一起看', ); // User configuration final userConfig = VideoConfig( drawChannelType: 1, watchTogetherRole: 'USER', hostGroupId: 12345, customCategory: '一起看', ); ``` -------------------------------- ### Flutter Ad Lifecycle Management with Controller Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/25-custom-ads Example of managing the ad lifecycle using a controller in a StatefulWidget. It highlights the importance of disposing of the controller to release resources and prevent memory leaks. ```dart class MyAdPage extends StatefulWidget { @override _MyAdPageState createState() => _MyAdPageState(); } class _MyAdPageState extends State { final _controller = DramaPlayerController(); @override void dispose() { // ✅ 重要:销毁时释放资源 _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return DramaPlayerNativeView( controller: _controller, config: DramaPlayerConfig( dramaId: 12345, episode: 1, customBannerAdViewId: 'my_ad', ), ); } } ``` -------------------------------- ### Video Listener Setup (NativeView in Flutter) Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/20-video-native-view Demonstrates how to set up event listeners for video playback using the VideoNativeView widget in Flutter. This allows tracking various video states and user interactions. ```dart VideoNativeView( listener: VideoListener( onVideoReady: (videoId) { debugPrint('✅ Video Ready: $videoId'); }, onVideoDisposed: () { debugPrint('🗑️ Video Disposed'); }, onVideoError: (error) { debugPrint('❌ Video Error: $error'); }, ), ) ``` -------------------------------- ### Flutter Custom Ad Event Tracking Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/25-custom-ads Example of using a listener to track custom ad events like impressions and clicks. This allows for analytics integration to monitor ad performance. ```dart StoryReaderListener( onMiddlePageAdShow: () { // 统计章间广告曝光 Analytics.logEvent('ad_show', {'type': 'middle_page'}); }, onMiddlePageAdClick: () { // 统计章间广告点击 Analytics.logEvent('ad_click', {'type': 'middle_page'}); }, ) ``` -------------------------------- ### Dart: Example Usage of UserProfileLauncher for Different Page Types Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/22-user-profile-native-view Provides example code snippets demonstrating how to use the `UserProfileLauncher` class to open different types of user profile pages. These examples show calls for the main user home page, the user's favorite video page, and the user's focus page. ```dart // 打开个人主页 await launcher.openUserProfile( pageType: UserProfilePageType.userHomePage, ); // 打开喜欢的视频页 await launcher.openUserProfile( pageType: UserProfilePageType.userFavoriteVideoPage, ); // 打开关注页 await launcher.openUserProfile( pageType: UserProfilePageType.userFocusPage, ); ``` -------------------------------- ### Flutter: Initialize and Start Pangrowth Content SDK Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/15-story-home Provides the correct sequence for initializing and starting the Pangrowth Content SDK, along with its dependencies like GroMore SDK. This is crucial for ensuring the StoryHomeNativeView renders correctly and avoids issues like black screens. ```dart // 确保初始化顺序正确 // 1. 初始化 GroMore SDK await GroMore.initialize(...); // 2. 初始化 PangrowthContent await PangrowthContent.initialize( configPath: 'assets/config.json', ); // 3. 启动短故事模块 await PangrowthContent.start(startStory: true); // 4. 使用 StoryHomeNativeView ``` -------------------------------- ### Configure Android Project-Level Gradle Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/01-installation Modify the project-level build.gradle file in your Android project to include necessary repositories for the Pangrowth SDK and its dependencies. Ensure the Kotlin version is compatible. ```gradle buildscript { ext.kotlin_version = '1.8.0' // Ensure Kotlin version >= 1.7.0 repositories { google() mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:7.3.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } allprojects { repositories { google() mavenCentral() // ⚠️ Required: Pangrowth Ads SDK repository (pangrowth depends on gromore_ads plugin) maven { url 'https://artifact.bytedance.com/repository/pangle' } // ⚠️ Required: Pangrowth Content SDK repository maven { url 'https://artifact.bytedance.com/repository/Volcengine' } } } ``` -------------------------------- ### Flutter Project Initialization with Config Path Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/01-installation This Dart snippet illustrates how to initialize the PangrowthContent SDK in a Flutter application, focusing on the `configPath` parameter. It shows recommended usage with just the filename (for Android) and how to specify subdirectories if the configuration file is not in the root assets folder. ```dart // ✅ 推荐:直接使用文件名(Android 会依次查找 Flutter assets 与原生 assets) PangrowthContent.initialize( configPath: 'SDK_Setting_5609594.json', ... ) // ⚠️ 子目录:如果放在 assets 子目录,需要带上相对路径 PangrowthContent.initialize( configPath: 'configs/SDK_Setting_5609594.json', // 对应 assets/configs/SDK_Setting_5609594.json ... ) ``` -------------------------------- ### Configure Android MainActivity with FlutterFragmentActivity Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/01-installation Ensure your MainActivity extends `FlutterFragmentActivity` instead of `FlutterActivity`. This is crucial for the pangrowth_content plugin's PlatformView components, which require FragmentActivity context for proper functionality. ```kotlin package com.your.package import io.flutter.embedding.android.FlutterFragmentActivity class MainActivity : FlutterFragmentActivity() ``` -------------------------------- ### Integrate Custom Ads in Story Reader (Flutter) Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/25-custom-ads Provides an example of integrating various custom ad types (Page, Line, Banner) within the StoryReaderNativeView. It configures ad view IDs and intervals for chapter and line-based ads. ```dart import 'package:flutter/material.dart'; import 'package:pangrowth_content/pangrowth_content.dart'; class CustomAdStoryReaderPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( body: StoryReaderNativeView( config: StoryReaderConfig( storyId: 67890, startChapter: 0, // 配置章间广告 customMiddlePageAdViewId: 'story_page_ad', middlePageInterval: 5, // 每5章插入一次章间广告 // 配置段间广告 customMiddleLineAdViewId: 'story_line_ad', middleLineStartLine: 10, // 从第10行开始插入段间广告 middleLineInterval: 20, // 每20行插入一次段间广告 // 配置Banner广告 customBannerAdViewId: 'story_banner_ad', ), listener: StoryReaderListener( onReaderReady: (readerId) { print('阅读器就绪: $readerId'); }, onMiddlePageAdShow: () { print('章间广告显示'); }, onMiddleLineAdShow: (lineNumber) { print('段间广告显示在第$lineNumber行'); }, ), ), ); } } ``` -------------------------------- ### iOS CocoaPods Troubleshooting Commands Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/01-installation This sequence of shell commands provides a common troubleshooting approach for iOS CocoaPods-related build errors. It involves deintegrating the existing Pods, reinstalling them, cleaning the Flutter project, and then running the project again. ```bash cd ios pod deintegrate pod install cd .. flutter clean flutter run ``` -------------------------------- ### Flutter Video Lifecycle Management with Pangrowth Content SDK Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/20-video-native-view This Flutter code snippet demonstrates the complete lifecycle of managing a video using the Pangrowth Content SDK. It covers creating a video instance with specific configurations, displaying it, controlling playback states (pause, resume, refresh), and finally destroying the instance to release resources. The example utilizes StatefulWidget to manage UI updates and asynchronous operations. ```dart import 'package:flutter/material.dart'; import 'package:pangrowth_content/pangrowth_content.dart'; class VideoAPIDemo extends StatefulWidget { const VideoAPIDemo({super.key}); @override State createState() => _VideoAPIDemoState(); } class _VideoAPIDemoState extends State { String? _videoId; bool _isLoading = false; Future _createAndShowVideo() async { setState(() { _isLoading = true; }); try { // 1. 创建视频配置 final config = VideoConfig( drawChannelType: 1, // 推荐频道 progressBarStyle: 1, // 浅色进度条 hideChannelName: false, // 显示频道名称 enableRefresh: true, // 支持下拉刷新 ); // 2. 创建视频 final result = await PangrowthContent.createVideo(config); if (result['success'] == true) { _videoId = result['videoId'] as String; debugPrint('创建成功: $_videoId'); // 3. 展示视频 await PangrowthContent.showVideo( _videoId!, // iOS专用:控制展示样式 presentationStyle: 'fullScreen', // fullScreen/pageSheet/formSheet // Android专用:指定容器ID // containerId: android.R.id.content, ); debugPrint('展示成功'); } } catch (e) { debugPrint('创建或展示失败: $e'); _showSnackBar('操作失败: $e'); } finally { setState(() { _isLoading = false; }); } } Future _pauseVideo() async { if (_videoId != null) { await PangrowthContent.pauseVideo(_videoId!); debugPrint('暂停成功'); } } Future _resumeVideo() async { if (_videoId != null) { await PangrowthContent.resumeVideo(_videoId!); debugPrint('恢复成功'); } } Future _refreshVideo() async { if (_videoId != null) { await PangrowthContent.refreshVideo(_videoId!); debugPrint('刷新成功'); } } Future _destroyVideo() async { if (_videoId != null) { await PangrowthContent.destroyVideo(_videoId!); debugPrint('销毁成功'); setState(() { _videoId = null; }); } } void _showSnackBar(String message) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(message)), ); } @override void dispose() { // 清理资源 if (_videoId != null) { PangrowthContent.destroyVideo(_videoId!); } super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('API方式演示')), body: Center( child: _isLoading ? const CircularProgressIndicator() : Column( mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton( onPressed: _videoId == null ? _createAndShowVideo : null, child: const Text('创建并显示'), ), const SizedBox(height: 10), ElevatedButton( onPressed: _videoId != null ? _pauseVideo : null, child: const Text('暂停'), ), const SizedBox(height: 10), ElevatedButton( onPressed: _videoId != null ? _resumeVideo : null, child: const Text('恢复'), ), const SizedBox(height: 10), ElevatedButton( onPressed: _videoId != null ? _refreshVideo : null, child: const Text('刷新'), ), const SizedBox(height: 10), ElevatedButton( onPressed: _videoId != null ? _destroyVideo : null, child: const Text('销毁'), ), ], ), ), ); } } ``` -------------------------------- ### Add CocoaPods Source to Podfile for iOS Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/01-installation For iOS integration, modify your `ios/Podfile` to include the necessary CocoaPods repository (`volcengine-specs`) required by the pangrowth_content plugin, as it depends on the Pangrowth Content SDK. ```ruby # Ensure this line is present or added to your Podfile: source 'https://artifact.bytedance.com/repository/Volcengine/' source 'https://cdn.cocoapods.org/' # ... other pod configurations ``` -------------------------------- ### Android Build Configuration for SDK Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/01-installation This Gradle snippet shows how to configure the `android/build.gradle` file to include the necessary Maven repositories for the Pangrowth SDK and its dependencies. It ensures that Gradle can resolve and download the required SDK libraries during the build process. ```gradle allprojects { repositories { google() mavenCentral() // 穿山甲广告SDK仓库(必需,因为 pangrowth_content 依赖 gromore_ads) maven { url 'https://artifact.bytedance.com/repository/pangle' } // 穿山甲内容SDK仓库(必需) maven { url 'https://artifact.bytedance.com/repository/Volcengine' } } } ``` -------------------------------- ### Configure Full Ad Setup with StoryReaderNativeView Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/17-story-reader Demonstrates a comprehensive configuration for ads within the StoryReaderNativeView, including inter-chapter, inter-paragraph, and banner ads. It also shows how to set up event listeners for ad-related callbacks. This setup requires valid ad unit IDs for each ad type. ```dart StoryReaderNativeView( config: StoryReaderConfig( storyId: 67890, startChapter: 0, defaultTextSize: 16, endPageRecSize: 6, // 文末推荐6个短故事 pageTurnType: 1, // 滑页模式(iOS) fontSizeLevel: 2, // 字体大小档位(iOS) // 配置章间广告 customMiddlePageAdViewId: 'story_page_ad', middlePageInterval: 5, // 每 5 章插入一次 // 配置段间广告 customMiddleLineAdViewId: 'story_line_ad', middleLineStartLine: 10, // 从第 10 行开始插入 middleLineInterval: 20, // 每 20 行插入一次 // 配置 Banner 广告 customBannerAdViewId: 'story_banner_ad', ), listener: StoryReaderListener( onMiddlePageAdShow: () { debugPrint('章间广告显示'); // 记录广告曝光 }, onMiddlePageAdClick: () { debugPrint('章间广告点击'); // 记录广告点击 }, onMiddlePageAdClose: () { debugPrint('章间广告关闭'); }, onMiddleLineAdShow: (lineNumber) { debugPrint('段间广告显示在第$lineNumber行'); }, onMiddleLineAdClick: () { debugPrint('段间广告点击'); }, onBannerAdShow: () { debugPrint('Banner广告显示'); }, onBannerAdClick: () { debugPrint('Banner广告点击'); }, ), ) ``` -------------------------------- ### Configure Android Manifest Permissions Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/01-installation Add necessary permissions to your AndroidManifest.xml file, including internet access, network state, and storage read/write permissions for caching. Also, configure application attributes like minSdkVersion and targetSdkVersion. ```xml ``` -------------------------------- ### Example Usage of StoryInfo in Flutter Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/14-story-info This Flutter code demonstrates how to access and display information from a StoryInfo object. It shows how to print details like story ID, title, author, category, chapter progress, favorite status, and read count. It also includes a conditional example for displaying a cover image based on the imageType. ```dart final story = stories.first; print('故事ID: ${story.storyId}'); print('标题: ${story.title}'); print('作者: ${story.author}'); print('分类: ${story.categoryName}'); print('总章节: ${story.totalChapters}章'); print('当前进度: 第${story.currentIndex + 1}章, ${(story.progress * 100).toStringAsFixed(1)}%'); print('是否收藏: ${story.isFavorited ? "是" : "否"}'); print('阅读次数: ${story.statsCount}'); // 显示封面图 if (story.imageType == 0) { Image.network(story.coverUrl); } ``` -------------------------------- ### Collaborative Video Watching Service (Flutter) Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/20-video-native-view Implement 'Watch Together' functionality with host and user roles, including starting, joining, and syncing playback. Requires `PangrowthContent` and `VideoConfig` from the SDK. ```dart class WatchTogetherService { /// 主控端:启动一起看视频 static Future startAsHost(String roomId) async { final config = VideoConfig( watchTogetherRole: 'HOST', hostGroupId: int.parse(roomId), drawChannelType: 1, customCategory: '一起看', scene: 'watch_together', ); final result = await PangrowthContent.createVideo(config); final videoId = result['videoId']; await PangrowthContent.showVideo(videoId); } /// 被控端:加入一起看视频 static Future joinAsUser(String roomId, String syncData) async { final config = VideoConfig( watchTogetherRole: 'USER', hostGroupId: int.parse(roomId), drawChannelType: 1, customCategory: '一起看', scene: 'watch_together', ); final result = await PangrowthContent.createVideo(config); final videoId = result['videoId']; // 设置同步数据 await PangrowthContent.setSyncData(videoId, syncData, 1); await PangrowthContent.showVideo(videoId); } /// 同步播放数据 static Future syncPlayback(String videoId, String syncData) async { await PangrowthContent.setSyncData(videoId, syncData, 2); } } ``` -------------------------------- ### Troubleshoot Pangrowth Content SDK Initialization and Configuration Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/22-user-profile-native-view This snippet provides solutions for common Pangrowth Content SDK issues, including ensuring plugin initialization with `PangrowthContent.start()`, verifying App ID and App Name, and correctly configuring the UserProfileConfig. ```dart // 1. 确保在使用个人主页前完成初始化 await PangrowthContent.start( startDrama: true, // 或 startStory: true ); // 2. 验证配置是否正确 UserProfileNativeView( config: const UserProfileConfig( pageType: UserProfilePageType.userHomePage, scene: 'user_center', // 必须提供场景标识 ), ); // 3. 监听错误事件 UserProfileListener( onProfileError: (error) { debugPrint('个人主页错误: $error'); }, ) ``` -------------------------------- ### Control Video Playback with VideoController in Flutter Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/20-video-native-view Illustrates how to use the VideoController to manage video playback within the VideoNativeView. This example shows how to pause and resume video playback externally and includes proper controller disposal. ```dart import 'package:flutter/material.dart'; import 'package:pangrowth_content/pangrowth_content.dart'; class VideoPlayerPage extends StatefulWidget { const VideoPlayerPage({super.key}); @override State createState() => _VideoPlayerPageState(); } class _VideoPlayerPageState extends State { final _controller = VideoController(); @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: Stack( children: [ VideoNativeView( controller: _controller, channelType: 3, // 推荐+关注双频道 listener: VideoListener( onVideoReady: (videoId) { debugPrint('视频就绪: $videoId'); }, ), ), Positioned( bottom: 50, right: 20, child: Row( children: [ FloatingActionButton( mini: true, onPressed: () => _controller.pause(), child: const Icon(Icons.pause), ), const SizedBox(width: 10), FloatingActionButton( mini: true, onPressed: () => _controller.resume(), child: const Icon(Icons.play_arrow), ), ], ), ), ], ), ); } } ``` -------------------------------- ### 短剧播放页:自定义 Flutter 弹窗接入 (Flutter) Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/07-drama-player 使用 Flutter 自定义解锁弹窗,但仍由 SDK 播放 GroMore 激励广告。通过 `hideRewardDialog: true` 隐藏 SDK 默认弹窗,并监听 `onUnlockStart` 事件来触发自定义弹窗。用户确认解锁后,调用 `PangrowthContent.confirmUnlock()`。 ```dart class SdkAdWithCustomDialog extends StatefulWidget { @override State createState() => _SdkAdWithCustomDialogState(); } class _SdkAdWithCustomDialogState extends State { String? _playerId; DramaInfo? _unlockDramaInfo; int? _unlockEpisode; int? _unlockTotalEpisodes; void _showCustomDialog() { showDialog( context: context, barrierDismissible: false, builder: (context) => AlertDialog( title: Text('解锁后续剧集'), content: Text('观看广告后可解锁接下来的 3 集'), actions: [ TextButton( onPressed: () { Navigator.pop(context); // 通知 SDK 用户取消解锁 PangrowthContent.cancelUnlock(_playerId!); }, child: Text('残忍离开'), ), ElevatedButton( onPressed: () { Navigator.pop(context); // 通知 SDK 用户确认解锁,SDK 将自动播放广告 PangrowthContent.confirmUnlock(_playerId!); }, child: Text('解锁短剧'), ), ], ), ); } @override Widget build(BuildContext context) { return DramaPlayerNativeView( config: DramaPlayerConfig( dramaId: 1008, episode: 1, adMode: 'common', // SDK 广告模式 freeSet: 2, unlockSet: 3, hideRewardDialog: true, // ⚠️ 隐藏 SDK 默认弹窗 ), listener: DramaPlayerListener( onPlayerReady: (playerId) { _playerId = playerId; debugPrint('播放器就绪: $playerId'); }, onUnlockStart: (dramaInfo, episode, totalEpisodes) { // 收到解锁流程开始事件,显示自定义弹窗 setState(() { _unlockDramaInfo = dramaInfo; _unlockEpisode = episode; _unlockTotalEpisodes = totalEpisodes; }); _showCustomDialog(); }, onUnlockEnd: (success) { debugPrint('解锁流程结束,结果: $success'); }, ), ); } } ``` -------------------------------- ### Configure Android Proguard Rules Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/01-installation If code obfuscation is enabled in your Android project, add the specified rules to `android/app/proguard-rules.pro` to prevent the removal of necessary Pangrowth SDK and Flutter plugin bridge classes. ```proguard # Keep Pangrowth SDK related classes -keep class com.bytedance.sdk.** { *; } -keep class com.pgl.sys.ces.* {*;} # Keep Flutter plugin bridge classes -keep class com.zhecent.pangrowth_content.** { *; } ``` -------------------------------- ### Add Pangrowth Content Plugin Dependency in Flutter Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/01-installation Declare the pangrowth_content plugin as a dependency in your Flutter project's pubspec.yaml file. Ensure you are using the latest available version for optimal compatibility and features. ```yaml dependencies: flutter: sdk: flutter pangrowth_content: ^1.0.0 # Please use the latest version ``` -------------------------------- ### Configure Drama Swipe Flow for New Users (Dart) Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/06-drama-swipe-flow Illustrates how to configure the Drama Swipe Flow for a new user scenario using DramaSwipeConfig. This configuration emphasizes guiding new users by showing channel names and detailed info, enabling refresh, and offering a certain number of free episodes with a light progress bar style. ```dart final config = DramaSwipeConfig( hideChannelName: false, // 显示频道名称,引导新用户 hideDramaInfo: false, // 显示详细信息 enableRefresh: true, // 支持下拉刷新 progressBarStyle: 1, // 浅色进度条 dramaFree: 3, // 新用户免费3集 unlockEpisodesCount: 1, // 每次解锁1集 channelType: 1, // 推荐频道 customCategory: '新人推荐', ); final result = await PangrowthContent.createDramaSwipeFlow(config: config); ``` -------------------------------- ### Configure Android App-Level Gradle Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/01-installation Update the app-level build.gradle file in your Android project to set compileSdkVersion, minSdkVersion, targetSdkVersion, and enable multiDex support if needed. Configure compilation options for Java 8 compatibility. ```gradle android { compileSdkVersion 33 // Or higher defaultConfig { applicationId "com.example.yourapp" minSdkVersion 21 // Minimum API 21 targetSdkVersion 33 // Target API 33 or higher // Enable multiDex support (if needed) multiDexEnabled true } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = '1.8' } } dependencies { // If multiDex is enabled implementation 'androidx.multidex:multidex:2.0.1' } ``` -------------------------------- ### 短剧播放页:SDK 默认弹窗接入 (Flutter) Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/07-drama-player 使用 SDK 默认弹窗接入短剧播放页,SDK 自动处理广告播放和解锁流程。适用于快速集成,无需自定义 UI。此模式配置 `adMode` 为 'common',`hideRewardDialog` 为 `false`。 ```dart DramaPlayerNativeView( config: DramaPlayerConfig( dramaId: 1008, episode: 1, adMode: 'common', // SDK 广告模式(可省略,默认值) freeSet: 2, // 前 2 集免费 unlockSet: 3, // 每次解锁 3 集 hideRewardDialog: false, // 显示 SDK 默认解锁弹窗 ), ) ``` -------------------------------- ### Enable MultiDex for Android Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/01-installation This Gradle snippet configures the `android/app/build.gradle` file to enable MultiDex support. MultiDex is often required for applications that exceed the default DEX file limit, ensuring all SDK classes are included in the final Android package. ```gradle defaultConfig { multiDexEnabled true } dependencies { implementation 'androidx.multidex:multidex:2.0.1' } ``` -------------------------------- ### Configure CocoaPods for iOS SDK Source: https://zhecent.com/sdks/flutter-pangrowth-content/docs/01-installation This snippet configures the CocoaPods environment for iOS development by adding necessary remote package sources and setting the deployment target. It ensures that the Flutter project can correctly fetch and link iOS dependencies for the SDK. ```ruby source 'https://github.com/CocoaPods/Specs.git' source 'https://github.com/volcengine/volcengine-specs.git' platform :ios, '11.0' target 'Runner' do use_frameworks! use_modular_headers! flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0' end end end end ```