Skip to content

Flutter版穿山甲SDK,支持Android、iOS。A Flutter plugin that supports Pangle SDK on Android and iOS.

License

Notifications You must be signed in to change notification settings

lianfanghua/pangle_flutter

 
 

Repository files navigation

Thanks for non-commercial open source development authorization by JetBrains.

穿山甲 Flutter SDK

`pangle_flutter`是一款集成了字节跳动穿山甲 Android 和 iOS SDK的 Flutter 插件。


目录

原生平台相关范例:

版本迁移

  1. 不再需要传入isExpress参数
  2. BannerView, FeedView, SplashView均需要包一层限制大小的Widget, 可选Container, SizeBox, AspectRatio, Expanded等
  3. BannerView, FeedView, SplashView的控制点击实现变动,可参考example进行更改。

SDK对应版本

  • 已经内部依赖相关sdk,无需额外导入。如需替换新的sdk,请自行fork本项目更改依赖。

[Android] 5.0+

[iOS] 5.0+

注:如果出现高版本不兼容问题,可联系我升级适配,或者使用上面指定版本。

官方文档(需要登陆)

使用文档

范例截图

集成步骤

1. 添加yaml依赖

dependencies:
  # 添加依赖
  pangle_flutter: latest

2. Android和iOS额外配置

  • 基本配置入口

  • iOS版本依赖配置

    本项目默认集成Ads-CN, 如果你是国内APP,无需额外配置;如果你是海外APP,请参照如下配置:(已移除)

  • 使用说明

支持开屏广告、激励视频、全屏视频(新模板渲染插屏广告)、模板渲染信息流、模板渲染插屏、模板渲染Banner。(如有自渲染广告位请联系我,或提交Feature request)

1. 信息流广告

pangle_flutter

pangle_flutter

2. iOS使用纯OC开发的项目导入该模块

  1. 创建一个Swift文件,名称随意
  2. 根据提示选择Create Bridging Header。如果没有提示,请自行搜索如何创建。

OC导入Swift模块

使用说明

1. 初始化

import 'package:pangle_flutter/pangle_flutter.dart';
/// 如果在runApp方法调用之前初始化,加入下面这句代码
WidgetsFlutterBinding.ensureInitialized();
/// 初始化,未列出所有参数
/// [kAppId] 申请穿山甲广告位后得到的appID
await pangle.init(
  iOS: IOSConfig(appId: kAppId),
  android: AndroidConfig(appId: kAppId),
);

2. 开屏广告

/// 全屏类型
/// [kSplashId] 开屏广告ID, 对应Android的CodeId,对应iOS的slotID
await pangle.loadSplashAd(
  iOS: IOSSplashConfig(slotId: kSplashId, isExpress: false),
  android: AndroidSplashConfig(slotId: kSplashId, isExpress: false),
);


/// 自定义类型
/// AndroidViewSurface支持
@override
void initState() {
  super.initState();
  SplashView.platform = SurfaceAndroidSplashView(hybridComposition: false);
}

/// 同Widget类用法
SplashView(
  iOS: IOSSplashConfig(slotId: kSplashId, isExpress: false),
  android: AndroidSplashConfig(slotId: kSplashId, isExpress: false),
  backgroundColor: Colors.white,
  /// 广告展示
  onShow: (){},
  /// 广告获取失败
  onError: (int code, String message){},
  /// 广告被点击
  onClick: (){},
  /// 广告已结束
  onClose: (){},
);

3. 激励视频广告

/// [kRewardedVideoId] 激励视频广告ID, 对应Android的CodeId,对应iOS的slotID
pangle.loadRewardVideoAd(
   iOS: IOSRewardedVideoConfig(slotId: kRewardedVideoId),
   android: AndroidRewardedVideoConfig(slotId: kRewardedVideoId),
 );

4. Banner广告

基本覆盖了原生回调事件,现在点击右上角关闭[ x ]按钮,需要开发者手动移除,不再自动移除Item。

/// AndroidViewSurface支持
@override
void initState() {
  super.initState();
  BannerView.platform = AndroidBannerView(hybridComposition: false);
}

/// Banner通过PlatformView实现,使用方法同Widget
/// [kBannerId] Banner广告ID, 对应Android的CodeId,对应iOS的slotID
BannerView(
  iOS: IOSBannerAdConfig(slotId: kBannerId),
  android: AndroidBannerAdConfig(slotId: kBannerId),
  // 还有其他回调,具体可导入查看
),


// 必须限定范围大小,可用Expaned,Container,SizeBox,AspectRatio等
Container(
  height: 260,
  child: BannerView(
    iOS: IOSBannerConfig(
      slotId: kBannerExpressId600x260,
      expressSize: PangleExpressSize(width: 600, height: 260),
    ),
    android: AndroidBannerConfig(
      slotId: kBannerExpressId600x260,
      expressSize: PangleExpressSize(width: 600, height: 260),
    ),
    onBannerViewCreated: (BannerViewController controller){
      // 传入[Rect.zero]与[]均为无额外点击区域
      controller.addTouchableBounds([Rect.zero]);
      // 清空额外点击区域
      controller.clearTouchableBounds();
    },
    onClick: () {},
  ),
),

