zjsdk_android

Creator: coderz1093

Last updated:

0 purchases

TODO
Add to Cart

Description:

zjsdk android

Android-ZjSdk Flutter Plugin #
Android 版本 ZjSdk 的 Flutter 桥接示例插件
支持的广告类型 #

开屏广告原生展示
开屏广告Widget
激励视频
插全屏广告
横幅广告
信息流广告
视频流广告
视频内容
短剧
新闻资讯
H5页面

开始接入 #

插件需要Flutter >=3.0.0,请升级Flutter版本
enhanced Enum需要指定SDK>=2.17.0,请调整SDK版本
SDK版本调整后依然报错,请手动删除.dart_tool目录重新执行pub-get

environment:
sdk: ">=2.17.0 <3.0.0"
copied to clipboard
引入依赖 #

参照example,在pubspec中引入zjsdk_android插件,并指定插件路径:

dependencies:
#...

zjsdk_android:
path: ../

#...
copied to clipboard
注意: 如使用example中的测试ID调试时,需要修改build.gradle的android->defaultConfig->applicationId为"com.zj.daylottery.demo"。广告ID与包名是绑定关系,使用其他包名会导致广告请求失败。
初始化SDK #

为适配隐私控制,建议在用户同意隐私政策后再调用初始化方法。

个性化推荐、程序化推荐配置
SDK提供了个性化推荐、程序化推荐配置开关,仅需在状态发生改变时调用,可在初始化方法调用之前配置。
class ZJAndroid {
/// 配置个性化推荐开关
/// [state] 是否开启推荐
static void setPersonalRecommend(bool state);

/// 配置程序化推荐开关
/// [state] 是否开启推荐
static void setProgrammaticRecommend(bool state);
}
copied to clipboard
隐私权限控制
SDK提供了隐私权限控制配置,需要在每次初始化时传入:
/// 隐私权限控制
class ZJCustomController {
static const List<String> defaultInstalledPackages = [];

/// 主动获取定位
final bool canReadLocation;

/// 经度
final double longitude;

/// 纬度
final double latitude;

/// 主动获取设备信息
final bool canUsePhoneState;

/// IMEI
final String imei;

/// 主动获取AndroidID
final bool canUseAndroidId;

/// AndroidID
final String androidId;

/// 主动获取MAC地址
final bool canUseMacAddress;

/// MAC地址
final String macAddress;

/// 主动获取OAID
final bool canUseOaid;

/// OAID/GAID
final String oaid;

/// 获取网络状态
final bool canUseNetworkState;

/// 使用存储
final bool canUseStoragePermission;

/// 主动读取已安装应用列表
final bool canReadInstalledPackages;

/// 已安装应用列表
final List<String> installedPackages;

/// 是否允许SDK在申明和授权了的情况下使用录音权限
bool canRecordAudio;

ZJCustomController({this.canReadLocation = true,
this.longitude = 0.0000,
this.latitude = 0.0000,
this.canUsePhoneState = true,
this.imei = "",
this.canUseAndroidId = true,
this.androidId = "",
this.canUseMacAddress = true,
this.macAddress = "",
this.canUseOaid = true,
this.oaid = "",
this.canUseNetworkState = true,
this.canUseStoragePermission = true,
this.canReadInstalledPackages = true,
this.installedPackages = defaultInstalledPackages,
this.canRecordAudio = true});
}
copied to clipboard
初始化接口
在用户同意隐私政策前可以调用initWithoutStart方法初始化SDK
class ZJAndroid {
/// 初始化SDK
/// 可以在进入应用后立即调用
/// 返回是否初始化成功
static void initWithoutStart(

/// 应用ID
String appId,
{
/// 控制日志打印
bool isDebug = true,

/// gdpr状态,-1为未知,0为用户未授权,1为用户授权
int gdpr = -1,

/// coppa状态,-1为未知,0为成人,1为儿童
int coppa = -1,

/// ccpa状态,-1为未知,0为允许出售,1为不允许出售
int ccpa = -1,

/// 用户年龄,默认为0
int age = 0,

/// 隐私权限控制
ZJCustomController? customController}) {
_sdkMethodChannel.invokeMethod("initWithoutStart", {
"appId": appId,
"isDebug": isDebug,
"gdpr": gdpr,
"coppa": coppa,
"ccpa": ccpa,
"age": age,
"customController": customController?.toMap(),
});
}
}
copied to clipboard
在用户同意隐私政策后调用start方法启动SDK
class ZJAndroid {
/// 启动SDK
/// 需要在用户同意隐私政策之后尽快调用
static void start({
/// 启动回调
/// [ret.event] {ZJEventAction.startSuccess | ZJEventAction.startFailed},启动失败时,需要解析ret.code等信息排查
/// [ret.code] 错误码
/// [ret.msg] 错误描述
Function(ZJEvent ret)? onStartListener}) {
ZJSdkMessageChannel.start(onStartListener);
_sdkMethodChannel.invokeMethod("start");
}
}
copied to clipboard
example:
/// 初始化SDK
void initSdk() {
ZJAndroid.initWithoutStart(TestPosId.appId,
customController: ZJCustomController(canUseAndroidId: true));
// 判断用户是否同意了隐私政策
if (_canStart) {
// 用于已同意隐私政策,调用启动方法,并在成功回调后调用广告
start();
} else {
// 展示隐私政策对话框,并在用户同意后调用`start`方法启动SDK
showPrivacyDialog(context);
}
}

