Flutter插件flutter_gromore的特性与使用方法

Flutter插件flutter_gromore的特性与使用方法

Flutter插件flutter_gromore特点

  • 引入了最新的融合SDK(具体新特性请查看官方文档)
  • 使用Kotlin和Swift语言开发
  • 提供了较为完整的广告配置和回调事件
  • 开屏广告支持配置Logo及自定义渲染

Flutter插件flutter_gromore支持平台

  • ✅ Android
  • ✅ iOS

Flutter插件flutter_gromore支持功能

  • ✅ 开屏广告
  • ✅ 插屏广告
  • ✅ 信息流广告
  • ✅ Banner广告
  • ✅ 激励视频广告

2.x版本特性

  • 引入融合SDK
  • 插件内部移除了某些参数/回调事件
  • 接入变得更加简单
  • 支持SurfaceView,提升Android广告性能

接入文档

初始工作

具体内容请参考官方SDK接入文档。

Android
  1. 将Gromore SDK【open_ad_sdk_6.0.1.4.arr】拷贝到资源目录(例如:android/app/libs)下,添加除穿山甲以外的广告SDK和对应的适配器,下面添加了广点通、百度和快手。
dependencies {
    // 广点通 SDK
    implementation (name: 'GDTSDK.unionNormal.4.563.1433', ext: 'aar')
    // 广点通 Adapter
    implementation(name: 'mediation_gdt_adapter_4.563.1433.0', ext: 'aar')
    // 百度SDK
    implementation(name: 'Baidu_MobAds_SDK_v9.34', ext: 'aar')
    // 百度 Adapter
    implementation(name: 'mediation_baidu_adapter_9.34.0', ext: 'aar')
    // 快手SDK
    implementation(name: 'kssdk-ad-3.3.59', ext: 'aar')
    // 快手 Adapter
    implementation(name: 'mediation_ks_adapter_3.3.59.0', ext: 'aar')
}
  1. AndroidManifest.xml中手动添加对应adn的配置项(具体请参考官方文档)
<!-- GDT start================== -->
<!-- targetSDKVersion >= 24时才需要添加这个provider。provider的authorities属性的值为${applicationId}.fileprovider,请开发者根据自己的${applicationId}来设置这个值,例如本例中applicationId为"com.qq.e.union.demo"。 -->
<provider
          android:name="com.qq.e.comm.GDTFileProvider"
          android:authorities="${applicationId}.gdt.fileprovider"
          android:exported="false"
          android:grantUriPermissions="true">
  <meta-data
             android:name="android.support.FILE_PROVIDER_PATHS"
             android:resource="@xml/gdt_file_path" />
</provider>

<activity
          android:name="com.qq.e.ads.PortraitADActivity"
          android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
          android:screenOrientation="portrait" />
<activity
          android:name="com.qq.e.ads.LandscapeADActivity"
          android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
          android:screenOrientation="landscape"
          tools:replace="android:screenOrientation" />

<!-- 声明SDK所需要的组件 -->
<service
         android:name="com.qq.e.comm.DownloadService"
         android:exported="false" />
<!-- 请开发者注意字母的大小写,ADActivity,而不是AdActivity -->

<activity
          android:name="com.qq.e.ads.ADActivity"
          android:configChanges="keyboard|keyboardHidden|orientation|screenSize" />
<!-- GDT end================== -->

<!-- baidu start================== -->
<!-- 声明打开落地页的Activity(不建议修改主题配置)-->
<activity
          android:name="com.baidu.mobads.sdk.api.AppActivity"
          android:configChanges="screenSize|keyboard|keyboardHidden|orientation"
          android:theme="@android:style/Theme.NoTitleBar" />
<!-- 声明打开显示激励视频/全屏视频的Activity-->
<activity
          android:name="com.baidu.mobads.sdk.api.MobRewardVideoActivity"
          android:configChanges="screenSize|orientation|keyboardHidden"
          android:launchMode="singleTask"
          android:theme="@android:style/Theme.Translucent.NoTitleBar" />

<!-- 如果targetSdkVersion设置值>=24,则强烈建议添加以下provider,否则会影响app变现 -->
<!-- android:authorities="${packageName}.bd.provider" authorities中${packageName}部分必须替换成app自己的包名 -->
<!-- 原来的FileProvider在新版本中改为BdFileProvider,继承自v4的FileProvider,需要在应用内引用support-v4包 -->
<provider
          android:name="com.baidu.mobads.sdk.api.BdFileProvider"
          android:authorities="${applicationId}.bd.provider"
          android:exported="false"
          android:grantUriPermissions="true">
  <meta-data
             android:name="android.support.FILE_PROVIDER_PATHS"
             android:resource="@xml/bd_file_paths" />