5. 信息流广告

基本覆盖了原生回调事件,现在点击右上角关闭[ x ]按钮,需要开发者手动移除,不再自动移除Item。

  • 获取信息流数据
/// 信息流实现逻辑
/// 首先进行网络请求,得到信息流数据
///
/// PangleFeedAd相应字段: 
/// [code] 响应码,0成功,-1失败
/// [message] 错误时,调试信息
/// [count] 获得信息流数量,一般同上面传入的count,最终结果以此count为主
/// [data] (string list) 用于展示信息流广告的键id
 PangleFeedAd feedAd = await pangle.loadFeedAd(
   iOS: IOSFeedAdConfig(slotId: kFeedId, count: 2),
   android: AndroidFeedAdConfig(slotId: kFeedId, count: 2),
 );
  • 加载数据
/// AndroidViewSurface支持
@override
void initState() {
  super.initState();
  FeedView.platform = AndroidFeedView(hybridComposition: false);
}

/// 使用方法
/// 你的数据模型
class Item {
  /// 添加字段
  final String feedId;
}
final items = <Item>[];
final feedAdDatas = feedAd.data;
final items = Item(feedId: feedAdDatas[0]);
items.insert(Random().nextInt(items.length), item);
/// Widget使用
FeedView(
  id: item.feedId,
  onRemove: () {
    setState(() {
      items.removeAt(index);
    });
  },
)
  • 清除缓存
 AspectRatio(
   aspectRatio: 375 / 284.0,
   child: FeedView(
     id: item.feedId,
     onDislike: (option) {
       // 1.移除FeedView两步
       
       // 可在dispose方法处移除所有(此处可选)
       pangle.removeFeedAd([item.feedId]);
       // 移除界面上的显示
       setState(() {
         items.removeAt(index);
       });
     },
   ),
 )

// 可选,点击不喜欢即右上角叉时清除
pangle.removeFeedAd([item.feedId]);

// 必须
@override
void dispose() {
  /// 不关心返回值
  pangle.removeFeedAd(feedIds);
  /// 关心返回值
  /// _removeFeedAd();
  super.dispose();
}

/// 移除广告
_removeFeedAd() async {
  /// 返回移除个数
  int count = await pangle.removeFeedAd(feedIds);
  print('Feed Ad Removed: $count');
}

6. 插屏广告

 final result = await pangle.loadInterstitialAd(
   iOS: IOSInterstitialAdConfig(
     slotId: kInterstitialId

     /// 该宽高为你申请的广告位宽高,请根据实际情况赋值
     expressSize: PangleExpressSize(width: width, height: height),
   ),
   android: AndroidInterstitialAdConfig(
     slotId: kInterstitialId,
   ),
 );
print(jsonEncode(result));

7. 点击穿透

本方案适用于SplashViewFeedViewBannerView

当我们点击覆盖在广告View上方的Widget时,最优先响应该事件的View是用来渲染被原生广告遮挡的Widget layer 的FlutterOverlayView,而FlutterOverlayView在初始化时被禁用了用户交互响应userInteractionEnabled=NO,所以点击事件就会在广告View上被响应。因采用方案Flutter原生广告优化处理了点击穿透问题,广告可点击区域存在屏蔽过度的情况,故增加方法添加额外点击区域。

  • 添加可点击区域(此处使用FeedView作为范例)
// 1.广告不可点击区域key
final _otherKey = GlobalKey();
// 2.可能覆盖在FeedView上的button
FloatingActionButton(
  key: _otherKey,
),
// 3. 获取FeedViewController并添加点击范围
 AspectRatio(
   aspectRatio: 375 / 284.0,
   child: FeedView(
     id: item.feedId,
     onFeedViewCreated: (controller) {
       // 限制FeedView点击范围
       _initConstraintBounds(controller);
     },
   ),
 )

_initConstraintBounds(FeedViewController controller) {
  if (!Platform.isIOS) {
    return;
  }

  RenderBox otherBox = _otherKey.currentContext.findRenderObject();
  final otherBound = PangleHelper.fromRenderBox(otherBox);
  final targetBound = Rect.fromLTWH(
    0,
    otherBound.top,
    kPangleScreenWidth - otherBound.width,
    otherBound.height,
  );
  controller.addTouchableBound(targetBound);
}

8. 其他广告

另外已实现全屏视频广告、新模板渲染插屏,使用方式大同小异。

贡献

  • 有任何更好的实现方式或增加额外的功能,提交PR
  • 有任何使用上的问题,提交 issue

交流

提交issue即可。

感谢赞助

BokAugust

About

Flutter版穿山甲SDK,支持Android、iOS。A Flutter plugin that supports Pangle SDK on Android and iOS.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Dart 55.0%
  • Kotlin 25.7%
  • Swift 18.8%
  • Other 0.5%