pangle_flutter 3.0.2
pangle_flutter: ^3.0.2 copied to clipboard
A Flutter plugin that supports ByteDance Pangle SDK on Android and iOS. Such as Splash Ads, Rewarded Video Ads, etc.
English | 中文
3.0.2 #
Build Infrastructure #
Android
- Upgraded Android Gradle Plugin: 8.11.1 → 9.0.1
- Upgraded Gradle wrapper: 8.14 → 9.1.0
- Upgraded Kotlin plugin: 2.2.20 → 2.3.20
- Refactored
android/build.gradle.kts: decoupled Kotlin compiler options viapluginManager.withPluginso the library builds correctly regardless of Kotlin plugin presence; switchedjvmToolchaintocompilerOptions.jvmTarget(typed enum) - Added
testOptionsblock with JUnit Platform support and per-test stdout/stderr logging - Example: switched
compileSdk/targetSdk/versionCode/versionNameto Flutter-provided values where applicable; fixed Gradle 9DirectoryAPI usage inbuild.gradle.kts - Added AGP 9 + Flutter Gradle plugin compatibility flags to
gradle.properties:android.newDsl=false,android.builtInKotlin=false
iOS
- Migrated plugin source layout from
ios/Classes/to a proper Swift Package atios/pangle_flutter/(Sources/pangle_flutter/) - Removed legacy Obj-C bridge files (
PangleFlutterPlugin.h/.m) — no longer needed under SPM - Updated
pangle_flutter.podspec:source_filesandresource_bundlespaths now point to the new SPM layout - Example: removed CocoaPods integration (Pods xcconfig includes,
Pods.xcodeprojworkspace reference, all[CP]build phases); replaced withFlutterGeneratedPluginSwiftPackageas anXCLocalSwiftPackageReference - Example: added a "Prepare Flutter Framework" pre-action to the Xcode scheme so SPM builds correctly trigger Flutter's
xcode_backend preparestep - Example: replaced CocoaPods xcconfig includes with explicit
OTHER_LDFLAGSweak-framework flags forAppTrackingTransparency,CoreHaptics,CoreML,DeviceCheck - Example: merged
Info-Debug.plist/Info-Release.plistinto a singleInfo.plist
Dart / pubspec
- Fixed iOS
pluginClassinpubspec.yaml:PangleFlutterPlugin→SwiftPangleFlutterPlugin - Relaxed Dart SDK constraint:
^3.11.5→'>=3.0.0 <4.0.0' - Raised minimum Flutter version:
3.3.0→3.10.0
3.0.1 #
New Features #
- Mediation support (
useMediation): addeduseMediationparameter to bothIOSConfigandAndroidConfig. Set totrueto enable Pangle's GroMore mediation layer.
await pangle.init(
iOS: const IOSConfig(appId: kIOSAppId, useMediation: true),
android: const AndroidConfig(appId: kAndroidAppId, useMediation: true),
);
SDK Dependency Updates #
- iOS: switched from
Ads-CN ~> 7.0toAds-CN-Beta/BUAdSDK ~> 7.0+Ads-CN-Beta/CSJMediation ~> 7.0 - Android: switched from
com.pangle.cn:ads-sdk-protocom.pangle_beta.cn:mediation-sdk
Example App #
- Test Measurement Suite: integrated
BUAdTestMeasurementManageron both iOS and Android. Tap the 🐛 button (debug builds only) to launch the Pangle test panel. - Theme picker: added SDK theme switcher (light / dark) as the first item on the home page.
- Setup page: SDK initialisation is now done on a dedicated
SetupPagebefore entering the main menu.
3.0.0 #
New Features #
Draw Ad (Vertical Full-Screen Video)
TikTok-style vertically scrollable video ads. Load a batch of IDs, then display each one inside a full-screen PageView.
// 1. Load
final PangleDrawAd drawAd = await pangle.loadDrawAd(
iOS: IOSDrawConfig(slotId: kDrawId, adCount: 3),
android: AndroidDrawConfig(slotId: kDrawId, adCount: 2),
);
// 2. Display — embed in a full-screen PageView
DrawView(
id: drawAd.data.first,
onClick: () {},
onShow: () {},
onRenderFail: (code, msg) {},
)
// 3. Clean up
await pangle.removeDrawAd(drawAd.data);
Stream Ad (Custom Player)
Returns video URL + metadata for use with your own video player. No SDK-rendered view required.
final PangleStreamAd streamAd = await pangle.loadStreamAd(
iOS: IOSStreamConfig(slotId: kStreamId),
android: AndroidStreamConfig(slotId: kStreamId),
);
for (final StreamAdItem item in streamAd.data) {
// item.videoUrl, item.title, item.imageUrl, item.videoDuration, etc.
}
EcMall Ad (Shopping / Native Ad)
Commerce-integrated native ad rendered as a platform view. Must be wrapped in a size-constraining widget.
SizedBox(
width: 600,
height: 257,
child: EcMallView(
slotId: kEcMallId,
width: 600,
height: 257,
onClick: () {},
onError: (code, msg) {},
),
)
Feed Icon Ad
Icon-sized feed ad for compact grid or list layouts. Rendered with the standard FeedView widget.
final PangleAd iconAd = await pangle.loadFeedIconAd(
android: AndroidFeedIconConfig(slotId: kFeedIconId),
);
FeedView(id: iconAd.data.first)
Half-Screen Splash (Android)
Show a splash ad occupying ~4/5 of the screen height instead of full-screen. Android only.
await pangle.loadSplashAd(
android: AndroidSplashConfig(slotId: kSplashId, isHalfSize: true),
iOS: IOSSplashConfig(slotId: kSplashId),
);
- [Dart]
BannerViewandFeedViewnow applyAspectRatiointernally based onexpressSize(whenheight > 0). No need to wrap them in an externalAspectRatioor manually set a matching container height.FeedViewaccepts a new optionalexpressSizeparameter — pass the same value used inloadFeedAd.
Bug Fixes #
- [Android] SDK is now initialised with
applicationContextinstead of the activity context, eliminating a class of context-leak issues on process restart. Splash ad no longer requires aFragmentActivityhost — anyActivityworks. - [iOS] Fixed critical bug: interstitial event sink was incorrectly mapped to the fullscreen sink in
PangleEventStreamHandler, causing interstitial callbacks to be silently dropped - [iOS] Fixed dead
initWithMessengerstatic method inFeedViewFactorythat returned aBannerViewFactoryinstance instead ofFeedViewFactory - [iOS] Fixed double force-unwrap (
!!) when resolving the key window inFLTView
Safety & Stability #
- [iOS] Replaced
[unowned self]captures with[weak self]+guard let selfin all async closures (PangleAdManager,FLTRewardedVideoExpressAdTask,FLTFullscreenVideoExpressAdTask) to prevent potential crashes on deallocation - [iOS] Replaced force casts (
as!,!) with safeguard letoptional binding throughout (FLTNativeExpressAdTask,FLTBannerView,FLTBannerView.loadExpressAd)
API Modernization #
- [iOS] Replaced deprecated
UIApplication.shared.windows/keyWindowwith theconnectedScenes-based approach, compatible with multi-window and scene-based UIKit - [iOS] Updated
swift_versionfrom5.0to5.9in the podspec - [Android] Replaced deprecated
.values()[index]enum access with.entries.getOrNull(index)with a safe default fallback (PangleLoadingType,PangleOrientation,PangleTitleBarTheme) - [Android] Replaced deprecated
systemUiVisibilitywithWindowInsetsControlleron API 30+; kept a backward-compatible path for API 24–29 - [Android] Added
constmodifier to package-level constants inPangleFlutterPlugin
Performance #
- [Android] Cached
Handler(Looper.getMainLooper())as a class field in view classes (FlutterBannerView,FlutterFeedView,FlutterSplashView,FlutterEcMallView) instead of allocating a new instance per call - [Dart] Changed top-level screen dimension variables (
kPangleScreenWidth,kPangleScreenHeight) tolate finalto defer initialization until first access
New Features #
Ad Load / Show Separation — RewardedAd & FullscreenAd
Rewarded and fullscreen video ads now have dedicated wrapper objects that cleanly separate loading from showing. load() is a static factory that resolves only on success and throws AdLoadException on failure — no more checking result.code manually.
try {
final ad = await RewardedAd.load(
slotId: 'your_slot_id',
iOS: const IOSRewardedVideoConfig(slotId: 'xxx'),
android: AndroidRewardedVideoConfig(slotId: 'xxx'),
);
// Reaching here guarantees load succeeded
final result = await ad.show(
onEvent: (event) {
if (event case AdRewardEvent(:final verified) when verified) {
grantReward();
}
},
);
} on AdLoadException catch (e) {
debugPrint('load failed: $e');
}
FullscreenAd follows the same pattern with FullscreenAd.load() / ad.show().
Preload Pools — RewardedAdPool & FullscreenAdPool
Singleton pool managers handle preloading, caching, and auto-refill after each show.
// Configure once at startup
await RewardedAdPool.instance.configure(
slotId: 'your_slot_id',
poolSize: 2, // keep 2 ads ready
autoRefill: true, // reload after each show
iOS: const IOSRewardedVideoConfig(slotId: 'xxx'),
android: AndroidRewardedVideoConfig(slotId: 'xxx'),
);
if (await RewardedAdPool.instance.isReady('your_slot_id')) {
await RewardedAdPool.instance.show(
slotId: 'your_slot_id',
onEvent: (event) { ... },
);
}
Type-safe Ad Events — PangleAdEvent sealed class
All native event strings are now mapped to a sealed class hierarchy, enabling exhaustive switch matching:
switch (event) {
case AdRewardEvent(:final verified): ...
case AdClosedEvent(): ...
case AdErrorEvent(): ...
default: ...
}
Available subtypes: AdLoadedEvent, AdCachedEvent, AdShownEvent, AdSkippedEvent, AdClickedEvent, AdCompletedEvent, AdClosedEvent, AdErrorEvent, AdRenderFailedEvent, AdRenderSuccessEvent, AdRewardEvent, AdUnknownEvent.
Native: show and has methods
- [Android/iOS] Added
showRewardedVideoAd(slotId)andshowFullscreenVideoAd(slotId)method channel calls — show a cached ad without triggering a new load. - [Android/iOS] Added
hasRewardedVideoAd(slotId)andhasFullscreenVideoAd(slotId)— query whether a non-expired cached ad is available. - [Android]
PangleAdManager: addedhasRewardedVideoAd()andhasFullscreenVideoAd()with the same expiration check asshowRewardedVideoAd(). - [iOS]
PangleAdManager: addedhasRewardedVideoAd(_:)andhasFullscreenVideoAd(_:)protected byadQueue.sync.
SplashView
- [iOS/Android/Dart] Differentiated
SplashViewerror callbacks:onRenderFail(render failure) andonError(load failure) — consistent with the existingBannerViewpattern - [SplashView] Added
onRenderFailcallback parameter to theSplashViewwidget
Deprecations #
pangle.loadRewardedVideoAd()— useRewardedAd.load()/RewardedAdPoolinstead.pangle.loadFullscreenVideoAd()— useFullscreenAd.load()/FullscreenAdPoolinstead.PangleLoadingType— now an internal implementation detail; do not reference in application code.
Improvements #
- [Dart]
IOSRewardedVideoConfig,IOSFullscreenVideoConfig,AndroidRewardedVideoConfig,AndroidFullscreenVideoConfig— addedcopyWith()methods. - [iOS] Simplified
FLTView.hitTest: removed the fragileFlutterOverlayViewclass-name detection (a no-op since Flutter 3+ switched to TLHC rendering).touchableBoundsnow directly restricts which areas of the native ad view receive touch events. - [iOS] Cleaned up
UIUtil: removedisOverlay,findTargetView, andfindTargetOverlayView(dead code in Flutter 3+ TLHC mode) - [Android]
SurfaceAndroidBannerView,SurfaceAndroidFeedView,SurfaceAndroidSplashView: removed thehybridCompositionparameter; all three now exclusively use TLHC (initSurfaceAndroidView). The Hybrid Composition path (initExpensiveAndroidView) has been removed.AndroidViewMixin.createViewsimplified accordingly.
Code Cleanup #
- [Android] Removed deprecated
NativeSplashDialogimplementation; splash dialog now exclusively uses the AndroidX-basedSupportSplashDialog - [Android] Removed dead code branches for API level < 24 (below
minSdk) - [Android] Removed redundant
get() = fieldgetter fromttAdNativeinPangleAdManager
Dart / Flutter Modernization #
- [Dart] Fixed
Future<dynamic>return type on internal method-call handlers infeedview_method_channel.dartandbannerview_method_channel.dart→Future<void> - [Dart] Added explicit
voidreturn type to the three public typedefs (PangleSplashCloseTypeCallback,PangleMessageCallback,PangleOptionCallback) inutil.dart - [Dart] Breaking: Renamed
PangleOrientation.veritical→PangleOrientation.vertical(typo fix). Update any usages accordingly. Kotlin-sidePangleOrientation.veriticalrenamed toPangleOrientation.verticalas well; ordinal values are unchanged. - [Dart] Replaced unsafe
List.values[index]enum lookups with.elementAtOrNull()+ safe default insplashview_method_channel.dart,model.dart, andpangle_plugin.dart - [Dart] Removed dead fields (
_bannerViewPlatformController,_feedViewPlatformController,_splashViewPlatformController,_platformCallbacksHandler,_widget) and the no-op_updateWidgetmethod fromBannerViewController,FeedViewController, andSplashViewController; removed unuseddart:asyncimport from all three view files - [Example] Updated
MediaQuery.of(context).size.width→MediaQuery.sizeOf(context).widthinfeed_page.dart
Ad Loading & Caching #
- [Android]
FlutterFeedViewnow firesonRenderFail(code=-1)to Dart when the requested ad is not found in the cache, instead of silently showing a blank view - [Android]
FlutterFeedView.dispose()now callsremoveExpressAd()to properly destroy the backingTTNativeExpressAdand prevent memory leaks when the Flutter widget is removed - [iOS]
FLTFeedView.deinitnow callsPangleAdManager.shared.removeExpressAd()to release the cachedBUNativeExpressAdViewwhen the platform view is destroyed - [iOS]
FeedView.loadExpressAd()now firesonRenderFail(code=-1)to Dart when the ad is not found in the cache (mirrors the Android behavior above) - [iOS] Added
CachedVideoAdwrapper struct with a 30-minute TTL for rewarded and fullscreen video ad caches inPangleAdManager. Expired entries are purged before each show attempt, aligning iOS behavior with Android's SDK-providedexpirationTimestampcheck - [iOS]
removeExpressAd()— removed force-unwrap (key!), added@discardableResult
2.0.1 #
- Optimize the use of Hybrid Composition
2.0.0 #
- Upgrade ads sdk to 5.0+.
- Adaptation method for removing overseas sdk
- Remove insertion ads implementation (according to the document has been taken over by fullscreen ads, need to change the original call method to
loadFullscreenVideoAd) - loadBannerAd has been adapted to use NativeAd implementation.
- Fixed and optimized the open screen ad implementation
1.9.7 #
- Fix analysis issues.
1.9.2 #
- Fix [#87], deprecated method.
1.9.1 #
- Optimize README (Clickthrough)
1.9.0 #
- Fix click through problem on iOS
- Remove "updateTouchableBounds" & "updateRestrictedBounds"
- Add "addTouchableBounds" & "clearTouchableBounds" (extra click areas)
1.8.0 #
- Adapt pangle SDK 4.7+ (Android & iOS)
- [SplashView] Remove "onSkip" & "onTimeOver", add "onClose"
- [SplashView] Fix "expressSize" not working on Android
1.7.0 #
- Adapt pangle SDK 4.6+ (Android & iOS)
- Adapt flutter 3.0.0
- Add getDeviceInfo method
1.6.0 #
- Adapt pangle SDK 4.3+ (Android & iOS)
- Delete the splashButtonType param in AndroidSplashConfig and IOSSplashConfig
- Delete the downloadType param in config_android.dart
- Add gdpr,idfa params (IOSConfig)
- Add openGDPRPrivacy method (iOS)
1.5.0+1 #
- Release
1.5.0+1-beta #
- Add useHybridComposition param (AndroidSplashView, AndroidBannerView, AndroidFeedView)
1.5.0-beta #
- Update ad sdk
- Android: Delete the rewardName and rewardAmount params in AndroidRewardedVideoConfig
- iOS: Delete the isPaidApp param in IOSConfig
1.4.7 #
- Fix the type conversion problem in FLTSplashView
1.4.6 #
- The useTextureView property defaults to true (pangle.init(...))
- Optimize gradle dependency library version limit
- Added callbacks for interstitial, full-screen video, and rewarded video events
1.4.5 #
- Fixed the issue that the onLoad of SplashView in iOS does not call back
- Fix that the initialization parameter isPaidApp in iOS was incorrectly written as coppa
- Optimized the problem that SplashView in iOS cannot adapt to the screen size due to the SDK upgrade, and added PangleExpressSize to configure the display size
1.4.4 #
- Add
onLoadcallback for SplashView when an ad is loaded.
1.4.3 #
- Downgrade kotlin's version
1.4.2 #
- Migrating the plugin to the V2 embedding
1.4.1 #
- Fix splashButtonType not work(IOSSplashConfig)
1.4.0 #
- Upgrade android sdk version to 3.9.0.5, upgrade ios sdk version to 3.9+
- Add new option for requesting ads(clickable area & downloading type popup dialog)
1.3.0 #
- Upgrade android sdk version to 3.9.0.0, upgrade ios sdk version to 3.8+
- Remove open_ad_sdk module, use maven repository instead of aar package
- Optimize example
1.2.0 #
- Adapt ads sdk(Android 3.8.0.0, iOS 3.7.0.5)
- Fix FeedView's onDislike not callback on iOS
1.1.0 #
- Adapt pangle overseas android sdk
1.0.1 #
- Solve build packages failed (remove unrelated files)
1.0.0 #
- null-safety
0.10.1 #
- Remove Self-rendering ads support(Remove parameter
isExpress) - Optimize loading rewarded video & fullscreen video ads
- Fix #20
- Refactor
BannerView,FeedView,SplashView - Add
pangle.removeFeedAd()interface (Remove caches of feed ads)
0.9.1 #
- Adapt to open_ad_sdk 3.5.0.0 for Android. iOS are not affected
0.8.2 #
- Fix property
tolerateTimeouttype cast error - Fix example's Podfile has not joined plugin
pangle_flutter
0.8.1 #
- Adapt to pangle sdk 3.4+ (part class is removed, part of the property is out of date)
- PangleResult add property
verify
0.7.1 #
- Upgrade min dependency version of
Bytedance-UnionADto 3.3
0.6.5 #
- Adapt to onRewardVerify/nativeExpressRewardedVideoAdServerRewardDidSucceed callback parameters for reward video
0.6.4 #
- Fix exception when BannerView & FeedView
dispose
0.6.3 #
- Optimize static analysis
0.6.2 #
- Support custom splash ads [#10]
- Upgrade pangle sdk
0.6.1 #
- Fix rendering banner more than 5 seconds
- Rename
PangleFeedAdtoPangleAd - Add
intervalforBannerView
0.5.1 #
- Remove
loadAwait - Adapt to
open_ad_sdk 3.3.0.0 - Podspec uses
'Bytedance-UnionAD', '~>3.2'
0.4.3 #
- Add click action conflict solution for iOS
- Add callback for splash ads
- Fix bugs
0.4.2 #
- Adds
isUserInteractionEnabledattribute for iOS config - Fix rewarded video & fullscreen video callback crashed on Android.
0.4.1 #
- Breaking changes.
- Replace method returning type
MaptoPangleResult - Support iOS 14 for request tracking authorization
0.3.6 #
- Fix feed express view for ios not works.
0.3.5 #
- Refactor Android & iOS implementation.
- Fix the memory leak of loading rewarded video ads & fullscreen video ads.
- Optimize callback messages for requesting various ads.
0.3.4 #
- On flutter android sdk, support
registerWithmethod to load this plugin. - Rename
loadRewardVideoAdtoloadRewardedVideoAd.
0.3.3 #
- Remove third party image loading framework dependency from Android & iOS.
0.3.2 #
- Downgrade
Bytedance-UnionADtov3.2.5.1.
0.3.1 #
- Adapt
open_ad_sdktov3.2.5.1. - Fix sdk printing a lot of log issue. (#7)
0.2.1 #
- Update
Bytedance-UnionADtov3.2.5.1. - Update
open_ad_sdktov3.2.5.0. - New expressSize parameter to request ads. ()(The previous releases make ads dislocation & rendering incompletely )
- Fix
BannerView、FeedViewtouch events not work on iOS.
0.1.11 #
- Splash ads
loadAwaitfunction. - Interestitial ads callbacks after closing.
0.1.10 #
- Support setting the size of feed express ads, banner ads.
0.1.9 #
- Fix the height of ConstraintLayout's Group widget not working.
0.1.8 #
- Optimize
BannerView, makes its config null safety. - Use new config class name.
0.1.7 #
- Fix rewarded video ads callback not works.
- Support fullscreen video ads.
0.1.6 #
- Fix feed ads showing incorrect height.
- Support preloading rewarded video ads.
0.1.5 #
- Refactor the ads loading logic of iOS.
- Support splash express ads (No test), rewarded video express ads.
0.1.4 #
- Fix feed ads loading issue on Android.
0.1.3 #
- Support express feed ads.
- Optimize
BannerView,FeedView(UsingGlobalObjectKeyto prevent destroyingPlatformView).
0.1.2 #
- Support template rendering of interstitial ads & banner ads.
- Optimize
BannerView,FeedViewremoving logic.
0.1.1 #
- Add interstitial ads.
- Make android native permission request deprecated.
0.0.6 #
- Remove the weak reference call of
FlutterResult.
0.0.5 #
- Add the default implemention of removing
FeedView,BannerView.
0.0.4 #
- Use
ConstraintLayoutto layout ads on Android. - Optimize
FeedView,BannerViewloading logic.
0.0.3 #
- Formats project files.
0.0.2 #
- Fixes the issues of
Dart Analysis.
0.0.1 #
- Init
Splash Ads,Rewarded Video Ads,Banner Ads,Feed Ads.