uni.createRewardedVideoAd 需安装并启用穿山甲原生插件(如 tt-ad),配置对应平台 AppID 与激励视频广告位 ID,预加载后调用 show(),并结合服务端验证 rewardedVideoAd.onClose 的 isEnded 及播放时长兜底判断。

uni.createRewardedVideoAd 能用,但得先装对插件
直接调用 uni.createRewardedVideoAd 会报错“not a function”,不是 API 失效,而是穿山甲 SDK 根本没接入。UniApp 的广告能力是靠原生插件桥接的,uni.createRewardedVideoAd 只有在正确安装并启用穿山甲原生插件后才真正可用。
- 必须从插件市场安装「字节跳动穿山甲广告」类插件(如
tt-ad或csj-ad),不能只配manifest.json里的ad模块 - 插件安装后,要在
manifest.json → App 原生插件配置中手动勾选该插件,否则运行时不可见 - Android 和 iOS 需分别配置:插件内部通常不自动区分平台,
appid必须按平台传对应值(后台创建应用时 Android/iOS 是两个独立条目) - 真机调试前必须「制作自定义基座」——普通云打包或标准基座不包含你装的原生插件
激励视频广告位 ID 不能乱填,要和初始化匹配
常见错误是把开屏广告位 ID 或 Banner 位 ID 直接塞进 uni.createRewardedVideoAd({adUnitId: 'xxx'}),结果一直加载失败或回调不触发。穿山甲要求广告位类型和 SDK 初始化、代码位 ID 三者严格一致。
- 广告位必须在穿山甲后台明确选择「激励视频(Reward Video)」类型创建,不能复用其他类型代码位
- 初始化 SDK 时传的
appid必须与该广告位所属应用一致(一个 App ID 下可挂多个 Reward 视频位,但不能跨 App ID) - 部分插件(如较新版本
tt-ad)要求额外传expressViewAcceptedSize参数,例如{width: 360, height: 240},漏掉会导致 onLoaded 不触发 - 测试阶段务必用「测试设备 + 测试广告位 ID」,否则可能因审核未过或流量控制返回空广告
onClose 回调里 isEnded 不可靠,得加兜底判断
rewardedVideoAd.onClose 返回的 res.isEnded 看似是发放奖励的唯一依据,但在实际机型(尤其低端 Android)或网络波动下,它可能为 true 却没播完,也可能为 false 但用户确实看完了——这是穿山甲 SDK 的已知行为,不是你代码写错了。
- 不要仅依赖
isEnded发放核心奖励(如游戏货币、关卡解锁),应结合服务端验证:前端上报播放完成事件,服务端调用穿山甲「激励视频播放完成回调」接口二次确认 - 前端可加简单时长兜底:用
videoAd.onLoad记录时间戳,onClose时计算播放时长,>= 15s再视为有效(具体阈值参考穿山甲文档) - 用户快速划走、切后台、系统弹窗打断等情况,
onClose可能根本不会触发,需监听onError并做降级处理(如提示“广告异常,稍后重试”)
load() 和 show() 必须分开调用,且不能省略 catch
很多人图省事写成 ad.load().then(() => ad.show()),但一旦 load() 失败(比如网络超时、广告库存空),show() 就永远不会执行,用户点击按钮毫无反应,还查不出问题。
-
load()应尽早调用(比如页面onLoad后),利用空闲时间预加载;show()留到用户真实触发动作(如按钮点击)时再调 - 每次
show()都必须.catch,捕获典型错误如"ad not loaded"、"ad already showing",并给出明确反馈 - 避免重复
load():广告实例加载成功后,可缓存并在下次show()前检查ad.loaded(若插件支持)或自行标记状态 - 激励视频广告有频控限制(如每 30 分钟最多展示 1 次),频繁调用
load()可能被限流,建议本地记录上次成功展示时间
穿山甲激励视频真正的难点不在写几行 JS,而在于插件选型、平台 ID 对齐、测试环境隔离、以及对 SDK 行为边界的准确预判——尤其是 isEnded 和加载失败这两处,线上最容易出问题。