主题
初始化
文档版本 v1.0.0
本页对应 SDK 1.0.0,与离线包 docs/ 目录里的同一份文档内容一致。其他版本见文档中心。
两步,顺序不可颠倒:init() 只读本地配置,start() 才联网并初始化各广告平台的 SDK。
接入方只配两个凭证
接入方不需要配置穿山甲 / 优量汇的应用 ID,也不需要配平台广告位 ID。
原因是平台的运营模式 —— 每个开发者在穿山甲、优量汇后台都是独立创建的应用, 应用 ID 和广告位各不相同(优量汇还会校验包名,共用广告位会直接报 5006 包名校验错误)。 如果这些值要写进宿主 App,平台每接一个开发者就得重新出一个接入包,接入成本没有下限。 所以广告平台的应用 ID 和广告位 ID 一律由配置服务下发,SDK 侧没有任何本地写入口。
| 谁来配 | 配什么 |
|---|---|
| 接入方 | AppID + App 密钥,就这两个。服务器地址内置在 SDK 里,不用配 |
| 平台运营 | 各广告平台的应用 ID、广告位与平台广告位 ID、底价、超时、瀑布顺序 —— 全部在管理后台维护,改动不需要接入方发版 |
AppID 和 App 密钥由平台运营在管理后台「应用管理 → 接入」里查看并交付。
第一步:init()
在 Application 中调用。只读取本地配置,不联网、不采集任何设备信息,一家广告平台也不会被初始化。
java
public class MyApplication extends Application {
@Override public void onCreate() {
super.onCreate();
AdMix.init(this, "AppID", "App密钥");
}
}绝大多数接入方写到这里就够了。AppID 或 App 密钥为空时 init() 直接抛 IllegalArgumentException,开发期第一次运行就能发现。
可选项
需要打开详细日志、处理用户关闭个性化推荐、或按渠道 / 人群分组时,用带可选项的重载:
java
AdMix.init(this, "AppID", "App密钥", new AdMixConfig.Builder()
.debug(BuildConfig.DEBUG) // 输出完整调度日志,上线包请关闭
.limitPersonalAds(userClosedPersonalAds) // 用户是否关闭个性化推荐
.channel("渠道标识") // 流量分组,可选
.subChannel("子渠道标识")
.build());| 可选项 | 默认 | 为什么留给接入方 |
|---|---|---|
debug(boolean) | false | 只有接入方知道当前是不是调试包。关闭时仍会输出配置拉取、初始化结果、错误等关键日志 |
limitPersonalAds(boolean) | false | 合规要求:用户关闭个性化推荐后必须透传给各广告平台,只有接入方知道用户的选择。透传方式见《合规与隐私》「个性化广告开关」 |
channel / subChannel / userValueGroup / segmentCustomInfo | 不填 | 流量分组,只对穿山甲(GroMore 通道)生效,不填也能正常出广告 |
关于流量分组:这些值会随请求带给 GroMore,并在广告返回的价格信息里原样读回, GroMore 后台可以按分组配置不同瀑布流(例如按用户价值分层)。取值应由宿主 App 或服务端决定, 不要写死。
流量分组字段不得放入个人信息
这些字段会上传给广告平台。手机号、身份证号、精确位置、可关联到自然人的账号 ID 一律不得放入, 否则构成未告知的个人信息共享。详见《合规与隐私》「流量分组标识」。
第二步:start()
必须在用户同意隐私政策之后调用。
java
AdMix.start(new AdMix.InitListener() {
@Override public void onSuccess() { /* 可以开始请求广告 */ }
@Override public void onFail(AdError error) { /* 本次会话不要请求广告,按无广告降级 */ }
});start() 做的事是把配置拿到手,而不是初始化广告平台:
| 情形 | 行为 |
|---|---|
| 本地已有配置(上一次拉到的缓存) | 立即回调 onSuccess,不等网络,同时后台静默刷新一次 |
| 本地什么都没有(装机后真正的第一次冷启动) | 必须等一次网络请求,拿到 adns 才知道要初始化谁。最多等 5 秒 |
| 超时或拉取失败 | 回调 onFail。此时不要请求广告,按无广告降级;后台线程仍会把这次请求跑完,配置到手后再调一次 start() 即可就绪 |
onSuccess = 可以请求广告,onFail = 不要请求。判据只有一条:广告平台配置到手没有。
合规硬性要求
用户同意隐私政策前调用 start() 属于违规采集个人信息,应用商店会驳回上架。
还有三条同样会被驳回的细节:同意结果必须持久化(否则每次启动都弹,用户当成弹窗广告)、 点「不同意」时 App 仍须可用(只是没广告,禁掉广告入口并留一个「重新查看隐私政策」入口)、 弹窗文案要能对应到实际集成的 SDK。详见《合规与隐私》「延迟初始化」。
SDK 侧另有一道兜底红线:用户未同意时任何 load() 都会直接失败(错误码 -1006), 不管从哪个入口进来都不会碰到任何广告 SDK。
广告平台是按需初始化的
start() 成功之后,仍然一家广告平台都没有初始化。 某家只在「首次加载到配置了它的广告位」时才初始化。
两个收益:
- 启动更快 —— 用不到的广告平台一次初始化都不做
- 合规更好 —— 未被使用的广告平台一行代码都不跑、不采集任何设备信息。 比如某个 App 只用激励视频,而激励视频的瀑布里没有优量汇,那优量汇 SDK 在这台设备上 就从未运行过。做隐私自查和应用商店审核时,这是能直接拿出来的证据
接入方不需要为此写任何代码,SDK 内部完成。只有一处需要留意:
首次加载会多出一次广告平台初始化的耗时
实测穿山甲装机后的第一次初始化要 2~4.4 秒(之后每个进程只要 200 ms 上下)。 开屏的超时预算本来就只有 3 秒出头,这段耗时可能把预算吃掉。两个办法,任选:
- 用
AdMix.preload()提前预热(开屏本来就该预加载,见《预加载与缓存》), 初始化成本由预加载承担 - 让平台运营把开屏的
total_timeout_ms放宽一点,留出余量
等待初始化的时间不会超过该广告位自己的 total_timeout_ms —— 开屏配 3.5 秒就最多等 3.5 秒, 绝不会出现「业务侧早就放行进主页了,广告还在等初始化」的情况。
Kotlin 写法
SDK 是纯 Java API,Kotlin 工程直接调用,不需要任何适配层或额外依赖。 监听器是多方法的 Java 接口,所以用 object : XxxListener { … },不能用 SAM lambda (只有单方法的 AdEventListener 可以)。
kotlin
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
// 只读本地配置:不联网、不采集、不碰任何广告 SDK
AdMix.init(this, BuildConfig.ADMIX_APP_ID, BuildConfig.ADMIX_APP_KEY,
AdMixConfig.Builder()
.debug(BuildConfig.DEBUG)
.build())
}
}
// 用户点「同意」之后,不是在 Application 里
AdMix.start(object : AdMix.InitListener {
override fun onSuccess() { /* 可以请求广告 */ }
override fun onFail(error: AdError) { /* 按无广告降级,本次会话不要请求 */ }
})三种广告位的 Kotlin 写法见《开屏广告》《激励视频广告》《Banner 广告》各自的末节。
日志排查
SDK 全部日志使用 AdMix 标签,debug(true) 时输出完整调度过程:
bash
adb logcat -s "AdMix:V"启动阶段先核对这两组日志(不受 debug 开关影响,关了也打):
text
adapter 就绪: csj (ADN SDK 7.7.1.6) ← 每个引入的适配器一行,没有就是依赖没引进来;
adapter 就绪: gdt (ADN SDK 4.680.1550) 带告警的是广告 SDK 版本与锁定版本不一致
拉取远端配置 … adapters=[csj,gdt] ← 上报给平台的能力清单,服务端据此裁剪下发一行 adapter 就绪 都没有、只有 没有发现任何 adapter 时,不用再往下查调度 —— 要么坐标没引全,要么打包策略把 META-INF/services/** 排除了,见《引入依赖》「按需集成单家广告平台」。
调度阶段的典型输出:
text
开始加载 reward_main 竞价位=0 瀑布层=2
瀑布层无填充 gdt AdError{gdt 5004 ...},下探
请求瀑布层[1] csj:***(price=***)
瀑布填充 csj ecpm=***
最终胜出: csj ecpm=***
[CSJ激励] GroMore 出价 adn=pangle ecpm原始值=*** 代码位=*** 竞价类型=0 分组=1636713 channel=xxx subChannel=yyy- 日志里的价格和平台广告位 ID 一律显示为
***:logcat 对宿主开发者可见,这两项不对接入方开放, 这与debug开关无关。需要定位到具体广告位时,把日志里的广告位标识、广告平台和时间点 交给平台运营查询 - 最后一行是 GroMore 的成交明细:
adn是真正出广告的那一家,代码位是 GroMore 瀑布流内部 那一行的 ID(平台不使用它,只在这条日志里出现);channel/subChannel应与初始化时传入的一致 —— 对不上就说明流量分组没生效,报表将无法按渠道拆分
上线前请将 debug 置为 false,否则影响性能。