主题
AdMix SDK 集成快速指南(一页纸跑通)
文档版本 v1.0.0
本页对应 SDK 1.0.0,与离线包内 docs/04-集成快速指南.md 是同一份内容。其他版本见文档中心。
适用版本 1.0.0 · 仅 Android · minSdk 25(Android 7.1.1)· 开屏 / 激励视频 / Banner
这份是最短路径:照着从上到下做,半天内能在真机上看到广告。 每一节末尾的「→」指向《接入文档》(
01-接入文档.md)里的完整说明,遇到问题再去那里看细节。 本文不含任何真实凭证与广告位 ID —— 它们全部由平台运营在管理后台创建后交付给你,见最后一节。
0. 动手之前,先跟运营要这四样
| 要什么 | 谁给 | 从哪来 | 能不能进 APK |
|---|---|---|---|
| AppID | 平台运营 | 后台「应用管理」创建应用时生成 | ✅ 能 |
| App 密钥 | 平台运营 | 后台「应用管理 → 接入」抽屉 | ✅ 需要进(SDK 用它签名,密钥本身不随请求发送) |
| 聚合广告位 ID 列表 | 平台运营 | 后台「广告位管理」,每个广告位一个,形如 splash_xxx / reward_xxx / banner_xxx | ✅ 能(写在业务代码里) |
| AppSecret | 平台运营(只显示一次) | 后台生成 | ❌ 绝对不能。只用于你的服务器验签(激励视频发奖回调),进了 APK 等于公开 |
你不需要穿山甲 / 优量汇的 appId,也不需要它们的代码位 ID。 这些由配置服务下发, SDK 侧没有任何本地写入口。运营改价格、调顺序、开关广告位、甚至停用一整家广告平台,你都不用发版。
⚠️ Banner 广告位在申请时必须同时把尺寸规格说清楚(运营在广告平台后台建代码位要用)。 尺寸不符会直接报
40006 广告位ID不合法,错误信息看不出是尺寸问题。
→《接入文档》二、二·五
1. 引依赖
根 settings.gradle(dependencyResolutionManagement 里)加两个仓库,都是公开只读、无需账号:
groovy
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven { url 'https://admin.maemi.cn/maven/' } // AdMix
maven { url 'https://artifact.bytedance.com/repository/pangle' } // 穿山甲官方仓库(接穿山甲时必需)
}
}App 模块 build.gradle:
groovy
dependencies {
implementation "com.admix:core:1.0.0" // 必需
implementation "com.admix:adapter-csj:1.0.0" // 穿山甲(GroMore 通道),自动带上穿山甲 SDK
implementation "com.admix:adapter-gdt:1.0.0" // 优量汇,自动带上优量汇 SDK
}
android {
defaultConfig {
minSdk 29 // ≥ 25 即可
ndk { abiFilters 'arm64-v8a', 'armeabi-v7a' } // 建议:显著减小包体积
}
}几条一次说清:
- 不要再单独引穿山甲 / 优量汇的 SDK,两个 adapter 的 pom 会自动带进来 (
com.pangle.cn:mediation-sdk:7.7.1.6、com.qq.e.union:union:4.680.1550,均为真机验证过的版本,不要自行升级) - 工程
libs/下如果放过这两家的 aar,删掉文件和对应的implementation files(...),否则重复类编译失败 - 混淆规则随 aar 自动生效(
consumer-rules.pro),你的proguard-rules.pro里一个字都不用加 - 不要写
packagingOptions/packaging { resources { … } }去动META-INF/services/**—— 适配器靠它自注册,排除掉就一条广告都没有 - 只接一家?只引那一个 adapter 即可,另一家在包里连声明都不存在,不会崩
备选:离线 zip(内网构建环境) 下载 https://admin.maemi.cn/maven/downloads/admix-android-sdk-1.0.0.zip, 或在开发者后台「接入指引」页下载。包内是三个 AdMix aar + 全套文档, 不含穿山甲 / 优量汇的 SDK(两家协议不允许第三方转发),需自行从各自后台下载同一版本; 本地 aar 不带传递依赖,要手动声明 androidx.annotation:annotation:1.3.0。步骤见包内 README.md。
→《接入文档》一
2. 清单合并冲突(必踩,先处理掉)
两家 SDK 的清单都写了 <application> 属性,且写法互相不一致 (穿山甲 allowBackup="true" + label="@string/app_name",优量汇 allowBackup="false")。 不处理就会编译失败:Attribute application@allowBackup value=(...) is also present at ...。
在你自己的 AndroidManifest.xml 上显式写出值并 tools:replace:
xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"> <!-- ← tools 命名空间别忘了 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- QUERY_ALL_PACKAGES 由优量汇 aar 合并进来,显式移除(真正的开关在 SDK 里,见合规清单) -->
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" tools:node="remove" />
<uses-permission android:name="com.android.permission.GET_INSTALLED_APPS" tools:node="remove" />
<application
android:allowBackup="false"
android:label="@string/app_name"
tools:replace="android:allowBackup,android:label">
...
</application>
</manifest>android:label 只在你的 label 与 @string/app_name 不同名时才冲突;不冲突就从 tools:replace 里去掉它。 报错信息会指名是哪个属性,照着加即可。
→《接入文档》一「清单合并冲突」
3. 初始化两步(顺序不可颠倒)
第一步 init():在 Application.onCreate 里。只读本地配置 —— 不联网、不采集、一家广告 SDK 都不初始化。
第二步 start():必须在用户点了「同意隐私政策」之后。 它才真正联网拉配置、按需初始化广告 SDK。
java
// MyApplication.java
public class MyApplication extends Application {
@Override public void onCreate() {
super.onCreate();
// 凭证建议从 BuildConfig / 本地 properties 注入,不要硬编码进源码提交到仓库
AdMix.init(this, BuildConfig.ADMIX_APP_ID, BuildConfig.ADMIX_APP_KEY,
new AdMixConfig.Builder()
.debug(BuildConfig.DEBUG) // 上线包必须 false
.limitPersonalAds(userClosedPersonalAds) // 用户关了个性化推荐就传 true
.build());
}
}java
// 用户点「同意」之后(不是在 Application 里!)
AdMix.start(new AdMix.InitListener() {
@Override public void onSuccess() { /* 可以请求广告了 */ }
@Override public void onFail(AdError e) { /* 本次会话按无广告降级,不要请求广告 */ }
});kotlin
// Kotlin
AdMix.init(this, BuildConfig.ADMIX_APP_ID, BuildConfig.ADMIX_APP_KEY,
AdMixConfig.Builder().debug(BuildConfig.DEBUG).build())
AdMix.start(object : AdMix.InitListener {
override fun onSuccess() { }
override fun onFail(error: AdError) { }
})三条必须遵守的:
- 同意结果要持久化(SharedPreferences 即可),否则每次启动都弹,用户当成弹窗广告
- 不同意也能用 App,只是没广告:禁掉广告入口 + 留一个「重新查看隐私政策」入口
onFail时不要请求广告。后台线程仍会把这次请求跑完,配置到手后再调一次start()就绪
⚠️ 同意之前调
start()= 违规采集个人信息,应用商店会驳回上架。 这是硬性红线,见《金融类 App 合规清单》。
→《接入文档》二、《隐私合规说明》4.1
4. 三种广告位的最小可用代码
下面的
"splash_main"/"reward_main"/"banner_main"是占位, 换成运营给你的那几个聚合广告位 ID。
4.1 开屏
开屏必须有一道不依赖任何回调的兜底放行,这不是最佳实践而是必备项 —— 见 4.4。
java
// Java(完整可跑版本见 4.4,这里只是主干)
SplashAd splashAd = new SplashAd("splash_main");
splashAd.load(this, new SplashAdListener() {
@Override public void onAdLoaded(String adnType) {
// show() 返回 false = 素材过期或不可用,必须立刻放行进主页
if (!splashAd.show(container)) { goMain(); }
}
@Override public void onAdLoadFailed(AdError error) { goMain(); }
@Override public void onAdShow() { }
@Override public void onAdClick() { }
@Override public void onAdClose() { goMain(); }
});
// onDestroy: splashAd.destroy();kotlin
val splashAd = SplashAd("splash_main")
splashAd.load(this, object : SplashAdListener {
override fun onAdLoaded(adnType: String) { if (!splashAd.show(container)) goMain() }
override fun onAdLoadFailed(error: AdError) = goMain()
override fun onAdShow() { }
override fun onAdClick() { }
override fun onAdClose() = goMain()
})- 容器(
container)要铺满屏幕 - 开屏在启动路径上,超时预算很短(后台建议配 3 秒内),拿不到就放行
- 线上事故最常见的形态不是没广告,而是卡在开屏页进不去
4.2 激励视频
java
RewardAd rewardAd = new RewardAd("reward_main");
rewardAd.load(activity, new RewardAdListener() {
@Override public void onAdLoaded(String adnType) { rewardAd.show(activity); }
@Override public void onAdLoadFailed(AdError error) { }
@Override public void onAdShow() { }
@Override public void onAdClick() { }
@Override public void onAdClose() { }
@Override public void onReward() { /* 发奖励(见下方要点)*/ }
@Override public void onVideoComplete() { }
});
// onDestroy: rewardAd.destroy();kotlin
val ad = RewardAd("reward_main")
ad.load(this, object : RewardAdListener {
override fun onAdLoaded(adnType: String) { ad.show(this@MyActivity) }
override fun onAdLoadFailed(error: AdError) { }
override fun onAdShow() { }
override fun onAdClick() { }
override fun onAdClose() { }
override fun onReward() { } // 与 onVideoComplete 是两件事
override fun onVideoComplete() { }
})四条必看:
- 一次
load只能show一次,展示后要重新load onReward与onVideoComplete是两件事,不要互相替代。实测优量汇的激励条件可能是 「打开 App 体验 15 秒」或「点击广告」,只播完视频onReward不触发;也实测到过onReward发了而onVideoComplete一次都没回调- 穿山甲点「跳过」不会直接关闭,会先弹挽留弹窗(「再看一个 / 坚持退出」), 点「坚持退出」才触发
onAdClose。不要假设「点跳过 == 广告结束」 - ⚠️ 奖励有现金价值(可提现 / 抵扣 / 抽奖)时,
onReward只用于界面反馈, 真实发奖必须以服务端通知为准 —— 客户端回调可被 Hook 和重放伪造。 金融类 App 基本都落在这一档,接法见《接入文档》四「服务端发奖验证」
4.3 Banner
java
ViewGroup container = findViewById(R.id.banner_container);
BannerAd bannerAd = new BannerAd("banner_main");
bannerAd.load(activity, container, new BannerAdListener() {
@Override public void onAdLoaded(String adnType) { } // 每次刷新都回调,adnType 可能变
@Override public void onAdLoadFailed(AdError error) { }
@Override public void onAdShow() { }
@Override public void onAdClick() { }
@Override public void onAdClose() { } // 用户关闭后刷新自动停止
});
// onDestroy: bannerAd.destroy(); ← 不调必然泄漏kotlin
val bannerAd = BannerAd("banner_main")
bannerAd.load(this, container, object : BannerAdListener {
override fun onAdLoaded(adnType: String) { }
override fun onAdLoadFailed(error: AdError) { }
override fun onAdShow() { }
override fun onAdClick() { }
override fun onAdClose() { }
})
// onDestroy: bannerAd.destroy()- 广告 View 由 SDK 挂进
container,不要自己addView - 刷新由聚合层按后台配的间隔驱动,每次重走完整调度,业务侧不用管
- Banner 长期持有 Activity 引用,
onDestroy不调destroy()必然泄漏, 且定时器还在转 → 内存持续上涨 + 曝光数虚高
4.4 开屏兜底放行(照抄,三段都不能省)
java
public class SplashActivity extends Activity {
private static final long GUARD_LOAD_MS = 5000; // ① load 后没有任何回调
private static final long GUARD_SHOW_MS = 2000; // ② show 后没有 onAdShow(白屏)
private static final long GUARD_SHOWN_MS = 12000; // ③ 展示后没有 onAdClose
private SplashAd mSplashAd;
private boolean mJumped;
private boolean mAdShown;
private final Handler mGuard = new Handler(Looper.getMainLooper());
@Override protected void onCreate(Bundle b) {
super.onCreate(b);
setContentView(R.layout.activity_splash);
final ViewGroup container = findViewById(R.id.splash_container);
mSplashAd = new SplashAd("splash_main");
// 先武装兜底,再 load —— 反过来写的话,命中缓存时回调是同步的,定时器还没装上
armGuard(GUARD_LOAD_MS, "load 后无回调");
mSplashAd.load(this, new SplashAdListener() {
@Override public void onAdLoaded(String adnType) {
if (!mSplashAd.show(container)) { goMain(); return; }
armGuard(GUARD_SHOW_MS, "show 后无 onAdShow");
}
@Override public void onAdLoadFailed(AdError error) { goMain(); }
@Override public void onAdShow() { mAdShown = true; armGuard(GUARD_SHOWN_MS, "展示后无 onAdClose"); }
@Override public void onAdClick() { }
@Override public void onAdClose() { goMain(); }
});
}
private void armGuard(long delayMs, final String why) {
mGuard.removeCallbacksAndMessages(null);
mGuard.postDelayed(new Runnable() {
@Override public void run() { Log.w("Splash", "兜底放行: " + why); goMain(); }
}, delayMs);
}
// 用户点广告跳到落地页:暂停计时,回来重新计时。
// 不做这一步,用户在落地页读 20 秒回来会发现开屏自己跳走了
@Override protected void onPause() {
if (mAdShown) mGuard.removeCallbacksAndMessages(null);
super.onPause();
}
@Override protected void onResume() {
super.onResume();
if (mAdShown && !mJumped) armGuard(GUARD_SHOWN_MS, "回到页面后仍无 onAdClose");
}
/** 五条路径(四个回调 + 兜底定时器)都收敛到这里,且只执行一次 */
private synchronized void goMain() {
if (mJumped) return;
mJumped = true;
mGuard.removeCallbacksAndMessages(null);
startActivity(new Intent(this, MainActivity.class));
finish();
}
@Override protected void onDestroy() {
mGuard.removeCallbacksAndMessages(null);
if (mSplashAd != null) mSplashAd.destroy();
super.onDestroy();
}
}为什么「把所有回调都收敛到 goMain()」不够:那只覆盖「回调来了」。真正出事故的是回调不来。
| 场景 | 现象 | 哪一段救它 |
|---|---|---|
| 广告平台回调丢失 / 被自身异常吞掉 | 开屏页白着不动 | ① GUARD_LOAD_MS |
show() 返回 true 但平台不渲染 | 画面全白,页面永远不关 | ② GUARD_SHOW_MS |
广告展示了但 onAdClose 没来 | 广告播完卡在开屏页 | ③ GUARD_SHOWN_MS |
中间那条是真机实测踩到的(优量汇开屏容器未完成布局时展示,回调了"展示成功"却不出画面)。 SDK 侧已修这个具体成因,但下一个平台、下一个版本还会有别的成因 —— 能不能进主页,不该取决于第三方 SDK 的回调是否守约。
GUARD_LOAD_MS 取该广告位后台配的 total_timeout_ms 再加 1~2 秒余量(首次广告 SDK 初始化会占掉一部分),另两段按上面的值即可。
4.5 建议加上:预加载(可选但收益明显)
java
AdMix.preload(this, "splash_main"); // 主页 onResume,为下一次(热启动)开屏备货
AdMix.preload(this, "reward_main"); // 激励入口页打开时- 必须在
start()之后调用,否则一律失败、一个请求都不发 - 用长期存活的页面(如主页)预加载,不要用马上 finish 的页面(如开屏页自己)
- 缓存只在进程内存里:真正的冷启动第一条开屏一定是实时请求, 缓存命中发生在热启动开屏、下一次激励视频等场景
→《接入文档》三、四、五、五·二、五·五
5. 接入自检清单(跑起来后逐条核对)
bash
adb logcat -s "AdMix:V"| # | 核对项 | 通过的标志 | 不通过怎么办 |
|---|---|---|---|
| 1 | 适配器被发现了 | 启动日志里每个引入的 adapter 一行:adapter 就绪: csj (SDK 7.7.1.6) / adapter 就绪: gdt (SDK 4.680.1550) | 出现 没有发现任何 adapter → 坐标没引全,或打包策略把 META-INF/services/** 排除了 |
| 2 | 同意之前不联网 | 停在隐私弹窗时 adb shell run-as <包名> ls files/ 为空,且没有 /v1/config 请求 | start() 被提前调了,挪到「同意」之后 |
| 3 | 能拉到配置 | 远端配置加载完成,ADN: [csj,gdt] …;start() 回调 onSuccess | 见下方常见报错第 4 组 |
| 4 | 能力上报正确 | 拉取远端配置 … adapters=[csj,gdt] 与你实际引的 adapter 一致 | 只引一家时应只有那一家;对不上说明依赖引错 |
| 5 | 三种广告位都能出广告 | 每种至少一次 最终胜出: xxx,并在屏幕上看到广告 | 见下方常见报错 |
| 6 | 埋点有上报 | 请运营在后台「数据报表」按你的 AppID 查当天,能看到请求 / 填充 / 曝光 | 确认 start() 已调、设备联网;AdMix.flushEvents() 可催一次 |
| 7 | 开屏五条路径都能进主页 | 手动测:正常展示后关闭 / 点广告再返回 / 飞行模式无填充 / 展示中杀掉网络,都能进主页 | 兜底定时器没装齐,回看 4.4 |
| 8 | Banner 刷新后仍正常 | 停在 Banner 页 2~3 个刷新周期,无空白、无闪烁、内存不持续上涨 | onDestroy 漏了 destroy() |
| 9 | ⚠️ Release 混淆包也验过 | 用 minifyEnabled true 的包重跑 1、5、8 | 见下方常见报错第 5 组 |
| 10 | 上线包关掉 debug | AdMixConfig.Builder().debug(false) | — |
第 9 条不能省:Debug 能跑不代表 Release 能跑。 适配器自注册与反射实例化在混淆 / 打包合并下 可能静默失效,表现是「一条广告都没有」而不是崩溃。
你会看到的两条 lint Error(都不用管,也改不掉)
assembleRelease / lintVital 不受影响,能正常打包(minSdk 29 + R8 的最小工程已实测)。 只有显式跑 ./gradlew lint 时会报这两条 Error:
| lint 检查 | 报什么 | 为什么不用管 |
|---|---|---|
NotificationPermission | 「targeting Android 13+ 时发通知需要 POST_NOTIFICATIONS(usage from com.byazt.bd.v)」 | com.byazt.* 是穿山甲 SDK 内部的类。为第三方 SDK 的内部行为向用户多要一个运行时权限并不合理,我方也没有声明它 |
QueryAllPackagesPermission | 「应该用 <queries> 而不是 QUERY_ALL_PACKAGES」 | 你恰恰是在移除这个权限(第 2 节那行 tools:node="remove"),但 lint 只看到清单里出现了这个权限名,识别不了 remove |
工程有 lint { abortOnError true } 或把 lint 接进 CI 时,把这两条降级即可(其余检查不要放松):
groovy
android {
lint {
warning 'NotificationPermission'
warning 'QueryAllPackagesPermission'
}
}另外构建时会有一条 manifest Warning uses-permission#com.android.permission.GET_INSTALLED_APPS was tagged ... but no other declaration present 和若干条穿山甲 aar 自身的 D8 Expected stack map table 警告 —— 两者都正常,不需要处理。 前者恰好证明没有任何 SDK 声明 GET_INSTALLED_APPS(华为是在运行时自己加的)。
6. 常见报错对照表
第 1 组:优量汇不出广告
| 现象 | 原因 | 怎么办 |
|---|---|---|
gdt 107076 请求包名与在优量汇注册的媒体全包名一致才返回广告 | 包名与优量汇后台登记的不一致 | 见下方「包名两个字段」 |
gdt 5004 没有匹配到合适的广告资源 | 调试期正常无填充 —— 但包名不符时也可能报这个(实测返回码不稳定,有时 107076 有时 5004) | 先按 107076 排查包名,排除后再当成真无填充 |
gdt 5006 包名校验错误 | 代码位被多个包名共用 | 优量汇代码位属于媒体、媒体绑定包名,不能共用。找运营为你的应用单独建 |
gdt 107030 App包名无效 | 优量汇后台**「程序全包名」**填错 | 见下方 |
gdt 100133 | 广告位状态异常 / 新建未满 30 分钟 | 等 30 分钟,或找运营查后台状态 |
gdt 3003 | 网络不可用 | 查设备网络 |
包名两个字段(最容易卡住的一条):优量汇后台有「主程序包名」和「程序全包名」两个字段, 服务端校验的是「程序全包名」。两者不一致就报 107030,而错误文案只说"和注册时填写的一致", 不告诉你是哪个字段。给运营报包名时,把两个字段分别念出来逐字核对。
第 2 组:穿山甲不出广告
| 现象 | 原因 | 怎么办 |
|---|---|---|
csj 602 未知异常 | 代码位 ID 体系填错了 | 穿山甲有两套代码位 ID:GroMore 聚合广告位 ID(10 开头)与瀑布流里的原生代码位 ID。我方走 GroMore 通道,后台必须填聚合广告位 ID。填成瀑布流里的原生代码位 ID 就报 602,错误信息毫无指向性 |
csj 20005 + message 方括号里是空的 | GroMore 后台只建了广告位、瀑布流没配代码位 | 找运营在穿山甲后台「瀑布流管理」里给这个广告位添加代码位(两步缺一不可) |
csj 20005 + message 方括号里有内容 | 瀑布流配了,是各家自己没填充 | 正常现象,看里面每家的 error_msg |
csj 20001 reason:234 | 聚合代码位用在了非聚合场景 | useMediation 没生效,联系我方 |
csj 20001 reason:112 | 无效重复请求过多 | 测试期高频请求同一代码位常见,换台设备或隔一会儿再试 |
csj 40006 广告位ID不合法 | Banner 尺寸与后台广告位规格不匹配 | 把你实际使用的 Banner 尺寸告诉运营,让他按同一规格建代码位 |
打开 debug(true) 时 SDK 会自动打开 GroMore 的 ADN 错误明细,20005 的 message 形如:
csj 20005 [{"adn_name":"pangle","mediation_rit":"***","error_code":20001,"error_msg":"reason: 112 ..."}]第 3 组:AdMix 自己的错误码
| 码 | 含义 | 怎么办 |
|---|---|---|
| -1001 | SDK 未初始化 | 检查 init() 调用位置与调用顺序 |
| -1002 | 广告位无配置 | 广告位 ID 拼错,或运营还没给这个广告位配代码位 |
| -1003 | 所有广告源均无填充 | 正常现象,看上面两组 ADN 错误码定位是哪一家的问题 |
| -1004 | 整体超时 | 请运营调大该广告位的 total_timeout_ms |
| -1005 | Adapter 不可用 | 该家的 adapter 没被发现 → 先看自检清单第 1 条 |
| -1006 | 用户尚未同意隐私政策 | start() 还没调(或调了但 onFail)就请求了广告 |
第 4 组:拉不到配置(没广告时先看这一组)
排查顺序,从上到下:
start()到底调了没有?调的时机在「同意隐私政策」之后吗?—— 没调就一定拉不到- 日志里有
远端配置加载完成吗?没有就按下表对号:
| 日志 | 原因 | 怎么办 |
|---|---|---|
远端配置鉴权失败(40101 签名错误) | AppID 与 App 密钥对不上,或该密钥已被作废 | 对照后台逐字核对。注意别把 AppSecret 当成 App 密钥 |
远端配置响应码异常 404 | AppID 不存在,或该应用还没发布过配置版本 | 找运营确认 AppID、让他发布一次配置 |
远端配置鉴权失败(40103 nonce 重放) | 链路上有会重放请求的代理 | 去掉代理;不要在中间加按 URL 缓存的代理(每次 nonce 都不同,协商缓存会失效) |
已按服务端时间校正时钟…重新签名重试一次 | 本机时间不准 | 不用管,SDK 自愈 |
远端配置加载失败…(超时 / IO) | 网络不通 | 确认设备能访问 https://api.maemi.cn;不要为 AdMix 配 network_security_config,也不要开 usesCleartextTraffic |
start 失败:没有拿到任何 ADN 配置 | 装机后第一次冷启动且这次拉取失败(本地一份缓存都没有) | 按无广告降级,联网后再调一次 start() |
- 配置拉到了但某家 ADN 不在里面 → 看日志里的
服务端按本机能力裁掉: gdt: 说明你没引那家的 adapter,服务端按上报的能力主动摘掉了(这是正常机制,不是故障)
第 5 组:Debug 正常、Release 混淆包一条广告都没有
先跑这一条,10 秒定位:
bash
unzip -p <你的 release apk> META-INF/services/com.admix.adapter.IAdnAdapter| 输出 | 结论 |
|---|---|
com.admix.adapter.csj.CsjAdapter + com.admix.adapter.gdt.GdtAdapter(各一行) | 声明正常,问题不在这里 → 看日志的 adapter 就绪 与 -1005 |
| 只有一行 / 空 / 文件不存在 | 打包策略把 META-INF/services/** 吃掉了 → 去掉你的 packagingOptions / packaging.resources 里对它的 exclude 或 pickFirst |
混淆规则随 aar 自动生效,你不需要为 AdMix 写任何
-keep。 自检清单第 9 条就是为这一组存在的。
第 6 组:其他真机踩过的坑
| 现象 | 说明 |
|---|---|
| 开屏白屏、页面永远不关 | 见 4.4 第 ② 段兜底。SDK 已修优量汇侧成因,但兜底仍必须有 |
| Banner 刷新后"看着没变" | 测试代码位素材池小且风格雷同,实际已经变了。用刷新计数确认,不要靠肉眼 |
| 激励视频点跳过没关闭 | 穿山甲会先弹挽留弹窗,点「坚持退出」才 onAdClose |
| 华为弹「读取已安装应用列表」 | 来自优量汇(已确认并已修)。若仍出现,把系统日志和时间点给我方 |
日志里价格和代码位显示 *** | 刻意如此,与 debug 开关无关。要定位到具体代码位,把广告位 ID + ADN + 时间点交给运营查 |
→《接入文档》六、七
7. 交付物与找谁要什么
| 你要的东西 | 去哪拿 |
|---|---|
| SDK(Maven 方式) | 根 settings.gradle 配 https://admin.maemi.cn/maven/ + 穿山甲官方仓库,引三个坐标 |
| SDK(离线包) | https://admin.maemi.cn/maven/downloads/admix-android-sdk-1.0.0.zip,或开发者后台「接入指引」页 |
| 本指南 / 完整文档 | 离线包 docs/ 目录,或开发者后台「接入指引」页 |
| AppID、App 密钥 | 找平台运营(后台「应用管理 → 接入」) |
| 聚合广告位 ID 列表 | 找平台运营(后台「广告位管理」)。Banner 记得同时确认尺寸规格 |
| AppSecret(只给服务端,别进 APK) | 找平台运营,只显示一次 |
| 报表 / 填充率 / 收益 | 开发者后台自己看(运营为你开账号) |
| 改价格、调瀑布顺序、开关广告位 | 找运营在后台改,你不用发版 |
出问题时给我方的信息,请一次给全:广告位 ID + ADN + 出问题的时间点 + adb logcat -s "AdMix:V" 的原始日志 + 是 Debug 还是 Release 包。
8. 完整文档索引
| 文档 | 什么时候看 |
|---|---|
01-接入文档.md | 本指南的完整版:每个参数、每个回调、服务端发奖验证、预加载与缓存、埋点事件表 |
02-隐私合规说明.md | 写隐私政策、做 SDK 自查时 |
03-配置格式说明.md | 想理解运营在后台配的价格 / 超时 / 瀑布顺序怎么影响出广告时(运营看这份) |
05-金融类App合规清单.md | 上架应用商店前(第三方 SDK 目录、隐私政策段落示例、遗留风险) |