/// 启动SDK
void start() {
ZJAndroid.start(onStartListener: (ret) {
if (ret.action == ZJEventAction.startSuccess) {
Fluttertoast.showToast(msg: "初始化成功");
} else {
Fluttertoast.showToast(msg: "初始化失败:" + ret.msg!);
if (kDebugMode) {
print("${ret.action}:${ret.code}");
}
}
});
}
copied to clipboard
请求广告 #
请确保SDK已初始化成功再请求广告
开屏广告 #
开屏广告分为原生接入与Widget接入,推荐使用原生Activity请求与展示。
原生接入
相比Widget接入方式,原生只需要处理请求失败与关闭回调,不需要处理其他情况,也不需要关闭容器的大小,接入更为简单。
method:
class ZJAndroid {
/// 加载原生开屏
static void loadSplashAd(

/// 广告位ID
String posId,
{
/// 自定义背景图的原生资源类型,仅支持(default|mipmap|drawable),其他值无效
/// default时不需要配置bgResName,SDK会读取原生的默认启动页背景
/// mipmap或drawable时,需要配置资源名,默认或原生资源不存在时默认主题背景
String bgResType = "",

/// 自定义背景图的原生资源名,需要搭配 bgResType 传入,默认开屏页为白色背景
String bgResName = "",

/// 开屏回调。具体事件见 example
Function(ZJEvent ret)? splashListener});
}
copied to clipboard
example:
/// 原生加载广告
void _loadSplashAd(String posId) {
ZJAndroid.loadSplashAd(
// 广告位ID
posId,
// 自定义背景图的原生资源类型,仅支持(default|mipmap|drawable),其他值无效
// default时不需要配置bgResName,SDK会读取原生的默认启动页背景
// mipmap或drawable时,需要配置资源名,默认或原生资源不存在时默认主题背景
bgResType: "default",
// 回调
splashListener: (ret) {
// 原生加载仅回调请求失败和关闭
switch (ret.action) {
// 广告出错
case ZJEventAction.onAdError:
Fluttertoast.showToast(msg: "开屏错误:${ret.msg}");
if (kDebugMode) {
print("${ret.action}:${ret.code}-${ret.msg}");
}
break;
// 广告关闭
case ZJEventAction.onAdClose:
Fluttertoast.showToast(msg: "开屏关闭");
break;
default:
// ignore
}
});
}
copied to clipboard
Widget接入
相比原生接入,Widget接入更加灵活,可以直接嵌入到FlutterView中。但需要处理View的移除,且**
需要保证容器的宽度大于屏幕宽度(非当前界面,是包含顶部StatusBar的整体屏幕)的95%,高度大于屏幕高度的85%**,否则会出现展示无效,不会计费的问题。
widget:
/// 开屏广告视图
class ZJSplashView extends StatelessWidget {
/// 广告位ID
final String posId;

/// 宽
final double width;

/// 高
final double height;

/// 回调
final Function(ZJEvent ret) splashListener;

const ZJSplashView(this.posId,
{Key? key,
required this.width,
required this.height,
required this.splashListener})
: super(key: key);
}
copied to clipboard
example:
child: ZJSplashView(
// 广告位ID
posId,
width: double.infinity,
height: double.infinity,
// 回调
splashListener: (ret) {
switch (ret.action) {
// 广告出错
case ZJEventAction.onAdError:
Fluttertoast.showToast(msg: "开屏错误:${ret.msg}");
if (kDebugMode) {
print("${ret.action}:${ret.code}-${ret.msg}");
}
_reset();
break;
// 展示成功
case ZJEventAction.onAdShow:
Fluttertoast.showToast(msg: "开屏展示");
break;
// 点击广告
case ZJEventAction.onAdClick:
Fluttertoast.showToast(msg: "开屏点击");
break;
// 关闭
case ZJEventAction.onAdClose:
Fluttertoast.showToast(msg: "开屏关闭");
_reset();
break;
default:
// ignore
}
},
),
copied to clipboard
激励视频 #
激励视频会弹出一个新的页面,用户观看达到一定时长时才可以跳过并退出,SDK会回调发奖。
激励视频分为加载并展示与预加载->手动展示两种方式,无特殊需要建议使用加载并展示方式接入。
加载并展示
调用加载并展示时,不需要额外判断广告加载情况和处理预加载广告对象过期后重新请求的问题。
需要屏蔽用户的重复点击操作,防止用户频繁点击导致的广告嵌套播放
method:
class ZJAndroid {
/// 加载激励视频
static void loadRewardVideo(

/// 广告位ID
String posId,

/// 用户ID,必填
String userId,

/// 回调。具体事件见 example
Function(ZJEvent ret) rewardListener, {
/// 是否开启视频声音
bool videoSoundEnable = true,

/// 透传信息(返回到服务端发校验接口)
String extra = "",

/// 是否为预加载,默认false
/// 非预加载时,加载成功后直接播放
/// 预加载时仅回调成功/失败,需要搭配[showRewardVideo]方法展示
bool isPreLoad = false,

/// FLAGS
int flags = 0,
});
}
copied to clipboard
example:
/// 加载并展示激励视频
void _loadRewardVideo(BuildContext context, String posId) {
_showLoading(context);
setState(() {
isRequesting = true;
});
ZJAndroid.loadRewardVideo(
// 广告位ID
posId,
// 用户ID,必填
TestPosId.testUserId,
// 回调
(ret) {
switch (ret.action) {
// 广告出错
case ZJEventAction.onAdError:
Navigator.of(context).pop();
_reset(context);
Fluttertoast.showToast(msg: "激励视频错误:${ret.msg}");
if (kDebugMode) {
print("${ret.action}:${ret.code}-${ret.msg}");
}
break;
// 展示成功
case ZJEventAction.onAdShow:
Fluttertoast.showToast(msg: "激励视频展示");
break;
// 点击广告
case ZJEventAction.onAdClick:
Fluttertoast.showToast(msg: "激励视频点击");
break;
// 满足条件,可以发奖
case ZJEventAction.onAdRewardVerify:
Fluttertoast.showToast(msg: "激励视频发奖");
break;
// 关闭
case ZJEventAction.onAdClose:
Navigator.of(context).pop();
_reset(context);
Fluttertoast.showToast(msg: "激励视频关闭");
break;
default:
// ignore
}
});
}
copied to clipboard
预加载->手动展示
建议使用加载并展示方式请求广告。使用预加载时需要指定属性isPreLoad: true
预加载模式需要判断加载状态,加载成功的回调后再播放广告,否则回调播放错误。
广告的请求行为与展示行为是对应关系,即一次请求对应一次展示,重复展示时会报错。
预加载广告的有效时间为20分钟,过期后展示会回调错误,需要重新请求。
预加载对于Flutter全局缓存一个对象,不需要在每个页面去单独预加载。
可以重复预加载广告,新返回的广告对象会替换旧对象。
method:
class ZJAndroid {
/// 加载激励视频
static void loadRewardVideo(

/// 广告位ID
String posId,

/// 用户ID,必填
String userId,

/// 回调。具体事件见 example
Function(ZJEvent ret) rewardListener, {
/// 是否开启视频声音
bool videoSoundEnable = true,

/// 透传信息(返回到服务端发校验接口)
String extra = "",

/// 是否为预加载,默认false
/// 非预加载时,加载成功后直接播放
/// 预加载时仅回调成功/失败,需要搭配[showRewardVideo]方法展示
bool isPreLoad = false,
});

/// 展示激励视频
static void showRewardVideo(

/// 展示回调
Function(ZJEvent ret)? rewardListener);
}
copied to clipboard
example:
/// 预加载激励视频
void _preloadRewardVideo(String posId) {
ZJAndroid.loadRewardVideo(posId, TestPosId.testUserId, (ret) {
// 预加载仅回调加载失败和加载成功
switch (ret.action) {
// 广告出错
case ZJEventAction.onAdError:
_reset(context);
Fluttertoast.showToast(msg: "激励视频错误:${ret.msg}");
if (kDebugMode) {
print("${ret.action}:${ret.code}-${ret.msg}");
}
break;
// 加载成功
case ZJEventAction.onAdLoaded:
_reset(context);
Fluttertoast.showToast(msg: "激励视频加载成功");
break;
default:
break;
}
},
// 指定预加载
isPreLoad: true);
}

