主题
uni-app 版
uni_modules 形态的 UTS 插件,内部封装原生 SDK。当前版本 1.0.0,离线包 admix-uniapp-1.0.0.zip。
这一页与插件包内的 readme 是同一份内容
插件目录里的 readme.md 是唯一来源,这一页由站点构建时同步生成。 原生 SDK 的完整文档在文档中心,uni-app 插件只是它的一层封装 —— 错误码、合规清单、服务端对接这些平台无关的内容不在这一页重复。
AdMix 广告聚合 SDK 的 uni-app UTS 插件,聚合穿山甲(GroMore 通道)与优量汇,支持开屏、激励视频、Banner 三种广告位。 支持 App-Android 与 App-iOS,适用于 uni-app(vue3)项目的 vue / nvue 页面,两个平台的页面代码相同。uni-app x 项目未经验证。
获取插件
离线包:https://admin.maemi.cn/maven/downloads/admix-uniapp-1.0.0.zip
解压得到 admix-ad/ 目录,整个放进宿主工程的 uni_modules/ 下(即 uni_modules/admix-ad/package.json)。多套一层目录时 HBuilderX 识别不到插件,也不报错。
下文各节的代码片段可以直接照抄,不依赖离线包之外的任何东西(片段取自示例工程 pages/index/index.vue 与 pages/banner/banner.nvue,示例工程本身不在离线包内)。
接入前必读
与 uni-AD 互斥。 使用本插件的 App 不能在
manifest.json的「App 模块配置 → uni-AD」里勾选优量汇、穿山甲、GroMore 模块。 uni-AD 以本地 aar 带入两家广告 SDK,与本插件通过 Maven 引入的同一批 SDK 重复,云打包在构建期失败: 勾优量汇报Duplicate class com.qq.e.*,勾穿山甲报2 files found with path 'lib/arm64-v8a/libPglbizssdk_ml.so'。
targetSdkVersion需在manifest.json里调高。 云打包默认值是 28,各大应用商店普遍要求 31 以上; 平台的真机验证也是在 targetSdk 34 下完成的。在「App 常用其它设置」或源码视图app-plus.distribute.android.targetSdkVersion设置。
minSdkVersion被抬到 25(Android 7.1.1)。 平台服务端证书在 Android 7.0 及以下不受信任,低于 7.1.1 的设备拉不到广告配置。
<admix-banner>的属性写驼峰unitId。 写成unit-id组件收不到,不发请求也不报错;控制台会在 1 秒后打出提示。
接入前需要从平台运营处获取
| 项 | 用途 |
|---|---|
| AppID | initAdMix 的 appId |
| App 密钥 | initAdMix 的 appKey |
| 同时上 iOS 时,iOS 应用的 AppID 与 App 密钥 | Android 与 iOS 在平台上是两个应用,凭证各一套,页面按运行平台选用(见「初始化」) |
各广告位的广告位标识(unitId) | 创建广告实例 / <admix-banner unitId> |
| 每个 Banner 广告位的尺寸规格 | 决定页面上 <admix-banner> 的宽高比例;只拿标识不确认尺寸,到真机上才会发现比例不对 |
宿主 App 的包名(manifest.json 里打包用的 Android 包名)需提前告知平台运营:优量汇按包名校验,不一致时不返回广告。 优量汇后台有「程序全包名」「主程序包名」两个字段,校验的是程序全包名;核对时两个字段都要逐字念出来对一遍。 包名不符时优量汇返回的错误码不稳定(107030、107076、5004 都出现过),排查时不要只认其中一个。
环境要求
| 项 | 要求 |
|---|---|
| HBuilderX | 4.36 及以上(config.json 的 project.repositories 从这个版本开始支持) |
| 运行 | 自定义基座(两个平台都是)。插件声明了原生依赖,标准基座不包含这些依赖 |
| 打包 | 云打包或离线打包。云打包需使用云端证书或自有证书(新应用已不能用公共测试证书) |
| iOS 最低系统 | iOS 12.0 |
| iOS 签名 | 自有证书 + 手动管理的描述文件(开发版需包含测试设备)。Xcode 自动管理的描述文件云打包不接受,报 is Xcode managed, but signing settings require a manually managed profile |
Android 依赖
插件依赖由 utssdk/app-android/config.json 声明,云打包时从以下仓库拉取,分发物里不带任何广告平台 SDK:
| 依赖 | 版本 | 仓库 |
|---|---|---|
com.admix:sdk | 1.0.0 | https://admin.maemi.cn/maven/ |
穿山甲 com.pangle.cn:mediation-sdk | 7.7.1.6(由 com.admix:sdk 带入) | https://artifact.bytedance.com/repository/pangle |
优量汇 com.qq.e.union:union | 4.680.1550(由 com.admix:sdk 带入) | Maven Central(云打包默认仓库已包含) |
插件按验证过的那一版锁定 com.admix:sdk(版本见上表),平台可能已经发布更新的 Android SDK; 换版本要重新打一次自定义基座并回归三种广告位,接入方不需要、也不应该自己改这个版本号。 平台新版里的 Banner 请求尺寸接口本插件用不上:resize 给出的是广告视图的实测尺寸, 素材与后台登记的规格不一致时,实测值才是页面该照着排版的那个。
只接一家广告平台时,把 config.json 里的 com.admix:sdk:1.0.0 换成 com.admix:sdk-csj:1.0.0 或 com.admix:sdk-gdt:1.0.0(版本号要一起写,漏了 Gradle 解析不到),其余不变: 未接入的那一家代码不进包,平台也不会下发它的配置。sdk-csj 已真机验证;sdk-gdt 机制相同,未单独真机验证。
iOS 依赖
由 utssdk/app-ios/config.json 声明,云打包时按 CocoaPods 拉取,分发物里同样不带广告平台 SDK:
json
{ "name": "AdMix", "version": "1.0.0", "source": "https://admin.maemi.cn/cocoapods/" },
{ "name": "Ads-CN/BUAdSDK", "version": "7.8.0.8", "source": "https://admin.maemi.cn/cocoapods/uniapp-deps/" },
{ "name": "GDTMobSDK", "version": "4.16.11", "source": "https://admin.maemi.cn/cocoapods/uniapp-deps/" }| 依赖 | 说明 |
|---|---|
AdMix | 平台 iOS SDK,与原生接入的 pod 'AdMix', '1.0.0' 是同一个 |
穿山甲 Ads-CN/BUAdSDK、优量汇 GDTMobSDK | AdMix 依赖的两家广告 SDK,版本必须与 AdMix 锁定的版本一致 |
两家广告 SDK 必须显式列出并指定源。 CocoaPods 解析带
source的 pod 时,它的依赖不会到这个 pod 的源里找, 只写AdMix一行的话,两家广告 SDK 会去 DCloud 打包机默认的镜像源里找,镜像源版本滞后时云打包报Unable to find a specification for Ads-CN/BUAdSDK (= 7.8.0.8)。uniapp-deps/源里只有这两个版本的 podspec,内容与 CocoaPods 官方源逐字节一致。
iOS 不提供只接一家的组合,两家广告 SDK 都会进包。
初始化
初始化分两步,不提供合并的便利方法:
| 方法 | 作用 | 调用时机 |
|---|---|---|
initAdMix(options) | 只读本地配置,不联网、不采集 | App.onLaunch |
startAdMix(callback) | 初始化各广告平台、拉取广告配置 | 用户同意隐私政策之后 |
在用户同意隐私政策之前调用 startAdMix,应用商店会因此驳回上架。uni-app 自带隐私弹窗(androidPrivacy.json)的,放在其同意回调里调用。
androidPrivacy.json只管 Android。 iOS 上 uni-app 没有这个内置弹窗,同意弹窗要宿主自己做, 同意之后再调startAdMix。两个平台都照搬 Android 那套的话,iOS 版会变成「没弹窗就直接 start」。
js
// App.vue
import { initAdMix } from '@/uni_modules/admix-ad'
export default {
onLaunch() {
// Android 与 iOS 是平台上的两个应用。运行时判断平台:vue 页面代码里 #ifdef APP-IOS 不生效
const ios = uni.getSystemInfoSync().platform === 'ios'
initAdMix(ios ? { appId: '<iOS AppID>', appKey: '<iOS App 密钥>' }
: { appId: '<AppID>', appKey: '<App 密钥>' })
}
}js
// 用户同意隐私政策之后
import { startAdMix } from '@/uni_modules/admix-ad'
startAdMix((res) => {
if (!res.success) console.log(res.error.code, res.error.message)
})initAdMix 的可选项:debug(调度日志,Android 为 logcat tag AdMix,iOS 为系统日志里的 [AdMix] 前缀,上线前关闭)、limitPersonalAds(关闭个性化广告)、 channel / subChannel / userValueGroup / segmentCustomInfo(GroMore 流量分组)。
激励视频
vue 与 nvue 页面均可使用。
js
import { AdMixRewardAd } from '@/uni_modules/admix-ad'
const ad = new AdMixRewardAd({ unitId: 'reward_main', userId: 'u123' })
ad.onLoaded((adnType) => {})
ad.onLoadFailed((e) => {})
ad.onReward(() => { /* 发奖 */ })
ad.onClose(() => {})
ad.load()
// 需要展示时
if (!ad.show()) { /* 没有可展示的广告,走无广告分支 */ }
// 页面卸载时
ad.destroy()- 用
new AdMixRewardAd({...})创建实例(开屏同理用new AdMixSplashAd({...})) - 发奖只认
onReward。 激励条件不一定是看完视频(实测有「点击广告」「浏览页面 10 秒」「打开 App 体验 15 秒」),onVideoComplete可能一次都不回调,不能作为发奖依据 - 点关闭按钮时广告平台可能先弹「放弃奖励」挽留框,用户确认后才回调
onClose userId/customData只在开启服务端发奖验证时需要,原样透传给广告平台的发奖回调- 事件:
onLoaded/onLoadFailed/onShow/onClick/onClose/onReward/onVideoComplete
开屏
已在 vue 页面真机验证(与页面类型无关,nvue 页面未单独验证)。页面不需要准备容器: Android 上全屏容器由插件在 show() 时挂到当前 Activity 最上层、关闭或 destroy() 时移除; iOS 上两家广告平台都把开屏盖在 window 上,由 SDK 自己添加和移除。
接入步骤:
manifest.json中把app-plus.splashscreen.autoclose设为false,让 uni-app 的启动图在开屏广告结束前保持显示- 用户同意隐私政策 →
startAdMix→ 加载开屏 - 广告关闭、加载失败、兜底超时,都走同一个「放行」出口:调用
plus.navigator.closeSplashscreen()关闭启动图并进入首页,且只执行一次
js
import { AdMixSplashAd } from '@/uni_modules/admix-ad'
// finish:页面自己的「放行」函数 —— 关闭启动图、进首页、ad.destroy(),且只执行一次
// arm(ms, why):重设兜底定时器,到点就 finish。两者的完整写法见下一节,可直接照抄
const ad = new AdMixSplashAd({ unitId: 'splash_main' })
ad.onLoaded(() => {
if (!ad.show()) return finish()
arm(2000, 'show 后没有 onShow')
})
ad.onShow(() => arm(12000, '展示后没有 onClose'))
ad.onLoadFailed(() => finish())
ad.onClose(() => finish())
arm(5000, 'load 后没有任何回调') // 先武装,再 load
ad.load()兜底放行
开屏必须有不依赖任何回调的定时器,否则任何一个回调缺失都会让启动卡死在开屏或启动图上。三段时限缺一不可:
| 时段 | 参考时限 | 防的情况 |
|---|---|---|
load 到首个回调 | 5000 ms | 一直没有任何回调 |
show 到 onShow | 2000 ms | 没有 onShow(典型是白屏) |
onShow 到 onClose | 12000 ms | 没有 onClose;用户从广告落地页回到 App 时重新计时 |
第一段要在
load之前武装。 命中缓存时onLoaded会在ad.load()里同步回调完, 把arm(5000, …)写在ad.load()之后的话,它会把回调里刚设好的第二段(2000 ms)覆盖成 5000 ms。
启动图(closeSplashscreen)必须在同一个兜底出口里关闭:只放行广告不关启动图,表现是广告在启动图后面播完; 只关启动图不放行,表现是白屏卡死。
可直接照抄的完整写法:
js
import { AdMixSplashAd } from '@/uni_modules/admix-ad'
function showSplash(onDone) {
const ad = new AdMixSplashAd({ unitId: 'splash_main' })
let done = false
let shown = false
let guard = null
// 重设兜底定时器:每一段都用它,后一段自动顶掉前一段
const arm = (ms, why) => {
clearTimeout(guard)
guard = setTimeout(() => finish('兜底放行:' + why), ms)
}
// 用户点广告去了落地页,回来时广告可能已经结束而 onClose 迟迟不到
const onResume = () => { if (shown && !done) arm(12000, '回到 App 后仍未收到 onClose') }
// 唯一出口:四个回调和三段定时器都走这里,且只执行一次
const finish = (why) => {
if (done) return
done = true
clearTimeout(guard)
// #ifdef APP-PLUS
plus.globalEvent.removeEventListener('resume', onResume)
// #endif
ad.destroy()
// #ifdef APP-PLUS
plus.navigator.closeSplashscreen() // 关掉 uni-app 的启动图
// #endif
onDone(why) // 进首页
}
ad.onLoaded(() => {
if (done) return
if (!ad.show()) return finish('show 返回 false')
arm(2000, 'show 后没有 onShow')
})
ad.onShow(() => { shown = true; arm(12000, '展示后没有 onClose') })
ad.onLoadFailed((e) => finish('load 失败 ' + e.code + ' ' + e.message))
ad.onClose(() => finish('关闭'))
arm(5000, 'load 后没有任何回调') // 先武装,再 load
// #ifdef APP-PLUS
plus.globalEvent.addEventListener('resume', onResume)
// #endif
ad.load()
}manifest.json 里 app-plus.splashscreen.autoclose 要设为 false,否则启动图会在广告出来之前自己关掉。
Banner
Banner 是原生组件,只能放在 nvue 页面(uni-app 3.x 的 vue 页面不支持第三方原生组件)。
html
<!-- pages/home/home.nvue -->
<admix-banner unitId="banner_main" :style="{ width: '702rpx', height: slotHeight }"
@resize="onResize"
@loaded="onLoaded" @loadfailed="onLoadFailed"
@show="onShow" @click="onClick" @close="onClose" />js
data() { return { slotHeight: '110rpx' } },
methods: {
// 广告缩放到槽位宽度,槽位高度按中标素材的宽高比调整
onResize(e) {
const { width, height } = e.detail
this.slotHeight = Math.round(702 * height / width) + 'rpx'
}
}- 属性写驼峰
unitId,写unit-id收不到 - 宽高必须在样式里写死。nvue 不支持按内容撑开,没有高度的槽位过不了广告平台的曝光检查,表现是一直不出广告、也不报错
- 尺寸涉及两处,含义不同:
- 请求尺寸由平台下发(后台平台广告位配置的宽高),必须与该广告位在广告平台后台登记的尺寸规格一致。 不一致时穿山甲返回
40006 广告位ID不合法—— 字面意思与真实原因无关,排查方向是尺寸,不是 ID。这一处由平台运营维护,改页面样式解决不了 - 槽位尺寸由页面样式决定,按同一尺寸规格的比例给(规格 320×50 时如
702rpx × 110rpx)。 穿山甲按请求尺寸取素材,槽位只负责承载;优量汇的 Banner 按槽位宽度自适应,槽位过窄或宽高比与规格相差太大时会拉伸或留白 —— 所以槽位要按规格比例给,不能取任意值
- 请求尺寸由平台下发(后台平台广告位配置的宽高),必须与该广告位在广告平台后台登记的尺寸规格一致。 不一致时穿山甲返回
- 同一个广告位下,各广告平台登记的尺寸规格可能不同(实测:优量汇 320×50、穿山甲 320×150),中标的是哪一家要竞价完成才知道。 每次广告挂载后组件触发
resize,e.detail为{ width, height }(Android 为 dp,iOS 为 point),只用它的宽高比。 两端的来源不同:Android 量的是广告视图树里最大的那个子视图,iOS 取的是广告平台给出的素材尺寸, 素材与后台登记的规格不一致时两端的数值会有出入,但都是「这条广告实际多大」,按比例用即可。 页面按槽位宽度 × height / width设置槽位高度。广告在两个平台上都填满槽位宽度 (iOS 上素材按登记尺寸生成,由组件等比缩放到槽位宽度,宽的缩小、窄的放大)。 不处理resize时,比槽位高的素材在 Android 上被裁掉、只露出上半截,在 iOS 上伸出槽位盖住下方内容。 更稳妥的做法是让平台运营在各广告平台为同一个 Banner 广告位登记同一尺寸规格 - 刷新由平台驱动,按后台配置的刷新间隔重新竞价;每次刷新都会再触发一次
loaded。页面不需要也不应自己刷新 - 页面关闭时组件自动销毁广告并停止刷新,页面不需要调用任何销毁方法
@click收到的是插件转发的「广告被点击」事件,不是组件的触摸事件;组件不支持 touch 类事件,广告本身的点击由广告平台处理- 事件参数在
e.detail里:loaded为{ adnType },loadfailed为{ code, message, adnType },resize为{ width, height }
预加载与缓存
js
import { preloadAd, getCachedCount, clearAdCache } from '@/uni_modules/admix-ad'
// 用户还在浏览时先把激励视频备好;之后同一广告位 load() 直接从缓存取,不再发请求
preloadAd('reward_main', (res) => {
if (res.success) console.log('已入缓存', res.adnType, getCachedCount('reward_main'))
else console.log('预加载失败', res.error.code, res.error.message)
})
clearAdCache() // 清空全部缓存并销毁其中的广告;返回时已清空- 每个广告位能缓存几条、过期时间、是否自动补位由平台后台配置。缓存条数为 0(后台关了缓存)或已满时,
preloadAd直接回调失败 startAdMix成功之前调用preloadAd一律失败,不发请求- 激励视频带了
userId/customData(服务端发奖验证)时,load()不取缓存,总是实时请求:缓存里的广告请求时没有这次的用户 ID,平台转发发奖回调时对不上人 - 缓存在进程内存里,进程被杀后清空
广告事件
js
import { onAdMixEvent, offAdMixEvent, flushEvents } from '@/uni_modules/admix-ad'
onAdMixEvent((e) => {
// 接宿主自己的数据平台。同一次调度的事件 requestId 相同:ad_request → adn_request → fill → impression
console.log(e.type, e.unitId, e.adn, e.requestId, e.costMs, e.cacheHit)
})
offAdMixEvent() // 取消
flushEvents() // 立即上报尚未发送的埋点(如确知马上退出时)- 全局只有一个监听,再次调用
onAdMixEvent会替换前一个;回调在主线程 - 字段:
type/unitId/adType/adn/adnSource/bidding/costMs/errCode/errMsg/requestId/sessionId/eventTime/loadSource/cacheHit,与原生 SDK 的AdEvent一致,不含价格 - 与平台自身的埋点上报是两条独立路径,注册与否都不影响上报;
flushEvents正常不需要调用
错误
错误原样透传自原生 SDK,结构为 { code, message, adnType }。adnType 为出错的广告平台,与具体平台无关的错误为空。 错误码含义见平台文档《错误码参考》:https://admin.maemi.cn/docs/latest/errors
| code | 含义 |
|---|---|
| -1001 | SDK 未就绪:未调用 initAdMix,或尚未 startAdMix |
| -1002 | 广告位无配置:unitId 与后台不一致,或该广告位未配置平台广告位 |
| -1003 | 所有广告平台均未填充 |
| -1004 | 超时 |
| -1005 | 宿主缺少对应广告平台的适配器 |
| -1006 | 未获隐私授权 |
常见现象排查
| 现象 | 先查什么 |
|---|---|
startAdMix 回调失败,错误码 -1002(无配置);debug 日志里配置版本为 0、广告平台列表为空 | 应用是否已在平台审核通过并启用。新建应用默认待审核且未启用,两步都完成前服务端返回空配置,HTTP 状态仍是 200,没有任何错误提示 |
只有某个广告位报 -1002 | unitId 与后台广告位标识是否一字不差;该广告位是否配了平台广告位 |
| 优量汇一直不填充,穿山甲正常 | 包名,见「接入前需要从平台运营处获取」 |
Banner 报 40006 广告位ID不合法 | 平台广告位配置的尺寸与广告平台登记的规格是否一致(与 ID 无关),见「Banner」 |
| Banner 只显示上半截(Android)或盖住下方内容(iOS) | 是否处理了 resize 事件;各广告平台登记的尺寸规格是否一致 |
| Banner 一直空白、没有任何回调 | 属性是否写成了 unitId(驼峰);样式里是否写死了宽高 |
| 启动卡在开屏或启动图上 | 三段兜底放行是否都有,closeSplashscreen 是否在同一个放行出口里 |
| 运行时弹「应用的uni-AD业务状态异常(-9001)」(Android、iOS 都出现过) | DCloud uni-app 运行时自身的行为(文案由 DCloud 服务端按打包所用的 DCloud AppID 下发),与本插件无关,广告照常加载。原因未确认(可能与打包所用 DCloud 账号的实名状态有关,也可能是 HBuilderX 误报),使用正常实名账号打包时的表现未实测 |
云打包报 Duplicate class com.qq.e.* 或 libPglbizssdk_ml.so 重复 | 是否勾选了 uni-AD 的优量汇 / 穿山甲 / GroMore 模块 |
iOS 云打包报 Unable to find a specification for Ads-CN/BUAdSDK 或 GDTMobSDK | app-ios/config.json 里两家广告 SDK 是否显式列出并指定了 uniapp-deps/ 源,见「iOS 依赖」 |
iOS 云打包报 is Xcode managed, but signing settings require a manually managed profile | 描述文件是否为手动管理,见「环境要求」 |
隐私合规
宿主 App 的隐私政策需披露实际集成的第三方 SDK(穿山甲、优量汇),只披露实际集成的那一家或两家。
iOS 上插件不弹跟踪授权(App Tracking Transparency)弹窗,弹不弹、何时弹由宿主决定; 要弹的话在 manifest.json 的 iOS 隐私描述里填写 NSUserTrackingUsageDescription。
插件清单已移除优量汇声明的 QUERY_ALL_PACKAGES(读取全部已安装应用),与原生 SDK 接入的最终权限保持一致,宿主不需要再处理。
打包产物里还会有以下权限,来自 DCloud 的 uni-app 运行基座,不是广告 SDK 带入的(与原生 SDK 接入的产物逐项对比得出): INSTALL_PACKAGES、READ_PHONE_STATE、READ_MEDIA_IMAGES、READ_MEDIA_VIDEO、READ_MEDIA_VISUAL_USER_SELECTED、 华为 / vivo 桌面角标权限。是否保留、如何披露由宿主按 uni-app 的权限配置处理(manifest.json 的「App 权限配置」),与本插件无关。 披露内容见平台文档《合规与隐私》。
本地编译附录
使用 HBuilderX 本地编译 UTS(「运行到手机」时对插件代码的本地编译)可能报 Could not find com.admix:sdk, 日志里伴随 The project declares repositories, effectively ignoring the repositories you have declared in the settings。 原因是 HBuilderX 本地编译模板没有使用 config.json 里声明的仓库;云打包不受影响。 遇到时先制作一次自定义基座(云打包),再运行到手机。
iOS 的插件代码只能云打包编译:自定义基座(云打包)里已包含插件,之后只改页面代码时直接运行到手机即可,不用重新打基座; 改了 utssdk/app-ios/ 下的文件则要重新打一次基座。
更新日志
AdMix 广告聚合 uni-app 插件(uni_modules/admix-ad)的发布说明。
[1.0.0] — 首个版本
交付内容
离线包 https://admin.maemi.cn/maven/downloads/admix-uniapp-1.0.0.zip,不经 DCloud 插件市场。解压得到 admix-ad/ 目录,放进宿主工程的 uni_modules/ 下即可使用。
插件本身不带任何广告平台 SDK。Android 云打包时按 utssdk/app-android/config.json 从以下仓库拉取:
| 依赖 | 版本 | 仓库 |
|---|---|---|
com.admix:sdk | 1.0.0 | https://admin.maemi.cn/maven/ |
穿山甲(GroMore 通道)com.pangle.cn:mediation-sdk | 7.7.1.6 | https://artifact.bytedance.com/repository/pangle |
优量汇 com.qq.e.union:union | 4.680.1550 | Maven Central |
iOS 云打包时按 utssdk/app-ios/config.json 通过 CocoaPods 拉取:
| 依赖 | 版本 | 源 |
|---|---|---|
AdMix | 1.0.0 | https://admin.maemi.cn/cocoapods/ |
穿山甲 Ads-CN/BUAdSDK | 7.8.0.8 | https://admin.maemi.cn/cocoapods/uniapp-deps/ |
优量汇 GDTMobSDK | 4.16.11 | https://admin.maemi.cn/cocoapods/uniapp-deps/ |
环境要求:HBuilderX 4.36 及以上;App-Android(宿主 minSdkVersion 25,即 Android 7.1.1)与 App-iOS(iOS 12.0 及以上)。
新增
- 三种广告位:开屏、激励视频(vue / nvue 页面均可用)、Banner(nvue 组件
<admix-banner>)。 两家广告平台在华为 ALN-AL10 / Android 12 上,自定义基座与正式云打包两种形态均真机跑通; iOS 在 iPhone 上以自定义基座(开发证书)真机跑通,两个平台的页面代码相同 - 按需裁剪:把依赖换成
com.admix:sdk-csj即只接穿山甲,优量汇的代码不进包,服务端按上报的能力裁掉优量汇的配置(真机验证) - 两步初始化:
initAdMix(不联网、不采集)与startAdMix(用户同意隐私政策之后),不提供合并方法 - 激励视频 / 开屏为实例式 API:
new AdMixRewardAd({...})/new AdMixSplashAd({...}),onXxx注册的回调可多次触发;show()/isReady()在 vue 与 nvue 页面均同步返回 - 开屏容器由插件管理:
show()时在当前页面最上层创建全屏容器,关闭或destroy()时移除 - Banner 组件:刷新由平台按后台配置驱动;页面卸载时组件自动销毁广告;
resize事件给出中标素材的尺寸,页面按其宽高比调整槽位高度(同一广告位下各广告平台登记的尺寸可能不同); 广告在两个平台上都填满槽位宽度,iOS 上由组件等比缩放 - 预加载与缓存:
preloadAd/getCachedCount/clearAdCache,对应原生AdMix.preload/getCachedCount/clearCache - 广告事件:
onAdMixEvent/offAdMixEvent/flushEvents,事件字段与原生AdEvent一致,不含价格 - 错误原样透传原生 SDK 的
{ code, message, adnType } - 插件清单处理:统一两家广告 SDK 的
allowBackup冲突(取false); 移除优量汇声明的QUERY_ALL_PACKAGES,与原生 SDK 接入的最终权限一致
接入注意
- 与 uni-AD 互斥:不能同时勾选 uni-AD 的优量汇 / 穿山甲 / GroMore 模块,云打包在构建期失败
targetSdkVersion需在宿主manifest.json中调高,云打包默认值为 28<admix-banner>的属性写驼峰unitId,写unit-id组件收不到- Android 与 iOS 在平台上是两个应用,凭证各一套,
initAdMix时按运行平台选用 - iOS 云打包需要手动管理的描述文件,Xcode 自动管理的描述文件会被拒绝
已知限制
- iOS 只验证过开发证书打的自定义基座,正式(App Store)证书的云打包未实测
- iOS 不提供只接一家的组合,两家广告 SDK 都会进包
- 只在 uni-app(vue3)项目里验证过,uni-app x 项目未经验证
- 只接优量汇(
com.admix:sdk-gdt)的组合未单独真机验证(只接穿山甲已验证,机制相同) - Banner 只能放在 nvue 页面;vue 页面放 Banner 需另行评估(subNVue 浮层)
- HBuilderX 本地编译 UTS 时不使用
config.json声明的仓库,报Could not find com.admix:sdk;云打包不受影响,见 readme 附录