A Flutter plugin that supports Pangle SDK on Android and iOS.

Overview

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] 3.9.0.5

[iOS] 3.9+

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

官方文档(需要登陆)

使用文档

范例截图

集成步骤

1. 添加yaml依赖

dependencies:
  # 添加依赖
  pangle_flutter: latest

2. Android和iOS额外配置

  • 基本配置入口

  • iOS版本依赖配置

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

    打开你flutter应用ios项目下的Podfile,在target 'Runner do上面添加如下代码即可(如果不熟悉Podfile,也可以参考本项目example/ios/Podfile里面的配置)。

# add code begin
  def flutter_install_ios_plugin_pods(ios_application_path = nil)
    # defined_in_file is set by CocoaPods and is a Pathname to the Podfile.
    ios_application_path ||= File.dirname(defined_in_file.realpath) if self.respond_to?(:defined_in_file)
    raise 'Could not find iOS application path' unless ios_application_path

    # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
    # referring to absolute paths on developers' machines.
      
    symlink_dir = File.expand_path('.symlinks', ios_application_path)
    system('rm', '-rf', symlink_dir) # Avoid the complication of dependencies like FileUtils.
      
    symlink_plugins_dir = File.expand_path('plugins', symlink_dir)
    system('mkdir', '-p', symlink_plugins_dir)
      
    plugins_file = File.join(ios_application_path, '..', '.flutter-plugins-dependencies')
    plugin_pods = flutter_parse_plugins_file(plugins_file)
    plugin_pods.each do |plugin_hash|
      plugin_name = plugin_hash['name']
      plugin_path = plugin_hash['path']
      if (plugin_name && plugin_path)
        symlink = File.join(symlink_plugins_dir, plugin_name)
        File.symlink(plugin_path, symlink)
      
        pod plugin_name, :path => File.join('.symlinks', 'plugins', plugin_name, 'ios')
        if plugin_name == 'pangle_flutter'
          # cn表示国内,global表示海外
          pod 'pangle_flutter/global', :path => File.join('.symlinks', 'plugins', plugin_name, 'ios')
        end
      
      end
    end
  end
  # add code end
  • Android版本依赖配置

    本项目默认依赖国内版本,如果你需要配置海外版本,以本插件example为例。在项目根目录下local.properties文件内配置一个属性,导入依赖方式同国内一样,查看配置方法

    # cn表示国内,global表示海外
    pangle_flutter.env=global

    海外版本使用方法基本与国内一致,需注意部分配置属性海外并不适用,在调用时填入了不存在的参数也不会有什么影响。

    pangle.init(
      iOS: IOSConfig(
        appId: kAppId,
        logLevel: PangleLogLevel.error,
      ),
      android: AndroidConfig(
        appId: kAppId,
        debug: false,
        allowShowNotify: true,
        allowShowPageWhenScreenLock: false,
        /// 海外不存在该配置
        directDownloadNetworkType: [
          AndroidDirectDownloadNetworkType.k2G,
        ]),
    )
    

使用说明

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),
);


/// 自定义类型
/// 同Widget类用法
SplashView(
  iOS: IOSSplashConfig(slotId: kSplashId, isExpress: false),
  android: AndroidSplashConfig(slotId: kSplashId, isExpress: false),
  backgroundColor: Colors.white,
  /// 广告展示
  onShow: (){},
  /// 广告获取失败
  onError: (int code, String message){},
  /// 广告被点击
  onClick: (){},
  /// 广告被点击跳过
  onSkip: (){},
  /// 广告倒计时结束
  onTimeOver: (){},
);

3. 激励视频广告

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

4. Banner广告

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

/// 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.updateTouchableBounds([Rect.zero]);
      // 传入Rect.zero无影响
      controller.updateRestrictedBounds([Rect.zero]);
    },
    onClick: () {},
  ),
),
  • 控制可点击区域(默认可点击)
// 因iOS的EXPRESS类型的广告内部使用WebView渲染,而WebView与FlutterView存在部分点击事件冲突,故提供该解决方案
onBannerViewCreated: (BannerViewController controller){
  // 禁止点击,传入一个Rect.zero即可
  controller.updateTouchableBounds([Rect.zero]);
  // 提供点击,传入空即可
  controller.updateTouchableBounds([]);

  // 额外不可点击区域(一般用于上面可点击范围上面,如可点击范围有一个悬浮按钮Widget)
  controller.updateRestrictedBounds([Rect.zero]);

},

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),
 );
  • 加载数据
/// 使用方法
/// 你的数据模型
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);
    });
  },
)
  • 控制可点击区域(默认可点击)