/// 展示激励视频
/// 仅预加载时需要手动调用展示方法
/// 需要预加载请求回调[ZJEventAction.onAdLoaded]调用,否则回调错误
/// 预加载状态全局生效,有效期20分钟,过期时会在播放时回调错误
void _showRewardVideo() {
ZJAndroid.showRewardVideo((ret) {
switch (ret.action) {
// 广告出错
case ZJEventAction.onAdError:
_reset(context);
Fluttertoast.showToast(msg: "激励视频错误:${ret.msg}");
if (kDebugMode) {
print("${ret.action}:${ret.code}-${ret.msg}");
}
break;
// 展示成功
case ZJEventAction.onAdShow:
Fluttertoast.showToast(msg: "激励视频展示");
break;
// 点击广告
case ZJEventAction.onAdClick:
Fluttertoast.showToast(msg: "激励视频点击");
break;
// 满足条件,可以发奖
case ZJEventAction.onAdRewardVerify:
Fluttertoast.showToast(msg: "激励视频发奖");
break;
// 关闭
case ZJEventAction.onAdClose:
Fluttertoast.showToast(msg: "激励视频关闭");
break;
default:
// ignore
}
});
}
copied to clipboard
插全屏广告 #
2.4.16版本起,插屏与全屏广告合并为插全屏广告,支持预加载功能
method:
class ZJAndroid {
/// 插全屏
static void interstitial(

/// 广告位ID
String posId, {

/// 是否开启视频声音
bool videoSoundEnable = true,

/// 是否为预加载,默认false
/// 非预加载时,加载成功后直接播放
/// 预加载时仅回调成功/失败,需要搭配[showInterstitial]方法展示
bool isPreLoad = false,

/// FLAGS
int flags = 0,

/// 回调。具体事件见 example
Function(ZJEvent ret)? interstitialListener,
});
}
copied to clipboard
example:
/// 加载并展示插全屏广告
void _interstitial(String posId) {
setState(() {
isRequesting = true;
});
ZJAndroid.interstitial(
// 广告位ID
posId,
// 视频类素材是否开启声音,默认true
videoSoundEnable: true,
interstitialListener: (ret) {
switch (ret.action) {
// 广告错误
case ZJEventAction.onAdError:
Fluttertoast.showToast(msg: "插全屏错误:${ret.msg}");
if (kDebugMode) {
print("${ret.action}:${ret.code}-${ret.msg}");
}
_reset();
break;
// 展示成功
case ZJEventAction.onAdShow:
Fluttertoast.showToast(msg: "插全屏展示");
break;
// 点击广告
case ZJEventAction.onAdClick:
Fluttertoast.showToast(msg: "插全屏点击");
break;
// 关闭
case ZJEventAction.onAdClose:
Fluttertoast.showToast(msg: "插全屏关闭");
_reset();
break;
default:
// ignore
}
});
}
copied to clipboard
全屏视频 #
2.4.16版本起,插屏与全屏广告合并为插全屏广告
横幅广告 #
横幅广告为插入页面的Widget,一般需要宽度占满屏幕,高度按照固定比例计算,当容器大于模板高度时会自动居中,接入时需要与我们确定尺寸比例。
widget:
/// 横幅广告视图
class ZJBannerView extends StatelessWidget {
/// 广告位ID
final String posId;

/// 自刷新频率(单位s,仅部分广告生效,0时不刷新)
final int refreshInterval;

/// 宽
final double width;

/// 高
final double height;

/// 回调
final Function(ZJEvent ret)? bannerListener;

const ZJBannerView(this.posId,
{Key? key,
required this.width,
required this.height,
this.refreshInterval = 0,
this.bannerListener})
: super(key: key);
}
copied to clipboard
example:
child: ZJBannerView(
// 广告位ID
posId,
width: double.infinity,
// 需要固定高度
height: 120,
bannerListener: (ret) {
switch (ret.action) {
case ZJEventAction.onAdError:
Fluttertoast.showToast(msg: "Banner1错误:${ret.msg}");
if (kDebugMode) {
print("${ret.action}:${ret.code}-${ret.msg}");
}
break;
case ZJEventAction.onAdShow:
Fluttertoast.showToast(msg: "Banner1展示");
break;
case ZJEventAction.onAdClick:
Fluttertoast.showToast(msg: "Banner1点击");
break;
case ZJEventAction.onAdClose:
Fluttertoast.showToast(msg: "Banner1关闭");
break;
default:
// ignore
}
},
),
copied to clipboard
信息流广告 #
信息流广告为插入页面的Widget,一般需要宽度占满屏幕,高度按照固定比例计算,当容器大于模板高度时会自动居中,接入时需要与我们确定尺寸比例。
相比横幅广告,信息流广告的模板样式更丰富,展现场景更灵活。
widget:
/// 信息流广告视图
class ZJNativeExpressView extends StatelessWidget {
/// 广告位ID
final String posId;

/// 视频类型素材的声音开关
final bool videoSoundEnable;

/// 宽
final double width;

/// 高
final double height;

/// 回调
final Function(ZJEvent ret)? nativeExpressListener;

const ZJNativeExpressView(this.posId,
{Key? key,
required this.width,
required this.height,
this.videoSoundEnable = false,
this.nativeExpressListener})
: super(key: key);
}
copied to clipboard
example:
child: ZJNativeExpressView(
// 广告位ID
posId,
width: double.infinity,
// 需要指定高度
height: 280,
nativeExpressListener: (ret) {
switch (ret.action) {
// 广告错误
case ZJEventAction.onAdError:
Fluttertoast.showToast(msg: "信息流1错误:${ret.msg}");
if (kDebugMode) {
print("${ret.action}:${ret.code}-${ret.msg}");
}
break;
// 展示成功
case ZJEventAction.onAdShow:
Fluttertoast.showToast(msg: "信息流1展示");
break;
// 点击广告
case ZJEventAction.onAdClick:
Fluttertoast.showToast(msg: "信息流1点击");
break;
// 关闭
case ZJEventAction.onAdClose:
Fluttertoast.showToast(msg: "信息流1关闭");
break;
default:
// ignore
}
},
),
copied to clipboard
视频流广告 #
视频流广告的模板样式为竖屏,适用于插入到应用已有的视频流中。
widget:
/// 视频流广告视图
class ZJDrawAdView extends StatelessWidget {
/// 广告位ID
final String posId;

/// 视频类型素材的声音开关
final bool videoSoundEnable;

/// 宽
final double width;

/// 高
final double height;

/// 回调
final Function(ZJEvent ret)? drawAdListener;

const ZJDrawAdView(this.posId,
{Key? key,
required this.width,
required this.height,
this.videoSoundEnable = true,
this.drawAdListener})
: super(key: key);
}
copied to clipboard
example:
child: ZJDrawAdView(
// 广告位ID
posId,
width: double.infinity,
height: double.infinity,
drawAdListener: (ret) {
switch (ret.action) {
// 广告错误
case ZJEventAction.onAdError:
Fluttertoast.showToast(msg: "视频流错误:${ret.msg}");
if (kDebugMode) {
print("${ret.action}:${ret.code}-${ret.msg}");
}
break;
// 展示成功
case ZJEventAction.onAdShow:
Fluttertoast.showToast(msg: "视频流展示");
break;
// 点击广告
case ZJEventAction.onAdClick:
Fluttertoast.showToast(msg: "视频流点击");
break;
// 关闭
case ZJEventAction.onAdClose:
Fluttertoast.showToast(msg: "视频流关闭");
break;
default:
// ignore
}
},
),
copied to clipboard
视频内容 #
视频内容分为原生加载与Widget加载。使用原生加载会在应用上层弹出新界面进行展示,性能更好。使用Widget加载可以嵌入到Flutter界面中,使用更加灵活。
注意: 使用Widget加载时,需要确保 Android 的MainActivity
继承io.flutter.embedding.android.FlutterFragmentActivity,Flutter 会默认继承 io.flutter.embedding.android.FlutterActivity。详见example/MainActivity
原生加载
method:
class ZJAndroid {
/// 原生展示视频内容
static void contentAd(

/// 广告位ID
String posId, {

/// 回调。具体事件见 example
Function(ZJEvent ret)? contentAdListener,
});
}
copied to clipboard
example:
/// 原生加载广告
void _loadContentAd(String posId) {
ZJAndroid.contentAd(
// 广告位ID
posId,
contentAdListener: (ret) {
switch (ret.action) {
case ZJEventAction.onAdError:
Fluttertoast.showToast(msg: "视频内容错误:${ret.msg}");
if (kDebugMode) {
print("${ret.action}:${ret.code}-${ret.msg}");
}
break;
case ZJEventAction.onAdClose:
Fluttertoast.showToast(msg: "视频内容关闭");
break;
default:
// ignore
}
}
);
}
copied to clipboard
widget加载
widget:
/// 视频内容视图
class ZJContentAdView extends StatelessWidget {
/// 广告位ID
final String posId;

/// 宽
final double width;

/// 高
final double height;

/// 回调
final Function(ZJEvent ret)? contentAdListener;

const ZJContentAdView(this.posId,
{Key? key,
required this.width,
required this.height,
this.contentAdListener})
: super(key: key);
}
copied to clipboard
example:
child: ZJContentAdView(
// 广告位ID
posId,
width: double.infinity,
height: double.infinity,
contentAdListener: (ret) {
switch (ret.action) {
// 广告错误
case ZJEventAction.onAdError:
Fluttertoast.showToast(msg: "视频内容错误:${ret.msg}");
if (kDebugMode) {
print("${ret.action}:${ret.code}-${ret.msg}");
}
_reset();
break;
// 展示成功
case ZJEventAction.onAdShow:
Fluttertoast.showToast(msg: "视频内容展示");
break;
// 关闭
case ZJEventAction.onAdClose:
Fluttertoast.showToast(msg: "视频内容关闭");
break;
default:
// ignore
}
},
),
copied to clipboard
短剧 #
注意: 接入短剧时,需要确保 Android 的MainActivity继承io.flutter.embedding.android.FlutterFragmentActivity,Flutter 会默认继承 io.flutter.embedding.android.FlutterActivity。详见example/MainActivity
widget加载
widget:
/// 短剧视图
class ZJTubeAdView extends StatefulWidget {
/// 广告位ID
final String posId;

/// 宽
final double width;

/// 高
final double height;

/// 配置
final ZJTubeAdConfig? config;

/// 回调
final Function(ZJEvent ret)? tubeAdListener;

/// 展示自定义短剧解锁对话框回调
final TubeAdShowCustomUnlockDialogCallback? showCustomUnlockDialogCallback;

/// 短剧解锁结果回调
final TubeAdUnlockCallback? unlockCallback;

/// 创建成功通知
final ZJTubeAdViewCreated onCreatedCallback;

const ZJTubeAdView(this.posId,
{Key? key,
required this.width,
required this.height,
this.config,
this.tubeAdListener,
this.showCustomUnlockDialogCallback,
this.unlockCallback,
required this.onCreatedCallback})
: super(key: key);
}
copied to clipboard
example:
child: ZJTubeAdView(
posId,
width: double.infinity,
height: double.infinity,
config: ZJTubeAdConfig(
userId: TestPosId.testUserId, isHideTitleBar: true),
// 禁用SDK自带的解锁对话框时,需要展示自定义解锁对话框并返回用户是否同意的状态
showCustomUnlockDialogCallback: _showCustomUnlockDialog,
// 短剧解锁结果回调
unlockCallback: _onUnlockCallback,
onCreatedCallback: _onTubeAdViewCreated,
tubeAdListener: (ret) {
if (ret.action == ZJEventAction.onAdError) {
Fluttertoast.showToast(msg: "视频内容错误:${ret.msg}");
if (kDebugMode) {
print("${ret.action}:${ret.code}-${ret.msg}");
}
_reset();
}
},
)