</provider>
<!-- baidu end================== -->
  1. 代码混淆及资源混淆配置,请务必配置!!!(参考官方文档)
iOS
  1. 引入除穿山甲以外的SDK和适配器,案例中使用 CocoaPods 引入百度和广点通,可见 example/ios/Podfile 。引入时需要注意 Adapter 所支持的 SDK 版本范围,可在 GroMore 接入文档查看。
  2. 在XCode中添加依赖库【 TARGETS -> Build Phases 中添加…】
  3. 建议允许 http 访问,info.plist 添加:
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

授权

  1. 请求非必要权限(仅Android) 方法已废弃,开发者请自行申请相关权限
FlutterGromore.requestPermissionIfNecessary(); // 已废弃

修改AndroidManifest配置(注:插件内部已经添加了必要权限,如下所示,可选权限参考官方文档)

<!-- 必要权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

<!-- 可选权限 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!--suppress DeprecatedClassUsageInspection -->
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />

<!--可选权限,申请后用于防作弊功能以及有助于广告平台投放广告-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<permission
            android:name="${applicationId}.openadsdk.permission.TT_PANGOLIN"
            android:protectionLevel="signature" />
<uses-permission android:name="${applicationId}.openadsdk.permission.TT_PANGOLIN" />

<!--建议添加“query_all_package”权限,穿山甲将通过此权限在Android R系统上判定广告对应的应用是否在用户的app上安装,避免投放错误的广告,以此提高用户的广告体验。若添加此权限,需要在您的用户隐私文档中声明! -->
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />

<!--可选权限,视情况添加,参考官方文档-->
  1. ATT授权(仅iOS) 从iOS 14开始,只有在获得用户明确许可的前提下,应用才可以访问用户的IDFA数据并向用户投放定向广告。在应用程序调用 App Tracking Transparency 框架向最终用户提出应用程序跟踪授权请求之前,IDFA将不可用。如果某个应用未提出此请求,则读取到的IDFA将返回全为0的字符串,这个可能会导致广告收入降低。
FlutterGromore.requestATT();

info.plist 中添加描述

<key>NSUserTrackingUsageDescription</key>
<string>ATT权限使用说明,需要开发者自行设置描述</string>

可配置 SKAdNetwork ,让 iOS 14 以上版本 IDFA 不可用时进行归因,参考 穿山甲 GroMore iOS14 适配说明

初始化SDK

新增参数:useMediation 是否使用聚合功能,默认为false

bool initResult = await FlutterGromore.initSDK(
  appId: "",
  appName: "",
  debug: true,
  useMediation: true);
参数名 说明 必选
appId
appName
debug debug模式,默认为true
useMediation 是否使用聚合
paid 是否为计费用户,默认为false。仅作用于Android
allowShowNotify 是否允许SDK弹出通知,默认为false。仅作用于Android
useTextureView 是否使用TextureView播放视频,默认为false。仅作用于Android
supportMultiProcess 是否支持多进程,默认为false。仅作用于Android
themeStatus 主题模式设置,0是正常模式;1是夜间模式。默认为正常模式

若需要添加本地缓存配置,请将文件 gromore_local_config 放在 android/src/main/assets/ 目录下,初始化时会尝试加载该文件配置

开屏广告

  1. 说明
  • 开屏广告提供了两种方式:第一种是自渲染(仅Android端可用,不建议使用,后续将不进行维护),第二种是拉起原生Activity
  • 自渲染方式以Widget的方式提供
  • 原生页面方式支持传入logo,渲染时logo会在底部显示(logo值不需要文件后缀)
  • 经线上反馈,部分场景下会导致开屏广告的activity无法关闭。所以增加了延时器自动关闭,事件为 onAutoCloseonAutoSkip
  1. 使用
// 拉起开屏页(会等待广告关闭或广告渲染失败)
await FlutterGromore.showSplashAd(
  config: GromoreSplashConfig(
    adUnitId: GoMoreAdConfig.splashId, logo: "launch_image"),
  callback: GromoreSplashCallback(onAdShow: () {
    print("callback --- onAdShow");
}));