// 因iOS的EXPRESS类型的广告内部使用WebView渲染,而WebView与FlutterView存在部分点击事件冲突,故提供该解决方案
// 1. 可点击区域key
final _bodyKey = GlobalKey();
// 不可点击区域key
final _otherKey = GlobalKey();
// 2.FeedView移动区域
Container(
  key: _bodyKey,
  child: ListView.builder(
    itemCount: items.length,
    itemBuilder: (context, index) {
      return _buildItem(index);
    },
)),
// 可能覆盖在FeedView上的button
FloatingActionButton(
  key: _otherKey,
),
// 3. 获取FeedViewController并限制点击范围
 AspectRatio(
   aspectRatio: 375 / 284.0,
   child: FeedView(
     id: item.feedId,
     onFeedViewCreated: (controller) {
       // 限制FeedView点击范围
       _initConstraintBounds(controller);
     },
     onDislike: (option) {
       // 移除FeedView两部曲
       pangle.removeFeedAd([item.feedId]);
       setState(() {
         items.removeAt(index);
       });
     },
   ),
 )

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

  RenderBox bodyBox = _bodyKey.currentContext.findRenderObject();
  final bodyBound = PangleHelper.fromRenderBox(bodyBox);
  controller.updateTouchableBounds([bodyBound]);

  RenderBox otherBox = _otherKey.currentContext.findRenderObject();
  final otherBound = PangleHelper.fromRenderBox(otherBox);

  controller.updateRestrictedBounds([otherBound]);
}


// 4.清除缓存
// 可选,点击不喜欢即右上角叉时清除
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));

开发说明

  1. iOS信息流广告的点击事件需要传入rootViewController,使用的是(UIApplication.shared.delegate?.window??.rootViewController)!,暂未发现问题。
  2. BannerViewFeedView通过Hybrid Composition实现。在安卓上,PlatformView最低支持API 19。

贡献

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

交流

提交issue即可。

感谢赞助