/// 展示短剧组件到容器中
void _show() {
if (controller == null) {
setState(() {
showTubeView = true;
});
} else {
controller!.show();
}
}

/// 隐藏短剧组件
void _hide() {
if (controller == null) {
Fluttertoast.showToast(msg: "还未加载成功");
} else {
// 隐藏
controller!.hide();
}
}

/// 禁用SDK自带的解锁对话框时,需要展示自定义解锁对话框并返回用户是否同意的状态
Future<bool> _showCustomUnlockDialog(ZJTubeAdItem adItem) async {
Completer<bool> completer = Completer();

/// 在展示自定义解锁对话框后回调结果
completer.complete(Random().nextBool()); // 此处模拟用户随机同意/取消解锁
return completer.future;
}

/// 短剧解锁结果回调
/// 成功时code==0,msg==null
/// 失败时code!=0,msg!=null
/// 失败事件不一定触发,成功事件一定触发
void _onUnlockCallback(bool isSuccess, int errCode, String? errMsg) {
if (isSuccess) {
Fluttertoast.showToast(msg: "解锁成功");
} else {
Fluttertoast.showToast(msg: "解锁失败[$errCode-$errMsg]");
}
}

/// 以Widget加载时的组件控制器
void _onTubeAdViewCreated(ZJTubeAdViewController controller) {
this.controller = controller;
// 在创建视图成功后,需要配置解锁需要的广告位ID(仅支持激励视频和插全屏广告)
this.controller!.setUnlockAdPosId(Random().nextBool()
? TestPosId.rewardVideoPosId
: TestPosId.interstitialPosId);
}