// 自渲染(由于iOS端SDK未提供相关支持,因此仅适用于安卓,后续将不进行维护)
child: GromoreSplashView(
  creationParams: GromoreSplashConfig(
    adUnitId: GoMoreAdConfig.splashId, height: height - 80),
  callback: GromoreSplashCallback(
    onAdEnd: () {
      Navigator.pop(context);
    }
),),
  1. 参数(GromoreSplashConfig) | 参数名 | 说明 | 必选 | | ------------ | ---------------------- | ---- | | adUnitId | 聚合开屏广告位id | 是 | | width | 广告宽度(自定义渲染可用) | 否 | | height | 广告高度(自定义渲染可用) | 否 | | logo | 如果传入了logo则会在底部显示logo,Android放在android/app/src/main/res/mipmap下,iOS放在Assets中,值不需要文件后缀(非自定义渲染可用)。不传则全屏显示。 | 否 | | muted | 静音,默认为true | 否 | | preload | 预加载,默认为true。仅Android可用 | 否 | | volume | 声音配置,与muted配合使用,默认为1。仅Android可用 | 否 | | buttonType | 按钮样式(1:全屏可点击,2:仅按钮可点击,默认为1) | 否 | | downloadType | 点击下载样式(0或者1,默认为1) | 否 | | splashShakeButton | 开屏摇一摇开关,默认为true。仅Android可用 | 否 | | bidNotify | bidding类型广告,竞价成功或者失败后是否通知对应的adn,默认为false | 否 | | timeout | 超时时间,默认为3500,单位:毫秒 | 否 | | useSurfaceView | 是否使用SurfaceView,默认为true。建议开启,仅对Android生效 | 否 |

  2. 回调(GromoreSplashCallback) | 回调方法名 | 说明 | | ------------------ | -------------------- | | onAdClicked | 点击 | | onAdShow | 展示成功 | | onSplashAdLoadFail | 加载失败 | | onSplashAdLoadSuccess | 加载成功 | | onSplashRenderSuccess | 渲染成功。貌似iOS不会触发回调 | | onSplashRenderFail | 渲染失败。貌似iOS不会触发回调 | | onSplashAdClose | 关闭 | | onAdEnd | 开屏广告结束,这个时候会销毁广告(点击跳过、倒计时结束或渲染错误等理应隐藏广告的情况都会触发此回调,建议统一在此回调处理路由跳转等逻辑) | | onAutoClose | 开屏广告自动关闭,超过6s未触发onAdShow回调时会执行(由于存在异常场景,导致广告无法正常展示,但无相关回调) | | onAutoSkip | 开屏广告自动跳过,onAdShow回调触发后6s内未关闭广告时会执行(由于存在部分场景,导致广告无法跳过) |

插屏广告

  1. 说明
  • 该广告类型支持插屏、全屏混出(穿山甲插屏/全屏代码位已无法新建,都使用GroMore【插全屏】广告位代替)
  • 先加载广告id,成功后再渲染展示
  • 某些1.x版本的参数/回调已经废弃
  1. 使用
// 加载全屏广告
interstitialId = await FlutterGromore.loadInterstitialAd(
    GromoreInterstitialConfig(
        adUnitId: GroMoreAdConfig.interstitialId,
        size: GromoreAdSize.withPercent(
            MediaQuery.of(context).size.width * 2 / 3, 2 / 3)));
if (interstitialId.isEmpty) {
    print("加载全屏广告失败");
}

// 合适的时机展示插屏广告
if (interstitialId.isNotEmpty) {
    await FlutterGromore.showInterstitialAd(
        interstitialId: interstitialId,
        callback: GromoreInterstitialCallback(onInterstitialShow: () {
            print("===== showInterstitialAd success ======");
        }, onInterstitialClosed: () {
            FlutterGromore.removeInterstitialAd(interstitialId);
            interstitialId = "";
            loadInterstitialAd();
        }));
}
  1. 配置(GromoreInterstitialConfig) | 参数名 | 说明 | 必填 | | ------------ | -------------- | ---- | | adUnitId | 插屏广告位id | 是 | | orientation | 设置横竖,仅Android可用。竖屏为1,横屏为2。默认竖屏 | 否 | | muted | 是否静音,默认为true | 否 | | useSurfaceView | 是否使用SurfaceView,默认为true。建议开启,仅对Android生效 | 否 |

  2. 回调(GromoreSplashCallback,命名和 Android 聚合文档基本一致) | 回调方法名 | 说明 | 备注 | | -------------------- | -------------- | ---- | | onInterstitialShow | 广告展示 | | | onInterstitialShowFail | 展示失败 | 仅iOS可用 | | onInterstitialAdClick | 广告被点击 | | | onInterstitialClosed | 广告关闭 | |