Comments
  • Feed Express Ad信息流广告视频元素残留

    Feed Express Ad信息流广告视频元素残留

    1.简述问题 Feed Express Ad信息流广告,如果内部是视频类广告的话,当用户切换路由时,视频元素仍旧残留在用户界面上

    2.重现步骤 1、使用最新版本1.4.4,编译example内demo 2、依次点击 Express AD -> Feed Express AD 等待列表渲染 3、如果信息流中显示的是视频类广告,视频开始播放时,点击Dislike 跳转到新的路由

    3.期望结果 期望:界面上正在播放的视频类广告消失 实际:视频仍残留在界面上

    4.SDK版本:

    • flutter: 2.5.3
    • dart: 2.14.4
    • pangle_flutter: 1.4.4
    • android: 9
    • iOS:

    额外信息

    question 
    opened by alexjie 7
  • 引入pangle_flutter: 1.2.0报如下错误

    引入pangle_flutter: 1.2.0报如下错误

    Running Gradle task 'assembleDebug'...
    e: D:\app\flutter2.2.1\.pub-cache\hosted\pub.flutter-io.cn\pangle_flutter-1.2.0\android\src\main\cn\io\github\nullptrx\pangleflutter\delegate\FLTFullScreenVideoAd.kt: (54, 3): 'onFullScreenVideoCached' overrides nothing
    e: D:\app\flutter2.2.1\.pub-cache\hosted\pub.flutter-io.cn\pangle_flutter-1.2.0\android\src\main\cn\io\github\nullptrx\pangleflutter\delegate\FLTRewardedVideoAd.kt: (32, 3): 'onRewardVideoCached' overrides nothing
    pangle_flutter: cn
    
    FAILURE: Build failed with an exception.
    
    * What went wrong:
    Execution failed for task ':pangle_flutter:compileDebugKotlin'.
    > Compilation error. See log for more details
    
    * Try:
    Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
    
    * Get more help at https://help.gradle.org
    
    BUILD FAILED in 1m 20s
    Exception: Gradle task assembleDebug failed with exit code 1
    
    

    环境信息: Flutter 2.2.1 • channel stable • https://github.com/flutter/flutter.git Framework • revision 02c026b03c (7 weeks ago) • 2021-05-27 12:24:44 -0700 Engine • revision 0fdb562ac8 Tools • Dart 2.13.1

    pangle_flutter: 1.2.0

    opened by sinacn555 7
  • 1.0.0版本profile&release模式报错

    1.0.0版本profile&release模式报错

    Android resource linking failed
    build/pangle_flutter/intermediates/packaged_res/profile/drawable/pangle_flutter_placeholder.xml:8: AAPT: error: resource drawable/tt_playable_l_logo (aka :drawable/tt_playable_l_logo) not found.

    build/pangle_flutter/intermediates/packaged_res/profile/drawable-xxhdpi-v4/pangle_flutter_bg_placeholder.xml:4: AAPT: error: resource color/tt_cancle_bg (aka :color/tt_cancle_bg) not found.

    opened by xiangzy1 7
  • iOS接入1.5.0+1版本报错

    iOS接入1.5.0+1版本报错

    1.简述问题 项目中接入1.5.0+1版本,直接报错,主要是找不到几个类,可以看下额外信息的图片。

    2.重现步骤

    3.期望结果

    4.SDK版本:

    • flutter: 2.10.2
    • dart: 2.16.1
    • pangle_flutter: 1.5.0+1
    • android:
    • iOS: 15.2

    额外信息 截屏2022-03-09 21 00 38

    opened by LuodiJackShen 6
  • IOS: type 'BUAdSDKManager' has no member 'setIsPaidApp'

    IOS: type 'BUAdSDKManager' has no member 'setIsPaidApp'

    1.简述问题

    在一个新项目中使用 pangle_flutter 无法启动,完整错误信息如下:

    Launching lib/main.dart on iPhone 13 in debug mode...
    Xcode build done.                                           14.6s
    Failed to build iOS app
    Error output from Xcode build:
    ↳
        --- xcodebuild: WARNING: Using the first of multiple matching destinations:
        { platform:iOS Simulator, id:dvtdevice-DVTiOSDeviceSimulatorPlaceholder-iphonesimulator:placeholder, name:Any iOS Simulator Device }
        { platform:iOS Simulator, id:6DF789CD-1E03-4B77-8F74-E1E992A2F9A6, OS:15.0, name:iPhone 13 }
        { platform:iOS Simulator, id:5DBF6BCF-928C-46AB-99A2-25DCC2ECBAFE, OS:15.0, name:iPhone 13 Pro }
        { platform:iOS Simulator, id:8DEFF211-09F5-4337-B187-0465B09C4ED4, OS:15.0, name:iPhone 13 mini }
        { platform:iOS Simulator, id:5CCE74B8-4ABD-4E3E-9E22-0AC13555BB38, OS:15.0, name:iPhone SE (2nd generation) }
        { platform:iOS, id:dvtdevice-DVTiPhonePlaceholder-iphoneos:placeholder, name:Any iOS Device }
        ** BUILD FAILED **
    Xcode's output:
    ↳
        /Users/cipchk/.pub-cache/hosted/pub.flutter-io.cn/pangle_flutter-1.4.7/ios/Classes/PangleAdManager.swift:48:28: error: type 'BUAdSDKManager' has no member 'setIsPaidApp'
                    BUAdSDKManager.setIsPaidApp(isPaidApp!)
                    ~~~~~~~~~~~~~~ ^~~~~~~~~~~~
        /Users/cipchk/.pub-cache/hosted/pub.flutter-io.cn/pangle_flutter-1.4.7/ios/Classes/PangleAdManager.swift:56:42: error: cannot convert value of type 'UInt' to expected argument type 'Int'
                    BUAdSDKManager.setCoppa(coppa!)
                                                 ^
                                            Int(  )
        /Users/cipchk/Library/Developer/Xcode/DerivedData/Runner-ewjykgsqdascxtdttfmoiryshgtl/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/pangle_flutter.build/Objects-normal/x86_64/FLTTaskProtocol.dia:1:1: warning: Could not read serialized diagnostics file: error("Invalid diagnostics signature") (in target 'pangle_flutter' from project 'Pods')
        Command CompileSwift failed with a nonzero exit code
        /Users/cipchk/.pub-cache/hosted/pub.flutter-io.cn/pangle_flutter-1.4.7/ios/Classes/PangleAdManager.swift:48:28: error: type 'BUAdSDKManager' has no member 'setIsPaidApp'
                    BUAdSDKManager.setIsPaidApp(isPaidApp!)
                    ~~~~~~~~~~~~~~ ^~~~~~~~~~~~
        /Users/cipchk/.pub-cache/hosted/pub.flutter-io.cn/pangle_flutter-1.4.7/ios/Classes/PangleAdManager.swift:56:42: error: cannot convert value of type 'UInt' to expected argument type 'Int'
                    BUAdSDKManager.setCoppa(coppa!)
                                                 ^
                                            Int(  )
        /Users/cipchk/.pub-cache/hosted/pub.flutter-io.cn/pangle_flutter-1.4.7/ios/Classes/PangleAdManager.swift:48:28: error: type 'BUAdSDKManager' has no member 'setIsPaidApp'
                    BUAdSDKManager.setIsPaidApp(isPaidApp!)
                    ~~~~~~~~~~~~~~ ^~~~~~~~~~~~
        /Users/cipchk/.pub-cache/hosted/pub.flutter-io.cn/pangle_flutter-1.4.7/ios/Classes/PangleAdManager.swift:56:42: error: cannot convert value of type 'UInt' to expected argument type 'Int'
                    BUAdSDKManager.setCoppa(coppa!)
                                                 ^
                                            Int(  )
        /Users/cipchk/Library/Developer/Xcode/DerivedData/Runner-ewjykgsqdascxtdttfmoiryshgtl/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/pangle_flutter.build/Objects-normal/arm64/FLTTaskProtocol.dia:1:1: warning: Could not read serialized diagnostics file: error("Invalid diagnostics signature") (in target 'pangle_flutter' from project 'Pods')
        Command CompileSwift failed with a nonzero exit code
        /Users/cipchk/.pub-cache/hosted/pub.flutter-io.cn/pangle_flutter-1.4.7/ios/Classes/PangleAdManager.swift:48:28: error: type 'BUAdSDKManager' has no member 'setIsPaidApp'
                    BUAdSDKManager.setIsPaidApp(isPaidApp!)
                    ~~~~~~~~~~~~~~ ^~~~~~~~~~~~
        /Users/cipchk/.pub-cache/hosted/pub.flutter-io.cn/pangle_flutter-1.4.7/ios/Classes/PangleAdManager.swift:56:42: error: cannot convert value of type 'UInt' to expected argument type 'Int'
                    BUAdSDKManager.setCoppa(coppa!)
                                                 ^
                                            Int(  )
        /Users/cipchk/Desktop/flutter-demo/ios/Pods/libwebp/src/enc/backward_references_enc.c:694:12: warning: variable 'best_offset' may be uninitialized when used here [-Wconditional-uninitialized]
                  (best_offset << MAX_LENGTH_BITS) | (uint32_t)best_length;
                   ^~~~~~~~~~~
        /Users/cipchk/Desktop/flutter-demo/ios/Pods/libwebp/src/enc/backward_references_enc.c:626:20: note: initialize the variable 'best_offset' to silence this warning
            int best_offset;
                           ^
                            = 0
        1 warning generated.
        note: Using new build system
        note: Planning
        note: Build preparation complete
        note: Building targets in parallel
        /Users/cipchk/Desktop/flutter-demo/ios/Pods/Pods.xcodeproj: warning: The iOS Simulator deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 8.0, but the range of supported deployment target versions is 9.0 to 15.0.99. (in target 'libwebp' from project 'Pods')
        /Users/cipchk/Desktop/flutter-demo/ios/Pods/Pods.xcodeproj: warning: The iOS Simulator deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 8.0, but the range of supported deployment target versions is 9.0 to 15.0.99. (in target 'Mantle' from project 'Pods')
        /Users/cipchk/Desktop/flutter-demo/ios/Pods/Pods.xcodeproj: warning: The iOS Simulator deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 8.0, but the range of supported deployment target versions is 9.0 to 15.0.99. (in target 'FMDB' from project 'Pods')
        /Users/cipchk/Desktop/flutter-demo/ios/Pods/Pods.xcodeproj: warning: The iOS Simulator deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 8.0, but the range of supported deployment target versions is 9.0 to 15.0.99. (in target 'AlipaySDK-iOS' from project 'Pods')
    Could not build the application for the simulator.
    Error launching application on iPhone 13.
    Exited (sigterm)
    

    2.重现步骤

    • flutter create flutter-demo
    • pubspec.yaml 增加 pangle_flutter: ^1.4.7
    • main.dart 增加以下代码
    @override
    void initState() {
      super.initState();
      testInit();
    }
    
    Future testInit() async {
      await pangle.init(
        iOS: const IOSConfig(appId: "kAppId"),
        android: const AndroidConfig(appId: "kAppId"),
      );
    }
    

    3.期望结果

    4.SDK版本:

    • Flutter 2.5.3 • channel stable • https://github.com/flutter/flutter.git
    • Framework • revision 18116933e7 (6 weeks ago) • 2021-10-15 10:46:35 -0700
    • Engine • revision d3ea636dc5
    • Tools • Dart 2.14.4
    • pangle_flutter: 1.4.7
    • iOS: 15.0

    额外信息

    opened by cipchk 6
  • 支持模版渲染Banner

    支持模版渲染Banner

    日志打印 :D/BannerAdManager( 5831): 媒体在平台上申请的代码位“是否原生”属性与代码中使用的接口不匹配。例如:1. 媒体在平台上选择的是个性化模板banner广告的话,Android代码中请参考BannerExpressActivity进行调用;iOS代码中请参考BUDExpressBannerViewController进行调用。2. 媒体在平台上选择的是个性化模板插屏广告的话,代码中请参考InteractionExpressActivity进行调用;iOS代码位中请参考BUDExpressInterstitialViewController进行调用。 PS:模板广告会带有express字样标识。 40022

    image 我在穿山甲后台,只能创建这种bannerId,没得选其他形式的BannerId

    enhancement 
    opened by wumingman 6
  • 点击事件穿透到BannerView问题

    点击事件穿透到BannerView问题

    如果有Flutter Widget 在 BannerView 上面,点击该 Flutter Widget 时,BannerView也会收到点击事情并打开相应的广告。请问此问题是个BUG还是应该如何解决呢?

    谢谢!


    iOS上存在,Android没有测试。

    ➜  ~ flutter --version
    Flutter 2.5.0 • channel stable • https://github.com/flutter/flutter.git
    Framework • revision 4cc385b4b8 (8 days ago) • 2021-09-07 23:01:49 -0700
    Engine • revision f0826da7ef
    Tools • Dart 2.14.0
    

    pangle版本:v1.4.4 但好像这几个版本都有这个问题。 最近两个flutter稳定版本都一样,更早的没有测试。

    opened by zeewell 5
  • 你好,信息流广告显示有些问题。

    你好,信息流广告显示有些问题。

    现在信息流广告都是个性化的模板。 我试了下,显示不成功。 我测试发现,信息流的广告id可以获取成功,但是feedview显示不出来。 下面是错误信息,这个错误信息是界面返回的时候提示的(没显示成功,穿山甲sdk也更新到最新的)。 最后是显示广告代码, 请指教

    .io/pangle_feedview_2), stack: #0      MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:159:7)
    I/flutter (19919): <asynchronous suspension>
    I/flutter (19919): #1      MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:334:12)
    I/flutter (19919): #2      FeedViewController.remove (package:pangle_flutter/src/feed_view.dart:232:20)
    I/flutter (19919): #3      FeedViewState._remove (package:pangle_flutter/src/feed_view.dart:143:18)
    I/flutter (19919): #4      FeedViewState.dispose (package:pangle_flutter/src/feed_view.dart:73:5)
    I/flutter (19919): #5      StatefulElement.unmount (package:flutter/src/widgets/framework.dart:4773:12)
    I/flutter (19919): #6      _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1935:13)
    I/flutter (19919): #7      _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1933:7)
    I/flutter (19919): #8      SingleChildRenderObjectElement.visitChildren (package:flutter/src/widgets/framework.dart:5861:14)
    I/flutter (19919): #9      _InactiveEl
    I/flutter (19919): interceptors
    
    class FeedSimpleAdWidget extends StatefulWidget {
      @override
      _FeedSimpleAdWidgetState createState() => _FeedSimpleAdWidgetState();
    }
    
    class _FeedSimpleAdWidgetState extends State<FeedSimpleAdWidget> {
      bool removed = false;
    
      Future<String> _loadFeedData() async {
        print("feedad_id begin");
        PangleAd feedAd = await pangle.loadFeedAd(
          iOS: IOSFeedConfig(
            slotId: "xxxxxx",
            isExpress: true,
            imgSize: PangleImgSize.feed228_150,
            // slotId: kFeedId,
            count: 3,
            expressSize: PangleExpressSize(width: 375, height: 126)
          ),
          android: AndroidFeedConfig(
            slotId: "xxxxxxxxx",
            isExpress: true,
            imgSize: PangleImgSize.feed228_150,
            count: 3,
            expressSize: PangleExpressSize(width: 375, height: 126)
          ),
        );
        final feedAdDatas = feedAd.data;
        print("feedad_id ${feedAdDatas[0]}");
        return Future.value(feedAdDatas[0]);
      }
    
      @override
      Widget build(BuildContext context) {
        Size size = MediaQuery.of(context).size;
        double adWidth = (size.width-8*2.0);
        double adHeight = (adWidth*0.336);
        return Container(
          child: removed
              ? Container()
              : FutureBuilder(
                  future: _loadFeedData(),
                  builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
                    print("feedad future build ${snapshot.data}");
                    if (snapshot.connectionState == ConnectionState.done &&
                        !snapshot.hasError) {
                      return Container(
                        width: adWidth,
                        height: adHeight,
                        child: FeedView(
                          id: "${snapshot.data}",
                          isExpress: false,
                          onRemove: () {
                            setState(() {
                              removed = true;
                            });
                          },
                        ),
                      );
                    } else {
                      if(snapshot.hasError){
                        print("Error : ${snapshot.error}");
                      }
                      return Container();
                    }
                  },
                ),
        );
      }
    }
    
    opened by bigtotorouk 5
  • 打印日志问题

    打印日志问题

    为啥运行一直打印这个日志,疯狂打印,这有影响吗?我运行你demo也是这样。我关闭打印日志也不行

    E/SQLiteDatabase(30445): android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: trackurl.id (code 2067 SQLITE_CONSTRAINT_UNIQUE) E/SQLiteDatabase(30445): at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method) E/SQLiteDatabase(30445): at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:883) E/SQLiteDatabase(30445): at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:790) E/SQLiteDatabase(30445): at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:88) E/SQLiteDatabase(30445): at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1663) E/SQLiteDatabase(30445): at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1532) E/SQLiteDatabase(30445): at com.bytedance.sdk.openadsdk.core.g$c.a(DBHelper.java:127) E/SQLiteDatabase(30445): at com.bytedance.sdk.openadsdk.multipro.a.b.a(DBMultiProviderImpl.java:136) E/SQLiteDatabase(30445): at com.bytedance.sdk.openadsdk.multipro.f.a(TTProviderManager.java:166) E/SQLiteDatabase(30445): at com.bytedance.sdk.openadsdk.multipro.TTMultiProvider.insert(TTMultiProvider.java:50) E/SQLiteDatabase(30445): at android.content.ContentProvider.insert(ContentProvider.java:1645) E/SQLiteDatabase(30445): at android.content.ContentProvider$Transport.insert(ContentProvider.java:330) E/SQLiteDatabase(30445): at android.content.ContentResolver.insert(ContentResolver.java:2045) E/SQLiteDatabase(30445): at android.content.ContentResolver.insert(ContentResolver.java:2007) E/SQLiteDatabase(30445): at com.bytedance.sdk.openadsdk.multipro.a.a.a(DBMultiAdapter.java:41) E/SQLiteDatabase(30445): at com.bytedance.sdk.openadsdk.l.g.a(TrackRetryRepertoryImpl.java:61) E/SQLiteDatabase(30445): at com.bytedance.sdk.openadsdk.l.b$a.a(TrackAdUrlImpl.java:168) E/SQLiteDatabase(30445): at com.bytedance.sdk.openadsdk.l.b$a.doInBackground(TrackAdUrlImpl.java:98) E/SQLiteDatabase(30445): at android.os.AsyncTask$3.call(AsyncTask.java:394) E/SQLiteDatabase(30445): at java.util.concurrent.FutureTask.run(FutureTask.java:266) E/SQLiteDatabase(30445): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) E/SQLiteDatabase(30445): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) E/SQLiteDatabase(30445): at java.lang.Thread.run(Thread.java:923) D/DBMultiProviderImpl(30445): insert: content://io.github.nullptrx.pangleflutterexample.TTMultiProvider/t_db/ttopensdk.db/trackurl E/SQLiteDatabase(30445): Error inserting id=e1d1f8bc-63c7-4cc2-8570-8596070c2556_1599122746976 url=https://adsmis.duxiaoman.com/adsmis/api/toutiaomonitor?state=-1&cid=1674796367471630&adid=1674724351572012&mac=a2f3168fa6d0c8a1d701bc52734c2fff&idfa=&imei=&mac1=MAC1&aaid=AAID&androidid=&duid=DUID&udid=&lbs=0.000000x-0.000000x100.0&os=0&ip=171.44.171.43&timestamp=1599122685000&callback_url=http%3A%2F%2Fad.toutiao.com%2Ftrack%2Factivate%2F%3Fcallback%3DCKzwybDy5PwCEI7It9T-5vwCGOfeoNbQ9NsEIOfeoNbQ9NsEKIPQpc_GsPwCMA44lPHmwgNCKTM4ZGU0MzkyLWZkZmMtNDNjMy1hNGJhLTljMzg3NTk3NzAyYnUzOTU3SIDSk60DUABoiICK5OXRq6RfcIiAieTl0aukX3iN4OSfnMb7AoABs-Cmyunk_AI%3D%26os%3D0%26muid%3D&ad_name=wcErlE5O1599-%E7%B3%BB%E7%BB%9F-%E6%A8%AA%E7%89%88%E8%A7%86%E9%A2%91-%E6%B2%99%E5%8F%91%E5%AE%A2%E6%9C%8D-%E7%A9%BF%E5%B1%B1%E7%94%B2-%E9%80%9A%E6%8A%95-0811-%E6%89%8B%E5%8A%A8%E5%87%BA%E4%BB%B7-%E5%85%A8%E9%93%BE%E8%B7%AF&csite=900000000&ctype=5&ua=Mozilla%2F5.0+%28Linux%3B+Android+10%3B+Build%2FRPP2.200227.014.A1%3B+wv%29+AppleWebKit%2F537.36+%28KHTML%2C+like+Gecko%29+Version%2F4.0+Chrome%2F82.0.4062.3+Mobile+Safari%2F537.36&click_id=CLICK_ID&convert_id=CONVERT_ID&callback_param=CKzwybDy5PwCEI7It9T-5vwCGOfeoNbQ9NsEIOfeoNbQ9NsEKIPQpc_GsPwCMA44lPHmwgNCKTM4ZGU0MzkyLWZkZmMtNDNjMy1hNGJhLTljMzg3NTk3NzAyYnUzOTU3SIDSk60DUABoiICK5OXRq6RfcIiAieTl0aukX3iN4OSfnMb7AoABs-Cmyunk_AI=&req_id=38de4392-fdfc-43c3-a4ba-9c387597702bu3957&oaid=&cid_name=&campaign_id=1674721989603379&campaign_name=%E7%A9%BF%E5%B1%B1%E7%94%B2%E5%AF%B9%E7%85%A7%E7%BB%840811&request_id=38de4392-fdfc-43c3-a4ba-9c387597702bu3957&geo=GEO&model= retry=5 replaceholder=1 E/SQLiteDatabase(30445): android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: trackurl.id (code 2067 SQLITE_CONSTRAINT_UNIQUE) E/SQLiteDatabase(30445): at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method) E/SQLiteDatabase(30445): at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:883) E/SQLiteDatabase(30445): at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:790) E/SQLiteDatabase(30445): at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:88) E/SQLiteDatabase(30445): at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1663) E/SQLiteDatabase(30445): at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1532) E/SQLiteDatabase(30445): at com.bytedance.sdk.openadsdk.core.g$c.a(DBHelper.java:127) E/SQLiteDatabase(30445): at com.bytedance.sdk.openadsdk.multipro.a.b.a(DBMultiProviderImpl.java:136) E/SQLiteDatabase(30445): at com.bytedance.sdk.openadsdk.multipro.f.a(TTProviderManager.java:166) E/SQLiteDatabase(30445): at com.bytedance.sdk.openadsdk.multipro.TTMultiProvider.insert(TTMultiProvider.java:50) E/SQLiteDatabase(30445): at android.content.ContentProvider.insert(ContentProvider.java:1645) E/SQLiteDatabase(30445): at android.content.ContentProvider$Transport.insert(ContentProvider.java:330) E/SQLiteDatabase(30445): at android.content.ContentResolver.insert(ContentResolver.java:2045) E/SQLiteDatabase(30445): at android.content.ContentResolver.insert(ContentResolver.java:2007) E/SQLiteDatabase(30445): at com.bytedance.sdk.openadsdk.multipro.a.a.a(DBMultiAdapter.java:41) E/SQLiteDatabase(30445): at com.bytedance.sdk.openadsdk.l.g.a(TrackRetryRepertoryImpl.java:61) E/SQLiteDatabase(30445): at com.bytedance.sdk.openadsdk.l.b$a.a(TrackAdUrlImpl.java:168) E/SQLiteDatabase(30445): at com.bytedance.sdk.openadsdk.l.b$a.doInBackground(TrackAdUrlImpl.java:98) E/SQLiteDatabase(30445): at android.os.AsyncTask$3.call(AsyncTask.java:394) E/SQLiteDatabase(30445): at java.util.concurrent.FutureTask.run(FutureTask.java:266) E/SQLiteDatabase(30445): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) E/SQLiteDatabase(30445): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) E/SQLiteDatabase(30445): at java.lang.Thread.run(Thread.java:923) Application finished.

    bug 
    opened by nnianhouss 5
  • example中找不到podfile文件?

    example中找不到podfile文件?

    1.简述问题 objc[44845]: Class AMSupportURLConnectionDelegate is implemented in both /usr/lib/libauthinstall.dylib (0x2084e6c10) and /System/Library/PrivateFrameworks/MobileDevice.framework/Versions/A/MobileDevice (0x1149082b8). One of the two will be used. Which one is undefined. objc[44845]: Class AMSupportURLSession is implemented in both /usr/lib/libauthinstall.dylib (0x2084e6c60) and /System/Library/PrivateFrameworks/MobileDevice.framework/Versions/A/MobileDevice (0x114908308). One of the two will be used. Which one is undefined. ** BUILD FAILED **

    Xcode's output: ↳ /Users/xxxxx/soft-install/flutter/.pub-cache/hosted/pub.flutter-io.cn/pangle_flutter-1.4.6/ios/Classes/FLTSplashView.swift:83:53: error: cannot convert value of type 'CGFloat' to expected argument type 'Double' let width = expressArgs["width"] ?? uiframe.width ^ Double( ) /Users/xxxx/soft-install/flutter/.pub-cache/hosted/pub.flutter-io.cn/pangle_flutter-1.4.6/ios/Classes/FLTSplashView.swift:84:55: error: cannot convert value of type 'CGFloat' to expected argument type 'Double' 运行报错。

    我集成到ios中,测试开屏广告。 程序无法跑起来。出现上述问题。 我已按照穿山甲xcode的基本设置了 。 我的电脑是m1. pod的安装方式: arch -x86_64 pod install --repo-update

    4.SDK版本:

    • flutter: 2.5
    • dart:2.14
    • pangle_flutter:1.4.6
    • android:
    • iOS:
    opened by bigtotorouk 4
  • iOS使用 SplashView 限制不了宽高

    iOS使用 SplashView 限制不了宽高

    1.简述问题 iOS上使用SplashView,是全屏显示的,无法限制宽高。用示例项目测试也是如此。Android是正常的。

    2.重现步骤

    3.期望结果 iOS上使用SplashView,可以限制宽高。

    4.SDK版本:

    • flutter: 2.0.0
    • dart: 2.12
    • pangle_flutter: 1.4.4
    • android:
    • iOS: 14.5

    额外信息

    opened by 50431040 4
  • ios splash 开屏加载方法无回调

    ios splash 开屏加载方法无回调

    1.简述问题 ios 开屏广告采用默认模式关闭广告后没有返回,即loadSplashAd方法无返回一直等待 2.重现步骤 直接使用即可

    3.期望结果 广告关闭后返回结果

    4.SDK版本:

    • flutter:3.3.3
    • dart:
    • pangle_flutter:1.9.7
    • android:
    • iOS:16.1.1

    额外信息 FLTSplashAd中splashAdDidClose增加一个回调 方法 func splashAdDidClose(_ splashAd: BUSplashAd, closeType: BUSplashAdCloseType) { self.success?("close") splashAd.removeSplashView() } WX20221120-133023@2x

    opened by xypmhxy 0
  • Specifying subspec(global) in Podfile is not working.

    Specifying subspec(global) in Podfile is not working.

    1.简述问题 I want to use pangle global, so I specified subspec to global as written in Readme.md. After pod install, flutter run will fail with error below.

    image

    2.重现步骤 In ios/Podfile, choose global.

          if plugin_name == 'pangle_flutter'
            # cn表示国内,global表示海外
            pod 'pangle_flutter/global', :path => File.join('.symlinks', 'plugins', plugin_name, 'ios')
          else
            pod plugin_name, :path => File.join('.symlinks', 'plugins', plugin_name, 'ios')
          end
    

    Then build flutter project to iOS Simulator. You will see an error like below.

    ios/Runner/GeneratedPluginRegistrant.m:162:9: fatal error: module 'pangle_flutter' not found
        @import pangle_flutter;
         ~~~~~~~^~~~~~~~~~~~~~
    

    3.期望结果 Build successfully.

    4.SDK版本:

    • flutter: 3.3.5
    • dart: 2.18.2
    • pangle_flutter: 1.9.7
    • android:
    • iOS:

    额外信息 If I add some changes, it works. But I don't think this is not right way.

    1. In Podfile, specify the pod name equal to flutter package name.
          if plugin_name == 'pangle_flutter'
            # cn表示国内,global表示海外
            pod 'pangle_flutter', :path => File.join('.symlinks', 'plugins', plugin_name, 'ios')
          else
            pod plugin_name, :path => File.join('.symlinks', 'plugins', plugin_name, 'ios')
          end
    

    But, this will install pangle CN, so,

    1. In pangle_flutter.podspec, change default subspec to global.
      s.default_subspec   = 'global'
    

    It seems your library works with CN, but not with global. Please provide correct way to switch CN and global or if there is correct way and I have some mistakes, please inform me.

    opened by krgpi 3
  • Could not resolve org.jetbrains.kotlin:kotlin-stdlib-jdk7:[1.3.40,1.6.10]

    Could not resolve org.jetbrains.kotlin:kotlin-stdlib-jdk7:[1.3.40,1.6.10]

    1.简述问题 Execution failed for task ':pangle_flutter:mergeReleaseResources'.

    Could not resolve all files for configuration ':pangle_flutter:releaseRuntimeClasspath'. Could not resolve org.jetbrains.kotlin:kotlin-stdlib-jdk7:[1.3.40,1.6.10].

    2.重现步骤

    3.期望结果 buildscript { ext.kotlin_version = '[1.3.2, 1.6.0]' -> ext.kotlin_version = '1.6.0'

    4.SDK版本:

    • flutter: 3.0
    • dart:
    • pangle_flutter: 2.40
    • android:
    • iOS:

    额外信息 目前我手动改,绕过这个问题。

    invalid 
    opened by hangzhi22 1
Releases(v1.2.0)
Owner
null
A robust Flutter plugin for making payments via Paystack Payment Gateway. Completely supports Android and iOS

?? Paystack Plugin for Flutter A Flutter plugin for making payments via Paystack Payment Gateway. Fully supports Android and iOS. ?? Installation To u

Wilberforce Uwadiegwu 165 Jan 4, 2023
A flutter plugin for integrating razorpay payment gateway. Supports Android and iOS.

Flutter Razorpay Plugin A flutter plugin for razorpay integration for both android and ios. If you use this library in your app, please let me know an

Chetan Kaushik 28 Dec 13, 2022
A Flutter plugin to read 🔖 metadata of 🎵 media files. Supports Windows, Linux & Android.

flutter_media_metadata A Flutter plugin to read metadata of media files. A part of Harmonoid open source project ?? Install Add in your pubspec.yaml.

Harmonoid 60 Dec 2, 2022
Paystack SDK for iOS. Accept Payments on iOS

Paystack iOS SDK The Paystack iOS SDK make it easy to collect your users' credit card details inside your iOS app. By charging the card immediately on

Paystack 22 May 29, 2022
Cross platform application for iOS and Android using Google's SDK Flutter.

scout Cross platform application for iOS and Android using Google's SDK Flutter. Launch screen for the application. The menu for selecting cookies. Cu

null 0 Nov 9, 2021
Task List application developed in Dart language with SDK Flutter for Android, iOS and Web

Task List application developed in Dart language with SDK (Software Development Kit) Flutter for Android, iOS and Web.

João Bruno 2 Jun 2, 2022
Hybrid App build on flutter SDK able to run on Android, IOS, web, desktop

Codeforces Visualizer APP Ready to use Flutter Application. Uses codeforces API. Useful for codeforces programmers. ScreenShots Single User Page Compa

vikas yadav 13 Dec 31, 2022
Quickstart guide for the Agora Flutter SDK(Android/iOS)

Agora Flutter Quickstart This tutorial describes how to create an Agora account and build a sample app with Agora using Flutter. Other Languages: 简体中文

Agora.io Community 501 Dec 30, 2022
Generate a new file by compressed video, and provide metadata. Get video thumbnail from a video path, supports JPEG/GIF. To reduce app size not using FFmpeg in IOS.

flutter_video_compress Generate a new path by compressed video, Choose to keep the source video or delete it by a parameter. Get video thumbnail from

天海るり 179 Dec 8, 2022
Paystack SDK for Android. Accept payments on Android

Paystack Android This is a library for easy integration of Paystack with your Android application. Use this library in your Android app so we shoulder

Paystack 117 Dec 12, 2022
A Flutter plugin for Yandex AppMetrica SDK, a marketing platform for app install attribution, app analytics, and push campaigns.

appmetrica_sdk A Flutter plugin for Yandex AppMetrica SDK. Plugin implementation status Implemented Events Profiles Not implemented yet Revenue. Comin

EM ALL iT Studio 15 Oct 21, 2021
A Flutter plugin to retrieve and manage contacts on Android and iOS devices. Maintainer: @lukasgit

contacts_service A Flutter plugin to access and manage the device's contacts. Usage To use this plugin, add contacts_service as a dependency in your p

Lukas Dickie 166 Dec 28, 2022
A Flutter plugin for the Google Mobile Ads SDK

A Flutter plugin for the Google Mobile Ads SDK

Google Ads 251 Jan 2, 2023
Official plugin for using Thepeer SDK with flutter https://thepeer.co

Flutter Thepeer This package makes it easy to use the Thepeer in a flutter project. ?? Screen Shots ?? How to Use plugin ThePeer Send Launch ThepeerSe

The Peer 23 Dec 27, 2022
Official plugin for using Thepeer SDK with flutter https://thepeer.co

Flutter Thepeer This package makes it easy to use the Thepeer in a flutter project. ?? Screen Shots ?? How to Use plugin Adding MaterialSupport Add th

Thepeer 23 Dec 27, 2022
A Flutter plugin for playing music on iOS and Android.

Stereo plugin for Flutter A Flutter plugin for playing music on iOS and Android. Features Play/pause Stop Duration / seek to position Load track from

2find 67 Sep 24, 2022
A flutter IM plugin for android and ios

flutter_openim_sdk Download demo flutter_openim_widget A flutter IM plugin for android and ios. Getting Started 1,Add dependency in yaml flutter_op

kostia7alania 1 Dec 3, 2021
Video player-2.2.10 - A Flutter plugin for iOS, Android and Web for playing back video on a Widget surface

Video Player plugin for Flutter A Flutter plugin for iOS, Android and Web for pl

null 2 Sep 29, 2022
A chatting app made with Flutter and FireBase. It supports GIPHY gifs, images, stcikers, dark mode, custom animations, google login, online storage, beautiful UI and more.

ChatMe A Flutter based chatting app which lets user chat from random peoples or strangers, has GIPHY gif support, sitckers, custom animations, dark mo

Hash Studios 20 Nov 7, 2022