copied to clipboard
新闻资讯 #
新闻资讯分为原生加载与widget加载,可作为任务模块加载,用户阅读的篇数和时长达到条件时会发放奖励。也可以不配置任务条件仅作为内容填充。
注意: 使用Widget加载时,需要确保 Android 的MainActivity继承io.flutter.embedding.android.FlutterFragmentActivity,Flutter 会默认继承 io.flutter.embedding.android.FlutterActivity。详见example/MainActivity
原生加载
method:
class ZJAndroid {
/// 原生展示新闻资讯
static void newsAd(

/// 广告位ID
String posId,

/// 用户ID,必填
String userId, {
/// 回调。具体事件见 example
Function(ZJEvent ret)? newsAdListener,
});
}
copied to clipboard
example:
/// 原生加载广告
void _loadNewsAd(String posId) {
ZJAndroid.newsAd(
// 广告位ID
posId,
// 用户ID,必填
TestPosId.testUserId,
newsAdListener: (ret) {
switch (ret.action) {
// 广告错误
case ZJEventAction.onAdError:
Fluttertoast.showToast(msg: "新闻资讯错误:${ret.msg}");
if (kDebugMode) {
print("${ret.action}:${ret.code}-${ret.msg}");
}
break;
// 满足任务条件,可以发奖(仅配置任务时在关闭前回调)
case ZJEventAction.onAdRewardVerify:
Fluttertoast.showToast(msg: "新闻资讯发奖");
break;
// 关闭
case ZJEventAction.onAdClose:
Fluttertoast.showToast(msg: "新闻资讯关闭");
break;
default:
// ignore
}
}
);
}
copied to clipboard
widget加载
widget:
/// 新闻资讯视图
class ZJNewsAdView extends StatelessWidget {
/// 广告位ID
final String posId;

/// 用户ID
final String userId;

/// 宽
final double width;

/// 高
final double height;

/// 回调
final Function(ZJEvent ret)? newsAdListener;

const ZJNewsAdView(this.posId,
{Key? key,
required this.width,
required this.height,
this.userId = "",
this.newsAdListener})
: super(key: key);
}
copied to clipboard
example:
child: ZJNewsAdView(
// 广告位ID
posId,
// 用户ID,必填
userId: TestPosId.testUserId,
width: double.infinity,
height: double.infinity,
newsAdListener: (ret) {
switch (ret.action) {
// 广告错误
case ZJEventAction.onAdError:
Fluttertoast.showToast(msg: "新闻资讯错误:${ret.msg}");
if (kDebugMode) {
print("${ret.action}:${ret.code}-${ret.msg}");
}
_reset();
break;
// 满足任务条件,可以发奖(仅配置任务时回调)
case ZJEventAction.onAdRewardVerify:
Fluttertoast.showToast(msg: "新闻资讯发奖");
break;
// 关闭
case ZJEventAction.onAdClose:
Fluttertoast.showToast(msg: "新闻资讯关闭");
break;
default:
// ignore
}
},
),
copied to clipboard
H5页面 #
H5页面会弹出新层级的界面,展示H5插件页面。用户在页面中进行浏览和互动。
method:
class ZJAndroid {
/// H5页面
static void h5Page(

/// 广告位ID
String posId,

/// 用户ID,必填
String userId, {
/// 回调。具体事件见 example
Function(ZJEvent ret)? h5PageListener,
});
}
copied to clipboard
example:
/// 加载并展示H5页面
void _h5Page(String posId) {
ZJAndroid.h5Page(
// 广告位ID
posId,
// 用户ID,必填
TestPosId.testUserId,
h5PageListener: (ret) {
switch (ret.action) {
case ZJEventAction.onAdError:
Fluttertoast.showToast(msg: "H5页面错误:${ret.msg}");
if (kDebugMode) {
print("${ret.action}:${ret.code}-${ret.msg}");
}
break;
case ZJEventAction.onAdClose:
Fluttertoast.showToast(msg: "H5页面关闭");
break;
default:
// ignore
}
}
);
}
copied to clipboard

License

For personal and professional use. You cannot resell or redistribute these repositories in their original state.

Files:

Customer Reviews

There are no reviews.