From c663eba0fab25580223459bcc3e503fa5494244b Mon Sep 17 00:00:00 2001 From: Zero <1300326388@qq.com> Date: Sun, 13 Aug 2023 21:01:20 +0800 Subject: [PATCH 01/14] =?UTF-8?q?1=E3=80=81=E5=8D=87=E7=BA=A7=E7=89=88?= =?UTF-8?q?=E6=9C=AC=EF=BC=8C=E6=B5=8B=E8=AF=95=E5=BC=80=E5=B1=8F=E5=AE=8C?= =?UTF-8?q?=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- android/build.gradle | 2 +- example/android/app/build.gradle | 8 +- example/ios/Podfile | 38 ++-- example/ios/Runner.xcodeproj/project.pbxproj | 17 +- example/ios/Runner/Info.plist | 2 + example/lib/ads_config.dart | 4 +- example/lib/home_page.dart | 2 +- ios/Classes/FGMGroMore.h | 6 +- ios/Classes/FlutterGromoreAdsPlugin.h | 8 +- ios/Classes/FlutterGromoreAdsPlugin.m | 53 +++-- ios/Classes/Load/FGMFeedAdLoad.h | 4 +- ios/Classes/Load/FGMFeedAdLoad.m | 16 +- ios/Classes/Load/FGMFeedAdManager.h | 4 +- ios/Classes/Page/FGMAdBannerView.m | 176 +++++++-------- ios/Classes/Page/FGMAdFeedView.m | 212 +++++++++---------- ios/Classes/Page/FGMFullVideoPage.h | 2 +- ios/Classes/Page/FGMFullVideoPage.m | 134 ++++++------ ios/Classes/Page/FGMInterstitialFullPage.h | 2 +- ios/Classes/Page/FGMInterstitialFullPage.m | 122 +++++------ ios/Classes/Page/FGMInterstitialPage.h | 2 +- ios/Classes/Page/FGMInterstitialPage.m | 124 +++++------ ios/Classes/Page/FGMNativeViewFactory.m | 30 +-- ios/Classes/Page/FGMSplashPage.h | 2 +- ios/Classes/Page/FGMSplashPage.m | 95 +++++++-- ios/flutter_gromore_ads.podspec | 3 +- 25 files changed, 573 insertions(+), 495 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 62f8490..9b281c4 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -55,7 +55,7 @@ dependencies { implementation 'com.google.android.material:material:1.3.0' implementation 'androidx.constraintlayout:constraintlayout:2.0.4' //GroMore_sdk - implementation "com.gromore.cn:gromore-sdk:3.9.0.2" //groMore sdk + implementation "com.pangle.cn:mediation-sdk:5.3.6.2" //融合SDK // Glide 图片加载框架 implementation 'com.github.bumptech.glide:glide:4.14.2' annotationProcessor 'com.github.bumptech.glide:compiler:4.14.2' diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index f2da196..0195179 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -58,9 +58,7 @@ flutter { dependencies { implementation 'androidx.multidex:multidex:2.0.1' //GroMore_sdk adapter - implementation "com.gromore.cn:gdt-adapter:4.500.1370.0" //gdt adapter - implementation 'com.qq.e.union:union:4.500.1370'// 广点通广告 SDK - implementation "com.gromore.cn:pangle-adapter:5.0.0.4.0" //穿山甲 adapter - implementation 'com.pangle.cn:ads-sdk-pro:5.0.0.4'//穿山甲广告 SDK - + implementation "com.pangle.cn:mediation-gdt-adapter:4.530.1400.3" //gdt adapter + implementation 'com.qq.e.union:union:4.530.1400'// 广点通广告 SDK + // 其他厂商参考 https://www.csjplatform.com/union/media/union/download/detail?id=142&docId=27562&osType=android } diff --git a/example/ios/Podfile b/example/ios/Podfile index 9b03c43..10eebac 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -32,32 +32,25 @@ target 'Runner' do # use_modular_headers! flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) #1.GroMoreSDK核心库 - pod 'Ads-Mediation-CN', :path=>'Frameworks/Ads-Mediation-CN' - # 2.GroMore官方适配adapter(请以接入文档0.3说明为准,请不要更换GroMoreSDK不支持的三方sdk版本) - # 穿山甲 - pod 'ABUAdCsjAdapter', :path=>'Frameworks/ABUAdCsjAdapter/' - pod 'Ads-CN','4.9.0.6' - # 穿山甲beta灰度版 - #pod 'Ads-CN-Beta', '3.8.0.0' # 广点通/优量汇 - pod 'ABUAdGdtAdapter', :path=>'Frameworks/ABUAdGdtAdapter' - pod 'GDTMobSDK','4.14.02' + pod 'CSJMGdtAdapter', '4.14.30.0' + pod 'GDTMobSDK','4.14.30' # 百度SDK -# pod 'ABUAdBaiduAdapter', :path=>'Frameworks/ABUAdBaiduAdapter' -# pod 'BaiduMobAdSDK', '4.901' + # pod 'CSJMBaiduAdapter', '5.300.0' + pod 'BaiduMobAdSDK', '5.300' # UnityAds -# pod 'ABUAdUnityAdapter', :path=>'Frameworks/ABUAdUnityAdapter' +# pod 'CSJMUnityAdapter', '4.3.0.0' # pod 'UnityAds', '4.3.0' # Admob/GoogleAd -# pod 'ABUAdAdmobAdapter', :path=>'Frameworks/ABUAdAdmobAdapter' -# pod 'Google-Mobile-Ads-SDK', '9.9.0' +# pod 'CSJMAdmobAdapter', '10.0.0.0' +# pod 'Google-Mobile-Ads-SDK', '10.0.0' # SigmobAd -# pod 'ABUAdSigmobAdapter', :path=>'Frameworks/ABUAdSigmobAdapter' -# pod 'SigmobAd-iOS', '4.3.0' +# pod 'CSJMSigmobAdapter', '4.8.0.0' +# pod 'SigmobAd-iOS', '4.8.0' # MintegralAdSDK -# pod 'ABUAdMintegralAdapter', :path=>'Frameworks/ABUAdMintegralAdapter' +# pod 'CSJMMintegralAdapter', '7.3.6.0.0' # MintegralAdSDK 使用时请务必使用cocoapod源 - # pod 'MintegralAdSDK', '7.1.9.0', :subspecs => [ + # pod 'MintegralAdSDK', '7.3.6.0', :subspecs => [ # 'SplashAd', # 'InterstitialAd', # 'NewInterstitialAd', @@ -71,12 +64,11 @@ target 'Runner' do # 'BidInterstitialVideoAd', # 'BidRewardVideoAd' # ] - # pod 'ABUAdKlevinAdapter', :path=>'Frameworks/ABUAdKlevinAdapter' - # pod 'KlevinAdSDK', '2.9.1.207' + # pod 'CSJMKlevinAdapter', '2.11.0.211.1' + # pod 'KlevinAdSDK', '2.11.0.211' # 快手 -# pod 'KSAdSDK' - # 调试 -# pod 'ABUVisualDebug', :path=>'Frameworks/ABUVisualDebug' + # pod 'CSJMKsAdapter', '3.3.47.0' + # pod 'KSAdSDK', '3.3.47' end post_install do |installer| diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 9f94e47..55c2e4a 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 51; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -221,10 +221,12 @@ /* Begin PBXShellScriptBuildPhase section */ 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", ); name = "Thin Binary"; outputPaths = ( @@ -235,6 +237,7 @@ }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -377,7 +380,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = N943VT2CQD; + DEVELOPMENT_TEAM = DRL7GUUB5S; ENABLE_BITCODE = NO; HEADER_SEARCH_PATHS = ( "$(inherited)", @@ -393,7 +396,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.zero.flutterGromoreAdsExample222; + PRODUCT_BUNDLE_IDENTIFIER = com.banjixiaoguanjia.app; PRODUCT_NAME = "$(TARGET_NAME)"; USER_HEADER_SEARCH_PATHS = ""; VERSIONING_SYSTEM = "apple-generic"; @@ -511,7 +514,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = N943VT2CQD; + DEVELOPMENT_TEAM = DRL7GUUB5S; ENABLE_BITCODE = NO; HEADER_SEARCH_PATHS = ( "$(inherited)", @@ -527,7 +530,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.zero.flutterGromoreAdsExample222; + PRODUCT_BUNDLE_IDENTIFIER = com.banjixiaoguanjia.app; PRODUCT_NAME = "$(TARGET_NAME)"; USER_HEADER_SEARCH_PATHS = ""; VERSIONING_SYSTEM = "apple-generic"; @@ -540,7 +543,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = N943VT2CQD; + DEVELOPMENT_TEAM = DRL7GUUB5S; ENABLE_BITCODE = NO; HEADER_SEARCH_PATHS = ( "$(inherited)", @@ -556,7 +559,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.zero.flutterGromoreAdsExample222; + PRODUCT_BUNDLE_IDENTIFIER = com.banjixiaoguanjia.app; PRODUCT_NAME = "$(TARGET_NAME)"; USER_HEADER_SEARCH_PATHS = ""; VERSIONING_SYSTEM = "apple-generic"; diff --git a/example/ios/Runner/Info.plist b/example/ios/Runner/Info.plist index bbd78f4..b93ccab 100644 --- a/example/ios/Runner/Info.plist +++ b/example/ios/Runner/Info.plist @@ -50,5 +50,7 @@ UIViewControllerBasedStatusBarAppearance + UIApplicationSupportsIndirectInputEvents + diff --git a/example/lib/ads_config.dart b/example/lib/ads_config.dart index 70198e2..f0114a9 100644 --- a/example/lib/ads_config.dart +++ b/example/lib/ads_config.dart @@ -23,7 +23,7 @@ class AdsConfig { /// 获取 App id static String get appId { if (Platform.isIOS) { - return '5209496'; + return '5324024'; } return '5216573'; } @@ -39,7 +39,7 @@ class AdsConfig { /// 获取开屏广告位id static String get splashId { if (Platform.isIOS) { - return '887383142'; + return '102420790'; } return '887382967'; } diff --git a/example/lib/home_page.dart b/example/lib/home_page.dart index 9e33cc3..4667a94 100644 --- a/example/lib/home_page.dart +++ b/example/lib/home_page.dart @@ -142,7 +142,7 @@ class _HomePageState extends State { try { bool result = await FlutterGromoreAds.initAd( AdsConfig.appId, - config: AdsConfig.config, + // config: AdsConfig.config, ); _result = "广告SDK 初始化${result ? '成功' : '失败'}"; setState(() {}); diff --git a/ios/Classes/FGMGroMore.h b/ios/Classes/FGMGroMore.h index d12fa2d..70d8d84 100644 --- a/ios/Classes/FGMGroMore.h +++ b/ios/Classes/FGMGroMore.h @@ -5,8 +5,4 @@ // Created by zero on 2021/12/12. // -# if __has_include() -#import -#else -#import -#endif +#import diff --git a/ios/Classes/FlutterGromoreAdsPlugin.h b/ios/Classes/FlutterGromoreAdsPlugin.h index 6a89151..a0b5426 100644 --- a/ios/Classes/FlutterGromoreAdsPlugin.h +++ b/ios/Classes/FlutterGromoreAdsPlugin.h @@ -9,10 +9,10 @@ @interface FlutterGromoreAdsPlugin : NSObject @property (strong,nonatomic) FlutterEventSink eventSink;// 事件 @property (strong,nonatomic) FGMSplashPage *sad;// 开屏广告 -@property (strong,nonatomic) FGMInterstitialPage *iad;// 插屏广告 -@property (strong,nonatomic) FGMInterstitialFullPage *ifad;//插屏全屏广告 -@property (strong,nonatomic) FGMFullVideoPage *fvad;// 全屏视频广告 -@property (strong,nonatomic) FGMFeedAdLoad * fad;// 信息流广告加载 +//@property (strong,nonatomic) FGMInterstitialPage *iad;// 插屏广告 +//@property (strong,nonatomic) FGMInterstitialFullPage *ifad;//插屏全屏广告 +//@property (strong,nonatomic) FGMFullVideoPage *fvad;// 全屏视频广告 +//@property (strong,nonatomic) FGMFeedAdLoad * fad;// 信息流广告加载 extern NSString *const kGMAdBannerViewId; extern NSString *const kGMAdFeedViewId; diff --git a/ios/Classes/FlutterGromoreAdsPlugin.m b/ios/Classes/FlutterGromoreAdsPlugin.m index d4dad81..68ee2ee 100644 --- a/ios/Classes/FlutterGromoreAdsPlugin.m +++ b/ios/Classes/FlutterGromoreAdsPlugin.m @@ -32,6 +32,7 @@ + (void)registerWithRegistrar:(NSObject*)registrar { } - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { NSString *methodStr=call.method; + NSLog(methodStr); if ([@"getPlatformVersion" isEqualToString:methodStr]) { result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]); }else if ([@"requestIDFA" isEqualToString:methodStr]) { @@ -72,17 +73,35 @@ - (void) requestIDFA:(FlutterMethodCall*) call result:(FlutterResult) result{ - (void) initAd:(FlutterMethodCall*) call result:(FlutterResult) result{ NSString *appId=call.arguments[@"appId"]; NSString *config=call.arguments[@"config"]; - [ABUAdSDKManager setupSDKWithAppId:appId config:^ABUUserConfig *(ABUUserConfig *c) { - #ifdef DEBUG - c.logEnable = YES; - #endif - // 导入本地配置 - if (![config isKindOfClass:[NSNull class]] && [config length]!=0) { - c.advanceSDKConfigPath = [[NSBundle mainBundle] pathForResource:config ofType:@"json"];//支持媒体本地提前导入配置信息 + NSLog(@"appid:%@",appId); + BUAdSDKConfiguration *configuration = [BUAdSDKConfiguration configuration]; + configuration.appID = appId; +// configuration.privacyProvider = [[BUDPrivacyProvider alloc] init]; +// configuration.appLogoImage = [UIImage imageNamed:@"AppIcon"]; + configuration.useMediation = YES; + configuration.debugLog = @(1); + + [BUAdSDKManager startWithAsyncCompletionHandler:^(BOOL success, NSError *error) { + if (success) { +// dispatch_async(dispatch_get_main_queue(), ^{ +//// [self useMediationPreload]; +// }); + result(@(YES)); } - return c; }]; - result(@(YES)); + + +// [ABUAdSDKManager setupSDKWithAppId:appId config:^ABUUserConfig *(ABUUserConfig *c) { +// #ifdef DEBUG +// c.logEnable = YES; +// #endif +// // 导入本地配置 +// if (![config isKindOfClass:[NSNull class]] && [config length]!=0) { +// c.advanceSDKConfigPath = [[NSBundle mainBundle] pathForResource:config ofType:@"json"];//支持媒体本地提前导入配置信息 +// } +// return c; +// }]; + } // 开屏广告 @@ -98,29 +117,29 @@ - (void) showSplashAd:(FlutterMethodCall*) call result:(FlutterResult) result{ // 插屏广告 - (void) showInterstitialAd:(FlutterMethodCall *)call result:(FlutterResult) result{ - self.iad=[[FGMInterstitialPage alloc] init]; - [self.iad showAd:call eventSink:self.eventSink]; +// self.iad=[[FGMInterstitialPage alloc] init]; +// [self.iad showAd:call eventSink:self.eventSink]; result(@(YES)); } // 插屏全屏广告 - (void) showInterstitialFullAd:(FlutterMethodCall *)call result:(FlutterResult) result{ - self.ifad=[[FGMInterstitialFullPage alloc] init]; - [self.ifad showAd:call eventSink:self.eventSink]; +// self.ifad=[[FGMInterstitialFullPage alloc] init]; +// [self.ifad showAd:call eventSink:self.eventSink]; result(@(YES)); } // 全屏视频广告 - (void) showFullVideoAd:(FlutterMethodCall *) call result:(FlutterResult) result{ - self.fvad=[[FGMFullVideoPage alloc] init]; - [self.fvad showAd:call eventSink:self.eventSink]; +// self.fvad=[[FGMFullVideoPage alloc] init]; +// [self.fvad showAd:call eventSink:self.eventSink]; result(@(YES)); } // 加载信息流广告 - (void) loadFeedAd:(FlutterMethodCall*) call result:(FlutterResult) result{ - self.fad=[[FGMFeedAdLoad alloc] init]; - [self.fad loadFeedAdList:call result:result eventSink:self.eventSink]; +// self.fad=[[FGMFeedAdLoad alloc] init]; +// [self.fad loadFeedAdList:call result:result eventSink:self.eventSink]; } // 清除信息流广告 diff --git a/ios/Classes/Load/FGMFeedAdLoad.h b/ios/Classes/Load/FGMFeedAdLoad.h index d6abf31..a5aae25 100644 --- a/ios/Classes/Load/FGMFeedAdLoad.h +++ b/ios/Classes/Load/FGMFeedAdLoad.h @@ -8,9 +8,9 @@ #import #import "FGMBasePage.h" -@interface FGMFeedAdLoad : FGMBasePage +@interface FGMFeedAdLoad : FGMBasePage @property (strong,nonatomic,nonnull) FlutterResult result; -@property (strong,nonatomic,nullable) ABUNativeAdsManager *adManager; +@property (strong,nonatomic,nullable) BUNativeAdsManager *adManager; // 加载信息流广告列表 -(void) loadFeedAdList:(nonnull FlutterMethodCall *)call result:(nonnull FlutterResult) result eventSink:(nonnull FlutterEventSink )events; @end diff --git a/ios/Classes/Load/FGMFeedAdLoad.m b/ios/Classes/Load/FGMFeedAdLoad.m index 4ba97f6..cb84632 100644 --- a/ios/Classes/Load/FGMFeedAdLoad.m +++ b/ios/Classes/Load/FGMFeedAdLoad.m @@ -24,11 +24,17 @@ - (void)loadAd:(FlutterMethodCall *)call{ int count = [call.arguments[@"count"] intValue]; // 配置广告加载 if(!self.adManager){ - self.adManager= [[ABUNativeAdsManager alloc] initWithAdUnitID:self.posId adSize:CGSizeMake(width, height)]; +// ABUNativeAdSlot slot=[[ABUNativeAdSlot alloc] ini]; + BUAdSlot* slot=[[BUAdSlot alloc] init]; + slot.ID = self.posId; + slot.AdType = BUAdSlotAdTypeFeed; + slot.position = BUAdSlotPositionMiddle; + slot.imgSize = [BUSize sizeBy:BUProposalSize_Banner600_400]; + self.adManager= [[BUNativeAdsManager alloc] initWithSlot:slot]; } self.adManager.adSize=CGSizeMake(width, height); - self.adManager.rootViewController=self.rootController; - self.adManager.startMutedIfCan= YES; +// self.adManager.rootViewController=self.rootController; +// self.adManager.startMutedIfCan= YES; self.adManager.delegate=self; // 加载广告 [self.adManager loadAdDataWithCount:count]; @@ -36,13 +42,13 @@ - (void)loadAd:(FlutterMethodCall *)call{ #pragma mark ABUNativeAdsManagerDelegate -- (void)nativeAdsManager:(ABUNativeAdsManager *)adsManager didFailWithError:(NSError *)error{ +- (void)nativeAdsManager:(BUNativeAdsManager *)adsManager didFailWithError:(NSError *)error{ NSLog(@"%s",__FUNCTION__); // 发送广告错误事件 [self sendErrorEvent:error]; } -- (void)nativeAdsManagerSuccessToLoad:(ABUNativeAdsManager *)adsManager nativeAds:(NSArray *)views{ +- (void)nativeAdsManagerSuccessToLoad:(BUNativeAdsManager *)adsManager nativeAds:(NSArray *)views{ NSLog(@"%s",__FUNCTION__); if (views.count) { // 广告列表,用于返回 Flutter 层 diff --git a/ios/Classes/Load/FGMFeedAdManager.h b/ios/Classes/Load/FGMFeedAdManager.h index 9dc8265..60915b4 100644 --- a/ios/Classes/Load/FGMFeedAdManager.h +++ b/ios/Classes/Load/FGMFeedAdManager.h @@ -11,9 +11,9 @@ @interface FGMFeedAdManager : NSObject + (instancetype) share; // 加入到缓存中 -- (void) putAd:(NSNumber*) key value:(ABUNativeAdView*) value; +- (void) putAd:(NSNumber*) key value:(BUNativeExpressAdView*) value; // 从缓存中获取 -- (ABUNativeAdView*) getAd:(NSNumber*) key; +- (BUNativeExpressAdView*) getAd:(NSNumber*) key; // 从缓存中删除 - (void) removeAd:(NSNumber*) key; diff --git a/ios/Classes/Page/FGMAdBannerView.m b/ios/Classes/Page/FGMAdBannerView.m index 66e6d5a..f4c1406 100644 --- a/ios/Classes/Page/FGMAdBannerView.m +++ b/ios/Classes/Page/FGMAdBannerView.m @@ -5,91 +5,91 @@ // Created by Zero on 2023/1/12. // -#import "FGMAdBannerView.h" - -@interface FGMAdBannerView() -@property (strong,nonatomic) ABUBannerAd *bad; -@property (strong,nonatomic) UIView *bannerView; - -@end - -@implementation FGMAdBannerView - -- (instancetype)initWithFrame:(CGRect)frame - viewIdentifier:(int64_t)viewId - arguments:(id _Nullable)args - binaryMessenger:(NSObject*)messenger - plugin:(FlutterGromoreAdsPlugin*) plugin{ - if (self = [super init]) { - self.bannerView = [[UIView alloc] init]; - FlutterMethodCall *call=[FlutterMethodCall methodCallWithMethodName:@"AdBannerView" arguments:args]; - [self showAd:call eventSink:plugin.eventSink]; - } - return self; -} - -- (UIView*)view { - return self.bannerView; -} -// 加载广告 -- (void)loadAd:(FlutterMethodCall *)call{ - // 刷新间隔 - int width = [call.arguments[@"width"] intValue]; - int height = [call.arguments[@"height"] intValue]; - self.bad=[[ABUBannerAd alloc] initWithAdUnitID:self.posId rootViewController:self.rootController adSize:CGSizeMake(width, height)]; - self.bad.delegate=self; - [self.bad loadAdData]; -} - - -#pragma mark ----- ABUBannerAdDelegate ----- -/// 加载成功回调 -- (void)bannerAdDidLoad:(ABUBannerAd *)bannerAd bannerView:(UIView *)bannerView { - NSLog(@"%s",__FUNCTION__); - [self.bannerView addSubview:bannerView]; - // 发送事件 - [self sendEventAction:onAdLoaded]; -} - -/// 加载失败回调 -- (void)bannerAd:(ABUBannerAd *)bannerAd didLoadFailWithError:(NSError *)error { - NSLog(@"%s-error:%@", __FUNCTION__, error); - // 发送事件 - [self sendErrorEvent:error]; - // 销毁广告 - [self destoryAd:nil]; -} - -/// 展示成功回调 -- (void)bannerAdDidBecomeVisible:(ABUBannerAd *)bannerAd bannerView:(UIView *)bannerView { - NSLog(@"%s",__FUNCTION__); - // 发送事件 - [self sendEventAction:onAdExposure]; -} - -/// 广告点击回调 -- (void)bannerAdDidClick:(ABUBannerAd *)ABUBannerAd bannerView:(UIView *)bannerView { - NSLog(@"%s",__FUNCTION__); - // 发送事件 - [self sendEventAction:onAdClicked]; -} - -/// 广告关闭回调 -- (void)bannerAdDidClosed:(ABUBannerAd *)ABUBannerAd bannerView:(UIView *)bannerView dislikeWithReason:(NSArray *)filterwords { - NSLog(@"%s",__FUNCTION__); - // 可于此处移除广告view - [self destoryAd:bannerView]; - // 发送事件 - [self sendEventAction:onAdClosed]; -} - -// 销毁广告 -- (void)destoryAd:(UIView *)bannerView{ - if(bannerView){ - [bannerView removeFromSuperview]; - } - self.bad.delegate=nil; - self.bad=nil; -} - -@end +//#import "FGMAdBannerView.h" +// +//@interface FGMAdBannerView() +//@property (strong,nonatomic) BUBannerAd *bad; +//@property (strong,nonatomic) UIView *bannerView; +// +//@end +// +//@implementation FGMAdBannerView +// +//- (instancetype)initWithFrame:(CGRect)frame +// viewIdentifier:(int64_t)viewId +// arguments:(id _Nullable)args +// binaryMessenger:(NSObject*)messenger +// plugin:(FlutterGromoreAdsPlugin*) plugin{ +// if (self = [super init]) { +// self.bannerView = [[UIView alloc] init]; +// FlutterMethodCall *call=[FlutterMethodCall methodCallWithMethodName:@"AdBannerView" arguments:args]; +// [self showAd:call eventSink:plugin.eventSink]; +// } +// return self; +//} +// +//- (UIView*)view { +// return self.bannerView; +//} +//// 加载广告 +//- (void)loadAd:(FlutterMethodCall *)call{ +// // 刷新间隔 +// int width = [call.arguments[@"width"] intValue]; +// int height = [call.arguments[@"height"] intValue]; +// self.bad=[[BUBannerAd alloc] initWithAdUnitID:self.posId rootViewController:self.rootController adSize:CGSizeMake(width, height)]; +// self.bad.delegate=self; +// [self.bad loadAdData]; +//} +// +// +//#pragma mark ----- ABUBannerAdDelegate ----- +///// 加载成功回调 +//- (void)bannerAdDidLoad:(ABUBannerAd *)bannerAd bannerView:(UIView *)bannerView { +// NSLog(@"%s",__FUNCTION__); +// [self.bannerView addSubview:bannerView]; +// // 发送事件 +// [self sendEventAction:onAdLoaded]; +//} +// +///// 加载失败回调 +//- (void)bannerAd:(ABUBannerAd *)bannerAd didLoadFailWithError:(NSError *)error { +// NSLog(@"%s-error:%@", __FUNCTION__, error); +// // 发送事件 +// [self sendErrorEvent:error]; +// // 销毁广告 +// [self destoryAd:nil]; +//} +// +///// 展示成功回调 +//- (void)bannerAdDidBecomeVisible:(ABUBannerAd *)bannerAd bannerView:(UIView *)bannerView { +// NSLog(@"%s",__FUNCTION__); +// // 发送事件 +// [self sendEventAction:onAdExposure]; +//} +// +///// 广告点击回调 +//- (void)bannerAdDidClick:(ABUBannerAd *)ABUBannerAd bannerView:(UIView *)bannerView { +// NSLog(@"%s",__FUNCTION__); +// // 发送事件 +// [self sendEventAction:onAdClicked]; +//} +// +///// 广告关闭回调 +//- (void)bannerAdDidClosed:(ABUBannerAd *)ABUBannerAd bannerView:(UIView *)bannerView dislikeWithReason:(NSArray *)filterwords { +// NSLog(@"%s",__FUNCTION__); +// // 可于此处移除广告view +// [self destoryAd:bannerView]; +// // 发送事件 +// [self sendEventAction:onAdClosed]; +//} +// +//// 销毁广告 +//- (void)destoryAd:(UIView *)bannerView{ +// if(bannerView){ +// [bannerView removeFromSuperview]; +// } +// self.bad.delegate=nil; +// self.bad=nil; +//} +// +//@end diff --git a/ios/Classes/Page/FGMAdFeedView.m b/ios/Classes/Page/FGMAdFeedView.m index ec0fc61..4c80d5e 100644 --- a/ios/Classes/Page/FGMAdFeedView.m +++ b/ios/Classes/Page/FGMAdFeedView.m @@ -6,109 +6,109 @@ // #import "FGMAdFeedView.h" - -@interface FGMAdFeedView() -@property (strong,nonatomic) UIView *feedView; -@property (strong,nonatomic) ABUNativeAdView *adView; -@property (strong,nonatomic) FlutterMethodChannel *methodChannel; -@end - -@implementation FGMAdFeedView - -- (instancetype)initWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId arguments:(id)args binaryMessenger:(NSObject *)messenger plugin:(FlutterGromoreAdsPlugin *)plugin{ - if(self==[super init]){ - self.viewId=viewId; - self.feedView =[[UIView alloc] init]; - self.methodChannel = [FlutterMethodChannel methodChannelWithName:[NSString stringWithFormat:@"%@/%lli",kGMAdFeedViewId,viewId] binaryMessenger:messenger]; - FlutterMethodCall *call= [FlutterMethodCall methodCallWithMethodName:@"AdFeedView" arguments:args]; - [self showAd:call eventSink:plugin.eventSink]; - } - NSLog(@"%s %lli",__FUNCTION__,viewId); - return self; -} - -- (UIView *)view{ - return self.feedView; -} - -- (void)dealloc{ - NSLog(@"%s",__FUNCTION__); -} - -- (void)loadAd:(FlutterMethodCall *)call{ - NSNumber *key=[NSNumber numberWithInteger:[self.posId integerValue]]; - self.adView=[FGMFeedAdManager.share getAd:key]; - self.adView.delegate=self; - self.adView.videoDelegate=self; - [self.feedView addSubview:self.adView]; - [self.adView render]; -} - -// 处理消息 -- (void) postMsghandler:(NSString*) event{ - NSLog(@"%s postMsghandler event:%@",__FUNCTION__,event); - if([event isEqualToString:onAdExposure]){ - // 渲染成功,设置高度 - CGSize size= self.feedView.frame.size; - [self setFlutterViewSize:size]; - }else if([event isEqualToString:onAdClosed]){ - self.adView.delegate = nil; - // 广告关闭移除广告,并且设置大小为 0,隐藏广告 - [self.adView removeFromSuperview]; - [self setFlutterViewSize:CGSizeZero]; - } -} -// 设置 FlutterAds 视图宽高 -- (void) setFlutterViewSize:(CGSize) size{ - NSNumber *width=[NSNumber numberWithFloat:size.width]; - NSNumber *height=[NSNumber numberWithFloat:size.height]; - NSDictionary *dicSize=[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:width,height, nil] forKeys:[NSArray arrayWithObjects:@"width",@"height", nil]]; - self.adView.center=self.feedView.center; - [self.methodChannel invokeMethod:@"setSize" arguments:dicSize]; -} - - -- (void)nativeAdExpressViewRenderFail:(ABUNativeAdView *)nativeExpressAdView error:(NSError *)error{ - NSLog(@"%s",__FUNCTION__); - // 发送广告错误事件 - [self sendErrorEvent:error]; - [self postMsghandler:onAdClosed]; -} - -- (void)nativeAdDidBecomeVisible:(ABUNativeAdView *)nativeAdView{ - NSLog(@"%s",__FUNCTION__); - // 发送广告事件 - [self sendEventAction:onAdExposure]; - [self postMsghandler:onAdExposure]; -} - -- (void)nativeAdDidClick:(ABUNativeAdView *)nativeAdView withView:(UIView *)view{ - NSLog(@"%s",__FUNCTION__); - // 发送广告事件 - [self sendEventAction:onAdClicked]; -} - - - -- (void)nativeExpressAdViewWillShow:(ABUNativeAdView *)nativeExpressAdView{ - NSLog(@"%s",__FUNCTION__); - // 发送广告事件 - [self sendEventAction:onAdExposure]; -} - -- (void)nativeAdExpressViewDidClosed:(ABUNativeAdView *)nativeAdView closeReason:(NSArray *)filterWords{ - NSLog(@"%s",__FUNCTION__); - NSNumber *key=[NSNumber numberWithInteger:[nativeAdView hash]]; - // 删除广告缓存 - [FGMFeedAdManager.share removeAd:key]; - // 发送广告事件 - [self sendEventAction:onAdClosed]; - // 关闭广告 - [self postMsghandler:onAdClosed]; -} - -- (void)nativeExpressAdViewDidRemoved:(ABUNativeAdView *)nativeExpressAdView{ - NSLog(@"%s",__FUNCTION__); -} - -@end +// +//@interface FGMAdFeedView() +//@property (strong,nonatomic) UIView *feedView; +//@property (strong,nonatomic) ABUNativeAdView *adView; +//@property (strong,nonatomic) FlutterMethodChannel *methodChannel; +//@end +// +//@implementation FGMAdFeedView +// +//- (instancetype)initWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId arguments:(id)args binaryMessenger:(NSObject *)messenger plugin:(FlutterGromoreAdsPlugin *)plugin{ +// if(self==[super init]){ +// self.viewId=viewId; +// self.feedView =[[UIView alloc] init]; +// self.methodChannel = [FlutterMethodChannel methodChannelWithName:[NSString stringWithFormat:@"%@/%lli",kGMAdFeedViewId,viewId] binaryMessenger:messenger]; +// FlutterMethodCall *call= [FlutterMethodCall methodCallWithMethodName:@"AdFeedView" arguments:args]; +// [self showAd:call eventSink:plugin.eventSink]; +// } +// NSLog(@"%s %lli",__FUNCTION__,viewId); +// return self; +//} +// +//- (UIView *)view{ +// return self.feedView; +//} +// +//- (void)dealloc{ +// NSLog(@"%s",__FUNCTION__); +//} +// +//- (void)loadAd:(FlutterMethodCall *)call{ +// NSNumber *key=[NSNumber numberWithInteger:[self.posId integerValue]]; +// self.adView=[FGMFeedAdManager.share getAd:key]; +// self.adView.delegate=self; +// self.adView.videoDelegate=self; +// [self.feedView addSubview:self.adView]; +// [self.adView render]; +//} +// +//// 处理消息 +//- (void) postMsghandler:(NSString*) event{ +// NSLog(@"%s postMsghandler event:%@",__FUNCTION__,event); +// if([event isEqualToString:onAdExposure]){ +// // 渲染成功,设置高度 +// CGSize size= self.feedView.frame.size; +// [self setFlutterViewSize:size]; +// }else if([event isEqualToString:onAdClosed]){ +// self.adView.delegate = nil; +// // 广告关闭移除广告,并且设置大小为 0,隐藏广告 +// [self.adView removeFromSuperview]; +// [self setFlutterViewSize:CGSizeZero]; +// } +//} +//// 设置 FlutterAds 视图宽高 +//- (void) setFlutterViewSize:(CGSize) size{ +// NSNumber *width=[NSNumber numberWithFloat:size.width]; +// NSNumber *height=[NSNumber numberWithFloat:size.height]; +// NSDictionary *dicSize=[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:width,height, nil] forKeys:[NSArray arrayWithObjects:@"width",@"height", nil]]; +// self.adView.center=self.feedView.center; +// [self.methodChannel invokeMethod:@"setSize" arguments:dicSize]; +//} +// +// +//- (void)nativeAdExpressViewRenderFail:(ABUNativeAdView *)nativeExpressAdView error:(NSError *)error{ +// NSLog(@"%s",__FUNCTION__); +// // 发送广告错误事件 +// [self sendErrorEvent:error]; +// [self postMsghandler:onAdClosed]; +//} +// +//- (void)nativeAdDidBecomeVisible:(ABUNativeAdView *)nativeAdView{ +// NSLog(@"%s",__FUNCTION__); +// // 发送广告事件 +// [self sendEventAction:onAdExposure]; +// [self postMsghandler:onAdExposure]; +//} +// +//- (void)nativeAdDidClick:(ABUNativeAdView *)nativeAdView withView:(UIView *)view{ +// NSLog(@"%s",__FUNCTION__); +// // 发送广告事件 +// [self sendEventAction:onAdClicked]; +//} +// +// +// +//- (void)nativeExpressAdViewWillShow:(ABUNativeAdView *)nativeExpressAdView{ +// NSLog(@"%s",__FUNCTION__); +// // 发送广告事件 +// [self sendEventAction:onAdExposure]; +//} +// +//- (void)nativeAdExpressViewDidClosed:(ABUNativeAdView *)nativeAdView closeReason:(NSArray *)filterWords{ +// NSLog(@"%s",__FUNCTION__); +// NSNumber *key=[NSNumber numberWithInteger:[nativeAdView hash]]; +// // 删除广告缓存 +// [FGMFeedAdManager.share removeAd:key]; +// // 发送广告事件 +// [self sendEventAction:onAdClosed]; +// // 关闭广告 +// [self postMsghandler:onAdClosed]; +//} +// +//- (void)nativeExpressAdViewDidRemoved:(ABUNativeAdView *)nativeExpressAdView{ +// NSLog(@"%s",__FUNCTION__); +//} +// +//@end diff --git a/ios/Classes/Page/FGMFullVideoPage.h b/ios/Classes/Page/FGMFullVideoPage.h index aefe4bc..48b8e7d 100644 --- a/ios/Classes/Page/FGMFullVideoPage.h +++ b/ios/Classes/Page/FGMFullVideoPage.h @@ -9,5 +9,5 @@ // 全屏视频 @interface FGMFullVideoPage : FGMBasePage -@property (strong,nonatomic) ABUFullscreenVideoAd *ad; +@property (strong,nonatomic) BUFullscreenVideoAd *ad; @end diff --git a/ios/Classes/Page/FGMFullVideoPage.m b/ios/Classes/Page/FGMFullVideoPage.m index 441b0a4..f7b4d55 100644 --- a/ios/Classes/Page/FGMFullVideoPage.m +++ b/ios/Classes/Page/FGMFullVideoPage.m @@ -6,70 +6,70 @@ // #import "FGMFullVideoPage.h" - -@interface FGMFullVideoPage() - -@end - -@implementation FGMFullVideoPage - -- (void)loadAd:(FlutterMethodCall *)call{ - self.ad=[[ABUFullscreenVideoAd alloc] initWithAdUnitID:self.posId]; - self.ad.delegate=self; - self.ad.mutedIfCan=YES; - [self.ad loadAdData]; -} - - -- (void)fullscreenVideoAdDidLoad:(ABUFullscreenVideoAd *)fullscreenVideoAd{ - NSLog(@"%s",__FUNCTION__); - if(self.ad && self.ad.isReady){ - [self.ad showAdFromRootViewController:self.rootController]; - } - // 发送事件 - [self sendEventAction:onAdLoaded]; -} - -- (void)fullscreenVideoAd:(ABUFullscreenVideoAd *)fullscreenVideoAd didFailWithError:(NSError *)error{ - NSLog(@"%s-error:%@", __FUNCTION__, error); - // 发送事件 - [self sendErrorEvent:error]; -} - -- (void)fullscreenVideoAdDidVisible:(ABUFullscreenVideoAd *)fullscreenVideoAd{ - NSLog(@"%s",__FUNCTION__); - // 发送事件 - [self sendEventAction:onAdExposure]; -} - -- (void)fullscreenVideoAdDidShowFailed:(ABUFullscreenVideoAd *)fullscreenVideoAd error:(NSError *)error{ - NSLog(@"%s-error:%@", __FUNCTION__, error); - // 发送事件 - [self sendErrorEvent:error]; -} - -- (void)fullscreenVideoAd:(ABUFullscreenVideoAd *)fullscreenVideoAd didPlayFinishWithError:(NSError *)error{ - NSLog(@"%s-error:%@", __FUNCTION__, error); - // 发送事件 - [self sendErrorEvent:error]; -} - -- (void)fullscreenVideoAdDidSkip:(ABUFullscreenVideoAd *)fullscreenVideoAd{ - NSLog(@"%s",__FUNCTION__); - // 发送事件 - [self sendEventAction:onAdSkip]; -} - -- (void)fullscreenVideoAdDidClick:(ABUFullscreenVideoAd *)fullscreenVideoAd{ - NSLog(@"%s",__FUNCTION__); - // 发送事件 - [self sendEventAction:onAdClicked]; -} - -- (void)fullscreenVideoAdDidClose:(ABUFullscreenVideoAd *)fullscreenVideoAd{ - NSLog(@"%s",__FUNCTION__); - // 发送事件 - [self sendEventAction:onAdClosed]; -} - -@end +// +//@interface FGMFullVideoPage() +// +//@end +// +//@implementation FGMFullVideoPage +// +//- (void)loadAd:(FlutterMethodCall *)call{ +// self.ad=[[ABUFullscreenVideoAd alloc] initWithAdUnitID:self.posId]; +// self.ad.delegate=self; +// self.ad.mutedIfCan=YES; +// [self.ad loadAdData]; +//} +// +// +//- (void)fullscreenVideoAdDidLoad:(ABUFullscreenVideoAd *)fullscreenVideoAd{ +// NSLog(@"%s",__FUNCTION__); +// if(self.ad && self.ad.isReady){ +// [self.ad showAdFromRootViewController:self.rootController]; +// } +// // 发送事件 +// [self sendEventAction:onAdLoaded]; +//} +// +//- (void)fullscreenVideoAd:(ABUFullscreenVideoAd *)fullscreenVideoAd didFailWithError:(NSError *)error{ +// NSLog(@"%s-error:%@", __FUNCTION__, error); +// // 发送事件 +// [self sendErrorEvent:error]; +//} +// +//- (void)fullscreenVideoAdDidVisible:(ABUFullscreenVideoAd *)fullscreenVideoAd{ +// NSLog(@"%s",__FUNCTION__); +// // 发送事件 +// [self sendEventAction:onAdExposure]; +//} +// +//- (void)fullscreenVideoAdDidShowFailed:(ABUFullscreenVideoAd *)fullscreenVideoAd error:(NSError *)error{ +// NSLog(@"%s-error:%@", __FUNCTION__, error); +// // 发送事件 +// [self sendErrorEvent:error]; +//} +// +//- (void)fullscreenVideoAd:(ABUFullscreenVideoAd *)fullscreenVideoAd didPlayFinishWithError:(NSError *)error{ +// NSLog(@"%s-error:%@", __FUNCTION__, error); +// // 发送事件 +// [self sendErrorEvent:error]; +//} +// +//- (void)fullscreenVideoAdDidSkip:(ABUFullscreenVideoAd *)fullscreenVideoAd{ +// NSLog(@"%s",__FUNCTION__); +// // 发送事件 +// [self sendEventAction:onAdSkip]; +//} +// +//- (void)fullscreenVideoAdDidClick:(ABUFullscreenVideoAd *)fullscreenVideoAd{ +// NSLog(@"%s",__FUNCTION__); +// // 发送事件 +// [self sendEventAction:onAdClicked]; +//} +// +//- (void)fullscreenVideoAdDidClose:(ABUFullscreenVideoAd *)fullscreenVideoAd{ +// NSLog(@"%s",__FUNCTION__); +// // 发送事件 +// [self sendEventAction:onAdClosed]; +//} +// +//@end diff --git a/ios/Classes/Page/FGMInterstitialFullPage.h b/ios/Classes/Page/FGMInterstitialFullPage.h index 6eaa4f9..cd5fc49 100644 --- a/ios/Classes/Page/FGMInterstitialFullPage.h +++ b/ios/Classes/Page/FGMInterstitialFullPage.h @@ -9,5 +9,5 @@ // 插屏全屏广告 @interface FGMInterstitialFullPage : FGMBasePage -@property (strong,nonatomic) ABUInterstitialProAd *ad; +@property (strong,nonatomic) BUNativeExpressFullscreenVideoAd *ad; @end diff --git a/ios/Classes/Page/FGMInterstitialFullPage.m b/ios/Classes/Page/FGMInterstitialFullPage.m index 036b75a..50f9b7b 100644 --- a/ios/Classes/Page/FGMInterstitialFullPage.m +++ b/ios/Classes/Page/FGMInterstitialFullPage.m @@ -6,64 +6,64 @@ // #import "FGMInterstitialFullPage.h" - -@interface FGMInterstitialFullPage() - -@end - -@implementation FGMInterstitialFullPage - -- (void)loadAd:(FlutterMethodCall *)call{ - bool muted=[call.arguments[@"muted"] boolValue]; - self.ad =[[ABUInterstitialProAd alloc] initWithAdUnitID:self.posId sizeForInterstitial:CGSizeZero]; - self.ad.delegate=self; - self.ad.mutedIfCan=muted; - [self.ad loadAdData]; -} - -- (void)interstitialProAdDidLoad:(ABUInterstitialProAd *)interstitialProAd{ - NSLog(@"%s",__FUNCTION__); - if(self.ad && self.ad.isReady){ - [self.ad showAdFromRootViewController:self.rootController extraInfos:nil]; - } - // 发送事件 - [self sendEventAction:onAdLoaded]; -} - -- (void)interstitialProAd:(ABUInterstitialProAd *)interstitialAd didFailWithError:(NSError *)error{ - NSLog(@"%s-error:%@", __FUNCTION__, error); - // 发送事件 - [self sendErrorEvent:error]; -} - -- (void)interstitialProAdDidVisible:(ABUInterstitialProAd *)interstitialAd{ - NSLog(@"%s",__FUNCTION__); - // 发送事件 - [self sendEventAction:onAdExposure]; -} - -- (void)interstitialProAdDidShowFailed:(ABUInterstitialProAd *)interstitialAd error:(NSError *)error{ - NSLog(@"%s-error:%@", __FUNCTION__, error); - // 发送事件 - [self sendErrorEvent:error]; -} - -- (void)interstitialProAdViewRenderFail:(ABUInterstitialProAd *)interstitialAd error:(NSError *)error{ - NSLog(@"%s-error:%@", __FUNCTION__, error); - // 发送事件 - [self sendErrorEvent:error]; -} - -- (void)interstitialProAdDidClick:(ABUInterstitialProAd *)interstitialAd{ - NSLog(@"%s",__FUNCTION__); - // 发送事件 - [self sendEventAction:onAdClicked]; -} - -- (void)interstitialProAdDidClose:(ABUInterstitialProAd *)interstitialAd{ - NSLog(@"%s",__FUNCTION__); - // 发送事件 - [self sendEventAction:onAdClosed]; -} - -@end +// +//@interface FGMInterstitialFullPage() +// +//@end +// +//@implementation FGMInterstitialFullPage +// +//- (void)loadAd:(FlutterMethodCall *)call{ +// bool muted=[call.arguments[@"muted"] boolValue]; +// self.ad =[[ABUInterstitialProAd alloc] initWithAdUnitID:self.posId sizeForInterstitial:CGSizeZero]; +// self.ad.delegate=self; +// self.ad.mutedIfCan=muted; +// [self.ad loadAdData]; +//} +// +//- (void)interstitialProAdDidLoad:(ABUInterstitialProAd *)interstitialProAd{ +// NSLog(@"%s",__FUNCTION__); +// if(self.ad && self.ad.isReady){ +// [self.ad showAdFromRootViewController:self.rootController extraInfos:nil]; +// } +// // 发送事件 +// [self sendEventAction:onAdLoaded]; +//} +// +//- (void)interstitialProAd:(ABUInterstitialProAd *)interstitialAd didFailWithError:(NSError *)error{ +// NSLog(@"%s-error:%@", __FUNCTION__, error); +// // 发送事件 +// [self sendErrorEvent:error]; +//} +// +//- (void)interstitialProAdDidVisible:(ABUInterstitialProAd *)interstitialAd{ +// NSLog(@"%s",__FUNCTION__); +// // 发送事件 +// [self sendEventAction:onAdExposure]; +//} +// +//- (void)interstitialProAdDidShowFailed:(ABUInterstitialProAd *)interstitialAd error:(NSError *)error{ +// NSLog(@"%s-error:%@", __FUNCTION__, error); +// // 发送事件 +// [self sendErrorEvent:error]; +//} +// +//- (void)interstitialProAdViewRenderFail:(ABUInterstitialProAd *)interstitialAd error:(NSError *)error{ +// NSLog(@"%s-error:%@", __FUNCTION__, error); +// // 发送事件 +// [self sendErrorEvent:error]; +//} +// +//- (void)interstitialProAdDidClick:(ABUInterstitialProAd *)interstitialAd{ +// NSLog(@"%s",__FUNCTION__); +// // 发送事件 +// [self sendEventAction:onAdClicked]; +//} +// +//- (void)interstitialProAdDidClose:(ABUInterstitialProAd *)interstitialAd{ +// NSLog(@"%s",__FUNCTION__); +// // 发送事件 +// [self sendEventAction:onAdClosed]; +//} +// +//@end diff --git a/ios/Classes/Page/FGMInterstitialPage.h b/ios/Classes/Page/FGMInterstitialPage.h index 67de2e2..458a8ff 100644 --- a/ios/Classes/Page/FGMInterstitialPage.h +++ b/ios/Classes/Page/FGMInterstitialPage.h @@ -8,5 +8,5 @@ #import "FGMBasePage.h" // 插屏广告 @interface FGMInterstitialPage : FGMBasePage -@property (strong,nonatomic) ABUInterstitialAd *ad; +@property (strong,nonatomic) BUNativeExpressFullscreenVideoAd *ad; @end diff --git a/ios/Classes/Page/FGMInterstitialPage.m b/ios/Classes/Page/FGMInterstitialPage.m index 17c99bc..b3a4679 100644 --- a/ios/Classes/Page/FGMInterstitialPage.m +++ b/ios/Classes/Page/FGMInterstitialPage.m @@ -6,65 +6,65 @@ // #import "FGMInterstitialPage.h" - -@interface FGMInterstitialPage() - -@end - -@implementation FGMInterstitialPage - -- (void)loadAd:(FlutterMethodCall *)call{ - int width=[call.arguments[@"width"] intValue]; - int height=[call.arguments[@"height"] intValue]; - self.ad= [[ABUInterstitialAd alloc] initWithAdUnitID:self.posId size:CGSizeMake(width, height)]; - self.ad.delegate=self; - self.ad.mutedIfCan=YES; - [self.ad loadAdData]; -} - -- (void)interstitialAdDidLoad:(ABUInterstitialAd *)interstitialAd{ - NSLog(@"%s",__FUNCTION__); - if(self.ad && self.ad.isReady){ - [self.ad showAdFromRootViewController:self.rootController]; - } - // 发送事件 - [self sendEventAction:onAdLoaded]; -} - -- (void)interstitialAd:(ABUInterstitialAd *)interstitialAd didFailWithError:(NSError *)error{ - NSLog(@"%s-error:%@", __FUNCTION__, error); - // 发送事件 - [self sendErrorEvent:error]; -} - -- (void)interstitialAdDidVisible:(ABUInterstitialAd *)interstitialAd{ - NSLog(@"%s",__FUNCTION__); - // 发送事件 - [self sendEventAction:onAdExposure]; -} - -- (void)interstitialAdDidShowFailed:(ABUInterstitialAd *)interstitialAd error:(NSError *)error{ - NSLog(@"%s-error:%@", __FUNCTION__, error); - // 发送事件 - [self sendErrorEvent:error]; -} - -- (void)interstitialAdViewRenderFail:(ABUInterstitialAd *)interstitialAd error:(NSError *)error{ - NSLog(@"%s-error:%@", __FUNCTION__, error); - // 发送事件 - [self sendErrorEvent:error]; -} - -- (void)interstitialAdDidClick:(ABUInterstitialAd *)interstitialAd{ - NSLog(@"%s",__FUNCTION__); - // 发送事件 - [self sendEventAction:onAdClicked]; -} - -- (void)interstitialAdDidClose:(ABUInterstitialAd *)interstitialAd{ - NSLog(@"%s",__FUNCTION__); - // 发送事件 - [self sendEventAction:onAdClosed]; -} - -@end +// +//@interface FGMInterstitialPage() +// +//@end +// +//@implementation FGMInterstitialPage +// +//- (void)loadAd:(FlutterMethodCall *)call{ +// int width=[call.arguments[@"width"] intValue]; +// int height=[call.arguments[@"height"] intValue]; +// self.ad= [[ABUInterstitialAd alloc] initWithAdUnitID:self.posId size:CGSizeMake(width, height)]; +// self.ad.delegate=self; +// self.ad.mutedIfCan=YES; +// [self.ad loadAdData]; +//} +// +//- (void)interstitialAdDidLoad:(ABUInterstitialAd *)interstitialAd{ +// NSLog(@"%s",__FUNCTION__); +// if(self.ad && self.ad.isReady){ +// [self.ad showAdFromRootViewController:self.rootController]; +// } +// // 发送事件 +// [self sendEventAction:onAdLoaded]; +//} +// +//- (void)interstitialAd:(ABUInterstitialAd *)interstitialAd didFailWithError:(NSError *)error{ +// NSLog(@"%s-error:%@", __FUNCTION__, error); +// // 发送事件 +// [self sendErrorEvent:error]; +//} +// +//- (void)interstitialAdDidVisible:(ABUInterstitialAd *)interstitialAd{ +// NSLog(@"%s",__FUNCTION__); +// // 发送事件 +// [self sendEventAction:onAdExposure]; +//} +// +//- (void)interstitialAdDidShowFailed:(ABUInterstitialAd *)interstitialAd error:(NSError *)error{ +// NSLog(@"%s-error:%@", __FUNCTION__, error); +// // 发送事件 +// [self sendErrorEvent:error]; +//} +// +//- (void)interstitialAdViewRenderFail:(ABUInterstitialAd *)interstitialAd error:(NSError *)error{ +// NSLog(@"%s-error:%@", __FUNCTION__, error); +// // 发送事件 +// [self sendErrorEvent:error]; +//} +// +//- (void)interstitialAdDidClick:(ABUInterstitialAd *)interstitialAd{ +// NSLog(@"%s",__FUNCTION__); +// // 发送事件 +// [self sendEventAction:onAdClicked]; +//} +// +//- (void)interstitialAdDidClose:(ABUInterstitialAd *)interstitialAd{ +// NSLog(@"%s",__FUNCTION__); +// // 发送事件 +// [self sendEventAction:onAdClosed]; +//} +// +//@end diff --git a/ios/Classes/Page/FGMNativeViewFactory.m b/ios/Classes/Page/FGMNativeViewFactory.m index ed7dabf..7b0ff7e 100644 --- a/ios/Classes/Page/FGMNativeViewFactory.m +++ b/ios/Classes/Page/FGMNativeViewFactory.m @@ -6,8 +6,8 @@ // #import "FGMNativeViewFactory.h" -#import "FGMAdBannerView.h" -#import "FGMAdFeedView.h" +//#import "FGMAdBannerView.h" +//#import "FGMAdFeedView.h" @implementation FGMNativeViewFactory @@ -29,19 +29,19 @@ - (instancetype)initWithViewName:(NSString *)viewName withMessenger:(NSObject*)createWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId arguments:(id _Nullable)args { - if (self.viewName==kGMAdBannerViewId) { - return [[FGMAdBannerView alloc] initWithFrame:frame - viewIdentifier:viewId - arguments:args - binaryMessenger:self.messenger - plugin:self.plugin]; - }else if (self.viewName==kGMAdFeedViewId) { - return [[FGMAdFeedView alloc] initWithFrame:frame - viewIdentifier:viewId - arguments:args - binaryMessenger:self.messenger - plugin:self.plugin]; - } +// if (self.viewName==kGMAdBannerViewId) { +// return [[FGMAdBannerView alloc] initWithFrame:frame +// viewIdentifier:viewId +// arguments:args +// binaryMessenger:self.messenger +// plugin:self.plugin]; +// }else if (self.viewName==kGMAdFeedViewId) { +// return [[FGMAdFeedView alloc] initWithFrame:frame +// viewIdentifier:viewId +// arguments:args +// binaryMessenger:self.messenger +// plugin:self.plugin]; +// } return nil; } diff --git a/ios/Classes/Page/FGMSplashPage.h b/ios/Classes/Page/FGMSplashPage.h index ca58cfd..6ebefe0 100644 --- a/ios/Classes/Page/FGMSplashPage.h +++ b/ios/Classes/Page/FGMSplashPage.h @@ -11,7 +11,7 @@ // 开屏广告 @interface FGMSplashPage :FGMBasePage // 开屏 -@property (strong,nonatomic) ABUSplashAd *ad; +@property (strong,nonatomic) BUSplashAd *ad; @property (retain,nonatomic) UIView *bottomView; @property (assign,nonatomic ) BOOL fullScreenAd; // 广告是否展示中 diff --git a/ios/Classes/Page/FGMSplashPage.m b/ios/Classes/Page/FGMSplashPage.m index 3326db0..9cb3ac2 100644 --- a/ios/Classes/Page/FGMSplashPage.m +++ b/ios/Classes/Page/FGMSplashPage.m @@ -7,30 +7,32 @@ #import "FGMSplashPage.h" -@interface FGMSplashPage () +@interface FGMSplashPage () @end @implementation FGMSplashPage - (void)loadAd:(FlutterMethodCall *)call{ - NSLog(@"%s",__FUNCTION__); + NSLog(@"%s,%@",__FUNCTION__,self.posId); self.isDisplay=YES; NSString* logo=call.arguments[@"logo"]; double timeout=[call.arguments[@"timeout"] doubleValue]; // logo 判断为空,则全屏展示 self.fullScreenAd=[logo isKindOfClass:[NSNull class]]||[logo length]==0; + // 创建广告 - self.ad =[[ABUSplashAd alloc] initWithAdUnitID:self.posId]; + self.ad =[[BUSplashAd alloc] initWithSlotID:self.posId adSize:CGSizeZero]; self.ad.delegate=self; + self.ad.supportCardView = YES; + self.ad.supportZoomOutView = YES; self.ad.tolerateTimeout=timeout; - self.ad.rootViewController=self.rootController; if (!self.fullScreenAd) { - // 设置底部 logo - self.bottomView=nil; CGSize size=[[UIScreen mainScreen] bounds].size; CGFloat width=size.width; CGFloat height=112.5;// 这里按照 15% 进行logo 的展示,防止尺寸不够的问题,750*15%=112.5 + // 设置底部 logo + self.bottomView=nil; self.bottomView=[[UIView alloc]initWithFrame:CGRectMake(0, 0,width, height)]; self.bottomView.backgroundColor=[UIColor whiteColor]; UIImageView *logoView=[[UIImageView alloc]initWithImage:[UIImage imageNamed:logo]]; @@ -38,58 +40,117 @@ - (void)loadAd:(FlutterMethodCall *)call{ logoView.contentMode=UIViewContentModeCenter; logoView.center=self.bottomView.center; [self.bottomView addSubview:logoView]; - [self.ad setCustomBottomView:self.bottomView]; + [self.ad.mediation setCustomBottomView:self.bottomView]; } [self.ad loadAdData]; } -- (void)splashAdDidLoad:(ABUSplashAd *)splashAd{ +- (void)splashAdLoadSuccess:(nonnull BUSplashAd *)splashAd { NSLog(@"%s",__FUNCTION__); - [self.ad showInWindow:self.mainWin]; + [self.ad showSplashViewInRootViewController:self.rootController]; // 发送事件 [self sendEventAction:onAdLoaded]; } -- (void)splashAd:(ABUSplashAd *)splashAd didFailWithError:(NSError *)error{ +- (void)splashAdLoadFail:(nonnull BUSplashAd *)splashAd error:(BUAdError * _Nullable)error { NSLog(@"%s-error:%@", __func__, error); // 发送事件 [self sendErrorEvent:error]; self.isDisplay=NO; } -- (void)splashAdWillVisible:(ABUSplashAd *)splashAd{ +- (void)splashAdDidShow:(nonnull BUSplashAd *)splashAd { NSLog(@"%s",__FUNCTION__); // 发送事件 [self sendEventAction:onAdExposure]; } -- (void)splashAdDidShowFailed:(ABUSplashAd *)splashAd error:(NSError *)error{ +- (void)splashAdDidShowFailed:(BUSplashAd *)splashAd error:(NSError *)error{ NSLog(@"%s",__FUNCTION__); // 发送事件 [self sendErrorEvent:error]; self.isDisplay=NO; } -- (void)splashAdDidClick:(ABUSplashAd *)splashAd{ +- (void)splashAdDidClick:(nonnull BUSplashAd *)splashAd { NSLog(@"%s",__FUNCTION__); // 发送事件 [self sendEventAction:onAdClicked]; } -- (void)splashAdDidClose:(ABUSplashAd *)splashAd{ +- (void)splashAdDidClose:(nonnull BUSplashAd *)splashAd closeType:(BUSplashAdCloseType)closeType { NSLog(@"%s",__FUNCTION__); // 发送事件 [self sendEventAction:onAdClosed]; // 销毁广告 if (self.ad) { - [self.ad destoryAd]; + [self.ad.mediation destoryAd]; } self.isDisplay=NO; } -- (void)splashAdCountdownToZero:(ABUSplashAd *)splashAd{ + +- (void)splashCardReadyToShow:(nonnull BUSplashAd *)splashAd { + NSLog(@"%s",__FUNCTION__); + [self.ad showSplashViewInRootViewController:self.rootController]; + // 发送事件 + [self sendEventAction:onAdLoaded]; +} + +- (void)splashCardViewDidClick:(nonnull BUSplashAd *)splashAd { + NSLog(@"%s",__FUNCTION__); + // 发送事件 + [self sendEventAction:onAdClicked]; +} + +- (void)splashCardViewDidClose:(nonnull BUSplashAd *)splashAd { NSLog(@"%s",__FUNCTION__); // 发送事件 - [self sendEventAction:onAdComplete]; + [self sendEventAction:onAdClosed]; + // 销毁广告 + if (self.ad) { + [self.ad.mediation destoryAd]; + } + self.isDisplay=NO; +} + +- (void)splashAdViewControllerDidClose:(BUSplashAd *)splashAd { + NSLog(@"%s",__FUNCTION__); +} + +- (void)splashDidCloseOtherController:(nonnull BUSplashAd *)splashAd interactionType:(BUInteractionType)interactionType { + NSLog(@"%s",__FUNCTION__); +} + + +- (void)splashVideoAdDidPlayFinish:(nonnull BUSplashAd *)splashAd didFailWithError:(nonnull NSError *)error { + NSLog(@"%s",__FUNCTION__); +} + + +- (void)splashZoomOutViewDidClick:(nonnull BUSplashAd *)splashAd { + NSLog(@"%s",__FUNCTION__); + // 发送事件 + [self sendEventAction:onAdClicked]; +} + + +- (void)splashZoomOutViewDidClose:(nonnull BUSplashAd *)splashAd { + NSLog(@"%s",__FUNCTION__); + // 发送事件 + [self sendEventAction:onAdClosed]; + // 销毁广告 + if (self.ad) { + [self.ad.mediation destoryAd]; + } + self.isDisplay=NO; +} + +- (void)splashZoomOutReadyToShow:(nonnull BUSplashAd *)splashAd { + NSLog(@"%s",__FUNCTION__); + // 接入方法一:使用SDK提供动画接入 + if (self.ad.zoomOutView) { + [self.ad showZoomOutViewInRootViewController:self.rootController]; + } } @end diff --git a/ios/flutter_gromore_ads.podspec b/ios/flutter_gromore_ads.podspec index cadf7e3..053172a 100644 --- a/ios/flutter_gromore_ads.podspec +++ b/ios/flutter_gromore_ads.podspec @@ -17,7 +17,8 @@ Pod::Spec.new do |s| s.public_header_files = 'Classes/**/*.h' s.dependency 'Flutter' # 这里仅加载 framework,在 Podfile 中加载 Ads-Mediation-CN 要去掉 framework 的加载,防止冲突 - s.vendored_frameworks = 'Frameworks/Ads-Mediation-CN/Ads-Mediation-CN/ABUAdSDK.framework' + # s.vendored_frameworks = 'Frameworks/Ads-Mediation-CN/Ads-Mediation-CN/ABUAdSDK.framework' + s.dependency 'Ads-Fusion-CN-Beta', '5.3.6.1' s.platform = :ios, '9.0' s.static_framework = true # Flutter.framework does not contain a i386 slice. From fc4cee8cd1605af5ad46cceed0ca10bcb123f7cd Mon Sep 17 00:00:00 2001 From: Zero <1300326388@qq.com> Date: Mon, 14 Aug 2023 09:18:35 +0800 Subject: [PATCH 02/14] =?UTF-8?q?1=E3=80=81=E6=B5=8B=E8=AF=95=E6=8F=92?= =?UTF-8?q?=E5=B1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/lib/ads_config.dart | 48 ++------- example/lib/home_page.dart | 54 ---------- ios/Classes/FlutterGromoreAdsPlugin.h | 2 +- ios/Classes/FlutterGromoreAdsPlugin.m | 4 +- ios/Classes/Page/FGMInterstitialPage.m | 132 ++++++++++++++++++++----- 5 files changed, 119 insertions(+), 121 deletions(-) diff --git a/example/lib/ads_config.dart b/example/lib/ads_config.dart index f0114a9..5522ff6 100644 --- a/example/lib/ads_config.dart +++ b/example/lib/ads_config.dart @@ -22,10 +22,7 @@ class AdsConfig { /// 获取 App id static String get appId { - if (Platform.isIOS) { - return '5324024'; - } - return '5216573'; + return '5324024'; } /// 获取 App Config @@ -38,50 +35,23 @@ class AdsConfig { /// 获取开屏广告位id static String get splashId { - if (Platform.isIOS) { - return '102420790'; - } - return '887382967'; + return '102420790'; } /// 获取插屏广告位id static String get interstitialId { - if (Platform.isIOS) { - return '945494755'; - } - return '945493679'; - } - - /// 获取插屏全屏广告位id - static String get interstitialFullId { - if (Platform.isIOS) { - return '946961656'; - } - return '946276599'; - } - - /// 获取全屏视频广告位id(纵向) - static String get fullVideoVerticalId { - if (Platform.isIOS) { - return '900546831'; - } - return '945493676'; - } - - /// 获取全屏视频广告位id(横向) - static String get fullVideoHorizontalId { - if (Platform.isIOS) { - return '945494751'; - } - return '945493675'; + return '102421471'; } /// 获取激励视频广告位id - static String get rewardVideoId => '946584890'; + static String get rewardVideoId => '102421199'; /// 获取 Banner 广告位id - static String get bannerId => Platform.isIOS ? '102253640' : '102252466'; + static String get bannerId => '102424305'; /// 获取 Feed 信息流广告位 id - static String get feedId => Platform.isIOS ? '102255258' : '102254613'; + static String get feedId => '102420797'; + + /// 获取 Draw 信息流广告位 id + static String get drawFeedId => '102420797'; } diff --git a/example/lib/home_page.dart b/example/lib/home_page.dart index 4667a94..2299f1a 100644 --- a/example/lib/home_page.dart +++ b/example/lib/home_page.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_gromore_ads/flutter_gromore_ads.dart'; -import 'package:flutter_gromore_ads/view/ad_banner_widget.dart'; import 'ads_config.dart'; import 'feed_page.dart'; @@ -87,27 +86,6 @@ class _HomePageState extends State { }, ), const SizedBox(height: 20), - ElevatedButton( - child: const Text('展示插屏全屏广告'), - onPressed: () { - showInterstitialFullAd(); - }, - ), - const SizedBox(height: 20), - ElevatedButton( - child: const Text('展示全屏视频广告(纵向)'), - onPressed: () { - showFullVideoAd(1); - }, - ), - const SizedBox(height: 20), - ElevatedButton( - child: const Text('展示全屏视频广告(横向)'), - onPressed: () { - showFullVideoAd(2); - }, - ), - const SizedBox(height: 20), ElevatedButton( child: const Text('信息流广告'), onPressed: () { @@ -223,36 +201,4 @@ class _HomePageState extends State { } setState(() {}); } - - /// 展示插屏全屏广告 - Future showInterstitialFullAd() async { - try { - bool result = await FlutterGromoreAds.showInterstitialFullAd( - AdsConfig.interstitialFullId, - muted: true, - ); - _result = "展示插屏全屏广告${result ? '成功' : '失败'}"; - } on PlatformException catch (e) { - _result = - "展示插屏全屏广告失败 code:${e.code} msg:${e.message} details:${e.details}"; - } - setState(() {}); - } - - /// 展示全屏视频广告 - Future showFullVideoAd(int orientation) async { - try { - bool result = await FlutterGromoreAds.showFullVideoAd( - orientation == 1 - ? AdsConfig.fullVideoVerticalId - : AdsConfig.fullVideoHorizontalId, - orientation: orientation, - ); - _result = "展示全屏视频广告${result ? '成功' : '失败'}"; - } on PlatformException catch (e) { - _result = - "展示全屏视频广告失败 code:${e.code} msg:${e.message} details:${e.details}"; - } - setState(() {}); - } } diff --git a/ios/Classes/FlutterGromoreAdsPlugin.h b/ios/Classes/FlutterGromoreAdsPlugin.h index a0b5426..1539e25 100644 --- a/ios/Classes/FlutterGromoreAdsPlugin.h +++ b/ios/Classes/FlutterGromoreAdsPlugin.h @@ -9,7 +9,7 @@ @interface FlutterGromoreAdsPlugin : NSObject @property (strong,nonatomic) FlutterEventSink eventSink;// 事件 @property (strong,nonatomic) FGMSplashPage *sad;// 开屏广告 -//@property (strong,nonatomic) FGMInterstitialPage *iad;// 插屏广告 +@property (strong,nonatomic) FGMInterstitialPage *iad;// 插屏广告 //@property (strong,nonatomic) FGMInterstitialFullPage *ifad;//插屏全屏广告 //@property (strong,nonatomic) FGMFullVideoPage *fvad;// 全屏视频广告 //@property (strong,nonatomic) FGMFeedAdLoad * fad;// 信息流广告加载 diff --git a/ios/Classes/FlutterGromoreAdsPlugin.m b/ios/Classes/FlutterGromoreAdsPlugin.m index 68ee2ee..b0e7244 100644 --- a/ios/Classes/FlutterGromoreAdsPlugin.m +++ b/ios/Classes/FlutterGromoreAdsPlugin.m @@ -117,8 +117,8 @@ - (void) showSplashAd:(FlutterMethodCall*) call result:(FlutterResult) result{ // 插屏广告 - (void) showInterstitialAd:(FlutterMethodCall *)call result:(FlutterResult) result{ -// self.iad=[[FGMInterstitialPage alloc] init]; -// [self.iad showAd:call eventSink:self.eventSink]; + self.iad=[[FGMInterstitialPage alloc] init]; + [self.iad showAd:call eventSink:self.eventSink]; result(@(YES)); } diff --git a/ios/Classes/Page/FGMInterstitialPage.m b/ios/Classes/Page/FGMInterstitialPage.m index b3a4679..05d9c7a 100644 --- a/ios/Classes/Page/FGMInterstitialPage.m +++ b/ios/Classes/Page/FGMInterstitialPage.m @@ -6,23 +6,22 @@ // #import "FGMInterstitialPage.h" -// -//@interface FGMInterstitialPage() -// -//@end -// -//@implementation FGMInterstitialPage -// -//- (void)loadAd:(FlutterMethodCall *)call{ -// int width=[call.arguments[@"width"] intValue]; -// int height=[call.arguments[@"height"] intValue]; -// self.ad= [[ABUInterstitialAd alloc] initWithAdUnitID:self.posId size:CGSizeMake(width, height)]; -// self.ad.delegate=self; -// self.ad.mutedIfCan=YES; -// [self.ad loadAdData]; -//} -// -//- (void)interstitialAdDidLoad:(ABUInterstitialAd *)interstitialAd{ + +@interface FGMInterstitialPage() + +@end + +@implementation FGMInterstitialPage + +- (void)loadAd:(FlutterMethodCall *)call{ + int width=[call.arguments[@"width"] intValue]; + int height=[call.arguments[@"height"] intValue]; + self.ad= [[BUNativeExpressFullscreenVideoAd alloc] initWithSlotID:self.posId]; + self.ad.delegate=self; + [self.ad loadAdData]; +} + +//- (void)interstitialAdDidLoad:(BUInterstitialAd *)interstitialAd{ // NSLog(@"%s",__FUNCTION__); // if(self.ad && self.ad.isReady){ // [self.ad showAdFromRootViewController:self.rootController]; @@ -31,40 +30,123 @@ // [self sendEventAction:onAdLoaded]; //} // -//- (void)interstitialAd:(ABUInterstitialAd *)interstitialAd didFailWithError:(NSError *)error{ +//- (void)interstitialAd:(BUInterstitialAd *)interstitialAd didFailWithError:(NSError *)error{ // NSLog(@"%s-error:%@", __FUNCTION__, error); // // 发送事件 // [self sendErrorEvent:error]; //} // -//- (void)interstitialAdDidVisible:(ABUInterstitialAd *)interstitialAd{ +//- (void)interstitialAdDidVisible:(BUInterstitialAd *)interstitialAd{ // NSLog(@"%s",__FUNCTION__); // // 发送事件 // [self sendEventAction:onAdExposure]; //} // -//- (void)interstitialAdDidShowFailed:(ABUInterstitialAd *)interstitialAd error:(NSError *)error{ +//- (void)interstitialAdDidShowFailed:(BUInterstitialAd *)interstitialAd error:(NSError *)error{ // NSLog(@"%s-error:%@", __FUNCTION__, error); // // 发送事件 // [self sendErrorEvent:error]; //} // -//- (void)interstitialAdViewRenderFail:(ABUInterstitialAd *)interstitialAd error:(NSError *)error{ +//- (void)interstitialAdViewRenderFail:(BUInterstitialAd *)interstitialAd error:(NSError *)error{ // NSLog(@"%s-error:%@", __FUNCTION__, error); // // 发送事件 // [self sendErrorEvent:error]; //} // -//- (void)interstitialAdDidClick:(ABUInterstitialAd *)interstitialAd{ +//- (void)interstitialAdDidClick:(BUInterstitialAd *)interstitialAd{ // NSLog(@"%s",__FUNCTION__); // // 发送事件 // [self sendEventAction:onAdClicked]; //} // -//- (void)interstitialAdDidClose:(ABUInterstitialAd *)interstitialAd{ +//- (void)interstitialAdDidClose:(BUInterstitialAd *)interstitialAd{ // NSLog(@"%s",__FUNCTION__); // // 发送事件 // [self sendEventAction:onAdClosed]; //} -// -//@end + + +#pragma mark - BUMNativeExpressFullscreenVideoAdDelegate +- (void)nativeExpressFullscreenVideoAdDidLoad:(BUNativeExpressFullscreenVideoAd *)fullscreenVideoAd { + NSLog(@"%s",__FUNCTION__); + if(self.ad && self.ad.mediation.isReady){ + [self.ad showAdFromRootViewController:self.rootController]; + } + // 发送事件 + [self sendEventAction:onAdLoaded]; +} + +- (void)nativeExpressFullscreenVideoAd:(BUNativeExpressFullscreenVideoAd *)fullscreenVideoAd didFailWithError:(NSError *_Nullable)error { + NSLog(@"%s-error:%@", __FUNCTION__, error); + // 发送事件 + [self sendErrorEvent:error]; +} + +- (void)nativeExpressFullscreenVideoAdViewRenderSuccess:(BUNativeExpressFullscreenVideoAd *)rewardedVideoAd { + NSLog(@"%s",__FUNCTION__); + // 发送事件 + [self sendEventAction:onAdExposure]; +} + +- (void)nativeExpressFullscreenVideoAdViewRenderFail:(BUNativeExpressFullscreenVideoAd *)rewardedVideoAd error:(NSError *_Nullable)error { + NSLog(@"%s-error:%@", __FUNCTION__, error); + // 发送事件 + [self sendErrorEvent:error]; +} + +- (void)nativeExpressFullscreenVideoAdDidDownLoadVideo:(BUNativeExpressFullscreenVideoAd *)fullscreenVideoAd { + NSLog(@"%s",__FUNCTION__); +} + +- (void)nativeExpressFullscreenVideoAdWillVisible:(BUNativeExpressFullscreenVideoAd *)fullscreenVideoAd { + NSLog(@"%s",__FUNCTION__); +} + +- (void)nativeExpressFullscreenVideoAdDidVisible:(BUNativeExpressFullscreenVideoAd *)fullscreenVideoAd { + NSLog(@"%s",__FUNCTION__); +} + +- (void)nativeExpressFullscreenVideoAdDidClick:(BUNativeExpressFullscreenVideoAd *)fullscreenVideoAd { + NSLog(@"%s",__FUNCTION__); + // 发送事件 + [self sendEventAction:onAdClicked]; +} + +- (void)nativeExpressFullscreenVideoAdDidClickSkip:(BUNativeExpressFullscreenVideoAd *)fullscreenVideoAd { + NSLog(@"%s",__FUNCTION__); + // 发送事件 + [self sendEventAction:onAdComplete]; +} + +- (void)nativeExpressFullscreenVideoAdWillClose:(BUNativeExpressFullscreenVideoAd *)fullscreenVideoAd { + NSLog(@"%s",__FUNCTION__); +} + +- (void)nativeExpressFullscreenVideoAdDidClose:(BUNativeExpressFullscreenVideoAd *)fullscreenVideoAd { + NSLog(@"%s",__FUNCTION__); + // 发送事件 + [self sendEventAction:onAdClosed]; +} + +- (void)nativeExpressFullscreenVideoAdDidPlayFinish:(BUNativeExpressFullscreenVideoAd *)fullscreenVideoAd didFailWithError:(NSError *_Nullable)error { + NSLog(@"%s",__FUNCTION__); +} + +- (void)nativeExpressFullscreenVideoAdCallback:(BUNativeExpressFullscreenVideoAd *)fullscreenVideoAd withType:(BUNativeExpressFullScreenAdType) nativeExpressVideoAdType{ + NSLog(@"%s",__FUNCTION__); +} + +- (void)nativeExpressFullscreenVideoAdDidCloseOtherController:(BUNativeExpressFullscreenVideoAd *)fullscreenVideoAd interactionType:(BUInteractionType)interactionType { + NSLog(@"%s",__FUNCTION__); +} + +- (void)nativeExpressFullscreenVideoAdServerRewardDidSucceed:(BUNativeExpressFullscreenVideoAd *)fullscreenVideoAd verify:(BOOL)verify { + NSLog(@"%s",__FUNCTION__); +} + +- (void)nativeExpressFullscreenVideoAdServerRewardDidFail:(BUNativeExpressFullscreenVideoAd *)fullscreenVideoAd error:(NSError *)error { + NSLog(@"%s",__FUNCTION__); +} + +@end From 6bf4b8146699f8cc35bc24445ce2dafdb46586b6 Mon Sep 17 00:00:00 2001 From: Zero <1300326388@qq.com> Date: Thu, 17 Aug 2023 13:50:11 +0800 Subject: [PATCH 03/14] =?UTF-8?q?1=E3=80=81=E5=AE=8C=E5=96=84=20iOS=20Bann?= =?UTF-8?q?er?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ios/Classes/FlutterGromoreAdsPlugin.h | 4 - ios/Classes/FlutterGromoreAdsPlugin.m | 4 - ios/Classes/Page/FGMAdBannerView.m | 183 +++++++++++---------- ios/Classes/Page/FGMFullVideoPage.h | 13 -- ios/Classes/Page/FGMFullVideoPage.m | 75 --------- ios/Classes/Page/FGMInterstitialFullPage.h | 13 -- ios/Classes/Page/FGMInterstitialFullPage.m | 69 -------- ios/Classes/Page/FGMInterstitialPage.m | 46 ------ ios/Classes/Page/FGMNativeViewFactory.m | 17 +- 9 files changed, 104 insertions(+), 320 deletions(-) delete mode 100644 ios/Classes/Page/FGMFullVideoPage.h delete mode 100644 ios/Classes/Page/FGMFullVideoPage.m delete mode 100644 ios/Classes/Page/FGMInterstitialFullPage.h delete mode 100644 ios/Classes/Page/FGMInterstitialFullPage.m diff --git a/ios/Classes/FlutterGromoreAdsPlugin.h b/ios/Classes/FlutterGromoreAdsPlugin.h index 1539e25..379a17f 100644 --- a/ios/Classes/FlutterGromoreAdsPlugin.h +++ b/ios/Classes/FlutterGromoreAdsPlugin.h @@ -1,8 +1,6 @@ #import #import "FGMSplashPage.h" #import "FGMInterstitialPage.h" -#import "FGMInterstitialFullPage.h" -#import "FGMFullVideoPage.h" #import "FGMFeedAdLoad.h" #import "FGMFeedAdManager.h" @@ -10,8 +8,6 @@ @property (strong,nonatomic) FlutterEventSink eventSink;// 事件 @property (strong,nonatomic) FGMSplashPage *sad;// 开屏广告 @property (strong,nonatomic) FGMInterstitialPage *iad;// 插屏广告 -//@property (strong,nonatomic) FGMInterstitialFullPage *ifad;//插屏全屏广告 -//@property (strong,nonatomic) FGMFullVideoPage *fvad;// 全屏视频广告 //@property (strong,nonatomic) FGMFeedAdLoad * fad;// 信息流广告加载 extern NSString *const kGMAdBannerViewId; diff --git a/ios/Classes/FlutterGromoreAdsPlugin.m b/ios/Classes/FlutterGromoreAdsPlugin.m index b0e7244..cefd9c9 100644 --- a/ios/Classes/FlutterGromoreAdsPlugin.m +++ b/ios/Classes/FlutterGromoreAdsPlugin.m @@ -43,10 +43,6 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { [self showSplashAd:call result:result]; }else if ([@"showInterstitialAd" isEqualToString:methodStr]) { [self showInterstitialAd:call result:result]; - }else if ([@"showInterstitialFullAd" isEqualToString:methodStr]) { - [self showInterstitialFullAd:call result:result]; - }else if ([@"showFullVideoAd" isEqualToString:methodStr]) { - [self showFullVideoAd:call result:result]; }else if ([@"loadFeedAd" isEqualToString:methodStr]) { [self loadFeedAd:call result:result]; }else if ([@"clearFeedAd" isEqualToString:methodStr]) { diff --git a/ios/Classes/Page/FGMAdBannerView.m b/ios/Classes/Page/FGMAdBannerView.m index f4c1406..f4bd987 100644 --- a/ios/Classes/Page/FGMAdBannerView.m +++ b/ios/Classes/Page/FGMAdBannerView.m @@ -5,91 +5,98 @@ // Created by Zero on 2023/1/12. // -//#import "FGMAdBannerView.h" -// -//@interface FGMAdBannerView() -//@property (strong,nonatomic) BUBannerAd *bad; -//@property (strong,nonatomic) UIView *bannerView; -// -//@end -// -//@implementation FGMAdBannerView -// -//- (instancetype)initWithFrame:(CGRect)frame -// viewIdentifier:(int64_t)viewId -// arguments:(id _Nullable)args -// binaryMessenger:(NSObject*)messenger -// plugin:(FlutterGromoreAdsPlugin*) plugin{ -// if (self = [super init]) { -// self.bannerView = [[UIView alloc] init]; -// FlutterMethodCall *call=[FlutterMethodCall methodCallWithMethodName:@"AdBannerView" arguments:args]; -// [self showAd:call eventSink:plugin.eventSink]; -// } -// return self; -//} -// -//- (UIView*)view { -// return self.bannerView; -//} -//// 加载广告 -//- (void)loadAd:(FlutterMethodCall *)call{ -// // 刷新间隔 -// int width = [call.arguments[@"width"] intValue]; -// int height = [call.arguments[@"height"] intValue]; -// self.bad=[[BUBannerAd alloc] initWithAdUnitID:self.posId rootViewController:self.rootController adSize:CGSizeMake(width, height)]; -// self.bad.delegate=self; -// [self.bad loadAdData]; -//} -// -// -//#pragma mark ----- ABUBannerAdDelegate ----- -///// 加载成功回调 -//- (void)bannerAdDidLoad:(ABUBannerAd *)bannerAd bannerView:(UIView *)bannerView { -// NSLog(@"%s",__FUNCTION__); -// [self.bannerView addSubview:bannerView]; -// // 发送事件 -// [self sendEventAction:onAdLoaded]; -//} -// -///// 加载失败回调 -//- (void)bannerAd:(ABUBannerAd *)bannerAd didLoadFailWithError:(NSError *)error { -// NSLog(@"%s-error:%@", __FUNCTION__, error); -// // 发送事件 -// [self sendErrorEvent:error]; -// // 销毁广告 -// [self destoryAd:nil]; -//} -// -///// 展示成功回调 -//- (void)bannerAdDidBecomeVisible:(ABUBannerAd *)bannerAd bannerView:(UIView *)bannerView { -// NSLog(@"%s",__FUNCTION__); -// // 发送事件 -// [self sendEventAction:onAdExposure]; -//} -// -///// 广告点击回调 -//- (void)bannerAdDidClick:(ABUBannerAd *)ABUBannerAd bannerView:(UIView *)bannerView { -// NSLog(@"%s",__FUNCTION__); -// // 发送事件 -// [self sendEventAction:onAdClicked]; -//} -// -///// 广告关闭回调 -//- (void)bannerAdDidClosed:(ABUBannerAd *)ABUBannerAd bannerView:(UIView *)bannerView dislikeWithReason:(NSArray *)filterwords { -// NSLog(@"%s",__FUNCTION__); -// // 可于此处移除广告view -// [self destoryAd:bannerView]; -// // 发送事件 -// [self sendEventAction:onAdClosed]; -//} -// -//// 销毁广告 -//- (void)destoryAd:(UIView *)bannerView{ -// if(bannerView){ -// [bannerView removeFromSuperview]; -// } -// self.bad.delegate=nil; -// self.bad=nil; -//} -// -//@end +#import "FGMAdBannerView.h" + +@interface FGMAdBannerView() +@property (strong,nonatomic) BUNativeExpressBannerView *bad; +@property (strong,nonatomic) UIView *bannerView; + +@end + +@implementation FGMAdBannerView + +- (instancetype)initWithFrame:(CGRect)frame + viewIdentifier:(int64_t)viewId + arguments:(id _Nullable)args + binaryMessenger:(NSObject*)messenger + plugin:(FlutterGromoreAdsPlugin*) plugin{ + if (self = [super init]) { + self.bannerView = [[UIView alloc] init]; + FlutterMethodCall *call=[FlutterMethodCall methodCallWithMethodName:@"AdBannerView" arguments:args]; + [self showAd:call eventSink:plugin.eventSink]; + } + return self; +} + +- (UIView*)view { + return self.bannerView; +} +// 加载广告 +- (void)loadAd:(FlutterMethodCall *)call{ + // 刷新间隔 + int width = [call.arguments[@"width"] intValue]; + int height = [call.arguments[@"height"] intValue]; + self.bad=[[BUNativeExpressBannerView alloc] initWithSlotID:self.posId rootViewController:self.rootController adSize:CGSizeMake(width, height)]; + self.bad.delegate=self; + [self.bad loadAdData]; +} + + +#pragma mark ----- ABUBannerAdDelegate ----- +/// 加载成功回调 +- (void)nativeExpressBannerAdViewDidLoad:(BUNativeExpressBannerView *)bannerAdView { + NSLog(@"%s",__FUNCTION__); + [self.bannerView addSubview:bannerAdView]; + // 发送事件 + [self sendEventAction:onAdLoaded]; +} + +/// 加载失败回调 +- (void)nativeExpressBannerAdView:(BUNativeExpressBannerView *)bannerAdView didLoadFailWithError:(NSError *)error { + NSLog(@"%s-error:%@", __FUNCTION__, error); + // 发送事件 + [self sendErrorEvent:error]; + // 销毁广告 + [self destoryAd:nil]; +} + +/// 展示成功回调 +- (void)nativeExpressBannerAdViewDidBecomeVisible:(BUNativeExpressBannerView *)bannerAdView { + NSLog(@"%s",__FUNCTION__); + // 发送事件 + [self sendEventAction:onAdExposure]; +} + +/// 广告点击回调 +- (void)nativeExpressBannerAdViewDidClick:(BUNativeExpressBannerView *)bannerAdView { + NSLog(@"%s",__FUNCTION__); + // 发送事件 + [self sendEventAction:onAdClicked]; +} + +- (void)nativeExpressBannerAdView:(BUNativeExpressBannerView *)bannerAdView dislikeWithReason:(NSArray *)filterwords { + NSLog(@"%s",__FUNCTION__); +} + +- (void)nativeExpressBannerAdViewDidCloseOtherController:(BUNativeExpressBannerView *)bannerAdView interactionType:(BUInteractionType)interactionType { + NSLog(@"%s",__FUNCTION__); +} + +- (void)nativeExpressBannerAdViewDidRemoved:(BUNativeExpressBannerView *)nativeExpressAdView { + NSLog(@"%s",__FUNCTION__); + // 可于此处移除广告view + [self destoryAd:self.bannerView]; + // 发送事件 + [self sendEventAction:onAdClosed]; +} + +// 销毁广告 +- (void)destoryAd:(UIView *)bannerView{ + if(bannerView){ + [bannerView removeFromSuperview]; + } + self.bad.delegate=nil; + self.bad=nil; +} + +@end diff --git a/ios/Classes/Page/FGMFullVideoPage.h b/ios/Classes/Page/FGMFullVideoPage.h deleted file mode 100644 index 48b8e7d..0000000 --- a/ios/Classes/Page/FGMFullVideoPage.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// FGMFullVideoPage.h -// flutter_gromore_ads -// -// Created by zero on 2021/12/12. -// - -#import "FGMBasePage.h" - -// 全屏视频 -@interface FGMFullVideoPage : FGMBasePage -@property (strong,nonatomic) BUFullscreenVideoAd *ad; -@end diff --git a/ios/Classes/Page/FGMFullVideoPage.m b/ios/Classes/Page/FGMFullVideoPage.m deleted file mode 100644 index f7b4d55..0000000 --- a/ios/Classes/Page/FGMFullVideoPage.m +++ /dev/null @@ -1,75 +0,0 @@ -// -// FGMFullVideoPage.m -// flutter_gromore_ads -// -// Created by zero on 2021/12/12. -// - -#import "FGMFullVideoPage.h" -// -//@interface FGMFullVideoPage() -// -//@end -// -//@implementation FGMFullVideoPage -// -//- (void)loadAd:(FlutterMethodCall *)call{ -// self.ad=[[ABUFullscreenVideoAd alloc] initWithAdUnitID:self.posId]; -// self.ad.delegate=self; -// self.ad.mutedIfCan=YES; -// [self.ad loadAdData]; -//} -// -// -//- (void)fullscreenVideoAdDidLoad:(ABUFullscreenVideoAd *)fullscreenVideoAd{ -// NSLog(@"%s",__FUNCTION__); -// if(self.ad && self.ad.isReady){ -// [self.ad showAdFromRootViewController:self.rootController]; -// } -// // 发送事件 -// [self sendEventAction:onAdLoaded]; -//} -// -//- (void)fullscreenVideoAd:(ABUFullscreenVideoAd *)fullscreenVideoAd didFailWithError:(NSError *)error{ -// NSLog(@"%s-error:%@", __FUNCTION__, error); -// // 发送事件 -// [self sendErrorEvent:error]; -//} -// -//- (void)fullscreenVideoAdDidVisible:(ABUFullscreenVideoAd *)fullscreenVideoAd{ -// NSLog(@"%s",__FUNCTION__); -// // 发送事件 -// [self sendEventAction:onAdExposure]; -//} -// -//- (void)fullscreenVideoAdDidShowFailed:(ABUFullscreenVideoAd *)fullscreenVideoAd error:(NSError *)error{ -// NSLog(@"%s-error:%@", __FUNCTION__, error); -// // 发送事件 -// [self sendErrorEvent:error]; -//} -// -//- (void)fullscreenVideoAd:(ABUFullscreenVideoAd *)fullscreenVideoAd didPlayFinishWithError:(NSError *)error{ -// NSLog(@"%s-error:%@", __FUNCTION__, error); -// // 发送事件 -// [self sendErrorEvent:error]; -//} -// -//- (void)fullscreenVideoAdDidSkip:(ABUFullscreenVideoAd *)fullscreenVideoAd{ -// NSLog(@"%s",__FUNCTION__); -// // 发送事件 -// [self sendEventAction:onAdSkip]; -//} -// -//- (void)fullscreenVideoAdDidClick:(ABUFullscreenVideoAd *)fullscreenVideoAd{ -// NSLog(@"%s",__FUNCTION__); -// // 发送事件 -// [self sendEventAction:onAdClicked]; -//} -// -//- (void)fullscreenVideoAdDidClose:(ABUFullscreenVideoAd *)fullscreenVideoAd{ -// NSLog(@"%s",__FUNCTION__); -// // 发送事件 -// [self sendEventAction:onAdClosed]; -//} -// -//@end diff --git a/ios/Classes/Page/FGMInterstitialFullPage.h b/ios/Classes/Page/FGMInterstitialFullPage.h deleted file mode 100644 index cd5fc49..0000000 --- a/ios/Classes/Page/FGMInterstitialFullPage.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// FGMInterstitialFullPage.h -// flutter_gromore_ads -// -// Created by zero on 2021/12/12. -// - -#import "FGMBasePage.h" - -// 插屏全屏广告 -@interface FGMInterstitialFullPage : FGMBasePage -@property (strong,nonatomic) BUNativeExpressFullscreenVideoAd *ad; -@end diff --git a/ios/Classes/Page/FGMInterstitialFullPage.m b/ios/Classes/Page/FGMInterstitialFullPage.m deleted file mode 100644 index 50f9b7b..0000000 --- a/ios/Classes/Page/FGMInterstitialFullPage.m +++ /dev/null @@ -1,69 +0,0 @@ -// -// FGMInterstitialFullPage.m -// flutter_gromore_ads -// -// Created by zero on 2021/12/12. -// - -#import "FGMInterstitialFullPage.h" -// -//@interface FGMInterstitialFullPage() -// -//@end -// -//@implementation FGMInterstitialFullPage -// -//- (void)loadAd:(FlutterMethodCall *)call{ -// bool muted=[call.arguments[@"muted"] boolValue]; -// self.ad =[[ABUInterstitialProAd alloc] initWithAdUnitID:self.posId sizeForInterstitial:CGSizeZero]; -// self.ad.delegate=self; -// self.ad.mutedIfCan=muted; -// [self.ad loadAdData]; -//} -// -//- (void)interstitialProAdDidLoad:(ABUInterstitialProAd *)interstitialProAd{ -// NSLog(@"%s",__FUNCTION__); -// if(self.ad && self.ad.isReady){ -// [self.ad showAdFromRootViewController:self.rootController extraInfos:nil]; -// } -// // 发送事件 -// [self sendEventAction:onAdLoaded]; -//} -// -//- (void)interstitialProAd:(ABUInterstitialProAd *)interstitialAd didFailWithError:(NSError *)error{ -// NSLog(@"%s-error:%@", __FUNCTION__, error); -// // 发送事件 -// [self sendErrorEvent:error]; -//} -// -//- (void)interstitialProAdDidVisible:(ABUInterstitialProAd *)interstitialAd{ -// NSLog(@"%s",__FUNCTION__); -// // 发送事件 -// [self sendEventAction:onAdExposure]; -//} -// -//- (void)interstitialProAdDidShowFailed:(ABUInterstitialProAd *)interstitialAd error:(NSError *)error{ -// NSLog(@"%s-error:%@", __FUNCTION__, error); -// // 发送事件 -// [self sendErrorEvent:error]; -//} -// -//- (void)interstitialProAdViewRenderFail:(ABUInterstitialProAd *)interstitialAd error:(NSError *)error{ -// NSLog(@"%s-error:%@", __FUNCTION__, error); -// // 发送事件 -// [self sendErrorEvent:error]; -//} -// -//- (void)interstitialProAdDidClick:(ABUInterstitialProAd *)interstitialAd{ -// NSLog(@"%s",__FUNCTION__); -// // 发送事件 -// [self sendEventAction:onAdClicked]; -//} -// -//- (void)interstitialProAdDidClose:(ABUInterstitialProAd *)interstitialAd{ -// NSLog(@"%s",__FUNCTION__); -// // 发送事件 -// [self sendEventAction:onAdClosed]; -//} -// -//@end diff --git a/ios/Classes/Page/FGMInterstitialPage.m b/ios/Classes/Page/FGMInterstitialPage.m index 05d9c7a..d4312db 100644 --- a/ios/Classes/Page/FGMInterstitialPage.m +++ b/ios/Classes/Page/FGMInterstitialPage.m @@ -21,52 +21,6 @@ - (void)loadAd:(FlutterMethodCall *)call{ [self.ad loadAdData]; } -//- (void)interstitialAdDidLoad:(BUInterstitialAd *)interstitialAd{ -// NSLog(@"%s",__FUNCTION__); -// if(self.ad && self.ad.isReady){ -// [self.ad showAdFromRootViewController:self.rootController]; -// } -// // 发送事件 -// [self sendEventAction:onAdLoaded]; -//} -// -//- (void)interstitialAd:(BUInterstitialAd *)interstitialAd didFailWithError:(NSError *)error{ -// NSLog(@"%s-error:%@", __FUNCTION__, error); -// // 发送事件 -// [self sendErrorEvent:error]; -//} -// -//- (void)interstitialAdDidVisible:(BUInterstitialAd *)interstitialAd{ -// NSLog(@"%s",__FUNCTION__); -// // 发送事件 -// [self sendEventAction:onAdExposure]; -//} -// -//- (void)interstitialAdDidShowFailed:(BUInterstitialAd *)interstitialAd error:(NSError *)error{ -// NSLog(@"%s-error:%@", __FUNCTION__, error); -// // 发送事件 -// [self sendErrorEvent:error]; -//} -// -//- (void)interstitialAdViewRenderFail:(BUInterstitialAd *)interstitialAd error:(NSError *)error{ -// NSLog(@"%s-error:%@", __FUNCTION__, error); -// // 发送事件 -// [self sendErrorEvent:error]; -//} -// -//- (void)interstitialAdDidClick:(BUInterstitialAd *)interstitialAd{ -// NSLog(@"%s",__FUNCTION__); -// // 发送事件 -// [self sendEventAction:onAdClicked]; -//} -// -//- (void)interstitialAdDidClose:(BUInterstitialAd *)interstitialAd{ -// NSLog(@"%s",__FUNCTION__); -// // 发送事件 -// [self sendEventAction:onAdClosed]; -//} - - #pragma mark - BUMNativeExpressFullscreenVideoAdDelegate - (void)nativeExpressFullscreenVideoAdDidLoad:(BUNativeExpressFullscreenVideoAd *)fullscreenVideoAd { NSLog(@"%s",__FUNCTION__); diff --git a/ios/Classes/Page/FGMNativeViewFactory.m b/ios/Classes/Page/FGMNativeViewFactory.m index 7b0ff7e..d043332 100644 --- a/ios/Classes/Page/FGMNativeViewFactory.m +++ b/ios/Classes/Page/FGMNativeViewFactory.m @@ -6,7 +6,7 @@ // #import "FGMNativeViewFactory.h" -//#import "FGMAdBannerView.h" +#import "FGMAdBannerView.h" //#import "FGMAdFeedView.h" @implementation FGMNativeViewFactory @@ -29,13 +29,14 @@ - (instancetype)initWithViewName:(NSString *)viewName withMessenger:(NSObject*)createWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId arguments:(id _Nullable)args { -// if (self.viewName==kGMAdBannerViewId) { -// return [[FGMAdBannerView alloc] initWithFrame:frame -// viewIdentifier:viewId -// arguments:args -// binaryMessenger:self.messenger -// plugin:self.plugin]; -// }else if (self.viewName==kGMAdFeedViewId) { + if (self.viewName==kGMAdBannerViewId) { + return [[FGMAdBannerView alloc] initWithFrame:frame + viewIdentifier:viewId + arguments:args + binaryMessenger:self.messenger + plugin:self.plugin]; + } +// else if (self.viewName==kGMAdFeedViewId) { // return [[FGMAdFeedView alloc] initWithFrame:frame // viewIdentifier:viewId // arguments:args From 7da357119028d369a92f1bacda1e925ecdae3d2d Mon Sep 17 00:00:00 2001 From: Zero <1300326388@qq.com> Date: Sat, 19 Aug 2023 12:02:54 +0800 Subject: [PATCH 04/14] =?UTF-8?q?1=E3=80=81=E6=94=AF=E6=8C=81=E9=9A=90?= =?UTF-8?q?=E7=A7=81=E8=AE=BE=E7=BD=AE=202=E3=80=81=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=AF=BC=E5=85=A5=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/ios/Runner.xcodeproj/project.pbxproj | 12 ++++---- example/ios/Runner/Info.plist | 4 +-- .../Runner/configs/ios_config_5209496.json | 2 +- example/lib/home_page.dart | 15 +++++----- ios/Classes/FlutterGromoreAdsPlugin.m | 29 +++++++++---------- lib/flutter_gromore_ads.dart | 4 ++- 6 files changed, 34 insertions(+), 32 deletions(-) diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 55c2e4a..5fb4687 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -380,7 +380,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = DRL7GUUB5S; + DEVELOPMENT_TEAM = N943VT2CQD; ENABLE_BITCODE = NO; HEADER_SEARCH_PATHS = ( "$(inherited)", @@ -396,7 +396,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.banjixiaoguanjia.app; + PRODUCT_BUNDLE_IDENTIFIER = com.flutterads.app; PRODUCT_NAME = "$(TARGET_NAME)"; USER_HEADER_SEARCH_PATHS = ""; VERSIONING_SYSTEM = "apple-generic"; @@ -514,7 +514,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = DRL7GUUB5S; + DEVELOPMENT_TEAM = N943VT2CQD; ENABLE_BITCODE = NO; HEADER_SEARCH_PATHS = ( "$(inherited)", @@ -530,7 +530,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.banjixiaoguanjia.app; + PRODUCT_BUNDLE_IDENTIFIER = com.flutterads.app; PRODUCT_NAME = "$(TARGET_NAME)"; USER_HEADER_SEARCH_PATHS = ""; VERSIONING_SYSTEM = "apple-generic"; @@ -543,7 +543,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = DRL7GUUB5S; + DEVELOPMENT_TEAM = N943VT2CQD; ENABLE_BITCODE = NO; HEADER_SEARCH_PATHS = ( "$(inherited)", @@ -559,7 +559,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.banjixiaoguanjia.app; + PRODUCT_BUNDLE_IDENTIFIER = com.flutterads.app; PRODUCT_NAME = "$(TARGET_NAME)"; USER_HEADER_SEARCH_PATHS = ""; VERSIONING_SYSTEM = "apple-generic"; diff --git a/example/ios/Runner/Info.plist b/example/ios/Runner/Info.plist index b93ccab..069f60b 100644 --- a/example/ios/Runner/Info.plist +++ b/example/ios/Runner/Info.plist @@ -31,6 +31,8 @@ NSUserTrackingUsageDescription 为了向您提供更优质、安全的个性化服务及内容,需要您允许使用相关权限 + UIApplicationSupportsIndirectInputEvents + UILaunchStoryboardName LaunchScreen UIMainStoryboardFile @@ -50,7 +52,5 @@ UIViewControllerBasedStatusBarAppearance - UIApplicationSupportsIndirectInputEvents - diff --git a/example/ios/Runner/configs/ios_config_5209496.json b/example/ios/Runner/configs/ios_config_5209496.json index e969f31..8a0ba63 100644 --- a/example/ios/Runner/configs/ios_config_5209496.json +++ b/example/ios/Runner/configs/ios_config_5209496.json @@ -1 +1 @@ -{"cypher":2,"message":"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"} \ No newline at end of file +{"cypher":2,"message":"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"} \ No newline at end of file diff --git a/example/lib/home_page.dart b/example/lib/home_page.dart index 2299f1a..4561ce2 100644 --- a/example/lib/home_page.dart +++ b/example/lib/home_page.dart @@ -66,7 +66,7 @@ class _HomePageState extends State { ), const SizedBox(height: 20), ElevatedButton( - child: const Text('展示开屏广告(Logo2)'), + child: const Text('展示开屏广告'), onPressed: () { showSplashAd(AdsConfig.logo2); }, @@ -103,11 +103,11 @@ class _HomePageState extends State { height: 75, ), const SizedBox(height: 20), - // AdBannerWidget( - // posId: AdsConfig.bannerId, - // width: 300, - // height: 75, - // ), + AdBannerWidget( + posId: AdsConfig.bannerId, + width: 300, + height: 75, + ), ], ), ), @@ -120,7 +120,8 @@ class _HomePageState extends State { try { bool result = await FlutterGromoreAds.initAd( AdsConfig.appId, - // config: AdsConfig.config, + config: AdsConfig.config, + limitPersonalAds: 1, ); _result = "广告SDK 初始化${result ? '成功' : '失败'}"; setState(() {}); diff --git a/ios/Classes/FlutterGromoreAdsPlugin.m b/ios/Classes/FlutterGromoreAdsPlugin.m index cefd9c9..2f86926 100644 --- a/ios/Classes/FlutterGromoreAdsPlugin.m +++ b/ios/Classes/FlutterGromoreAdsPlugin.m @@ -69,13 +69,24 @@ - (void) requestIDFA:(FlutterMethodCall*) call result:(FlutterResult) result{ - (void) initAd:(FlutterMethodCall*) call result:(FlutterResult) result{ NSString *appId=call.arguments[@"appId"]; NSString *config=call.arguments[@"config"]; + int limitPersonalAds=[call.arguments[@"limitPersonalAds"] intValue]; NSLog(@"appid:%@",appId); BUAdSDKConfiguration *configuration = [BUAdSDKConfiguration configuration]; + // 是否开启调试 + #ifdef DEBUG + configuration.debugLog = @(1); + #endif + // 配置 appid 和使用聚合 configuration.appID = appId; -// configuration.privacyProvider = [[BUDPrivacyProvider alloc] init]; -// configuration.appLogoImage = [UIImage imageNamed:@"AppIcon"]; configuration.useMediation = YES; - configuration.debugLog = @(1); + // 隐私合规 + configuration.mediation.limitPersonalAds = @(limitPersonalAds); + configuration.mediation.limitProgrammaticAds = @(limitPersonalAds); + configuration.mediation.forbiddenCAID = @(limitPersonalAds); + // 提前导入配置 + if (![config isKindOfClass:[NSNull class]] && [config length]!=0) { + configuration.mediation.advanceSDKConfigPath = [[NSBundle mainBundle]pathForResource:config ofType:@"json"]; + } [BUAdSDKManager startWithAsyncCompletionHandler:^(BOOL success, NSError *error) { if (success) { @@ -86,18 +97,6 @@ - (void) initAd:(FlutterMethodCall*) call result:(FlutterResult) result{ } }]; - -// [ABUAdSDKManager setupSDKWithAppId:appId config:^ABUUserConfig *(ABUUserConfig *c) { -// #ifdef DEBUG -// c.logEnable = YES; -// #endif -// // 导入本地配置 -// if (![config isKindOfClass:[NSNull class]] && [config length]!=0) { -// c.advanceSDKConfigPath = [[NSBundle mainBundle] pathForResource:config ofType:@"json"];//支持媒体本地提前导入配置信息 -// } -// return c; -// }]; - } // 开屏广告 diff --git a/lib/flutter_gromore_ads.dart b/lib/flutter_gromore_ads.dart index 996e933..950f745 100644 --- a/lib/flutter_gromore_ads.dart +++ b/lib/flutter_gromore_ads.dart @@ -49,12 +49,14 @@ class FlutterGromoreAds { /// 初始化广告 /// [appId] 应用ID /// [config] 配置文件名称 - static Future initAd(String appId, {String? config}) async { + static Future initAd(String appId, + {String? config, int limitPersonalAds = 0}) async { final bool result = await _methodChannel.invokeMethod( 'initAd', { 'appId': appId, 'config': config, + 'limitPersonalAds': limitPersonalAds, }, ); return result; From c6cdc1403f070c451e3a5f676a8ac74e5a87cefa Mon Sep 17 00:00:00 2001 From: Zero <1300326388@qq.com> Date: Sat, 19 Aug 2023 17:15:46 +0800 Subject: [PATCH 05/14] =?UTF-8?q?1=E3=80=81=E5=A2=9E=E5=8A=A0=E5=BC=80?= =?UTF-8?q?=E5=B1=8F=202=E3=80=81=E5=A2=9E=E5=8A=A0=E6=8F=92=E5=B1=8F=203?= =?UTF-8?q?=E3=80=81=E5=A2=9E=E5=8A=A0Banner?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- android/build.gradle | 2 +- .../flutter_gromore_ads/PluginDelegate.java | 93 +++-- .../flutter_gromore_ads/load/FeedAdLoad.java | 180 ++++----- .../load/FeedAdManager.java | 114 +++--- .../page/AdBannerView.java | 124 +++--- .../flutter_gromore_ads/page/AdFeedView.java | 368 +++++++++--------- .../page/AdSplashActivity.java | 105 +++-- .../flutter_gromore_ads/page/BaseAdPage.java | 10 +- .../page/FullVideoPage.java | 119 ------ .../page/InterstitialFullPage.java | 130 ------- .../page/InterstitialPage.java | 90 +++-- .../page/NativeViewFactory.java | 5 +- example/android/app/build.gradle | 6 +- .../main/assets/android_config_5216573.json | 2 +- example/lib/home_page.dart | 10 +- 15 files changed, 556 insertions(+), 802 deletions(-) delete mode 100644 android/src/main/java/com/zero/flutter_gromore_ads/page/FullVideoPage.java delete mode 100644 android/src/main/java/com/zero/flutter_gromore_ads/page/InterstitialFullPage.java diff --git a/android/build.gradle b/android/build.gradle index 9b281c4..200b3f0 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -55,7 +55,7 @@ dependencies { implementation 'com.google.android.material:material:1.3.0' implementation 'androidx.constraintlayout:constraintlayout:2.0.4' //GroMore_sdk - implementation "com.pangle.cn:mediation-sdk:5.3.6.2" //融合SDK + implementation "com.pangle.cn:mediation-sdk:5.5.1.5" //融合SDK // Glide 图片加载框架 implementation 'com.github.bumptech.glide:glide:4.14.2' annotationProcessor 'com.github.bumptech.glide:compiler:4.14.2' diff --git a/android/src/main/java/com/zero/flutter_gromore_ads/PluginDelegate.java b/android/src/main/java/com/zero/flutter_gromore_ads/PluginDelegate.java index eeb3024..37dc07f 100644 --- a/android/src/main/java/com/zero/flutter_gromore_ads/PluginDelegate.java +++ b/android/src/main/java/com/zero/flutter_gromore_ads/PluginDelegate.java @@ -7,15 +7,17 @@ import androidx.annotation.NonNull; -import com.bytedance.msdk.api.v2.GMAdConfig; -import com.bytedance.msdk.api.v2.GMMediationAdSdk; -import com.bytedance.msdk.api.v2.GMPangleOption; -import com.zero.flutter_gromore_ads.load.FeedAdLoad; -import com.zero.flutter_gromore_ads.load.FeedAdManager; + +//import com.zero.flutter_gromore_ads.load.FeedAdLoad; +//import com.zero.flutter_gromore_ads.load.FeedAdManager; +import com.bytedance.sdk.openadsdk.TTAdConfig; +import com.bytedance.sdk.openadsdk.TTAdSdk; +import com.bytedance.sdk.openadsdk.mediation.init.MediationConfig; import com.zero.flutter_gromore_ads.page.AdSplashActivity; -import com.zero.flutter_gromore_ads.page.FullVideoPage; -import com.zero.flutter_gromore_ads.page.InterstitialFullPage; +//import com.zero.flutter_gromore_ads.page.FullVideoPage; +//import com.zero.flutter_gromore_ads.page.InterstitialFullPage; import com.zero.flutter_gromore_ads.page.InterstitialPage; +//import com.zero.flutter_gromore_ads.page.NativeViewFactory; import com.zero.flutter_gromore_ads.page.NativeViewFactory; import com.zero.flutter_gromore_ads.utils.FileUtils; @@ -154,8 +156,8 @@ public void registerBannerView() { * 展示 Feed 信息流广告 */ public void registerFeedView() { - bind.getPlatformViewRegistry() - .registerViewFactory(KEY_FEED_VIEW, new NativeViewFactory(KEY_FEED_VIEW, this)); +// bind.getPlatformViewRegistry() +// .registerViewFactory(KEY_FEED_VIEW, new NativeViewFactory(KEY_FEED_VIEW, this)); } /** @@ -165,7 +167,7 @@ public void registerFeedView() { * @param result Result */ public void requestPermissionIfNecessary(MethodCall call, MethodChannel.Result result) { - GMMediationAdSdk.requestPermissionIfNecessary(activity); + TTAdSdk.getMediationManager().requestPermissionIfNecessary(activity); result.success(true); } @@ -178,6 +180,14 @@ public void requestPermissionIfNecessary(MethodCall call, MethodChannel.Result r public void initAd(MethodCall call, final MethodChannel.Result result) { String appId = call.argument("appId"); String config = call.argument("config"); + + // 构建基础配置 + TTAdConfig.Builder configBuilder = new TTAdConfig.Builder() + .appId(appId) + .useMediation(true) + .debug(BuildConfig.DEBUG) + .supportMultiProcess(false); + // 离线配置 JSONObject localConfigJson = null; if (!TextUtils.isEmpty(config)) { String localConfigStr = FileUtils.getJson(config, activity); @@ -187,22 +197,27 @@ public void initAd(MethodCall call, final MethodChannel.Result result) { e.printStackTrace(); } } - // 穿山甲配置 - GMPangleOption gmPangleOption=new GMPangleOption.Builder() - .setIsUseTextureView(true) - .build(); // 构建配置 - GMAdConfig adConfig = new GMAdConfig.Builder() - .setAppId(appId) - .setAppName("测试App") - .setDebug(BuildConfig.DEBUG) - .setOpenAdnTest(BuildConfig.DEBUG) - .setCustomLocalConfig(localConfigJson) - .setPangleOption(gmPangleOption) - .build(); + TTAdConfig gmPangleOption; + if (localConfigJson != null) { + gmPangleOption = configBuilder.setMediationConfig(new MediationConfig.Builder() + .setCustomLocalConfig(localConfigJson) + .build()).build(); + } else { + gmPangleOption = configBuilder.build(); + } // 初始化 SDK - GMMediationAdSdk.initialize(activity.getApplicationContext(), adConfig); - result.success(true); + TTAdSdk.init(activity.getApplicationContext(), gmPangleOption, new TTAdSdk.InitCallback() { + @Override + public void success() { + result.success(true); + } + + @Override + public void fail(int code, String message) { + result.success(false); + } + }); } /** @@ -244,9 +259,9 @@ public void showInterstitialAd(MethodCall call, MethodChannel.Result result) { * @param result Result */ public void showInterstitialFullAd(MethodCall call, MethodChannel.Result result) { - InterstitialFullPage adPage = new InterstitialFullPage(); - adPage.showAd(activity, call); - result.success(true); +// InterstitialFullPage adPage = new InterstitialFullPage(); +// adPage.showAd(activity, call); +// result.success(true); } /** @@ -256,9 +271,9 @@ public void showInterstitialFullAd(MethodCall call, MethodChannel.Result result) * @param result Result */ public void showFullVideoAd(MethodCall call, MethodChannel.Result result) { - FullVideoPage adPage = new FullVideoPage(); - adPage.showAd(activity, call); - result.success(true); +// FullVideoPage adPage = new FullVideoPage(); +// adPage.showAd(activity, call); +// result.success(true); } /** @@ -280,8 +295,8 @@ public void showRewardVideoAd(MethodCall call, MethodChannel.Result result) { * @param result Result */ public void loadFeedAd(MethodCall call, MethodChannel.Result result) { - FeedAdLoad feedAd = new FeedAdLoad(); - feedAd.loadFeedAdList(activity, call, result); +// FeedAdLoad feedAd = new FeedAdLoad(); +// feedAd.loadFeedAdList(activity, call, result); } /** @@ -291,13 +306,13 @@ public void loadFeedAd(MethodCall call, MethodChannel.Result result) { * @param result Result */ public void clearFeedAd(MethodCall call, MethodChannel.Result result) { - List adList = call.argument("list"); - if (adList != null) { - for (int ad : adList) { - FeedAdManager.getInstance().removeAd(ad); - } - } - result.success(true); +// List adList = call.argument("list"); +// if (adList != null) { +// for (int ad : adList) { +// FeedAdManager.getInstance().removeAd(ad); +// } +// } +// result.success(true); } } diff --git a/android/src/main/java/com/zero/flutter_gromore_ads/load/FeedAdLoad.java b/android/src/main/java/com/zero/flutter_gromore_ads/load/FeedAdLoad.java index c16a0e8..a02cf76 100644 --- a/android/src/main/java/com/zero/flutter_gromore_ads/load/FeedAdLoad.java +++ b/android/src/main/java/com/zero/flutter_gromore_ads/load/FeedAdLoad.java @@ -1,92 +1,92 @@ -package com.zero.flutter_gromore_ads.load; - -import android.app.Activity; -import android.util.Log; - -import androidx.annotation.NonNull; - -import com.bytedance.msdk.api.AdError; -import com.bytedance.msdk.api.v2.GMAdConstant; -import com.bytedance.msdk.api.v2.ad.nativeAd.GMNativeAd; -import com.bytedance.msdk.api.v2.ad.nativeAd.GMNativeAdLoadCallback; -import com.bytedance.msdk.api.v2.ad.nativeAd.GMUnifiedNativeAd; -import com.bytedance.msdk.api.v2.slot.GMAdOptionUtil; -import com.bytedance.msdk.api.v2.slot.GMAdSlotNative; -import com.zero.flutter_gromore_ads.event.AdEventAction; -import com.zero.flutter_gromore_ads.page.BaseAdPage; -import com.zero.flutter_gromore_ads.utils.UIUtils; - -import java.util.ArrayList; -import java.util.List; - -import io.flutter.plugin.common.MethodCall; -import io.flutter.plugin.common.MethodChannel; - -/** - * 信息流加载对象 - */ -public class FeedAdLoad extends BaseAdPage implements GMNativeAdLoadCallback { - private final String TAG = FeedAdLoad.class.getSimpleName(); - GMUnifiedNativeAd ad; - private MethodChannel.Result result; - - /** - * 加载信息流广告列表 - * @param call - * @param result - */ - public void loadFeedAdList(Activity activity, @NonNull MethodCall call, @NonNull MethodChannel.Result result) { - this.result=result; - showAd(activity,call); - } - - @Override - public void loadAd(@NonNull MethodCall call) { - // 获取请求模板广告素材的尺寸 - int expressViewWidth = call.argument("width"); - int expressViewHeight = call.argument("height"); - int count = call.argument("count"); - // 如果为空则创建 -// if (ad == null) { +//package com.zero.flutter_gromore_ads.load; // +//import android.app.Activity; +//import android.util.Log; +// +//import androidx.annotation.NonNull; +// +//import com.bytedance.msdk.api.AdError; +//import com.bytedance.msdk.api.v2.GMAdConstant; +//import com.bytedance.msdk.api.v2.ad.nativeAd.GMNativeAd; +//import com.bytedance.msdk.api.v2.ad.nativeAd.GMNativeAdLoadCallback; +//import com.bytedance.msdk.api.v2.ad.nativeAd.GMUnifiedNativeAd; +//import com.bytedance.msdk.api.v2.slot.GMAdOptionUtil; +//import com.bytedance.msdk.api.v2.slot.GMAdSlotNative; +//import com.zero.flutter_gromore_ads.event.AdEventAction; +//import com.zero.flutter_gromore_ads.page.BaseAdPage; +//import com.zero.flutter_gromore_ads.utils.UIUtils; +// +//import java.util.ArrayList; +//import java.util.List; +// +//import io.flutter.plugin.common.MethodCall; +//import io.flutter.plugin.common.MethodChannel; +// +///** +// * 信息流加载对象 +// */ +//public class FeedAdLoad extends BaseAdPage implements GMNativeAdLoadCallback { +// private final String TAG = FeedAdLoad.class.getSimpleName(); +// GMUnifiedNativeAd ad; +// private MethodChannel.Result result; +// +// /** +// * 加载信息流广告列表 +// * @param call +// * @param result +// */ +// public void loadFeedAdList(Activity activity, @NonNull MethodCall call, @NonNull MethodChannel.Result result) { +// this.result=result; +// showAd(activity,call); +// } +// +// @Override +// public void loadAd(@NonNull MethodCall call) { +// // 获取请求模板广告素材的尺寸 +// int expressViewWidth = call.argument("width"); +// int expressViewHeight = call.argument("height"); +// int count = call.argument("count"); +// // 如果为空则创建 +//// if (ad == null) { +//// +//// } +// // 原生广告 +// ad = new GMUnifiedNativeAd(activity, posId); +// // 广告配置 +// GMAdSlotNative adSlot = new GMAdSlotNative.Builder() +// .setAdStyleType(GMAdConstant.TYPE_EXPRESS_AD)//必传,表示请求的模板广告还是原生广告,AdSlot.TYPE_EXPRESS_AD:模板广告 ; AdSlot.TYPE_NATIVE_AD:原生广告 +// // 备注 +// // 1:如果是信息流自渲染广告,设置广告图片期望的图片宽高 ,不能为0 +// // 2:如果是信息流模板广告,宽度设置为希望的宽度,高度设置为0(0为高度选择自适应参数) +// .setImageAdSize((int) UIUtils.getScreenWidthDp(activity), 0)// 必选参数 单位dp ,详情见上面备注解释 +// .setAdCount(count)//请求广告数量为1到3条 +// .build(); +// ad.loadAd(adSlot,this); +// } +// +// @Override +// public void onAdLoaded(@NonNull List list) { +// List adResultList=new ArrayList<>(); +// Log.i(TAG, "onNativeExpressAdLoad onAdLoaded"); +// if (list.isEmpty()) { +// this.result.success(adResultList); +// return; // } - // 原生广告 - ad = new GMUnifiedNativeAd(activity, posId); - // 广告配置 - GMAdSlotNative adSlot = new GMAdSlotNative.Builder() - .setAdStyleType(GMAdConstant.TYPE_EXPRESS_AD)//必传,表示请求的模板广告还是原生广告,AdSlot.TYPE_EXPRESS_AD:模板广告 ; AdSlot.TYPE_NATIVE_AD:原生广告 - // 备注 - // 1:如果是信息流自渲染广告,设置广告图片期望的图片宽高 ,不能为0 - // 2:如果是信息流模板广告,宽度设置为希望的宽度,高度设置为0(0为高度选择自适应参数) - .setImageAdSize((int) UIUtils.getScreenWidthDp(activity), 0)// 必选参数 单位dp ,详情见上面备注解释 - .setAdCount(count)//请求广告数量为1到3条 - .build(); - ad.loadAd(adSlot,this); - } - - @Override - public void onAdLoaded(@NonNull List list) { - List adResultList=new ArrayList<>(); - Log.i(TAG, "onNativeExpressAdLoad onAdLoaded"); - if (list.isEmpty()) { - this.result.success(adResultList); - return; - } - Log.i(TAG, "onNativeExpressAdLoad onAdLoaded :"+list.size()); - for (GMNativeAd adItem : list) { - int key=adItem.hashCode(); - adResultList.add(key); - FeedAdManager.getInstance().putAd(key,adItem); - } - // 添加广告事件 - sendEvent(AdEventAction.onAdLoaded); - this.result.success(adResultList); - } - - @Override - public void onAdLoadedFail(@NonNull AdError adError) { - Log.e(TAG, "onError code:" + adError.code + " msg:" + adError.message); - sendErrorEvent(adError.code, adError.message); - this.result.error(""+adError.code, adError.message,adError.message); - } -} +// Log.i(TAG, "onNativeExpressAdLoad onAdLoaded :"+list.size()); +// for (GMNativeAd adItem : list) { +// int key=adItem.hashCode(); +// adResultList.add(key); +// FeedAdManager.getInstance().putAd(key,adItem); +// } +// // 添加广告事件 +// sendEvent(AdEventAction.onAdLoaded); +// this.result.success(adResultList); +// } +// +// @Override +// public void onAdLoadedFail(@NonNull AdError adError) { +// Log.e(TAG, "onError code:" + adError.code + " msg:" + adError.message); +// sendErrorEvent(adError.code, adError.message); +// this.result.error(""+adError.code, adError.message,adError.message); +// } +//} diff --git a/android/src/main/java/com/zero/flutter_gromore_ads/load/FeedAdManager.java b/android/src/main/java/com/zero/flutter_gromore_ads/load/FeedAdManager.java index 1b20e86..ef6fb02 100644 --- a/android/src/main/java/com/zero/flutter_gromore_ads/load/FeedAdManager.java +++ b/android/src/main/java/com/zero/flutter_gromore_ads/load/FeedAdManager.java @@ -1,57 +1,57 @@ -package com.zero.flutter_gromore_ads.load; - -import com.bytedance.msdk.api.v2.ad.nativeAd.GMNativeAd; - -import java.util.HashMap; -import java.util.Map; - -/** - * 信息流广告管理 - */ -public class FeedAdManager { - private final String TAG = FeedAdManager.class.getSimpleName(); - // 信息流广告管理类对象 - private static FeedAdManager _instance; - - public static synchronized FeedAdManager getInstance() { - if (_instance == null) { - synchronized (FeedAdManager.class) { - _instance = new FeedAdManager(); - } - } - return _instance; - } - - // 信息流广告列表 - private final Map feedAdList = new HashMap(); - - /** - * 添加广告渲染对象 - * - * @param key 广告缓存id - * @param ad 广告渲染对象 - */ - public void putAd(int key, GMNativeAd ad) { - feedAdList.put(key, ad); - } - - /** - * 获取广告渲染对象 - * - * @param key 广告缓存id - * @return 广告渲染对象 - */ - public GMNativeAd getAd(int key) { - return feedAdList.get(key); - } - - /** - * 删除广告渲染对象 - * - * @param key 广告缓存id - * @return 广告渲染对象 - */ - public GMNativeAd removeAd(int key) { - return feedAdList.remove(key); - } -} +//package com.zero.flutter_gromore_ads.load; +// +//import com.bytedance.msdk.api.v2.ad.nativeAd.GMNativeAd; +// +//import java.util.HashMap; +//import java.util.Map; +// +///** +// * 信息流广告管理 +// */ +//public class FeedAdManager { +// private final String TAG = FeedAdManager.class.getSimpleName(); +// // 信息流广告管理类对象 +// private static FeedAdManager _instance; +// +// public static synchronized FeedAdManager getInstance() { +// if (_instance == null) { +// synchronized (FeedAdManager.class) { +// _instance = new FeedAdManager(); +// } +// } +// return _instance; +// } +// +// // 信息流广告列表 +// private final Map feedAdList = new HashMap(); +// +// /** +// * 添加广告渲染对象 +// * +// * @param key 广告缓存id +// * @param ad 广告渲染对象 +// */ +// public void putAd(int key, GMNativeAd ad) { +// feedAdList.put(key, ad); +// } +// +// /** +// * 获取广告渲染对象 +// * +// * @param key 广告缓存id +// * @return 广告渲染对象 +// */ +// public GMNativeAd getAd(int key) { +// return feedAdList.get(key); +// } +// +// /** +// * 删除广告渲染对象 +// * +// * @param key 广告缓存id +// * @return 广告渲染对象 +// */ +// public GMNativeAd removeAd(int key) { +// return feedAdList.remove(key); +// } +//} diff --git a/android/src/main/java/com/zero/flutter_gromore_ads/page/AdBannerView.java b/android/src/main/java/com/zero/flutter_gromore_ads/page/AdBannerView.java index 879e1ca..3f90b0a 100644 --- a/android/src/main/java/com/zero/flutter_gromore_ads/page/AdBannerView.java +++ b/android/src/main/java/com/zero/flutter_gromore_ads/page/AdBannerView.java @@ -1,46 +1,24 @@ package com.zero.flutter_gromore_ads.page; import android.content.Context; -import android.text.TextUtils; import android.util.Log; -import android.view.LayoutInflater; import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; import android.widget.FrameLayout; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.RelativeLayout; -import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import com.bumptech.glide.Glide; -import com.bytedance.msdk.api.AdError; -import com.bytedance.msdk.api.TToast; -import com.bytedance.msdk.api.nativeAd.TTNativeAdAppInfo; -import com.bytedance.msdk.api.nativeAd.TTViewBinder; -import com.bytedance.msdk.api.v2.GMAdConstant; -import com.bytedance.msdk.api.v2.GMAdDislike; -import com.bytedance.msdk.api.v2.GMAdSize; -import com.bytedance.msdk.api.v2.GMDislikeCallback; -import com.bytedance.msdk.api.v2.ad.banner.GMBannerAd; -import com.bytedance.msdk.api.v2.ad.banner.GMBannerAdListener; -import com.bytedance.msdk.api.v2.ad.banner.GMBannerAdLoadCallback; -import com.bytedance.msdk.api.v2.ad.banner.GMNativeAdInfo; -import com.bytedance.msdk.api.v2.ad.banner.GMNativeToBannerListener; -import com.bytedance.msdk.api.v2.ad.nativeAd.GMViewBinder; -import com.bytedance.msdk.api.v2.slot.GMAdSlotBanner; +import com.bytedance.sdk.openadsdk.AdSlot; +import com.bytedance.sdk.openadsdk.TTAdDislike; +import com.bytedance.sdk.openadsdk.TTAdNative; +import com.bytedance.sdk.openadsdk.TTNativeExpressAd; import com.zero.flutter_gromore_ads.PluginDelegate; -import com.zero.flutter_gromore_ads.R; import com.zero.flutter_gromore_ads.event.AdEventAction; +import com.zero.flutter_gromore_ads.utils.UIUtils; -import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.Set; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.platform.PlatformView; @@ -48,13 +26,13 @@ /** * Banner 广告 View */ -class AdBannerView extends BaseAdPage implements PlatformView, GMBannerAdListener, GMBannerAdLoadCallback { +class AdBannerView extends BaseAdPage implements PlatformView, TTAdNative.NativeExpressAdListener, TTNativeExpressAd.ExpressAdInteractionListener, TTAdDislike.DislikeInteractionCallback { private final String TAG = AdBannerView.class.getSimpleName(); @NonNull private final FrameLayout frameLayout; private final PluginDelegate pluginDelegate; private final int id; - private GMBannerAd bad; + private TTNativeExpressAd bad; AdBannerView(@NonNull Context context, int id, @Nullable Map creationParams, PluginDelegate pluginDelegate) { @@ -81,17 +59,12 @@ public void loadAd(@NonNull MethodCall call) { // 获取请求模板广告素材的尺寸 int expressViewWidth = call.argument("width"); int expressViewHeight = call.argument("height"); - bad = new GMBannerAd(activity, posId); - // 设置广告事件监听 - bad.setAdBannerListener(this); - // 设置广告配置 - GMAdSlotBanner slotBanner = new GMAdSlotBanner.Builder() - .setBannerSize(GMAdSize.BANNER_CUSTOME) - .setImageAdSize(expressViewWidth, expressViewHeight)// GMAdSize.BANNER_CUSTOME可以调用setImageAdSize设置大小 - .setMuted(true) // 控制视频是否静音 + this.adslot = new AdSlot.Builder() + .setCodeId(posId) + .setImageAcceptedSize(UIUtils.dp2px(activity,expressViewWidth), UIUtils.dp2px(activity,expressViewHeight)) .build(); // 加载广告 - bad.loadAd(slotBanner, this); + adNativeLoader.loadBannerExpressAd(adslot, this); } /** @@ -100,68 +73,79 @@ public void loadAd(@NonNull MethodCall call) { private void disposeAd() { frameLayout.removeAllViews(); if (bad != null) { - bad.setAdBannerListener(null); + bad.setExpressInteractionListener(null); bad.destroy(); } } @Override - public void onAdClicked() { - Log.i(TAG, "onAdClicked"); - // 添加广告事件 - sendEvent(AdEventAction.onAdClicked); - } - - @Override - public void onAdClosed() { - Log.i(TAG, "onAdClosed"); - // 添加广告事件 - sendEvent(AdEventAction.onAdClosed); + public void onError(int i, String s) { + Log.e(TAG, "onError code:" + i + " msg:" + s); + sendErrorEvent(i, s); disposeAd(); } @Override - public void onAdLeftApplication() { - + public void onNativeExpressAdLoad(List list) { + if (list == null || list.size() == 0) { + Log.e(TAG, "onNativeExpressAdLoad list is null or size is 0"); + return; + } + bad = list.get(0); + bad.setExpressInteractionListener(this); + bad.setDislikeCallback(activity, this); + bad.render(); } @Override - public void onAdOpened() { - + public void onAdClicked(View view, int i) { + Log.i(TAG, "onAdClicked"); + // 添加广告事件 + sendEvent(AdEventAction.onAdClicked); } @Override - public void onAdShow() { + public void onAdShow(View view, int i) { Log.i(TAG, "onAdShow"); // 添加广告事件 sendEvent(AdEventAction.onAdExposure); } @Override - public void onAdShowFail(@NonNull AdError adError) { - Log.e(TAG, "onAdShowFail code:" + adError.code + " msg:" + adError.message); - sendErrorEvent(adError.code, adError.message); + public void onRenderFail(View view, String s, int i) { + Log.e(TAG, "onRenderFail code:" + i + " msg:" + s); + sendErrorEvent(i, s); disposeAd(); } @Override - public void onAdFailedToLoad(@NonNull AdError adError) { - Log.e(TAG, "onAdFailedToLoad code:" + adError.code + " msg:" + adError.message); - sendErrorEvent(adError.code, adError.message); - disposeAd(); - } - - @Override - public void onAdLoaded() { - Log.i(TAG, "onAdLoaded"); - if (bad != null && bad.isReady()) { + public void onRenderSuccess(View view, float v, float v1) { + Log.i(TAG, "onRenderSuccess"); + if (bad != null) { frameLayout.removeAllViews(); - frameLayout.addView(bad.getBannerView()); + frameLayout.addView(bad.getExpressAdView()); // 添加广告事件 sendEvent(AdEventAction.onAdPresent); + }else{ + disposeAd(); } + } + + @Override + public void onShow() { + Log.i(TAG, "Dislike onShow"); + } + + @Override + public void onSelected(int i, String s, boolean b) { + Log.i(TAG, "Dislike onSelected"); // 添加广告事件 - sendEvent(AdEventAction.onAdLoaded); + disposeAd(); + sendEvent(AdEventAction.onAdClosed); } + @Override + public void onCancel() { + Log.i(TAG, "Dislike onCancel"); + } } \ No newline at end of file diff --git a/android/src/main/java/com/zero/flutter_gromore_ads/page/AdFeedView.java b/android/src/main/java/com/zero/flutter_gromore_ads/page/AdFeedView.java index 01d1c31..abfc425 100644 --- a/android/src/main/java/com/zero/flutter_gromore_ads/page/AdFeedView.java +++ b/android/src/main/java/com/zero/flutter_gromore_ads/page/AdFeedView.java @@ -1,184 +1,184 @@ -package com.zero.flutter_gromore_ads.page; - -import android.content.Context; -import android.util.Log; -import android.view.View; -import android.view.ViewGroup; -import android.widget.FrameLayout; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.bytedance.msdk.api.v2.GMDislikeCallback; -import com.bytedance.msdk.api.v2.ad.nativeAd.GMNativeAd; -import com.bytedance.msdk.api.v2.ad.nativeAd.GMNativeExpressAdListener; -import com.zero.flutter_gromore_ads.PluginDelegate; -import com.zero.flutter_gromore_ads.event.AdEventAction; -import com.zero.flutter_gromore_ads.load.FeedAdManager; -import com.zero.flutter_gromore_ads.utils.UIUtils; - -import java.util.HashMap; -import java.util.Map; - -import io.flutter.plugin.common.MethodCall; -import io.flutter.plugin.common.MethodChannel; -import io.flutter.plugin.platform.PlatformView; - -/** - * Feed 信息流广告 View - */ -class AdFeedView extends BaseAdPage implements PlatformView, GMNativeExpressAdListener { - private final String TAG = AdFeedView.class.getSimpleName(); - @NonNull - private final FrameLayout frameLayout; - private final PluginDelegate pluginDelegate; - private int id; - private GMNativeAd fad; - private View adView; - private MethodChannel methodChannel; - - - AdFeedView(@NonNull Context context, int id, @Nullable Map creationParams, PluginDelegate pluginDelegate) { - this.id = id; - this.pluginDelegate = pluginDelegate; - methodChannel = new MethodChannel(this.pluginDelegate.bind.getBinaryMessenger(), PluginDelegate.KEY_FEED_VIEW + "/" + id); - frameLayout = new FrameLayout(context); - FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); - frameLayout.setLayoutParams(params); - MethodCall call = new MethodCall("AdFeedView", creationParams); - showAd(this.pluginDelegate.activity, call); - } - - @NonNull - @Override - public View getView() { - return frameLayout; - } - - @Override - public void dispose() { - removeAd(); - } - - @Override - public void loadAd(@NonNull MethodCall call) { - fad = FeedAdManager.getInstance().getAd(Integer.parseInt(this.posId)); - if (fad != null) { - fad.setNativeAdListener(this); - bindDislikeAction(fad); - adView = fad.getExpressView(); - if (adView != null && adView.getParent() != null) { - ((ViewGroup) adView.getParent()).removeAllViews(); - } - FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, UIUtils.getScreenHeightInPx(activity)); - frameLayout.setLayoutParams(params); - frameLayout.addView(adView); - fad.render(); - } - } - - /** - * 移除广告 - */ - private void removeAd() { - frameLayout.removeAllViews(); - } - - /** - * 销毁广告 - */ - private void disposeAd() { - removeAd(); - FeedAdManager.getInstance().removeAd(Integer.parseInt(this.posId)); - if (fad != null) { - fad.destroy(); - } - // 更新宽高 - setFlutterViewSize(0f, 0f); - } - - public void onAdClosed() { - Log.i(TAG, "onAdDismiss"); - // 添加广告事件 - sendEvent(AdEventAction.onAdClosed); - disposeAd(); - } - - @Override - public void onAdClick() { - Log.i(TAG, "onAdClicked"); - // 添加广告事件 - sendEvent(AdEventAction.onAdClicked); - } - - @Override - public void onAdShow() { - Log.i(TAG, "onAdShow"); - // 添加广告事件 - sendEvent(AdEventAction.onAdExposure); - } - - @Override - public void onRenderFail(View view, String s, int i) { - Log.e(TAG, "onRenderFail code:" + i + " msg:" + s); - // 添加广告错误事件 - sendErrorEvent(i, s); - // 更新宽高 - setFlutterViewSize(0f, 0f); - } - - @Override - public void onRenderSuccess(float width, float height) { - Log.i(TAG, "onRenderSuccess v:" + width + " v1:" + height); - // 添加广告事件 - sendEvent(AdEventAction.onAdPresent); - if (width > 0 && height > 0) { - setFlutterViewSize(width, height); - } - } - - /** - * 设置 FlutterAds 视图宽高 - * - * @param width 宽度 - * @param height 高度 - */ - private void setFlutterViewSize(float width, float height) { - Map sizeMap = new HashMap<>(); - sizeMap.put("width", (double) width); - sizeMap.put("height", (double) height); - if (methodChannel != null) { - methodChannel.invokeMethod("setSize", sizeMap); - } - } - - /** - * 接入dislike 逻辑,有助于提示广告精准投放度 - * 和后续广告关闭逻辑处理 - * - * @param ad 广告 View - */ - private void bindDislikeAction(GMNativeAd ad) { - ad.setDislikeCallback(activity, new GMDislikeCallback() { - @Override - public void onSelected(int position, String value) { - onAdClosed(); - } - - @Override - public void onCancel() { - - } - - @Override - public void onRefuse() { - - } - - @Override - public void onShow() { - - } - }); - } -} \ No newline at end of file +//package com.zero.flutter_gromore_ads.page; +// +//import android.content.Context; +//import android.util.Log; +//import android.view.View; +//import android.view.ViewGroup; +//import android.widget.FrameLayout; +// +//import androidx.annotation.NonNull; +//import androidx.annotation.Nullable; +// +//import com.bytedance.msdk.api.v2.GMDislikeCallback; +//import com.bytedance.msdk.api.v2.ad.nativeAd.GMNativeAd; +//import com.bytedance.msdk.api.v2.ad.nativeAd.GMNativeExpressAdListener; +//import com.zero.flutter_gromore_ads.PluginDelegate; +//import com.zero.flutter_gromore_ads.event.AdEventAction; +//import com.zero.flutter_gromore_ads.load.FeedAdManager; +//import com.zero.flutter_gromore_ads.utils.UIUtils; +// +//import java.util.HashMap; +//import java.util.Map; +// +//import io.flutter.plugin.common.MethodCall; +//import io.flutter.plugin.common.MethodChannel; +//import io.flutter.plugin.platform.PlatformView; +// +///** +// * Feed 信息流广告 View +// */ +//class AdFeedView extends BaseAdPage implements PlatformView, GMNativeExpressAdListener { +// private final String TAG = AdFeedView.class.getSimpleName(); +// @NonNull +// private final FrameLayout frameLayout; +// private final PluginDelegate pluginDelegate; +// private int id; +// private GMNativeAd fad; +// private View adView; +// private MethodChannel methodChannel; +// +// +// AdFeedView(@NonNull Context context, int id, @Nullable Map creationParams, PluginDelegate pluginDelegate) { +// this.id = id; +// this.pluginDelegate = pluginDelegate; +// methodChannel = new MethodChannel(this.pluginDelegate.bind.getBinaryMessenger(), PluginDelegate.KEY_FEED_VIEW + "/" + id); +// frameLayout = new FrameLayout(context); +// FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); +// frameLayout.setLayoutParams(params); +// MethodCall call = new MethodCall("AdFeedView", creationParams); +// showAd(this.pluginDelegate.activity, call); +// } +// +// @NonNull +// @Override +// public View getView() { +// return frameLayout; +// } +// +// @Override +// public void dispose() { +// removeAd(); +// } +// +// @Override +// public void loadAd(@NonNull MethodCall call) { +// fad = FeedAdManager.getInstance().getAd(Integer.parseInt(this.posId)); +// if (fad != null) { +// fad.setNativeAdListener(this); +// bindDislikeAction(fad); +// adView = fad.getExpressView(); +// if (adView != null && adView.getParent() != null) { +// ((ViewGroup) adView.getParent()).removeAllViews(); +// } +// FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, UIUtils.getScreenHeightInPx(activity)); +// frameLayout.setLayoutParams(params); +// frameLayout.addView(adView); +// fad.render(); +// } +// } +// +// /** +// * 移除广告 +// */ +// private void removeAd() { +// frameLayout.removeAllViews(); +// } +// +// /** +// * 销毁广告 +// */ +// private void disposeAd() { +// removeAd(); +// FeedAdManager.getInstance().removeAd(Integer.parseInt(this.posId)); +// if (fad != null) { +// fad.destroy(); +// } +// // 更新宽高 +// setFlutterViewSize(0f, 0f); +// } +// +// public void onAdClosed() { +// Log.i(TAG, "onAdDismiss"); +// // 添加广告事件 +// sendEvent(AdEventAction.onAdClosed); +// disposeAd(); +// } +// +// @Override +// public void onAdClick() { +// Log.i(TAG, "onAdClicked"); +// // 添加广告事件 +// sendEvent(AdEventAction.onAdClicked); +// } +// +// @Override +// public void onAdShow() { +// Log.i(TAG, "onAdShow"); +// // 添加广告事件 +// sendEvent(AdEventAction.onAdExposure); +// } +// +// @Override +// public void onRenderFail(View view, String s, int i) { +// Log.e(TAG, "onRenderFail code:" + i + " msg:" + s); +// // 添加广告错误事件 +// sendErrorEvent(i, s); +// // 更新宽高 +// setFlutterViewSize(0f, 0f); +// } +// +// @Override +// public void onRenderSuccess(float width, float height) { +// Log.i(TAG, "onRenderSuccess v:" + width + " v1:" + height); +// // 添加广告事件 +// sendEvent(AdEventAction.onAdPresent); +// if (width > 0 && height > 0) { +// setFlutterViewSize(width, height); +// } +// } +// +// /** +// * 设置 FlutterAds 视图宽高 +// * +// * @param width 宽度 +// * @param height 高度 +// */ +// private void setFlutterViewSize(float width, float height) { +// Map sizeMap = new HashMap<>(); +// sizeMap.put("width", (double) width); +// sizeMap.put("height", (double) height); +// if (methodChannel != null) { +// methodChannel.invokeMethod("setSize", sizeMap); +// } +// } +// +// /** +// * 接入dislike 逻辑,有助于提示广告精准投放度 +// * 和后续广告关闭逻辑处理 +// * +// * @param ad 广告 View +// */ +// private void bindDislikeAction(GMNativeAd ad) { +// ad.setDislikeCallback(activity, new GMDislikeCallback() { +// @Override +// public void onSelected(int position, String value) { +// onAdClosed(); +// } +// +// @Override +// public void onCancel() { +// +// } +// +// @Override +// public void onRefuse() { +// +// } +// +// @Override +// public void onShow() { +// +// } +// }); +// } +//} \ No newline at end of file diff --git a/android/src/main/java/com/zero/flutter_gromore_ads/page/AdSplashActivity.java b/android/src/main/java/com/zero/flutter_gromore_ads/page/AdSplashActivity.java index e88ef00..0fe4147 100644 --- a/android/src/main/java/com/zero/flutter_gromore_ads/page/AdSplashActivity.java +++ b/android/src/main/java/com/zero/flutter_gromore_ads/page/AdSplashActivity.java @@ -11,12 +11,11 @@ import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.AppCompatImageView; -import com.bytedance.msdk.api.AdError; -import com.bytedance.msdk.api.v2.GMAdConstant; -import com.bytedance.msdk.api.v2.ad.splash.GMSplashAd; -import com.bytedance.msdk.api.v2.ad.splash.GMSplashAdListener; -import com.bytedance.msdk.api.v2.ad.splash.GMSplashAdLoadCallback; -import com.bytedance.msdk.api.v2.slot.GMAdSlotSplash; +import com.bytedance.sdk.openadsdk.AdSlot; +import com.bytedance.sdk.openadsdk.CSJAdError; +import com.bytedance.sdk.openadsdk.CSJSplashAd; +import com.bytedance.sdk.openadsdk.TTAdNative; +import com.bytedance.sdk.openadsdk.TTAdSdk; import com.zero.flutter_gromore_ads.PluginDelegate; import com.zero.flutter_gromore_ads.R; import com.zero.flutter_gromore_ads.event.AdErrorEvent; @@ -29,7 +28,7 @@ /** * 开屏广告 */ -public class AdSplashActivity extends AppCompatActivity implements GMSplashAdListener, GMSplashAdLoadCallback { +public class AdSplashActivity extends AppCompatActivity implements TTAdNative.CSJSplashAdListener,CSJSplashAd.SplashAdListener { private final String TAG = AdSplashActivity.class.getSimpleName(); // 广告容器 private FrameLayout ad_container; @@ -38,7 +37,7 @@ public class AdSplashActivity extends AppCompatActivity implements GMSplashAdLis // 广告位 id private String posId; // 开屏广告 - private GMSplashAd gmSplashAd; + private CSJSplashAd gmSplashAd; @Override @@ -63,6 +62,7 @@ private void initView() { * 初始化数据 */ private void initData() { + // 获取参数 posId = getIntent().getStringExtra(PluginDelegate.KEY_POSID); String logo = getIntent().getStringExtra(PluginDelegate.KEY_LOGO); @@ -91,14 +91,12 @@ private void initData() { height = height - ad_logo.getLayoutParams().height; } // 创建开屏广告 - gmSplashAd = new GMSplashAd(this, posId); - gmSplashAd.setAdSplashListener(this); - GMAdSlotSplash adSlot = new GMAdSlotSplash.Builder() - .setImageAdSize(width, height) // 既适用于原生类型,也适用于模版类型。 - .setTimeOut(absTimeout)//设置超时 + AdSlot adSlot = new AdSlot.Builder() + .setCodeId(posId) + .setImageAcceptedSize(width, height) // 单位是px .build(); // 加载广告 - gmSplashAd.loadAd(adSlot, this); + TTAdSdk.getAdManager().createAdNative(this).loadSplashAd(adSlot,this,absTimeout); } /** @@ -109,8 +107,9 @@ private void finishPage() { // 设置退出动画 overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out); // 销毁 - if (gmSplashAd != null) { - gmSplashAd.destroy(); + if (gmSplashAd != null&&gmSplashAd.getMediationManager()!=null) { + gmSplashAd.setSplashAdListener(null); + gmSplashAd.getMediationManager().destroy(); gmSplashAd = null; } } @@ -137,62 +136,62 @@ private int getMipmapId(String resName) { } @Override - public void onAdClicked() { - Log.d(TAG, "onAdClicked"); - AdEventHandler.getInstance().sendEvent(new AdEvent(this.posId, AdEventAction.onAdClicked)); - finishPage(); + public void onSplashLoadSuccess() { + Log.d(TAG, "onSplashLoadSuccess"); + AdEventHandler.getInstance().sendEvent(new AdEvent(this.posId, AdEventAction.onAdLoaded)); } @Override - public void onAdShow() { - Log.d(TAG, "onAdShow"); - AdEventHandler.getInstance().sendEvent(new AdEvent(this.posId, AdEventAction.onAdExposure)); + public void onSplashLoadFail(CSJAdError adError) { + Log.e(TAG, "onSplashLoadFail code:" + adError.getCode() + " msg:" + adError.getMsg()); + AdEventHandler.getInstance().sendEvent(new AdErrorEvent(this.posId, adError.getCode(), adError.getMsg())); + finishPage(); } @Override - public void onAdShowFail(@NonNull AdError adError) { - Log.e(TAG, "onAdShowFail code:" + adError.code + " msg:" + adError.message); - AdEventHandler.getInstance().sendEvent(new AdErrorEvent(this.posId, adError.code, adError.message)); + public void onSplashRenderSuccess(CSJSplashAd csjSplashAd) { + //获取SplashView + if (this.isFinishing()) { + finishPage(); + return; + } + gmSplashAd=csjSplashAd; + csjSplashAd.setSplashAdListener(this); + View splashView = csjSplashAd.getSplashView(); + if (splashView == null) { + finishPage(); + return; + } + UIUtils.removeFromParent(splashView); + ad_container.removeAllViews(); + ad_container.addView(splashView); + // 加载事件 + AdEventHandler.getInstance().sendEvent(new AdEvent(this.posId, AdEventAction.onAdPresent)); } @Override - public void onAdSkip() { - Log.d(TAG, "onAdSkip"); - AdEventHandler.getInstance().sendEvent(new AdEvent(this.posId, AdEventAction.onAdSkip)); - finishPage(); + public void onSplashRenderFail(CSJSplashAd csjSplashAd, CSJAdError adError) { + Log.e(TAG, "onSplashRenderFail code:" + adError.getCode() + " msg:" + adError.getMsg()); + AdEventHandler.getInstance().sendEvent(new AdErrorEvent(this.posId, adError.getCode(), adError.getMsg())); } @Override - public void onAdDismiss() { - Log.d(TAG, "onAdDismiss"); - AdEventHandler.getInstance().sendEvent(new AdEvent(this.posId, AdEventAction.onAdClosed)); - finishPage(); + public void onSplashAdShow(CSJSplashAd csjSplashAd) { + Log.d(TAG, "onAdShow"); + AdEventHandler.getInstance().sendEvent(new AdEvent(this.posId, AdEventAction.onAdExposure)); } @Override - public void onSplashAdLoadFail(@NonNull AdError adError) { - Log.e(TAG, "onSplashAdLoadFail code:" + adError.code + " msg:" + adError.message); - AdEventHandler.getInstance().sendEvent(new AdErrorEvent(this.posId, adError.code, adError.message)); + public void onSplashAdClick(CSJSplashAd csjSplashAd) { + Log.d(TAG, "onAdClicked"); + AdEventHandler.getInstance().sendEvent(new AdEvent(this.posId, AdEventAction.onAdClicked)); finishPage(); } @Override - public void onSplashAdLoadSuccess() { - Log.d(TAG, "onSplashAdLoad"); - //获取SplashView - if (!this.isFinishing()) { - ad_container.removeAllViews(); - gmSplashAd.showAd(ad_container); - } else { - finishPage(); - } - // 加载事件 - AdEventHandler.getInstance().sendEvent(new AdEvent(this.posId, AdEventAction.onAdLoaded)); - } - - @Override - public void onAdLoadTimeout() { - Log.e(TAG, "onAdLoadTimeout"); + public void onSplashAdClose(CSJSplashAd csjSplashAd, int i) { + Log.d(TAG, "onSplashAdClose"); + AdEventHandler.getInstance().sendEvent(new AdEvent(this.posId, AdEventAction.onAdClosed)); finishPage(); } } \ No newline at end of file diff --git a/android/src/main/java/com/zero/flutter_gromore_ads/page/BaseAdPage.java b/android/src/main/java/com/zero/flutter_gromore_ads/page/BaseAdPage.java index b6470cb..9ca2ef0 100644 --- a/android/src/main/java/com/zero/flutter_gromore_ads/page/BaseAdPage.java +++ b/android/src/main/java/com/zero/flutter_gromore_ads/page/BaseAdPage.java @@ -4,8 +4,9 @@ import android.app.Activity; -import com.bytedance.msdk.api.v2.ad.GMBaseAd; -import com.bytedance.msdk.api.v2.slot.GMAdSlotBase; +import com.bytedance.sdk.openadsdk.AdSlot; +import com.bytedance.sdk.openadsdk.TTAdNative; +import com.bytedance.sdk.openadsdk.TTAdSdk; import com.zero.flutter_gromore_ads.event.AdErrorEvent; import com.zero.flutter_gromore_ads.event.AdEvent; import com.zero.flutter_gromore_ads.event.AdEventHandler; @@ -20,6 +21,10 @@ public abstract class BaseAdPage { protected Activity activity; // 广告位 id protected String posId; + // 广告配置 + protected AdSlot adslot; + // 广告加载器 + protected TTAdNative adNativeLoader; /** * 显示广告 @@ -30,6 +35,7 @@ public abstract class BaseAdPage { public void showAd(Activity activity, MethodCall call) { this.activity = activity; this.posId = call.argument(KEY_POSID); + this.adNativeLoader= TTAdSdk.getAdManager().createAdNative(activity); loadAd(call); } diff --git a/android/src/main/java/com/zero/flutter_gromore_ads/page/FullVideoPage.java b/android/src/main/java/com/zero/flutter_gromore_ads/page/FullVideoPage.java deleted file mode 100644 index fe50549..0000000 --- a/android/src/main/java/com/zero/flutter_gromore_ads/page/FullVideoPage.java +++ /dev/null @@ -1,119 +0,0 @@ -package com.zero.flutter_gromore_ads.page; - -import android.util.Log; - -import androidx.annotation.NonNull; - -import com.bytedance.msdk.api.AdError; -import com.bytedance.msdk.api.reward.RewardItem; -import com.bytedance.msdk.api.v2.GMAdConstant; -import com.bytedance.msdk.api.v2.ad.fullvideo.GMFullVideoAd; -import com.bytedance.msdk.api.v2.ad.fullvideo.GMFullVideoAdListener; -import com.bytedance.msdk.api.v2.ad.fullvideo.GMFullVideoAdLoadCallback; -import com.bytedance.msdk.api.v2.slot.GMAdOptionUtil; -import com.bytedance.msdk.api.v2.slot.GMAdSlotFullVideo; -import com.zero.flutter_gromore_ads.event.AdEventAction; - -import io.flutter.plugin.common.MethodCall; - -/** - * 全屏视频广告 - */ -public class FullVideoPage extends BaseAdPage implements GMFullVideoAdLoadCallback, GMFullVideoAdListener { - private final String TAG = FullVideoPage.class.getSimpleName(); - private GMFullVideoAd ad; - - @Override - public void loadAd(@NonNull MethodCall call) { - int orientation = call.argument("orientation"); - - ad = new GMFullVideoAd(activity, this.posId); - GMAdSlotFullVideo adSlot = new GMAdSlotFullVideo.Builder() - .setGMAdSlotGDTOption(GMAdOptionUtil.getGMAdSlotGDTOption().build()) - .setGMAdSlotBaiduOption(GMAdOptionUtil.getGMAdSlotBaiduOption().build()) - .setUserID("user123")//用户id,必传参数 - .setOrientation(orientation)//必填参数,期望视频的播放方向:TTAdConstant.HORIZONTAL 或 TTAdConstant.VERTICAL; - .build(); - ad.loadAd(adSlot, this); - } - - @Override - public void onFullVideoLoadFail(@NonNull AdError adError) { - Log.e(TAG, "onFullVideoLoadFail code:" + adError.code + " msg:" + adError.message); - sendErrorEvent(adError.code, adError.message); - } - - @Override - public void onFullVideoAdLoad() { - Log.i(TAG, "onFullVideoAdLoad"); - // 添加广告事件 - sendEvent(AdEventAction.onAdLoaded); - // 显示广告 - if (ad != null && ad.isReady()) { - ad.setFullVideoAdListener(this); - ad.showFullAd(activity); - } - } - - @Override - public void onFullVideoAdShow() { - Log.i(TAG, "onFullVideoAdShow"); - // 添加广告事件 - sendEvent(AdEventAction.onAdExposure); - } - - @Override - public void onFullVideoAdShowFail(@NonNull AdError adError) { - Log.e(TAG, "onFullVideoAdShowFail code:" + adError.code + " msg:" + adError.message); - sendErrorEvent(adError.code, adError.message); - } - - @Override - public void onFullVideoAdClick() { - Log.i(TAG, "onFullVideoAdClick"); - // 添加广告事件 - sendEvent(AdEventAction.onAdClicked); - } - - @Override - public void onFullVideoAdClosed() { - Log.i(TAG, "onFullVideoAdClosed"); - // 添加广告事件 - sendEvent(AdEventAction.onAdClosed); - if (ad != null) { - ad.destroy(); - ad = null; - } - } - - @Override - public void onVideoComplete() { - Log.i(TAG, "onVideoComplete"); - // 添加广告事件 - sendEvent(AdEventAction.onAdComplete); - } - - @Override - public void onVideoError() { - Log.i(TAG, "onVideoError"); - // 添加广告事件 - sendErrorEvent(-200, "onVideoError"); - } - - @Override - public void onSkippedVideo() { - Log.i(TAG, "onSkippedVideo"); - // 添加广告事件 - sendEvent(AdEventAction.onAdSkip); - } - - @Override - public void onRewardVerify(@NonNull RewardItem rewardItem) { - - } - - @Override - public void onFullVideoCached() { - Log.i(TAG, "onFullVideoCached"); - } -} \ No newline at end of file diff --git a/android/src/main/java/com/zero/flutter_gromore_ads/page/InterstitialFullPage.java b/android/src/main/java/com/zero/flutter_gromore_ads/page/InterstitialFullPage.java deleted file mode 100644 index dac8d80..0000000 --- a/android/src/main/java/com/zero/flutter_gromore_ads/page/InterstitialFullPage.java +++ /dev/null @@ -1,130 +0,0 @@ -package com.zero.flutter_gromore_ads.page; - -import android.util.Log; - -import androidx.annotation.NonNull; - -import com.bytedance.msdk.api.AdError; -import com.bytedance.msdk.api.reward.RewardItem; -import com.bytedance.msdk.api.v2.GMAdConstant; -import com.bytedance.msdk.api.v2.ad.interstitialFull.GMInterstitialFullAd; -import com.bytedance.msdk.api.v2.ad.interstitialFull.GMInterstitialFullAdListener; -import com.bytedance.msdk.api.v2.ad.interstitialFull.GMInterstitialFullAdLoadCallback; -import com.bytedance.msdk.api.v2.slot.GMAdOptionUtil; -import com.bytedance.msdk.api.v2.slot.GMAdSlotInterstitialFull; -import com.zero.flutter_gromore_ads.event.AdEventAction; - -import io.flutter.plugin.common.MethodCall; - -/** - * 全屏插屏广告 - */ -public class InterstitialFullPage extends BaseAdPage implements GMInterstitialFullAdLoadCallback, GMInterstitialFullAdListener { - private final String TAG = InterstitialFullPage.class.getSimpleName(); - private GMInterstitialFullAd ad; - - @Override - public void loadAd(@NonNull MethodCall call) { - boolean muted = call.argument("muted"); - ad = new GMInterstitialFullAd(activity, this.posId); - GMAdSlotInterstitialFull adSlot = new GMAdSlotInterstitialFull.Builder() - .setGMAdSlotBaiduOption(GMAdOptionUtil.getGMAdSlotBaiduOption().build()) - .setGMAdSlotGDTOption(GMAdOptionUtil.getGMAdSlotGDTOption().build()) - .setMuted(muted) - .setVolume(0.5f) //admob 声音配置,与setMuted配合使用 - .setUserID("user123")//用户id,必传参数 (插全屏类型下_全屏广告使用) - .setOrientation(GMAdConstant.VERTICAL)//必填参数,期望视频的播放方向:TTAdConstant.HORIZONTAL 或 TTAdConstant.VERTICAL; (插全屏类型下_全屏广告使用) - .build(); - ad.loadAd(adSlot, this); - } - - @Override - public void onInterstitialFullLoadFail(@NonNull AdError adError) { - Log.e(TAG, "onInterstitialLoadFail code:" + adError.code + " msg:" + adError.message); - sendErrorEvent(adError.code, adError.message); - } - - @Override - public void onInterstitialFullAdLoad() { - Log.i(TAG, "onInterstitialLoad"); - // 添加广告事件 - sendEvent(AdEventAction.onAdLoaded); - // 显示广告 - if (ad != null && ad.isReady()) { - ad.setAdInterstitialFullListener(this); - ad.showAd(activity); - } - } - - @Override - public void onInterstitialFullShow() { - Log.i(TAG, "onInterstitialFullShow"); - // 添加广告事件 - sendEvent(AdEventAction.onAdExposure); - } - - @Override - public void onInterstitialFullShowFail(@NonNull AdError adError) { - Log.e(TAG, "onInterstitialLoadFail code:" + adError.code + " msg:" + adError.message); - sendErrorEvent(adError.code, adError.message); - } - - @Override - public void onInterstitialFullClick() { - Log.i(TAG, "onInterstitialFullClick"); - // 添加广告事件 - sendEvent(AdEventAction.onAdClicked); - } - - @Override - public void onInterstitialFullClosed() { - Log.i(TAG, "onInterstitialFullClosed"); - // 添加广告事件 - sendEvent(AdEventAction.onAdClosed); - if (ad != null) { - ad.destroy(); - ad = null; - } - } - - @Override - public void onVideoComplete() { - Log.i(TAG, "onVideoComplete"); - // 添加广告事件 - sendEvent(AdEventAction.onAdComplete); - } - - @Override - public void onVideoError() { - Log.i(TAG, "onVideoError"); - // 添加广告事件 - sendErrorEvent(-200, "onVideoError"); - } - - @Override - public void onSkippedVideo() { - Log.i(TAG, "onVideoComplete"); - // 添加广告事件 - sendEvent(AdEventAction.onAdSkip); - } - - @Override - public void onAdOpened() { - Log.i(TAG, "onAdOpened"); - } - - @Override - public void onAdLeftApplication() { - Log.i(TAG, "onAdLeftApplication"); - } - - @Override - public void onRewardVerify(@NonNull RewardItem rewardItem) { - - } - - @Override - public void onInterstitialFullCached() { - Log.i(TAG, "onInterstitialFullCached"); - } -} \ No newline at end of file diff --git a/android/src/main/java/com/zero/flutter_gromore_ads/page/InterstitialPage.java b/android/src/main/java/com/zero/flutter_gromore_ads/page/InterstitialPage.java index fc94da6..1a4f611 100644 --- a/android/src/main/java/com/zero/flutter_gromore_ads/page/InterstitialPage.java +++ b/android/src/main/java/com/zero/flutter_gromore_ads/page/InterstitialPage.java @@ -1,16 +1,13 @@ package com.zero.flutter_gromore_ads.page; import android.util.Log; -import android.view.View; import androidx.annotation.NonNull; -import com.bytedance.msdk.api.AdError; -import com.bytedance.msdk.api.v2.ad.interstitial.GMInterstitialAd; -import com.bytedance.msdk.api.v2.ad.interstitial.GMInterstitialAdListener; -import com.bytedance.msdk.api.v2.ad.interstitial.GMInterstitialAdLoadCallback; -import com.bytedance.msdk.api.v2.slot.GMAdOptionUtil; -import com.bytedance.msdk.api.v2.slot.GMAdSlotInterstitial; +import com.bytedance.sdk.openadsdk.AdSlot; +import com.bytedance.sdk.openadsdk.TTAdConstant; +import com.bytedance.sdk.openadsdk.TTAdNative; +import com.bytedance.sdk.openadsdk.TTFullScreenVideoAd; import com.zero.flutter_gromore_ads.event.AdEventAction; import io.flutter.plugin.common.MethodCall; @@ -18,79 +15,80 @@ /** * 插屏广告 */ -public class InterstitialPage extends BaseAdPage implements GMInterstitialAdLoadCallback, GMInterstitialAdListener { +public class InterstitialPage extends BaseAdPage implements TTAdNative.FullScreenVideoAdListener, TTFullScreenVideoAd.FullScreenVideoAdInteractionListener { private final String TAG = InterstitialPage.class.getSimpleName(); - private GMInterstitialAd ad; + private TTFullScreenVideoAd ad; @Override public void loadAd(@NonNull MethodCall call) { - int width = call.argument("width"); - int height = call.argument("height"); - ad = new GMInterstitialAd(activity, this.posId); - GMAdSlotInterstitial adSlot = new GMAdSlotInterstitial.Builder() - .setGMAdSlotBaiduOption(GMAdOptionUtil.getGMAdSlotBaiduOption().build()) - .setGMAdSlotGDTOption(GMAdOptionUtil.getGMAdSlotGDTOption().build()) - .setImageAdSize(width, height) + adslot = new AdSlot.Builder() + .setCodeId(this.posId) .build(); - ad.loadAd(adSlot, this); + adNativeLoader.loadFullScreenVideoAd(adslot, this); } @Override - public void onInterstitialLoadFail(@NonNull AdError adError) { - Log.e(TAG, "onInterstitialLoadFail code:" + adError.code + " msg:" + adError.message); - sendErrorEvent(adError.code, adError.message); + public void onError(int i, String s) { + Log.e(TAG, "onInterstitialLoadFail code:" + i + " msg:" + s); + sendErrorEvent(i, s); } @Override - public void onInterstitialLoad() { - Log.i(TAG, "onInterstitialLoad"); + public void onFullScreenVideoAdLoad(TTFullScreenVideoAd ttFullScreenVideoAd) { + Log.i(TAG, "onFullScreenVideoAdLoad"); + ad=ttFullScreenVideoAd; + ad.setFullScreenVideoAdInteractionListener(this); + ad.showFullScreenVideoAd(activity); // 添加广告事件 sendEvent(AdEventAction.onAdLoaded); - // 显示广告 - if (ad != null && ad.isReady()) { - ad.setAdInterstitialListener(this); - ad.showAd(activity); - } } @Override - public void onInterstitialShow() { - Log.i(TAG, "onInterstitialShow"); - // 添加广告事件 - sendEvent(AdEventAction.onAdExposure); + public void onFullScreenVideoCached() { + + } + + @Override + public void onFullScreenVideoCached(TTFullScreenVideoAd ttFullScreenVideoAd) { + } @Override - public void onInterstitialShowFail(@NonNull AdError adError) { - Log.e(TAG, "onInterstitialLoadFail code:" + adError.code + " msg:" + adError.message); - sendErrorEvent(adError.code, adError.message); + public void onAdShow() { + Log.i(TAG, "onAdShow"); + // 添加广告事件 + sendEvent(AdEventAction.onAdExposure); } @Override - public void onInterstitialAdClick() { - Log.i(TAG, "onInterstitialAdClick"); + public void onAdVideoBarClick() { + Log.i(TAG, "onAdVideoBarClick"); // 添加广告事件 sendEvent(AdEventAction.onAdClicked); } @Override - public void onInterstitialClosed() { - Log.i(TAG, "onInterstitialClosed"); + public void onAdClose() { + Log.i(TAG, "onAdClose"); + if (ad != null && ad.getMediationManager() != null) { + ad.setFullScreenVideoAdInteractionListener(null); + ad.getMediationManager().destroy(); + } // 添加广告事件 sendEvent(AdEventAction.onAdClosed); - if (ad != null) { - ad.destroy(); - ad = null; - } } @Override - public void onAdOpened() { - Log.i(TAG, "onAdOpened"); + public void onVideoComplete() { + Log.i(TAG, "onVideoComplete"); + // 添加广告事件 + sendEvent(AdEventAction.onAdComplete); } @Override - public void onAdLeftApplication() { - Log.i(TAG, "onAdLeftApplication"); + public void onSkippedVideo() { + Log.i(TAG, "onSkippedVideo"); + // 添加广告事件 + sendEvent(AdEventAction.onAdSkip); } } \ No newline at end of file diff --git a/android/src/main/java/com/zero/flutter_gromore_ads/page/NativeViewFactory.java b/android/src/main/java/com/zero/flutter_gromore_ads/page/NativeViewFactory.java index 96e82e5..daf1394 100644 --- a/android/src/main/java/com/zero/flutter_gromore_ads/page/NativeViewFactory.java +++ b/android/src/main/java/com/zero/flutter_gromore_ads/page/NativeViewFactory.java @@ -33,9 +33,10 @@ public PlatformView create(@NonNull Context context, int id, @Nullable Object ar final Map creationParams = (Map) args; if (this.viewName.equals(PluginDelegate.KEY_BANNER_VIEW)) { return new AdBannerView(context, id, creationParams, pluginDelegate); - }else if (this.viewName.equals(PluginDelegate.KEY_FEED_VIEW)) { - return new AdFeedView(context, id, creationParams, pluginDelegate); } +// else if (this.viewName.equals(PluginDelegate.KEY_FEED_VIEW)) { +// return new AdFeedView(context, id, creationParams, pluginDelegate); +// } return null; } } \ No newline at end of file diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 0195179..871de98 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -34,7 +34,7 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.zero.flutter_gromore_ads_example" + applicationId "com.flutterads.app" minSdkVersion 19 targetSdkVersion 30 versionCode flutterVersionCode.toInteger() @@ -58,7 +58,7 @@ flutter { dependencies { implementation 'androidx.multidex:multidex:2.0.1' //GroMore_sdk adapter - implementation "com.pangle.cn:mediation-gdt-adapter:4.530.1400.3" //gdt adapter - implementation 'com.qq.e.union:union:4.530.1400'// 广点通广告 SDK + implementation "com.pangle.cn:mediation-gdt-adapter:4.540.1410.1" //gdt adapter + implementation 'com.qq.e.union:union:4.540.1410'// 广点通广告 SDK // 其他厂商参考 https://www.csjplatform.com/union/media/union/download/detail?id=142&docId=27562&osType=android } diff --git a/example/android/app/src/main/assets/android_config_5216573.json b/example/android/app/src/main/assets/android_config_5216573.json index edf4be5..8a0ba63 100644 --- a/example/android/app/src/main/assets/android_config_5216573.json +++ b/example/android/app/src/main/assets/android_config_5216573.json @@ -1 +1 @@ -{"cypher":2,"message":"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"} \ No newline at end of file +{"cypher":2,"message":"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"} \ No newline at end of file diff --git a/example/lib/home_page.dart b/example/lib/home_page.dart index 4561ce2..6a23222 100644 --- a/example/lib/home_page.dart +++ b/example/lib/home_page.dart @@ -103,11 +103,11 @@ class _HomePageState extends State { height: 75, ), const SizedBox(height: 20), - AdBannerWidget( - posId: AdsConfig.bannerId, - width: 300, - height: 75, - ), + // AdBannerWidget( + // posId: AdsConfig.bannerId, + // width: 300, + // height: 75, + // ), ], ), ), From 4b6d4e8454ab43eae0ec1a817f8806666c6cb372 Mon Sep 17 00:00:00 2001 From: Zero <1300326388@qq.com> Date: Sat, 19 Aug 2023 21:58:01 +0800 Subject: [PATCH 06/14] =?UTF-8?q?1=E3=80=81=E5=A2=9E=E5=8A=A0=E4=B8=AA?= =?UTF-8?q?=E6=80=A7=E5=8C=96=E9=9A=90=E7=A7=81=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../flutter_gromore_ads/PluginDelegate.java | 68 ++++++++++++++++++- 1 file changed, 66 insertions(+), 2 deletions(-) diff --git a/android/src/main/java/com/zero/flutter_gromore_ads/PluginDelegate.java b/android/src/main/java/com/zero/flutter_gromore_ads/PluginDelegate.java index 37dc07f..e854f93 100644 --- a/android/src/main/java/com/zero/flutter_gromore_ads/PluginDelegate.java +++ b/android/src/main/java/com/zero/flutter_gromore_ads/PluginDelegate.java @@ -12,7 +12,9 @@ //import com.zero.flutter_gromore_ads.load.FeedAdManager; import com.bytedance.sdk.openadsdk.TTAdConfig; import com.bytedance.sdk.openadsdk.TTAdSdk; +import com.bytedance.sdk.openadsdk.TTCustomController; import com.bytedance.sdk.openadsdk.mediation.init.MediationConfig; +import com.bytedance.sdk.openadsdk.mediation.init.MediationPrivacyConfig; import com.zero.flutter_gromore_ads.page.AdSplashActivity; //import com.zero.flutter_gromore_ads.page.FullVideoPage; //import com.zero.flutter_gromore_ads.page.InterstitialFullPage; @@ -180,6 +182,7 @@ public void requestPermissionIfNecessary(MethodCall call, MethodChannel.Result r public void initAd(MethodCall call, final MethodChannel.Result result) { String appId = call.argument("appId"); String config = call.argument("config"); + int limitPersonalAds=call.argument("limitPersonalAds"); // 构建基础配置 TTAdConfig.Builder configBuilder = new TTAdConfig.Builder() @@ -200,11 +203,15 @@ public void initAd(MethodCall call, final MethodChannel.Result result) { // 构建配置 TTAdConfig gmPangleOption; if (localConfigJson != null) { - gmPangleOption = configBuilder.setMediationConfig(new MediationConfig.Builder() + gmPangleOption = configBuilder + .customController(getTTCustomController(limitPersonalAds==0)) + .setMediationConfig(new MediationConfig.Builder() .setCustomLocalConfig(localConfigJson) .build()).build(); } else { - gmPangleOption = configBuilder.build(); + gmPangleOption = configBuilder + .customController(getTTCustomController(limitPersonalAds==0)) + .build(); } // 初始化 SDK TTAdSdk.init(activity.getApplicationContext(), gmPangleOption, new TTAdSdk.InitCallback() { @@ -220,6 +227,63 @@ public void fail(int code, String message) { }); } + + private TTCustomController getTTCustomController(boolean limitPersonalAds){ + return new TTCustomController() { + + @Override + public boolean isCanUseWifiState() { + return super.isCanUseWifiState(); + } + + @Override + public String getMacAddress() { + return super.getMacAddress(); + } + + @Override + public boolean isCanUseWriteExternal() { + return super.isCanUseWriteExternal(); + } + + @Override + public String getDevOaid() { + return super.getDevOaid(); + } + + @Override + public boolean isCanUseAndroidId() { + return super.isCanUseAndroidId(); + } + + @Override + public String getAndroidId() { + return super.getAndroidId(); + } + + @Override + public MediationPrivacyConfig getMediationPrivacyConfig() { + return new MediationPrivacyConfig() { + + @Override + public boolean isLimitPersonalAds() { + return limitPersonalAds; + } + + @Override + public boolean isProgrammaticRecommend() { + return limitPersonalAds; + } + }; + } + + @Override + public boolean isCanUsePermissionRecordAudio() { + return super.isCanUsePermissionRecordAudio(); + } + }; + } + /** * 显示开屏广告 * From df26d4d2663394eaaa507e85c39a6bfef330af71 Mon Sep 17 00:00:00 2001 From: Zero <1300326388@qq.com> Date: Sun, 20 Aug 2023 10:42:07 +0800 Subject: [PATCH 07/14] =?UTF-8?q?1=E3=80=81=E5=A4=84=E7=90=86=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=EF=BC=8C=E4=BC=98=E5=8C=96=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/analysis_options.yaml | 2 +- example/lib/feed_page.dart | 19 ++-- example/lib/home_page.dart | 161 ++++++++++++++++++----------- example/lib/pro_page.dart | 23 +++++ lib/view/ad_feed_widget.dart | 2 +- test/flutter_gromore_ads_test.dart | 19 +--- 6 files changed, 133 insertions(+), 93 deletions(-) create mode 100644 example/lib/pro_page.dart diff --git a/example/analysis_options.yaml b/example/analysis_options.yaml index 61b6c4d..cd3b168 100644 --- a/example/analysis_options.yaml +++ b/example/analysis_options.yaml @@ -22,7 +22,7 @@ linter: # `// ignore_for_file: name_of_lint` syntax on the line or in the file # producing the lint. rules: - # avoid_print: false # Uncomment to disable the `avoid_print` rule + avoid_print: false # Uncomment to disable the `avoid_print` rule # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule # Additional information about this file can be found at diff --git a/example/lib/feed_page.dart b/example/lib/feed_page.dart index 04b4447..20b8aed 100644 --- a/example/lib/feed_page.dart +++ b/example/lib/feed_page.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:flutter_gromore_ads/flutter_gromore_ads.dart'; -import 'package:flutter_gromore_ads/view/ad_feed_widget.dart'; import 'package:flutter_gromore_ads_example/ads_config.dart'; import 'package:loadany/loadany.dart'; @@ -34,7 +33,7 @@ class _FeedPageState extends State { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text('信息流(FlutterAds)'), + title: const Text('信息流(FlutterAds)'), ), body: LoadAny( onLoadMore: () async { @@ -83,7 +82,7 @@ class _FeedPageState extends State { setState(() { loadStatus = LoadStatus.loading; }); - await Future.delayed(Duration(seconds: 1)); + await Future.delayed(const Duration(seconds: 1)); for (var i = 0; i < 15; i++) { feedList.add(i); } @@ -125,20 +124,20 @@ class LoadingItemWidget extends StatelessWidget { height: 80, width: double.maxFinite, alignment: Alignment.centerLeft, - padding: EdgeInsets.all(10), - margin: EdgeInsets.symmetric(vertical: 10), + padding: const EdgeInsets.all(10), + margin: const EdgeInsets.symmetric(vertical: 10), color: Colors.white, child: Row( children: [ Container( width: 60, height: 60, - decoration: BoxDecoration( + decoration: const BoxDecoration( shape: BoxShape.circle, color: Color(0xFFEBEBF4), ), ), - SizedBox(width: 20), + const SizedBox(width: 20), Expanded( child: Padding( padding: const EdgeInsets.all(4), @@ -148,15 +147,15 @@ class LoadingItemWidget extends StatelessWidget { Container( width: double.maxFinite, height: 20, - decoration: BoxDecoration( + decoration: const BoxDecoration( color: Color(0xFFEBEBF4), ), ), - Spacer(), + const Spacer(), Container( width: 200, height: 20, - decoration: BoxDecoration( + decoration: const BoxDecoration( color: Color(0xFFE4E4F4), ), ), diff --git a/example/lib/home_page.dart b/example/lib/home_page.dart index 6a23222..5e90a76 100644 --- a/example/lib/home_page.dart +++ b/example/lib/home_page.dart @@ -3,7 +3,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_gromore_ads/flutter_gromore_ads.dart'; import 'ads_config.dart'; -import 'feed_page.dart'; +import 'pro_page.dart'; /// 首页 class HomePage extends StatefulWidget { @@ -36,80 +36,115 @@ class _HomePageState extends State { title: const Text('Flutter GroMore Ads'), ), body: SingleChildScrollView( - child: Center( - child: Column( - children: [ - const SizedBox(height: 10), - Text('Result: $_result'), - const SizedBox(height: 10), - Text('onAdEvent: $_adEvent'), - const SizedBox(height: 20), - ElevatedButton( + padding: const EdgeInsets.all(20), + child: Column( + children: [ + const SizedBox(height: 10), + Text('Result: $_result'), + const SizedBox(height: 10), + Text('onAdEvent: $_adEvent'), + const SizedBox(height: 20), + SizedBox( + width: double.maxFinite, + child: ElevatedButton( child: const Text('初始化'), onPressed: () { init(); }, ), - const SizedBox(height: 20), - ElevatedButton( - child: const Text('请求应用跟踪透明度授权(仅 iOS)'), - onPressed: () { - requestIDFA(); - }, - ), - const SizedBox(height: 20), - ElevatedButton( - child: const Text('动态请求相关权限(仅 Android)'), - onPressed: () { - requestPermissionIfNecessary(); - }, - ), - const SizedBox(height: 20), - ElevatedButton( - child: const Text('展示开屏广告'), - onPressed: () { - showSplashAd(AdsConfig.logo2); - }, - ), - const SizedBox(height: 20), - ElevatedButton( - child: const Text('展示开屏广告(全屏)'), - onPressed: () { - showSplashAd(); - }, - ), - const SizedBox(height: 20), - ElevatedButton( + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: ElevatedButton( + child: const Text('请求应用跟踪授权'), + onPressed: () { + requestIDFA(); + }, + ), + ), + const SizedBox(height: 20), + Flexible( + child: ElevatedButton( + child: const Text('动态请求相关权限'), + onPressed: () { + requestPermissionIfNecessary(); + }, + ), + ), + ], + ), + const SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ElevatedButton( + child: const Text('开屏广告(Logo)'), + onPressed: () { + showSplashAd(AdsConfig.logo2); + }, + ), + const SizedBox(height: 20), + ElevatedButton( + child: const Text('开屏广告(全屏)'), + onPressed: () { + showSplashAd(); + }, + ), + ], + ), + SizedBox( + width: double.maxFinite, + child: ElevatedButton( child: const Text('展示插屏广告'), onPressed: () { showInterstitialAd(); }, ), - const SizedBox(height: 20), - ElevatedButton( - child: const Text('信息流广告'), - onPressed: () { - Navigator.push( + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ElevatedButton( + child: const Text('信息流广告(Pro)'), + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const ProPage(), + )); + }, + ), + const SizedBox(height: 20), + ElevatedButton( + child: const Text('激励视频广告(Pro)'), + onPressed: () { + Navigator.push( context, MaterialPageRoute( - builder: (context) => const FeedPage(), - )); - }, - ), - const SizedBox(height: 20), - AdBannerWidget( - posId: AdsConfig.bannerId, - width: 300, - height: 75, - ), - const SizedBox(height: 20), - // AdBannerWidget( - // posId: AdsConfig.bannerId, - // width: 300, - // height: 75, - // ), - ], - ), + builder: (context) => const ProPage(), + ), + ); + }, + ), + ], + ), + const SizedBox(height: 20), + const Center(child: Text('👇🏻 Banner 广告 👇🏻')), + const SizedBox(height: 10), + AdBannerWidget( + posId: AdsConfig.bannerId, + width: 300, + height: 75, + ), + const SizedBox(height: 20), + AdBannerWidget( + posId: AdsConfig.bannerId, + width: 300, + height: 75, + ), + ], ), ), ); diff --git a/example/lib/pro_page.dart b/example/lib/pro_page.dart new file mode 100644 index 0000000..96ad36c --- /dev/null +++ b/example/lib/pro_page.dart @@ -0,0 +1,23 @@ +import 'package:flutter/material.dart'; + +/// Pro 页面 +class ProPage extends StatefulWidget { + const ProPage({Key? key}) : super(key: key); + + @override + State createState() => _ProPageState(); +} + +class _ProPageState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Pro 付费功能'), + ), + body: const Center( + child: Text('此功能是插件 Pro 付费功能,需要购买插件后才能使用,请联系微信:toponelan 咨询购买并获得技术支持'), + ), + ); + } +} diff --git a/lib/view/ad_feed_widget.dart b/lib/view/ad_feed_widget.dart index 087c68b..d7bc58a 100644 --- a/lib/view/ad_feed_widget.dart +++ b/lib/view/ad_feed_widget.dart @@ -6,7 +6,7 @@ import 'package:flutter/widgets.dart'; /// Feed 信息流广告组件 /// 建议在个性化模板的广告view中,宽度自动铺满整个view,期望模板尺寸的参数设置中,高度可以设置为0,高度会自适应,达到最佳的展示比例 class AdFeedWidget extends StatefulWidget { - AdFeedWidget({ + const AdFeedWidget({ Key? key, required this.posId, this.show = true, diff --git a/test/flutter_gromore_ads_test.dart b/test/flutter_gromore_ads_test.dart index 3178dfa..ab73b3a 100644 --- a/test/flutter_gromore_ads_test.dart +++ b/test/flutter_gromore_ads_test.dart @@ -1,18 +1 @@ -import 'package:flutter/services.dart'; -import 'package:flutter_test/flutter_test.dart'; - -void main() { - const MethodChannel channel = MethodChannel('flutter_gromore_ads'); - - TestWidgetsFlutterBinding.ensureInitialized(); - - setUp(() { - channel.setMockMethodCallHandler((MethodCall methodCall) async { - return '42'; - }); - }); - - tearDown(() { - channel.setMockMethodCallHandler(null); - }); -} +void main() {} From 0e232e00650bcab8f0d2a62fd780ae931fedc197 Mon Sep 17 00:00:00 2001 From: Zero <1300326388@qq.com> Date: Sun, 20 Aug 2023 11:04:51 +0800 Subject: [PATCH 08/14] =?UTF-8?q?1=E3=80=81=E4=BC=98=E5=8C=96=E5=B9=BF?= =?UTF-8?q?=E5=91=8A=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 7 +++--- example/README.md | 19 ++++++----------- example/assets/images/img_pro.png | Bin 0 -> 112009 bytes example/lib/home_page.dart | 24 ++++++++++----------- example/lib/pro_page.dart | 34 ++++++++++++++++++++++++++++-- example/pubspec.yaml | 4 ++-- 6 files changed, 55 insertions(+), 33 deletions(-) create mode 100644 example/assets/images/img_pro.png diff --git a/README.md b/README.md index 1175adf..1505c3f 100644 --- a/README.md +++ b/README.md @@ -24,10 +24,9 @@ - ✅ 开屏广告 - ✅ 插屏广告 -- ✅ 全屏视频 -- ✅ Banner -- ✅ 信息流 -- 🔲 激励视频 +- ✅ 横幅广告 +- 🤴信息流[Pro 版本](example/README.md) +- 🤴激励视频[Pro 版本](example/README.md) ## 入门使用 diff --git a/example/README.md b/example/README.md index 1aec20c..6f5c133 100644 --- a/example/README.md +++ b/example/README.md @@ -1,16 +1,9 @@ -# flutter_gromore_ads_example +# Pro 付费功能 -Demonstrates how to use the flutter_gromore_ads plugin. +- 此功能是插件 Pro 付费功能,需要购买插件后才能使用 +- 请联系微信:`toponelan` 咨询购买并获得技术支持 +- 日活 10W 以上,可咨询其他合作模式,目前已合作百万级别的 App 客户 -## Getting Started +---- -This project is a starting point for a Flutter application. - -A few resources to get you started if this is your first Flutter project: - -- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) -- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) - -For help getting started with Flutter, view our -[online documentation](https://flutter.dev/docs), which offers tutorials, -samples, guidance on mobile development, and a full API reference. +![Pro 版](assets/images/img_pro.png) diff --git a/example/assets/images/img_pro.png b/example/assets/images/img_pro.png new file mode 100644 index 0000000000000000000000000000000000000000..7a303bef6c995e7c18de4ecbde257af90087e7fb GIT binary patch literal 112009 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

L`vfb?7_gBz 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 z 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 S_DOP^l;qWp=N~(L`M&`7ng|yF literal 0 HcmV?d00001 diff --git a/example/lib/home_page.dart b/example/lib/home_page.dart index 5e90a76..189e5f1 100644 --- a/example/lib/home_page.dart +++ b/example/lib/home_page.dart @@ -132,21 +132,21 @@ class _HomePageState extends State { ), const SizedBox(height: 20), const Center(child: Text('👇🏻 Banner 广告 👇🏻')), - const SizedBox(height: 10), - AdBannerWidget( - posId: AdsConfig.bannerId, - width: 300, - height: 75, - ), - const SizedBox(height: 20), - AdBannerWidget( - posId: AdsConfig.bannerId, - width: 300, - height: 75, - ), ], ), ), + bottomNavigationBar: SafeArea( + child: Container( + width: double.maxFinite, + height: 100, + alignment: Alignment.center, + child: AdBannerWidget( + posId: AdsConfig.bannerId, + width: 300, + height: 75, + ), + ), + ), ); } diff --git a/example/lib/pro_page.dart b/example/lib/pro_page.dart index 96ad36c..ebcf8e0 100644 --- a/example/lib/pro_page.dart +++ b/example/lib/pro_page.dart @@ -15,8 +15,38 @@ class _ProPageState extends State { appBar: AppBar( title: const Text('Pro 付费功能'), ), - body: const Center( - child: Text('此功能是插件 Pro 付费功能,需要购买插件后才能使用,请联系微信:toponelan 咨询购买并获得技术支持'), + body: SingleChildScrollView( + child: Column( + children: [ + const Center( + child: Padding( + padding: EdgeInsets.all(10.0), + child: Text( + '此功能是插件 Pro 付费功能,需要购买插件后才能使用\n请联系微信:toponelan 咨询购买并获得技术支持', + textAlign: TextAlign.center, + ), + ), + ), + Image.asset( + 'assets/images/img_pro.png', + fit: BoxFit.cover, + ), + const Center( + child: Padding( + padding: EdgeInsets.all(10.0), + child: Text( + '日活 10W 以上,可咨询其他合作模式,目前已合作百万级别的 App 客户', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.purple, + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ], + ), ), ); } diff --git a/example/pubspec.yaml b/example/pubspec.yaml index a7c346b..a514751 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -53,8 +53,8 @@ flutter: uses-material-design: true # To add assets to your application, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg + assets: + - assets/images/img_pro.png # - images/a_dot_ham.jpeg # An image asset can refer to one or more resolution-specific "variants", see From a211672240dad319ecac695fbd46747bff8d174a Mon Sep 17 00:00:00 2001 From: Zero <1300326388@qq.com> Date: Sun, 20 Aug 2023 16:38:42 +0800 Subject: [PATCH 09/14] =?UTF-8?q?1=E3=80=81=E6=9B=B4=E6=96=B0=E8=AF=B4?= =?UTF-8?q?=E6=98=8E=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 67 +++++------ example/android/app/build.gradle | 5 + example/android/app/proguard-rules.pro | 107 ++++++++++++++++++ .../android/app/src/main/AndroidManifest.xml | 39 +++---- example/ios/Podfile | 2 +- lib/flutter_gromore_ads.dart | 1 + 6 files changed, 167 insertions(+), 54 deletions(-) create mode 100644 example/android/app/proguard-rules.pro diff --git a/README.md b/README.md index 1505c3f..9abe04d 100644 --- a/README.md +++ b/README.md @@ -14,19 +14,23 @@ gromore

+## Gromore 有什么特点? + +就一点可以帮你较大幅度的提升收益,但是需要技术和运营都懂,其他就不多说了。 + ## 插件特点 - 🔨 接入简单快速(封装原生端配置,仅需引入即可开始) - 📡 事件统一返回(将原生端各种重要回调事件统一返回,方便业务处理和埋点统计等需求) - 🎁 注重优化体验(无闪烁 Logo 开屏、iOS 开屏防止事件穿透、权限申请、隐私跟踪申请等) -- 🏆 极客代码封装(原生端代码不凑合,两端统一基础框架、广告事件封装抽象、易扩展新广告形式、方便开发个性化需求) +- 🏆 极客代码封装(原生端代码不凑合,两端统一基础框架、广告事件封装抽象、易扩展) ## 支持功能 - ✅ 开屏广告 - ✅ 插屏广告 - ✅ 横幅广告 -- 🤴信息流[Pro 版本](example/README.md) -- 🤴激励视频[Pro 版本](example/README.md) +- 🏆 信息流([Pro 版本](example/README.md)) +- 🏆 激励视频 ([Pro 版本](example/README.md)) ## 入门使用 @@ -45,6 +49,8 @@ dependencies: // 导包 import 'package:flutter_gromore_ads/flutter_gromore_ads.dart'; /// [appId] 应用ID +/// [config] 配置文件名称 +/// [limitPersonalAds] 是否限制个性化广告,0:不限制 1:限制 FlutterGromoreAds.initAd(appId); ``` @@ -91,27 +97,26 @@ FlutterGromoreAds.showInterstitialAd( ); ``` -- 全插屏 +### 横幅广告 ``` Dart /// [posId] 广告位 id -/// [muted] 是否静音播放视频 -FlutterGromoreAds.showInterstitialFullAd( - posId, - muted: false, -); +/// [width] 宽度 +/// [height] 高度 +AdBannerWidget( + posId: posId, + width: 300, + height: 75, +) ``` -### 全屏视频 +### 🏆 信息流广告 -``` Dart -/// [posId] 广告位 id -/// [orientation] 期望视频的播放方向,1:VERTICAL 2:HORIZONTAL -FlutterGromoreAds.showFullVideoAd( - posId, - orientation: 1, -); -``` +- 查看 [🚀 Pro 版本](example/README.md) + +### 🏆 激励视频广告 + +- 查看 [🚀 Pro 版本](example/README.md) ### 设置广告事件监听 @@ -147,18 +152,15 @@ FlutterGromoreAds.onEventListener((event) { |参考示例|官方文档| |--|--| -|[build.gradle](https://github.com/FlutterAds/flutter_gromore_ads/blob/develop/example/android/app/build.gradle)|[点击这里](https://www.csjplatform.com/union/media/union/download/detail?id=75&docId=604de8b510af03004cbcbf69&osType=android#_1-1sdk包的导入)| +|[build.gradle](https://github.com/FlutterAds/flutter_gromore_ads/blob/develop/example/android/app/build.gradle)|[点击这里](https://www.csjplatform.com/union/media/union/download/detail?id=142&docId=27562&osType=android)| 打开 `android/app/build.gradle` 添加依赖,需要哪个添加哪个,`Adapter` 和 `SDK` 要成对添加 ``` gradle dependencies { //GroMore_sdk adapter - implementation "com.gromore.cn:gdt-adapter:4.482.1352.1" //gdt adapter - implementation 'com.qq.e.union:union:4.482.1352'// 广点通广告 SDK - implementation "com.gromore.cn:pangle-adapter:4.7.1.2.1" //穿山甲 adapter - implementation 'com.pangle.cn:ads-sdk-pro:4.7.1.2'//穿山甲广告 SDK - // 其他参考官方文档 引入即可 + implementation "com.pangle.cn:mediation-gdt-adapter:4.540.1410.1" //gdt adapter + implementation 'com.qq.e.union:union:4.540.1410'// 广点通广告 SDK } ``` @@ -201,7 +203,7 @@ dependencies { - + +1、在修改 `ios/Podfile` 引入 `SDK`,参考 [Podfile](https://github.com/FlutterAds/flutter_gromore_ads/blob/master/example/ios/Podfile) -2、修改 `ios/Podfile` 引入 `SDK`,参考 [Podfile](https://github.com/FlutterAds/flutter_gromore_ads/blob/master/example/ios/Podfile) - -image +``` ruby +#1.GroMoreSDK核心库 +# 广点通/优量汇 +pod 'CSJMGdtAdapter', '4.14.30.0' +pod 'GDTMobSDK','4.14.30' +``` - 添加配置文件 diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 871de98..f02daa7 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -47,6 +47,11 @@ android { // TODO: Add your own signing config for the release build. // Signing with the debug keys for now, so `flutter run --release` works. signingConfig signingConfigs.debug + // 开启混淆 + minifyEnabled true + // Zipalign优化 + zipAlignEnabled true + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } } diff --git a/example/android/app/proguard-rules.pro b/example/android/app/proguard-rules.pro new file mode 100644 index 0000000..96a3d3d --- /dev/null +++ b/example/android/app/proguard-rules.pro @@ -0,0 +1,107 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile +//聚合混淆 +-keep class bykvm*.** +-keep class com.bytedance.msdk.adapter.**{ public *; } +-keep class com.bytedance.msdk.api.** { + public *; +} +-keep class com.bytedance.msdk.base.TTBaseAd{*;} +-keep class com.bytedance.msdk.adapter.TTAbsAdLoaderAdapter{ + public *; + protected ; +} + +# baidu sdk 不接入baidu sdk可以不引入 +-ignorewarnings +-dontwarn com.baidu.mobads.sdk.api.** +-keepclassmembers class * extends android.app.Activity { + public void *(android.view.View); +} + +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +-keep class com.baidu.mobads.** { *; } +-keep class com.style.widget.** {*;} +-keep class com.component.** {*;} +-keep class com.baidu.ad.magic.flute.** {*;} +-keep class com.baidu.mobstat.forbes.** {*;} + +#ks 不接入ks sdk可以不引入 +-keep class org.chromium.** {*;} +-keep class org.chromium.** { *; } +-keep class aegon.chrome.** { *; } +-keep class com.kwai.**{ *; } +-dontwarn com.kwai.** +-dontwarn com.kwad.** +-dontwarn com.ksad.** +-dontwarn aegon.chrome.** + +# Admob 不接入admob sdk可以不引入 +-keep class com.google.android.gms.ads.MobileAds { + public *; +} + +#sigmob 不接入sigmob sdk可以不引入 +-dontwarn android.support.v4.** +-keep class android.support.v4.** { *; } +-keep interface android.support.v4.** { *; } +-keep public class * extends android.support.v4.** + +-keep class sun.misc.Unsafe { *; } +-dontwarn com.sigmob.** +-keep class com.sigmob.**.**{*;} + +#oaid 不同的版本混淆代码不太一致,你注意你接入的oaid版本 ,不接入oaid可以不添加 +-dontwarn com.bun.** +-keep class com.bun.** {*;} +-keep class a.**{*;} +-keep class XI.CA.XI.**{*;} +-keep class XI.K0.XI.**{*;} +-keep class XI.XI.K0.**{*;} +-keep class XI.vs.K0.**{*;} +-keep class XI.xo.XI.XI.**{*;} +-keep class com.asus.msa.SupplementaryDID.**{*;} +-keep class com.asus.msa.sdid.**{*;} +-keep class com.huawei.hms.ads.identifier.**{*;} +-keep class com.samsung.android.deviceidservice.**{*;} +-keep class com.zui.opendeviceidlibrary.**{*;} +-keep class org.json.**{*;} +-keep public class com.netease.nis.sdkwrapper.Utils {public ;} + + +#klevin 游可赢 +-keep class com.tencent.tgpa.**{*;} +-keep class com.tencent.klevin.**{*;} + + +#Mintegral 不接入Mintegral sdk,可以不引入 +-keepattributes Signature +-keepattributes *Annotation* +-keep class com.mbridge.** {*; } +-keep interface com.mbridge.** {*; } +-keep class android.support.v4.** { *; } +-dontwarn com.mbridge.** +-keep class **.R$* { public static final int mbridge*; } \ No newline at end of file diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml index a8c3aaf..da92977 100644 --- a/example/android/app/src/main/AndroidManifest.xml +++ b/example/android/app/src/main/AndroidManifest.xml @@ -60,7 +60,24 @@ android:value="2" /> - + + + + + + + + + - - - - - - - - - - - diff --git a/example/ios/Podfile b/example/ios/Podfile index 10eebac..6150018 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -37,7 +37,7 @@ target 'Runner' do pod 'GDTMobSDK','4.14.30' # 百度SDK # pod 'CSJMBaiduAdapter', '5.300.0' - pod 'BaiduMobAdSDK', '5.300' + # pod 'BaiduMobAdSDK', '5.300' # UnityAds # pod 'CSJMUnityAdapter', '4.3.0.0' # pod 'UnityAds', '4.3.0' diff --git a/lib/flutter_gromore_ads.dart b/lib/flutter_gromore_ads.dart index 950f745..a04af3d 100644 --- a/lib/flutter_gromore_ads.dart +++ b/lib/flutter_gromore_ads.dart @@ -49,6 +49,7 @@ class FlutterGromoreAds { /// 初始化广告 /// [appId] 应用ID /// [config] 配置文件名称 + /// [limitPersonalAds] 是否限制个性化广告,0:不限制 1:限制 static Future initAd(String appId, {String? config, int limitPersonalAds = 0}) async { final bool result = await _methodChannel.invokeMethod( From 5f7ed6e6853218f555f51d95988ea89a78cd6f81 Mon Sep 17 00:00:00 2001 From: Zero <1300326388@qq.com> Date: Sun, 20 Aug 2023 17:28:46 +0800 Subject: [PATCH 10/14] =?UTF-8?q?1=E3=80=81=E6=9B=B4=E6=96=B0=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E8=AF=B4=E6=98=8E=E5=92=8C=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 8 +++++++- README.md | 2 +- android/build.gradle | 3 --- example/android/app/proguard-rules.pro | 2 +- example/android/build.gradle | 2 +- example/pubspec.yaml | 1 + ios/flutter_gromore_ads.podspec | 2 +- pubspec.yaml | 4 ++-- 8 files changed, 14 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ebff19..e8e9cfd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,10 @@ -## 1.3.3 +## v2.0.0 +* 从此版本开始,Gromore 插件更新为 Gromore 融合 SDK 版本 +* 升级 iOS SDK 到 `v5.3.6.1` +* 升级 Android SDK 到 `v5.5.1.5` + +> 此版本升级后建议多自测,如有问题请及时反馈。 +## 2.0.0 * 增加信息流广告支持 ## 1.3.2 * 增加 Banner 广告支持 diff --git a/README.md b/README.md index 9abe04d..ea19c78 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ ``` Dart dependencies: - flutter_gromore_ads: ^1.3.3 + flutter_gromore_ads: ^2.0.0 ``` > 下面 `导入 SDK` 是必须的配置,千万别省略了,仔细看文档来配置。 diff --git a/android/build.gradle b/android/build.gradle index 200b3f0..4be7183 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -56,7 +56,4 @@ dependencies { implementation 'androidx.constraintlayout:constraintlayout:2.0.4' //GroMore_sdk implementation "com.pangle.cn:mediation-sdk:5.5.1.5" //融合SDK - // Glide 图片加载框架 - implementation 'com.github.bumptech.glide:glide:4.14.2' - annotationProcessor 'com.github.bumptech.glide:compiler:4.14.2' } diff --git a/example/android/app/proguard-rules.pro b/example/android/app/proguard-rules.pro index 96a3d3d..4824e70 100644 --- a/example/android/app/proguard-rules.pro +++ b/example/android/app/proguard-rules.pro @@ -19,7 +19,7 @@ # If you keep the line number information, uncomment this to # hide the original source file name. #-renamesourcefileattribute SourceFile -//聚合混淆 +# 聚合混淆 -keep class bykvm*.** -keep class com.bytedance.msdk.adapter.**{ public *; } -keep class com.bytedance.msdk.api.** { diff --git a/example/android/build.gradle b/example/android/build.gradle index 622ddc5..77a69d0 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -22,6 +22,6 @@ subprojects { project.evaluationDependsOn(':app') } -task clean(type: Delete) { +tasks.register("clean", Delete) { delete rootProject.buildDir } diff --git a/example/pubspec.yaml b/example/pubspec.yaml index a514751..9724991 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -4,6 +4,7 @@ description: Demonstrates how to use the flutter_gromore_ads plugin. # The following line prevents the package from being accidentally published to # pub.dev using `flutter pub publish`. This is preferred for private packages. publish_to: "none" # Remove this line if you wish to publish to pub.dev +version: 2.0.0+14 environment: sdk: ">=2.12.0 <3.0.0" diff --git a/ios/flutter_gromore_ads.podspec b/ios/flutter_gromore_ads.podspec index 053172a..b2dbd5f 100644 --- a/ios/flutter_gromore_ads.podspec +++ b/ios/flutter_gromore_ads.podspec @@ -4,7 +4,7 @@ # Pod::Spec.new do |s| s.name = 'flutter_gromore_ads' - s.version = '1.3.3' + s.version = '2.0.0' s.summary = '一款优质的 Flutter 广告插件(GroMore、穿山甲)' s.description = <<-DESC FlutterAds 致力于构建优质的 Flutter 广告插件 diff --git a/pubspec.yaml b/pubspec.yaml index 436ddb0..8f74d24 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,12 +1,12 @@ name: flutter_gromore_ads description: 一款优质的 Flutter 广告插件(Gromore、穿山甲) -version: 1.3.3 +version: 2.0.0 homepage: https://github.com/FlutterAds/flutter_gromore_ads repository: https://github.com/FlutterAds/flutter_gromore_ads issue_tracker: https://github.com/FlutterAds/flutter_gromore_ads/issues environment: - sdk: ">=2.12.0 <3.0.0" + sdk: ">=2.12.0 <4.0.0" flutter: ">=1.20.0" dependencies: From 0ad5af20b169878cd870dce7defcec17e3627eac Mon Sep 17 00:00:00 2001 From: Zero <1300326388@qq.com> Date: Sun, 20 Aug 2023 18:02:02 +0800 Subject: [PATCH 11/14] =?UTF-8?q?1=E3=80=81=E4=BC=98=E5=8C=96=E6=8F=92?= =?UTF-8?q?=E5=B1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/lib/ads_config.dart | 12 ++++-- example/lib/home_page.dart | 71 +++++++++++++++++++++++------------ lib/flutter_gromore_ads.dart | 73 +----------------------------------- 3 files changed, 56 insertions(+), 100 deletions(-) diff --git a/example/lib/ads_config.dart b/example/lib/ads_config.dart index 5522ff6..15d8a7a 100644 --- a/example/lib/ads_config.dart +++ b/example/lib/ads_config.dart @@ -38,10 +38,14 @@ class AdsConfig { return '102420790'; } - /// 获取插屏广告位id - static String get interstitialId { - return '102421471'; - } + /// 获取插屏广告位id 竖屏 + static String get interstitialId => '102421471'; + + /// 获取插屏广告位id 横屏 + static String get interstitialIdHorizontal => '102428790'; + + /// 获取插屏广告位id 半屏 + static String get interstitialIdHalf => '102428146'; /// 获取激励视频广告位id static String get rewardVideoId => '102421199'; diff --git a/example/lib/home_page.dart b/example/lib/home_page.dart index 189e5f1..0455ecf 100644 --- a/example/lib/home_page.dart +++ b/example/lib/home_page.dart @@ -94,15 +94,35 @@ class _HomePageState extends State { ), ], ), - SizedBox( - width: double.maxFinite, - child: ElevatedButton( - child: const Text('展示插屏广告'), - onPressed: () { - showInterstitialAd(); - }, - ), + const SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ElevatedButton( + child: const Text('插竖屏)'), + onPressed: () { + showInterstitialAd(AdsConfig.interstitialId); + }, + ), + const SizedBox(height: 10), + ElevatedButton( + child: const Text('插横屏)'), + onPressed: () { + showInterstitialAd(AdsConfig.interstitialIdHorizontal); + }, + ), + const SizedBox(height: 10), + ElevatedButton( + child: const Text('插半屏)'), + onPressed: () { + showInterstitialAd(AdsConfig.interstitialIdHalf); + }, + ), + ], ), + const SizedBox(height: 20), + const Center(child: Text('🏆 付费 Pro 版功能 🏆')), + const SizedBox(height: 10), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -130,22 +150,27 @@ class _HomePageState extends State { ), ], ), - const SizedBox(height: 20), - const Center(child: Text('👇🏻 Banner 广告 👇🏻')), ], ), ), bottomNavigationBar: SafeArea( child: Container( - width: double.maxFinite, - height: 100, - alignment: Alignment.center, - child: AdBannerWidget( - posId: AdsConfig.bannerId, - width: 300, - height: 75, - ), - ), + width: double.maxFinite, + height: 140, + color: Colors.grey[200], + alignment: Alignment.center, + child: Column( + children: [ + const SizedBox(height: 10), + const Center(child: Text('👇🏻 Banner 广告 👇🏻')), + const SizedBox(height: 10), + AdBannerWidget( + posId: AdsConfig.bannerId, + width: 300, + height: 75, + ), + ], + )), ), ); } @@ -224,13 +249,9 @@ class _HomePageState extends State { } /// 展示插屏广告 - Future showInterstitialAd() async { + Future showInterstitialAd(String posid) async { try { - bool result = await FlutterGromoreAds.showInterstitialAd( - AdsConfig.interstitialId, - width: 300, - height: 300, - ); + bool result = await FlutterGromoreAds.showInterstitialAd(posid); _result = "展示插屏广告${result ? '成功' : '失败'}"; } on PlatformException catch (e) { _result = "展示插屏广告失败 code:${e.code} msg:${e.message} details:${e.details}"; diff --git a/lib/flutter_gromore_ads.dart b/lib/flutter_gromore_ads.dart index a04af3d..f8aa68b 100644 --- a/lib/flutter_gromore_ads.dart +++ b/lib/flutter_gromore_ads.dart @@ -7,7 +7,6 @@ import 'event/ad_event_handler.dart'; export 'event/ad_event_handler.dart'; export 'view/ad_banner_widget.dart'; -export 'view/ad_feed_widget.dart'; /// GroMore 广告插件 class FlutterGromoreAds { @@ -82,79 +81,11 @@ class FlutterGromoreAds { /// 展示插屏广告 /// [posId] 广告位 id - /// [width] 宽度 - /// [height] 高度 - static Future showInterstitialAd( - String posId, { - int width = 300, - int height = 300, - }) async { + static Future showInterstitialAd(String posId) async { final bool result = await _methodChannel.invokeMethod( 'showInterstitialAd', { - 'posId': posId, - 'width': width, - 'height': height, - }, - ); - return result; - } - - /// 展示插屏全屏广告 - /// [posId] 广告位 id - /// [muted] 是否静音播放视频 - static Future showInterstitialFullAd(String posId, - {bool muted = false}) async { - final bool result = await _methodChannel.invokeMethod( - 'showInterstitialFullAd', - {'posId': posId, 'muted': muted}, - ); - return result; - } - - /// 展示全屏视频广告 - /// [posId] 广告位 id - /// [orientation] 期望视频的播放方向,1:VERTICAL 2:HORIZONTAL - static Future showFullVideoAd( - String posId, { - int orientation = 1, - }) async { - final bool result = await _methodChannel.invokeMethod( - 'showFullVideoAd', - { - 'posId': posId, - 'orientation': orientation, - }, - ); - return result; - } - - /// 加载信息流广告列表 - /// [posId] 广告位 id - /// [width] 宽度 - /// [height] 高度 - /// [count] 获取广告数量,建议 1~3 个 - static Future> loadFeedAd(String posId, - {int width = 375, int height = 0, int count = 1}) async { - final List result = await _methodChannel.invokeMethod( - 'loadFeedAd', - { - 'posId': posId, - 'width': width, - 'height': height, - 'count': count, - }, - ); - return List.from(result); - } - - /// 清除信息流广告列表 - /// [list] 信息流广告 id 列表 - static Future clearFeedAd(List list) async { - final bool result = await _methodChannel.invokeMethod( - 'clearFeedAd', - { - 'list': list, + 'posId': posId }, ); return result; From 92367556a5033e1c7a0a7df2b6e20863ac12ac0c Mon Sep 17 00:00:00 2001 From: Zero <1300326388@qq.com> Date: Sun, 20 Aug 2023 18:02:24 +0800 Subject: [PATCH 12/14] =?UTF-8?q?1=E3=80=81=E5=8E=BB=E6=8E=89=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../flutter_gromore_ads/page/AdFeedView.java | 184 ------------------ .../page/NativeViewFactory.java | 3 - example/lib/feed_page.dart | 170 ---------------- lib/flutter_gromore_ads.dart | 4 +- lib/view/ad_feed_widget.dart | 95 --------- 5 files changed, 1 insertion(+), 455 deletions(-) delete mode 100644 android/src/main/java/com/zero/flutter_gromore_ads/page/AdFeedView.java delete mode 100644 example/lib/feed_page.dart delete mode 100644 lib/view/ad_feed_widget.dart diff --git a/android/src/main/java/com/zero/flutter_gromore_ads/page/AdFeedView.java b/android/src/main/java/com/zero/flutter_gromore_ads/page/AdFeedView.java deleted file mode 100644 index abfc425..0000000 --- a/android/src/main/java/com/zero/flutter_gromore_ads/page/AdFeedView.java +++ /dev/null @@ -1,184 +0,0 @@ -//package com.zero.flutter_gromore_ads.page; -// -//import android.content.Context; -//import android.util.Log; -//import android.view.View; -//import android.view.ViewGroup; -//import android.widget.FrameLayout; -// -//import androidx.annotation.NonNull; -//import androidx.annotation.Nullable; -// -//import com.bytedance.msdk.api.v2.GMDislikeCallback; -//import com.bytedance.msdk.api.v2.ad.nativeAd.GMNativeAd; -//import com.bytedance.msdk.api.v2.ad.nativeAd.GMNativeExpressAdListener; -//import com.zero.flutter_gromore_ads.PluginDelegate; -//import com.zero.flutter_gromore_ads.event.AdEventAction; -//import com.zero.flutter_gromore_ads.load.FeedAdManager; -//import com.zero.flutter_gromore_ads.utils.UIUtils; -// -//import java.util.HashMap; -//import java.util.Map; -// -//import io.flutter.plugin.common.MethodCall; -//import io.flutter.plugin.common.MethodChannel; -//import io.flutter.plugin.platform.PlatformView; -// -///** -// * Feed 信息流广告 View -// */ -//class AdFeedView extends BaseAdPage implements PlatformView, GMNativeExpressAdListener { -// private final String TAG = AdFeedView.class.getSimpleName(); -// @NonNull -// private final FrameLayout frameLayout; -// private final PluginDelegate pluginDelegate; -// private int id; -// private GMNativeAd fad; -// private View adView; -// private MethodChannel methodChannel; -// -// -// AdFeedView(@NonNull Context context, int id, @Nullable Map creationParams, PluginDelegate pluginDelegate) { -// this.id = id; -// this.pluginDelegate = pluginDelegate; -// methodChannel = new MethodChannel(this.pluginDelegate.bind.getBinaryMessenger(), PluginDelegate.KEY_FEED_VIEW + "/" + id); -// frameLayout = new FrameLayout(context); -// FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); -// frameLayout.setLayoutParams(params); -// MethodCall call = new MethodCall("AdFeedView", creationParams); -// showAd(this.pluginDelegate.activity, call); -// } -// -// @NonNull -// @Override -// public View getView() { -// return frameLayout; -// } -// -// @Override -// public void dispose() { -// removeAd(); -// } -// -// @Override -// public void loadAd(@NonNull MethodCall call) { -// fad = FeedAdManager.getInstance().getAd(Integer.parseInt(this.posId)); -// if (fad != null) { -// fad.setNativeAdListener(this); -// bindDislikeAction(fad); -// adView = fad.getExpressView(); -// if (adView != null && adView.getParent() != null) { -// ((ViewGroup) adView.getParent()).removeAllViews(); -// } -// FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, UIUtils.getScreenHeightInPx(activity)); -// frameLayout.setLayoutParams(params); -// frameLayout.addView(adView); -// fad.render(); -// } -// } -// -// /** -// * 移除广告 -// */ -// private void removeAd() { -// frameLayout.removeAllViews(); -// } -// -// /** -// * 销毁广告 -// */ -// private void disposeAd() { -// removeAd(); -// FeedAdManager.getInstance().removeAd(Integer.parseInt(this.posId)); -// if (fad != null) { -// fad.destroy(); -// } -// // 更新宽高 -// setFlutterViewSize(0f, 0f); -// } -// -// public void onAdClosed() { -// Log.i(TAG, "onAdDismiss"); -// // 添加广告事件 -// sendEvent(AdEventAction.onAdClosed); -// disposeAd(); -// } -// -// @Override -// public void onAdClick() { -// Log.i(TAG, "onAdClicked"); -// // 添加广告事件 -// sendEvent(AdEventAction.onAdClicked); -// } -// -// @Override -// public void onAdShow() { -// Log.i(TAG, "onAdShow"); -// // 添加广告事件 -// sendEvent(AdEventAction.onAdExposure); -// } -// -// @Override -// public void onRenderFail(View view, String s, int i) { -// Log.e(TAG, "onRenderFail code:" + i + " msg:" + s); -// // 添加广告错误事件 -// sendErrorEvent(i, s); -// // 更新宽高 -// setFlutterViewSize(0f, 0f); -// } -// -// @Override -// public void onRenderSuccess(float width, float height) { -// Log.i(TAG, "onRenderSuccess v:" + width + " v1:" + height); -// // 添加广告事件 -// sendEvent(AdEventAction.onAdPresent); -// if (width > 0 && height > 0) { -// setFlutterViewSize(width, height); -// } -// } -// -// /** -// * 设置 FlutterAds 视图宽高 -// * -// * @param width 宽度 -// * @param height 高度 -// */ -// private void setFlutterViewSize(float width, float height) { -// Map sizeMap = new HashMap<>(); -// sizeMap.put("width", (double) width); -// sizeMap.put("height", (double) height); -// if (methodChannel != null) { -// methodChannel.invokeMethod("setSize", sizeMap); -// } -// } -// -// /** -// * 接入dislike 逻辑,有助于提示广告精准投放度 -// * 和后续广告关闭逻辑处理 -// * -// * @param ad 广告 View -// */ -// private void bindDislikeAction(GMNativeAd ad) { -// ad.setDislikeCallback(activity, new GMDislikeCallback() { -// @Override -// public void onSelected(int position, String value) { -// onAdClosed(); -// } -// -// @Override -// public void onCancel() { -// -// } -// -// @Override -// public void onRefuse() { -// -// } -// -// @Override -// public void onShow() { -// -// } -// }); -// } -//} \ No newline at end of file diff --git a/android/src/main/java/com/zero/flutter_gromore_ads/page/NativeViewFactory.java b/android/src/main/java/com/zero/flutter_gromore_ads/page/NativeViewFactory.java index daf1394..9c5701d 100644 --- a/android/src/main/java/com/zero/flutter_gromore_ads/page/NativeViewFactory.java +++ b/android/src/main/java/com/zero/flutter_gromore_ads/page/NativeViewFactory.java @@ -34,9 +34,6 @@ public PlatformView create(@NonNull Context context, int id, @Nullable Object ar if (this.viewName.equals(PluginDelegate.KEY_BANNER_VIEW)) { return new AdBannerView(context, id, creationParams, pluginDelegate); } -// else if (this.viewName.equals(PluginDelegate.KEY_FEED_VIEW)) { -// return new AdFeedView(context, id, creationParams, pluginDelegate); -// } return null; } } \ No newline at end of file diff --git a/example/lib/feed_page.dart b/example/lib/feed_page.dart deleted file mode 100644 index 20b8aed..0000000 --- a/example/lib/feed_page.dart +++ /dev/null @@ -1,170 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_gromore_ads/flutter_gromore_ads.dart'; -import 'package:flutter_gromore_ads_example/ads_config.dart'; -import 'package:loadany/loadany.dart'; - -/// 信息流页面 -class FeedPage extends StatefulWidget { - const FeedPage({Key? key}) : super(key: key); - - @override - _FeedPageState createState() => _FeedPageState(); -} - -class _FeedPageState extends State { - List feedList = []; - List feedAdList = []; - - LoadStatus loadStatus = LoadStatus.normal; - - @override - void initState() { - getFeedList(); - super.initState(); - } - - @override - void dispose() { - clearFeedAd(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('信息流(FlutterAds)'), - ), - body: LoadAny( - onLoadMore: () async { - getFeedList(); - }, - status: loadStatus, - child: CustomScrollView( - slivers: [ - SliverList( - delegate: SliverChildBuilderDelegate( - (BuildContext context, int index) { - if (index % 5 == 3) { - int adIndex = index ~/ 5; - print('adIndex:$adIndex'); - if (adIndex >= feedAdList.length) { - return Container( - height: 80, - width: double.maxFinite, - color: Colors.blueAccent, - alignment: Alignment.centerLeft, - child: Text('暂无广告 $index'), - ); - } - - int adId = feedAdList[adIndex]; - return AdFeedWidget( - posId: '$adId', - width: 360, - height: 120, - show: true, - ); - } - return const LoadingItemWidget(); - }, - childCount: feedList.length, - ), - ) - ], - ), - ), - ); - } - - /// 加载信息流 - Future getFeedList() async { - setState(() { - loadStatus = LoadStatus.loading; - }); - await Future.delayed(const Duration(seconds: 1)); - for (var i = 0; i < 15; i++) { - feedList.add(i); - } - getFeedAdList(); - } - - // 加载信息流广告 - Future getFeedAdList() async { - try { - List adResultList = await FlutterGromoreAds.loadFeedAd( - AdsConfig.feedId, - count: 3, - ); - feedAdList.addAll(adResultList); - } catch (e) { - print(e.toString()); - } - setState(() { - loadStatus = LoadStatus.normal; - }); - } - - // 清除信息流广告 - Future clearFeedAd() async { - bool result = await FlutterGromoreAds.clearFeedAd(feedAdList); - print('clearFeedAd:$result'); - } -} - -/// 加载项组件 -class LoadingItemWidget extends StatelessWidget { - const LoadingItemWidget({ - Key? key, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - return Container( - height: 80, - width: double.maxFinite, - alignment: Alignment.centerLeft, - padding: const EdgeInsets.all(10), - margin: const EdgeInsets.symmetric(vertical: 10), - color: Colors.white, - child: Row( - children: [ - Container( - width: 60, - height: 60, - decoration: const BoxDecoration( - shape: BoxShape.circle, - color: Color(0xFFEBEBF4), - ), - ), - const SizedBox(width: 20), - Expanded( - child: Padding( - padding: const EdgeInsets.all(4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - width: double.maxFinite, - height: 20, - decoration: const BoxDecoration( - color: Color(0xFFEBEBF4), - ), - ), - const Spacer(), - Container( - width: 200, - height: 20, - decoration: const BoxDecoration( - color: Color(0xFFE4E4F4), - ), - ), - ], - ), - ), - ) - ], - ), - ); - } -} diff --git a/lib/flutter_gromore_ads.dart b/lib/flutter_gromore_ads.dart index f8aa68b..1f95b07 100644 --- a/lib/flutter_gromore_ads.dart +++ b/lib/flutter_gromore_ads.dart @@ -84,9 +84,7 @@ class FlutterGromoreAds { static Future showInterstitialAd(String posId) async { final bool result = await _methodChannel.invokeMethod( 'showInterstitialAd', - { - 'posId': posId - }, + {'posId': posId}, ); return result; } diff --git a/lib/view/ad_feed_widget.dart b/lib/view/ad_feed_widget.dart deleted file mode 100644 index d7bc58a..0000000 --- a/lib/view/ad_feed_widget.dart +++ /dev/null @@ -1,95 +0,0 @@ -import 'dart:io'; - -import 'package:flutter/services.dart'; -import 'package:flutter/widgets.dart'; - -/// Feed 信息流广告组件 -/// 建议在个性化模板的广告view中,宽度自动铺满整个view,期望模板尺寸的参数设置中,高度可以设置为0,高度会自适应,达到最佳的展示比例 -class AdFeedWidget extends StatefulWidget { - const AdFeedWidget({ - Key? key, - required this.posId, - this.show = true, - this.width = 375, - this.height = 128, - }) : super(key: key); - // 返回的广告 id,这里不是广告位id - final String posId; - // 是否显示广告 - final bool show; - // 宽高 - final double width, height; - - @override - _AdFeedWidgetState createState() => _AdFeedWidgetState(); -} - -class _AdFeedWidgetState extends State - with AutomaticKeepAliveClientMixin { - // View 类型 - final String viewType = 'flutter_gromore_ads_feed'; - // 创建参数 - late Map creationParams; - // 通道 - late MethodChannel _channel; - // 宽高 - double width = 375, height = 128; - - @override - void initState() { - width = widget.width; - height = widget.height; - creationParams = { - "posId": widget.posId, - }; - super.initState(); - } - - @override - Widget build(BuildContext context) { - super.build(context); - if (!widget.show || width <= 0 || height <= 0) { - return const SizedBox.shrink(); - } - Widget view; - if (Platform.isIOS) { - view = UiKitView( - viewType: viewType, - creationParams: creationParams, - creationParamsCodec: const StandardMessageCodec(), - onPlatformViewCreated: (id) { - _channel = MethodChannel('$viewType/$id'); - _channel.setMethodCallHandler(onMethodCallHandler); - }, - ); - } else { - view = AndroidView( - viewType: viewType, - creationParams: creationParams, - creationParamsCodec: const StandardMessageCodec(), - onPlatformViewCreated: (id) { - _channel = MethodChannel('$viewType/$id'); - _channel.setMethodCallHandler(onMethodCallHandler); - }, - ); - } - // 有宽高信息了(渲染成功了)设置对应宽高 - return SizedBox.fromSize( - size: Size(width, height), - child: view, - ); - } - - @override - bool get wantKeepAlive => true; - - Future onMethodCallHandler(MethodCall call) async { - String method = call.method; - // 设置大小 - if (method == 'setSize') { - width = call.arguments['width'] ?? 0; - height = call.arguments['height'] ?? 0; - setState(() {}); - } - } -} From ed839c03ca5bddcaa72eddf6404d699ea27861bb Mon Sep 17 00:00:00 2001 From: Zero <1300326388@qq.com> Date: Sun, 20 Aug 2023 18:19:40 +0800 Subject: [PATCH 13/14] =?UTF-8?q?1=E3=80=81=E4=BC=98=E5=8C=96=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../flutter_gromore_ads/PluginDelegate.java | 106 +--------------- example/lib/home_page.dart | 16 ++- example/lib/pro_page.dart | 6 +- ios/Classes/FlutterGromoreAdsPlugin.h | 2 - ios/Classes/FlutterGromoreAdsPlugin.m | 41 ------- ios/Classes/Page/FGMAdFeedView.h | 22 ---- ios/Classes/Page/FGMAdFeedView.m | 114 ------------------ ios/Classes/Page/FGMNativeViewFactory.m | 7 -- 8 files changed, 21 insertions(+), 293 deletions(-) delete mode 100644 ios/Classes/Page/FGMAdFeedView.h delete mode 100644 ios/Classes/Page/FGMAdFeedView.m diff --git a/android/src/main/java/com/zero/flutter_gromore_ads/PluginDelegate.java b/android/src/main/java/com/zero/flutter_gromore_ads/PluginDelegate.java index e854f93..3edc5e6 100644 --- a/android/src/main/java/com/zero/flutter_gromore_ads/PluginDelegate.java +++ b/android/src/main/java/com/zero/flutter_gromore_ads/PluginDelegate.java @@ -7,28 +7,19 @@ import androidx.annotation.NonNull; - -//import com.zero.flutter_gromore_ads.load.FeedAdLoad; -//import com.zero.flutter_gromore_ads.load.FeedAdManager; import com.bytedance.sdk.openadsdk.TTAdConfig; import com.bytedance.sdk.openadsdk.TTAdSdk; import com.bytedance.sdk.openadsdk.TTCustomController; import com.bytedance.sdk.openadsdk.mediation.init.MediationConfig; import com.bytedance.sdk.openadsdk.mediation.init.MediationPrivacyConfig; import com.zero.flutter_gromore_ads.page.AdSplashActivity; -//import com.zero.flutter_gromore_ads.page.FullVideoPage; -//import com.zero.flutter_gromore_ads.page.InterstitialFullPage; import com.zero.flutter_gromore_ads.page.InterstitialPage; -//import com.zero.flutter_gromore_ads.page.NativeViewFactory; import com.zero.flutter_gromore_ads.page.NativeViewFactory; import com.zero.flutter_gromore_ads.utils.FileUtils; import org.json.JSONException; import org.json.JSONObject; -import java.util.ArrayList; -import java.util.List; - import io.flutter.BuildConfig; import io.flutter.embedding.engine.plugins.FlutterPlugin; import io.flutter.plugin.common.EventChannel; @@ -55,16 +46,12 @@ public static PluginDelegate getInstance() { // Banner View public static final String KEY_BANNER_VIEW = "flutter_gromore_ads_banner"; - // Feed View - public static final String KEY_FEED_VIEW = "flutter_gromore_ads_feed"; // 广告参数 public static final String KEY_POSID = "posId"; // logo 参数 public static final String KEY_LOGO = "logo"; // timeout 参数 public static final String KEY_TIMEOUT = "timeout"; - // splashButtonType 参数 - public static final String KEY_SPLASH_BUTTON_TYPE = "buttonType"; /** * 插件代理构造函数构造函数 @@ -96,16 +83,6 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result showSplashAd(call, result); } else if ("showInterstitialAd".equals(method)) { showInterstitialAd(call, result); - } else if ("showInterstitialFullAd".equals(method)) { - showInterstitialFullAd(call, result); - } else if ("showFullVideoAd".equals(method)) { - showFullVideoAd(call, result); - } else if ("showRewardVideoAd".equals(method)) { - showRewardVideoAd(call, result); - } else if ("loadFeedAd".equals(method)) { - loadFeedAd(call, result); - } else if ("clearFeedAd".equals(method)) { - clearFeedAd(call, result); } else { result.notImplemented(); } @@ -154,14 +131,6 @@ public void registerBannerView() { .registerViewFactory(KEY_BANNER_VIEW, new NativeViewFactory(KEY_BANNER_VIEW, this)); } - /** - * 展示 Feed 信息流广告 - */ - public void registerFeedView() { -// bind.getPlatformViewRegistry() -// .registerViewFactory(KEY_FEED_VIEW, new NativeViewFactory(KEY_FEED_VIEW, this)); - } - /** * 请求权限 * @@ -182,7 +151,7 @@ public void requestPermissionIfNecessary(MethodCall call, MethodChannel.Result r public void initAd(MethodCall call, final MethodChannel.Result result) { String appId = call.argument("appId"); String config = call.argument("config"); - int limitPersonalAds=call.argument("limitPersonalAds"); + int limitPersonalAds = call.argument("limitPersonalAds"); // 构建基础配置 TTAdConfig.Builder configBuilder = new TTAdConfig.Builder() @@ -204,13 +173,13 @@ public void initAd(MethodCall call, final MethodChannel.Result result) { TTAdConfig gmPangleOption; if (localConfigJson != null) { gmPangleOption = configBuilder - .customController(getTTCustomController(limitPersonalAds==0)) + .customController(getTTCustomController(limitPersonalAds == 0)) .setMediationConfig(new MediationConfig.Builder() - .setCustomLocalConfig(localConfigJson) - .build()).build(); + .setCustomLocalConfig(localConfigJson) + .build()).build(); } else { gmPangleOption = configBuilder - .customController(getTTCustomController(limitPersonalAds==0)) + .customController(getTTCustomController(limitPersonalAds == 0)) .build(); } // 初始化 SDK @@ -228,7 +197,7 @@ public void fail(int code, String message) { } - private TTCustomController getTTCustomController(boolean limitPersonalAds){ + private TTCustomController getTTCustomController(boolean limitPersonalAds) { return new TTCustomController() { @Override @@ -316,67 +285,4 @@ public void showInterstitialAd(MethodCall call, MethodChannel.Result result) { result.success(true); } - /** - * 显示插屏全屏广告 - * - * @param call MethodCall - * @param result Result - */ - public void showInterstitialFullAd(MethodCall call, MethodChannel.Result result) { -// InterstitialFullPage adPage = new InterstitialFullPage(); -// adPage.showAd(activity, call); -// result.success(true); - } - - /** - * 显示全屏视频广告 - * - * @param call MethodCall - * @param result Result - */ - public void showFullVideoAd(MethodCall call, MethodChannel.Result result) { -// FullVideoPage adPage = new FullVideoPage(); -// adPage.showAd(activity, call); -// result.success(true); - } - - /** - * 显示激励视频广告 - * - * @param call MethodCall - * @param result Result - */ - public void showRewardVideoAd(MethodCall call, MethodChannel.Result result) { -// RewardVideoPage adPage = new RewardVideoPage(); -// adPage.showAd(activity, call); -// result.success(true); - } - - /** - * 加载信息流广告列表 - * - * @param call MethodCall - * @param result Result - */ - public void loadFeedAd(MethodCall call, MethodChannel.Result result) { -// FeedAdLoad feedAd = new FeedAdLoad(); -// feedAd.loadFeedAdList(activity, call, result); - } - - /** - * 删除信息流广告列表 - * - * @param call MethodCall - * @param result Result - */ - public void clearFeedAd(MethodCall call, MethodChannel.Result result) { -// List adList = call.argument("list"); -// if (adList != null) { -// for (int ad : adList) { -// FeedAdManager.getInstance().removeAd(ad); -// } -// } -// result.success(true); - - } } diff --git a/example/lib/home_page.dart b/example/lib/home_page.dart index 0455ecf..9ff344d 100644 --- a/example/lib/home_page.dart +++ b/example/lib/home_page.dart @@ -99,21 +99,21 @@ class _HomePageState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ ElevatedButton( - child: const Text('插竖屏)'), + child: const Text('插竖屏'), onPressed: () { showInterstitialAd(AdsConfig.interstitialId); }, ), const SizedBox(height: 10), ElevatedButton( - child: const Text('插横屏)'), + child: const Text('插横屏'), onPressed: () { showInterstitialAd(AdsConfig.interstitialIdHorizontal); }, ), const SizedBox(height: 10), ElevatedButton( - child: const Text('插半屏)'), + child: const Text('插半屏'), onPressed: () { showInterstitialAd(AdsConfig.interstitialIdHalf); }, @@ -121,7 +121,15 @@ class _HomePageState extends State { ], ), const SizedBox(height: 20), - const Center(child: Text('🏆 付费 Pro 版功能 🏆')), + const Center( + child: Text( + '🏆 Pro 版付费功能 🏆', + style: TextStyle( + color: Colors.purple, + fontWeight: FontWeight.bold, + ), + ), + ), const SizedBox(height: 10), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, diff --git a/example/lib/pro_page.dart b/example/lib/pro_page.dart index ebcf8e0..0f6de11 100644 --- a/example/lib/pro_page.dart +++ b/example/lib/pro_page.dart @@ -13,7 +13,7 @@ class _ProPageState extends State { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: const Text('Pro 付费功能'), + title: const Text('Pro 版付费功能'), ), body: SingleChildScrollView( child: Column( @@ -22,7 +22,7 @@ class _ProPageState extends State { child: Padding( padding: EdgeInsets.all(10.0), child: Text( - '此功能是插件 Pro 付费功能,需要购买插件后才能使用\n请联系微信:toponelan 咨询购买并获得技术支持', + '此功能是插件 Pro 版付费功能,需要购买插件后才能使用\n请联系微信:toponelan 咨询购买并获得技术支持', textAlign: TextAlign.center, ), ), @@ -35,7 +35,7 @@ class _ProPageState extends State { child: Padding( padding: EdgeInsets.all(10.0), child: Text( - '日活 10W 以上,可咨询其他合作模式,目前已合作百万级别的 App 客户', + '日活 10W 以上,可咨询其他合作模式,目前已有百万级别的客户在合作,获得了非常好的收益提升', textAlign: TextAlign.center, style: TextStyle( color: Colors.purple, diff --git a/ios/Classes/FlutterGromoreAdsPlugin.h b/ios/Classes/FlutterGromoreAdsPlugin.h index 379a17f..edcf8b0 100644 --- a/ios/Classes/FlutterGromoreAdsPlugin.h +++ b/ios/Classes/FlutterGromoreAdsPlugin.h @@ -8,8 +8,6 @@ @property (strong,nonatomic) FlutterEventSink eventSink;// 事件 @property (strong,nonatomic) FGMSplashPage *sad;// 开屏广告 @property (strong,nonatomic) FGMInterstitialPage *iad;// 插屏广告 -//@property (strong,nonatomic) FGMFeedAdLoad * fad;// 信息流广告加载 extern NSString *const kGMAdBannerViewId; -extern NSString *const kGMAdFeedViewId; @end diff --git a/ios/Classes/FlutterGromoreAdsPlugin.m b/ios/Classes/FlutterGromoreAdsPlugin.m index 2f86926..00bfcee 100644 --- a/ios/Classes/FlutterGromoreAdsPlugin.m +++ b/ios/Classes/FlutterGromoreAdsPlugin.m @@ -7,8 +7,6 @@ @implementation FlutterGromoreAdsPlugin // AdBannerView NSString *const kGMAdBannerViewId=@"flutter_gromore_ads_banner"; -// AdFeedView -NSString *const kGMAdFeedViewId=@"flutter_gromore_ads_feed"; + (void)registerWithRegistrar:(NSObject*)registrar { FlutterMethodChannel* methodChannel = [FlutterMethodChannel @@ -23,16 +21,13 @@ + (void)registerWithRegistrar:(NSObject*)registrar { // 注册平台View 工厂 FGMNativeViewFactory *bannerFactory=[[FGMNativeViewFactory alloc] initWithViewName:kGMAdBannerViewId withMessenger:registrar.messenger withPlugin:instance]; - FGMNativeViewFactory *feedFactory=[[FGMNativeViewFactory alloc] initWithViewName:kGMAdFeedViewId withMessenger:registrar.messenger withPlugin:instance]; // 注册 View [registrar registerViewFactory:bannerFactory withId:kGMAdBannerViewId]; - [registrar registerViewFactory:feedFactory withId:kGMAdFeedViewId]; } - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { NSString *methodStr=call.method; - NSLog(methodStr); if ([@"getPlatformVersion" isEqualToString:methodStr]) { result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]); }else if ([@"requestIDFA" isEqualToString:methodStr]) { @@ -43,10 +38,6 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { [self showSplashAd:call result:result]; }else if ([@"showInterstitialAd" isEqualToString:methodStr]) { [self showInterstitialAd:call result:result]; - }else if ([@"loadFeedAd" isEqualToString:methodStr]) { - [self loadFeedAd:call result:result]; - }else if ([@"clearFeedAd" isEqualToString:methodStr]) { - [self clearFeedAd:call result:result]; }else { result(FlutterMethodNotImplemented); } @@ -90,9 +81,6 @@ - (void) initAd:(FlutterMethodCall*) call result:(FlutterResult) result{ [BUAdSDKManager startWithAsyncCompletionHandler:^(BOOL success, NSError *error) { if (success) { -// dispatch_async(dispatch_get_main_queue(), ^{ -//// [self useMediationPreload]; -// }); result(@(YES)); } }]; @@ -117,35 +105,6 @@ - (void) showInterstitialAd:(FlutterMethodCall *)call result:(FlutterResult) res result(@(YES)); } -// 插屏全屏广告 -- (void) showInterstitialFullAd:(FlutterMethodCall *)call result:(FlutterResult) result{ -// self.ifad=[[FGMInterstitialFullPage alloc] init]; -// [self.ifad showAd:call eventSink:self.eventSink]; - result(@(YES)); -} - -// 全屏视频广告 -- (void) showFullVideoAd:(FlutterMethodCall *) call result:(FlutterResult) result{ -// self.fvad=[[FGMFullVideoPage alloc] init]; -// [self.fvad showAd:call eventSink:self.eventSink]; - result(@(YES)); -} - -// 加载信息流广告 -- (void) loadFeedAd:(FlutterMethodCall*) call result:(FlutterResult) result{ -// self.fad=[[FGMFeedAdLoad alloc] init]; -// [self.fad loadFeedAdList:call result:result eventSink:self.eventSink]; -} - -// 清除信息流广告 -- (void) clearFeedAd:(FlutterMethodCall*) call result:(FlutterResult) result{ - NSArray *list= call.arguments[@"list"]; - for (NSNumber *ad in list) { - [FGMFeedAdManager.share removeAd:ad]; - } - result(@(YES)); -} - #pragma mark - FlutterStreamHandler - (FlutterError *)onCancelWithArguments:(id)arguments{ diff --git a/ios/Classes/Page/FGMAdFeedView.h b/ios/Classes/Page/FGMAdFeedView.h deleted file mode 100644 index f9b8b64..0000000 --- a/ios/Classes/Page/FGMAdFeedView.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// FGMAdFeedView.h -// flutter_gromore_ads -// -// Created by Zero on 2023/2/3. -// - -#import "FGMBasePage.h" -#import "FGMFeedAdManager.h" -#import "FlutterGromoreAdsPlugin.h" - -@interface FGMAdFeedView : FGMBasePage -@property (strong,nonatomic,nullable) FlutterGromoreAdsPlugin *plugin; -@property int64_t viewId; - -- (nonnull instancetype)initWithFrame:(CGRect)frame - viewIdentifier:(int64_t)viewId - arguments:(id _Nullable)args - binaryMessenger:(NSObject* _Nullable)messenger plugin:(FlutterGromoreAdsPlugin* _Nullable) plugin; - -- (nonnull UIView*)view; -@end diff --git a/ios/Classes/Page/FGMAdFeedView.m b/ios/Classes/Page/FGMAdFeedView.m deleted file mode 100644 index 4c80d5e..0000000 --- a/ios/Classes/Page/FGMAdFeedView.m +++ /dev/null @@ -1,114 +0,0 @@ -// -// FGMAdFeedView.m -// flutter_gromore_ads -// -// Created by Zero on 2023/2/3. -// - -#import "FGMAdFeedView.h" -// -//@interface FGMAdFeedView() -//@property (strong,nonatomic) UIView *feedView; -//@property (strong,nonatomic) ABUNativeAdView *adView; -//@property (strong,nonatomic) FlutterMethodChannel *methodChannel; -//@end -// -//@implementation FGMAdFeedView -// -//- (instancetype)initWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId arguments:(id)args binaryMessenger:(NSObject *)messenger plugin:(FlutterGromoreAdsPlugin *)plugin{ -// if(self==[super init]){ -// self.viewId=viewId; -// self.feedView =[[UIView alloc] init]; -// self.methodChannel = [FlutterMethodChannel methodChannelWithName:[NSString stringWithFormat:@"%@/%lli",kGMAdFeedViewId,viewId] binaryMessenger:messenger]; -// FlutterMethodCall *call= [FlutterMethodCall methodCallWithMethodName:@"AdFeedView" arguments:args]; -// [self showAd:call eventSink:plugin.eventSink]; -// } -// NSLog(@"%s %lli",__FUNCTION__,viewId); -// return self; -//} -// -//- (UIView *)view{ -// return self.feedView; -//} -// -//- (void)dealloc{ -// NSLog(@"%s",__FUNCTION__); -//} -// -//- (void)loadAd:(FlutterMethodCall *)call{ -// NSNumber *key=[NSNumber numberWithInteger:[self.posId integerValue]]; -// self.adView=[FGMFeedAdManager.share getAd:key]; -// self.adView.delegate=self; -// self.adView.videoDelegate=self; -// [self.feedView addSubview:self.adView]; -// [self.adView render]; -//} -// -//// 处理消息 -//- (void) postMsghandler:(NSString*) event{ -// NSLog(@"%s postMsghandler event:%@",__FUNCTION__,event); -// if([event isEqualToString:onAdExposure]){ -// // 渲染成功,设置高度 -// CGSize size= self.feedView.frame.size; -// [self setFlutterViewSize:size]; -// }else if([event isEqualToString:onAdClosed]){ -// self.adView.delegate = nil; -// // 广告关闭移除广告,并且设置大小为 0,隐藏广告 -// [self.adView removeFromSuperview]; -// [self setFlutterViewSize:CGSizeZero]; -// } -//} -//// 设置 FlutterAds 视图宽高 -//- (void) setFlutterViewSize:(CGSize) size{ -// NSNumber *width=[NSNumber numberWithFloat:size.width]; -// NSNumber *height=[NSNumber numberWithFloat:size.height]; -// NSDictionary *dicSize=[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:width,height, nil] forKeys:[NSArray arrayWithObjects:@"width",@"height", nil]]; -// self.adView.center=self.feedView.center; -// [self.methodChannel invokeMethod:@"setSize" arguments:dicSize]; -//} -// -// -//- (void)nativeAdExpressViewRenderFail:(ABUNativeAdView *)nativeExpressAdView error:(NSError *)error{ -// NSLog(@"%s",__FUNCTION__); -// // 发送广告错误事件 -// [self sendErrorEvent:error]; -// [self postMsghandler:onAdClosed]; -//} -// -//- (void)nativeAdDidBecomeVisible:(ABUNativeAdView *)nativeAdView{ -// NSLog(@"%s",__FUNCTION__); -// // 发送广告事件 -// [self sendEventAction:onAdExposure]; -// [self postMsghandler:onAdExposure]; -//} -// -//- (void)nativeAdDidClick:(ABUNativeAdView *)nativeAdView withView:(UIView *)view{ -// NSLog(@"%s",__FUNCTION__); -// // 发送广告事件 -// [self sendEventAction:onAdClicked]; -//} -// -// -// -//- (void)nativeExpressAdViewWillShow:(ABUNativeAdView *)nativeExpressAdView{ -// NSLog(@"%s",__FUNCTION__); -// // 发送广告事件 -// [self sendEventAction:onAdExposure]; -//} -// -//- (void)nativeAdExpressViewDidClosed:(ABUNativeAdView *)nativeAdView closeReason:(NSArray *)filterWords{ -// NSLog(@"%s",__FUNCTION__); -// NSNumber *key=[NSNumber numberWithInteger:[nativeAdView hash]]; -// // 删除广告缓存 -// [FGMFeedAdManager.share removeAd:key]; -// // 发送广告事件 -// [self sendEventAction:onAdClosed]; -// // 关闭广告 -// [self postMsghandler:onAdClosed]; -//} -// -//- (void)nativeExpressAdViewDidRemoved:(ABUNativeAdView *)nativeExpressAdView{ -// NSLog(@"%s",__FUNCTION__); -//} -// -//@end diff --git a/ios/Classes/Page/FGMNativeViewFactory.m b/ios/Classes/Page/FGMNativeViewFactory.m index d043332..0376866 100644 --- a/ios/Classes/Page/FGMNativeViewFactory.m +++ b/ios/Classes/Page/FGMNativeViewFactory.m @@ -36,13 +36,6 @@ - (instancetype)initWithViewName:(NSString *)viewName withMessenger:(NSObject Date: Sun, 20 Aug 2023 20:42:10 +0800 Subject: [PATCH 14/14] =?UTF-8?q?1=E3=80=81=E6=9B=B4=E6=96=B0=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/zero/flutter_gromore_ads/FlutterGromoreAdsPlugin.java | 1 - 1 file changed, 1 deletion(-) diff --git a/android/src/main/java/com/zero/flutter_gromore_ads/FlutterGromoreAdsPlugin.java b/android/src/main/java/com/zero/flutter_gromore_ads/FlutterGromoreAdsPlugin.java index f9b0f13..321cda6 100644 --- a/android/src/main/java/com/zero/flutter_gromore_ads/FlutterGromoreAdsPlugin.java +++ b/android/src/main/java/com/zero/flutter_gromore_ads/FlutterGromoreAdsPlugin.java @@ -46,7 +46,6 @@ public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { methodChannel.setMethodCallHandler(delegate); eventChannel.setStreamHandler(delegate); this.delegate.registerBannerView(); - this.delegate.registerFeedView(); } @Override