信息流广告

  1. 说明
  • 先加载广告id,成功后再渲染展示
  • 渲染成功回调中(onRenderSuccess)提供了一个参数,表示渲染后的广告高度,可以用来动态控制组件显示与否
  • 广告加载成功后会存放在内存当中,当广告不再展示时(用户主动关闭、某种条件触发关闭等场景)开发者不需要手动移除缓存中的广告,因为插件内部在销毁时会进行处理。(当然也提供了 removeCacheFeedAd 方法来手动移除)
  • 具体使用参考example
  1. 使用
// 加载信息流广告
List<String> idList = await FlutterGromore.loadFeedAd(GromoreFeedConfig(adUnitId: GroMoreAdConfig.feedId));
if (idList.isNotEmpty) {
    String id = idList.removeLast();
    feedAdIdList.addAll(idList);
    return id;
} else {
    // 加载信息流广告失败
}

// 展示信息流广告
GromoreFeedView(
  creationParams: {
      "feedId": _feedAdId!
  },
  callback: GromoreFeedCallback(
    onRenderSuccess: (double height) {
      print("GromoreFeedView | onRenderSuccess | $height");
      setState(() {
        _height = height;
      });
    },
    onSelected: () {
      setState(() {
        _show = false;
      });
    },
    onAdTerminate: () {
      setState(() {
        _show = false;
      });
    }
))
  1. 配置(GromoreFeedConfig) | 参数名 | 说明 | 必填 | | ------------ | -------------- | ---- | | adUnitId | 信息流广告位id | 是 | | count | 请求数量,默认为3 | 否 | | width | 宽度,默认宽度占满。double类型 | 否 | | height | 高度,默认150。double类型 | 是 | | useSurfaceView | 是否使用SurfaceView,默认为true。建议开启,仅对Android生效 | 否 |

  2. 回调(GromoreFeedCallback,命名和 Android 聚合文档基本一致) | 回调方法名 | 说明 | 备注 | | ---------------- | -------------- | ---- | | onAdClick | 信息流广告点击 | | | onAdShow | 信息流广告在视图中展示 | | | onRenderFail | 模板渲染失败 | | | onRenderSuccess | 模板渲染成功 | 此回调有一个参数:height,表示广告渲染后高度 | | onSelected | 用户选择不喜欢原因 | | | onCancel | 取消选择不喜欢原因 | 仅Android可用 | | onRefuse | 拒绝填写原因 | 仅Android可用 | | onShow | 拒绝弹框显示 | 仅Android可用 | | onAdTerminate | 广告被强制移除 | 仅iOS可用,当收到此回调时应当移除该组件 |

激励视频

  1. 说明
  • 先加载广告id,成功后再渲染展示
  • 没有服务端奖励验证功能
  1. 使用
String rewardAdId = await FlutterGromore.loadRewardAd(
  GromoreRewardConfig(adUnitId: GroMoreAdConfig.rewardId));

if (rewardAdId.isNotEmpty) {
  showRewardAd(rewardAdId);
}

Future<void> showRewardAd(String rewardId) async {
  await FlutterGromore.showRewardAd(rewardId: rewardId, callback: GromoreRewardCallback(
    onRewardVerify: (bool verify) {
      if (verify) {
        // 如果需要在关闭广告后再判断,可以先把这个值用变量存储一下,在onAdClose回调中根据变量的值进行判断
        print("恭喜你,获得奖励");
      }
    }
  ));
}
  1. 配置(GromoreRewardConfig) | 参数名 | 说明 | 必填 | | ------------ | -------------- | ---- | | adUnitId | 信息流广告位id | 是 | | orientation | 播放方向。竖屏:1,横屏:2。默认为竖屏。仅Android端有效 | 否 | | muted | 是否静音,默认为true | 否 | | volume | 音量,默认为0。仅Android端有效 | 否 | | useSurfaceView | 是否使用SurfaceView,默认为true。建议开启,仅对Android生效 | 否 |

  2. 回调(GromoreFeedCallback,命名和 Android 聚合文档基本一致) | 回调方法名 | 说明 | 备注 | | ---------------- | -------------- | ---- | | onAdShow | 广告的展示回调 | | | onAdVideoBarClick | 广告的下载bar点击回调,非所有广告商的广告都会触发 | | | onAdClose | 广告关闭的回调 | | | onVideoComplete | 视频播放完毕的回调,非所有广告商的广告都会触发 | | | onVideoError | 视频播放失败的回调 | | | onRewardVerify | 激励视频播放完毕,验证是否有效发放奖励的回调 | 参数 verify 表示是否验证成功 | | onSkippedVideo | 跳过视频播放 | |

Banner广告

  1. 说明
  • 不需要加载广告id
  • 高度为申请广告位时选择的高度
  • 具体使用参考example
  1. 使用
SizedBox(
  height: _height,
  child: GromoreBannerView(
    creationParams: {"adUnitId": GroMoreAdConfig.bannerId, "height": _bannerHeight.toString()},
    callback: GromoreBannerCallback(onRenderSuccess: () {
      print("GromoreBannerView | onRenderSuccess");
      setState(() {
        _height = _bannerHeight;
      });
    }, onSelected: () {
      setState(() {
        _show = false;
      });
    }, onLoadError: () {
      setState(() {
        _show = false;
      });
    }, onAdTerminate: () {
      setState(() {
        _show = false;
      });
    })),
)

更多关于Flutter插件flutter_gromore的特性与使用方法的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter插件flutter_gromore的特性与使用方法的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter开发中,插件(package)扮演着扩展应用功能的重要角色。虽然flutter_gromore这个名称听起来像是一个特定功能的插件,但实际上,在Flutter的官方包管理网站Pub.dev上并没有找到名为flutter_gromore的插件。因此,我将基于一个假设的插件功能来展示一些潜在的代码使用案例。

假设flutter_gromore是一个提供高级图形渲染和更多UI组件的插件,我们可以构想一些可能的功能,并给出相应的代码示例。请注意,以下代码是基于假设的,实际使用时需要根据flutter_gromore(如果它存在)的官方文档进行调整。

假设功能1:高级图形渲染

假设flutter_gromore提供了高级的图形渲染功能,比如3D图形渲染。我们可以使用它来创建一个简单的3D立方体。

import 'package:flutter/material.dart';
import 'package:flutter_gromore/flutter_gromore.dart'; // 假设的导入路径

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('3D Cube Demo'),
        ),
        body: Center(
          child: Gromore3DCube(
            size: 100.0, // 立方体大小
            color: Colors.blue, // 立方体颜色
            rotationSpeed: 1.0, // 旋转速度
          ),
        ),
      ),
    );
  }
}

// 假设的3D立方体组件
class Gromore3DCube extends StatefulWidget {
  final double size;
  final Color color;
  final double rotationSpeed;

  Gromore3DCube({required this.size, required this.color, required this.rotationSpeed});

  @override
  _Gromore3DCubeState createState() => _Gromore3DCubeState();
}

class _Gromore3DCubeState extends State<Gromore3DCube> with SingleTickerProviderStateMixin {
  late AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(seconds: 5),
      vsync: this,
    )..repeat(reverse: true);
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    // 使用假设的Gromore3DRenderer进行渲染
    return Gromore3DRenderer(
      animationController: _controller,
      cubeSize: widget.size,
      cubeColor: widget.color,
      rotationSpeed: widget.rotationSpeed,
    );
  }
}

假设功能2:更多UI组件

假设flutter_gromore提供了丰富的UI组件,比如一个自定义的日期选择器。

import 'package:flutter/material.dart';
import 'package:flutter_gromore/flutter_gromore.dart'; // 假设的导入路径

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Date Picker Demo'),
        ),
        body: Center(
          child: GromoreDatePicker(
            initialDate: DateTime.now(),
            firstDate: DateTime(2000),
            lastDate: DateTime(2101),
            onDateChanged: (DateTime selectedDate) {
              print('Selected date: $selectedDate');
            },
          ),
        ),
      ),
    );
  }
}

// 假设的日期选择器组件
class GromoreDatePicker extends StatefulWidget {
  final DateTime initialDate;
  final DateTime firstDate;
  final DateTime lastDate;
  final ValueChanged<DateTime> onDateChanged;

  GromoreDatePicker({
    required this.initialDate,
    required this.firstDate,
    required this.lastDate,
    required this.onDateChanged,
  });

  @override
  _GromoreDatePickerState createState() => _GromoreDatePickerState();
}

class _GromoreDatePickerState extends State<GromoreDatePicker> {
  DateTime? _selectedDate;

  @override
  void initState() {
    super.initState();
    _selectedDate = widget.initialDate;
  }

  void _selectDate(DateTime picked) {
    setState(() {
      _selectedDate = picked;
      widget.onDateChanged(picked);
    });
  }

  @override
  Widget build(BuildContext context) {
    // 使用假设的GromoreDatePickerUI进行渲染
    return GromoreDatePickerUI(
      selectedDate: _selectedDate,
      firstDate: widget.firstDate,
      lastDate: widget.lastDate,
      onChanged: _selectDate,
    );
  }
}

请注意,上述代码是基于对flutter_gromore功能的假设编写的,实际插件可能具有完全不同的API和实现。因此,在使用任何第三方插件时,建议查阅其官方文档和示例代码。

回到顶部