GMA SDK 广告预加载审计实战:skills 仓库中的跨平台 Preload API 校验规则详解
【免费下载链接】skillsAgent Skills for Google products and technologies项目地址: https://gitcode.com/GitHub_Trending/skills29/skills
本文围绕 skills 仓库中google-mobile-ads-validate技能的一项核心审计规则——广告预加载(Ad Preloading)校验展开。你将完整掌握 Google Mobile Ads(GMA)SDK 在 Android、iOS、Unity 三个平台上预加载 API 的对照关系,理解 6 类必须判 Fail、1 类 Warning 及 N/A 的判定标准,并结合仓库内的 Next-Gen SDK 迁移映射表,学会如何在应用发布前对预加载实现做合规审查。
一、这项校验在 GMA 集成审计中的定位
在 skills 仓库中,google-mobile-ads-validate 是一个面向 AI Agent 的集成校验技能,用于对已接入 GMA SDK 的 iOS、Android 或 Unity 工程做上线前审计。它支持两种工作模式:
- 完整审计(Full Audit):当用户提出泛化的"校验/完整审计"请求时,评估全部检查项;
- 单项检查(Specific Checks):当用户只要求校验某个领域(例如只查广告预加载)时,仅评估对应的检查项,而不运行整个清单。
完整审计清单包含 5 个检查项,广告预加载校验是其中之一,其余 4 项各有独立的参考文档:
| 检查项 | 参考文档 |
|---|---|
| 项目中不存在测试 Application ID 且格式正确 | application-id.md |
| 项目中不存在测试广告单元且格式正确 | ad-units.md |
| 已实现全部 Google SKAdNetwork ID | google-skadnetwork-ids.md |
| 中介(Mediation)适配器版本兼容性 | mediation-adapter-compatibility.md |
| 广告预加载校验 | ad-preloading.md |
每个检查项的状态按统一的评分规则取值(见 SKILL.md 的 Scoring Rules 一节):
- Pass:不满足任何 Warning、Fail 或 N/A 条件;
- Warning / Fail / N/A:满足对应状态描述的条件;
- 校验结论最终以 Markdown 报告输出,表格列为
Check | Status | Findings | Next Steps,且只包含实际执行过的检查项。
二、跨平台预加载 API 对照表:定位代码的第一步
ad-preloading.md 给出的操作步骤是:在目标工程中搜索当前平台对应的 GMA SDK 预加载调用。三套平台的 API 命名风格差异很大,审计时必须先按本表锁定搜索关键词:
| API | Android | iOS | Unity |
|---|---|---|---|
| Start Preload | startPreload | preload | Preload |
| Stop Preload | destroyAll | stopPreloadingAndRemoveAllAds | DestroyAll |
| Poll Ad | pollAd | ad(withPreloadID:) | DequeueAd |
| Ad Preloaded | onAdPreloaded | adAvailable(forPreloadID:) | OnAdPreloaded |
| Ad Exhausted | onAdsExhausted | adsExhausted(forPreloadID:) | OnAdsExhausted |
| Ad Available Check | isAdAvailable | isAdAvailable(withPreloadID:) | IsAdAvailable |
从这张表可以读出三套平台的命名约定差异,这也是搜索时的注意点:
- Android:方法名全部小驼峰,回调以
on开头(onAdPreloaded、onAdsExhausted),停止预加载直接叫destroyAll; - iOS:以 Swift 风格 API 呈现,回调是
...Available(forPreloadID:)、...Exhausted(forPreloadID:)这类带PreloadID参数的方法,preload ID 是贯穿 iOS 预加载流程的显式参数; - Unity:首字母大写的 C# 风格(
Preload、DequeueAd、OnAdPreloaded),取广告的叫DequeueAd而非Poll。
审计时建议按平台逐一搜索这些关键词,确认工程中实际使用了哪些预加载能力,再对照下文的 Pass/Fail 条件逐项判定。
三、Pass/Fail 判定标准:六类 Fail 模式逐条拆解
原文档给出的判定标准是本次校验的核心,必须完整保留。以下按原文逐条继承,并补充每条模式的实际含义与规避方式。
3.1 Fail 条件:任一不当预加载模式被检出即判 Fail
(1)在同一个方法作用域内poll出广告却没有展示(Polls an ad without showing it within the same method scope)
pollAd(Android)/ad(withPreloadID:)(iOS)/DequeueAd(Unity)是"从预加载队列中取出一个广告"的操作,取出后即消耗掉队列中的一个实例。如果在同一方法作用域内调用了 poll 却没有任何展示路径(例如忘记调用show(),或仅在日志中打印),该广告就被白白丢弃,预加载的意义荡然无存。正确的写法是 poll 与 show 处于同一逻辑流程中且 show 一定会被执行。
(2)在"广告已预加载"或"广告已耗尽"回调中启动预加载(Starts preloading in the ad preloaded or ad exhausted callback)
onAdPreloaded/adAvailable(forPreloadID:)/OnAdPreloaded与onAdsExhausted/adsExhausted(forPreloadID:)/OnAdsExhausted这两组回调的职责是通知状态变化,而不是重新发起预加载。在回调内部嵌套startPreload/preload/Preload会形成难以追踪的重入链路,容易造成状态错乱。启动预加载应当放在明确的生命周期位置(如页面初始化),而不是被动回调里。
(3)在"广告已预加载"或"广告已耗尽"回调中停止预加载(Stops preloading in the ad preloaded or ad exhausted callback)
与上一条同理:destroyAll/stopPreloadingAndRemoveAllAds/DestroyAll表示终止整个预加载器并清空队列,属于生命周期级操作。把它放进预加载回调中,会导致"预加载完成 → 立即销毁预加载器"这种自相矛盾的循环;正确做法是把停止操作与页面/功能的销毁流程绑定。
(4)对同一个 preload ID 多次启动预加载,且中途未先停止预加载器(Starts preloading for the same preload ID multiple times without stopping the preloader first)
预加载器实例与 preload ID 绑定。若要在同一 ID 上再次startPreload,必须先调用停止 API 释放旧实例,否则会出现重复预加载、队列状态不可预期等问题。审计时应检查所有对同一 ID 的启动点,确认存在"先停后启"的调用顺序。
(5)使用空字符串或 null 作为 preload ID(Uses an empty string or null as the preload ID)
preload ID 是区分不同预加载队列/实例的键。传入""或null会使多个逻辑队列混用同一键,或触发 SDK 内部状态异常。代码审查时应关注 preload ID 的赋值来源,避免把可能为空的变量直接传入预加载 API。
(6)在 Unity 中于Update循环内检查广告可用性(Checks ad availability inside an Update loop on Unity)
这条只针对 Unity 平台。IsAdAvailable/isAdAvailable/isAdAvailable(withPreloadID:)属于可能涉及跨线程查询的 API,若放在每帧执行的Update()中高频轮询,会造成不必要的性能开销。可用性的检查应挂在事件回调(如OnAdPreloaded)或用户触发点上进行。
3.2 Warning 条件
- 对同一广告格式预加载了多个广告单元 ID(Preloads multiple ad unit IDs for the same ad format):例如同一 banner 格式下为两个广告单元分别建立预加载队列。这未必是错误(有时是多源冗余策略),但会成倍消耗预加载配额与流量,因此只判 Warning 并提示确认必要性。
3.3 N/A 条件
- 工程根本没有使用预加载 API(按上表搜索不到任何命中)→ 判定 N/A,而不是 Pass。
四、结合 Next-Gen SDK 迁移映射:预加载 API 的底层变化佐证
skills 仓库中还有一份与预加载直接相关的映射文档——google-mobile-ads-android-migrate-to-next-gen 技能,它描述了从旧版 GMA SDK(com.google.android.gms:play-services-ads)迁移到 GMA Next-Gen SDK(com.google.android.libraries.ads.mobile.sdk:ads-mobile-sdk)的规则。其中与预加载相关的变化,可以作为审计时判断"代码属于哪代 SDK、应使用哪套 API"的依据:
| 预加载要素 | 旧 SDK | GMA Next-Gen SDK |
|---|---|---|
| 预加载配置 | preload.PreloadConfiguration,通过PreloadConfiguration.Builder(String adUnitId).build()构建 | common.PreloadConfiguration,改为PreloadConfiguration(AdRequest request),广告单元 ID 声明在AdRequest中 |
| 预加载回调 | preload.PreloadCallbackV2(抽象类) | common.PreloadCallback(改为接口 interface) |
| 插页广告预加载器 | interstitial.InterstitialPreloader | interstitial.InterstitialAdPreloader |
| 预加载完成回调 | onAdPreloaded(preloadId: String, responseInfo: ResponseInfo?) | onAdPreloaded(preloadId: String, responseInfo: ResponseInfo)(responseInfo不再可空) |
从该映射文档的结构看(见 SKILL.md 的 "Ad preloading" 一节):除映射表中明确列出的差异外,Next-Gen SDK 的预加载方法保留与旧 SDK 相同的 API 签名与参数。这意味着第二节的跨平台 API 表(startPreload、onAdPreloaded、onAdsExhausted等关键词)对两代 SDK 都同样适用,审计搜索时不会因为 SDK 版本不同而漏检;但配置构建方式(Builder(adUnitId)还是PreloadConfiguration(AdRequest))与回调可空性(ResponseInfo?还是ResponseInfo)是区分新旧代码的信号,可用于在 Findings 中描述工程所处的 SDK 代际。
此外该迁移文档强调的 UI 线程规则同样适用于预加载回调:GMA Next-Gen SDK 的回调在后台线程触发,回调内的所有 UI 操作必须包裹在runOnUiThread {}或Dispatchers.Main.launch {}中——审计onAdPreloaded回调体时可以把这一点作为附加检查项,因为它直接决定预加载后的展示逻辑是否会崩溃。
五、审计执行方式与报告输出
以 ad-preloading.md 为执行蓝本,一次完整的预加载校验流程是:
- 确定平台:识别工程是 Android、iOS 还是 Unity(或跨平台,如 Unity 工程同时含原生插件),选定第二节的关键词表;
- 搜索定位:对 6 组 API(Start/Stop Preload、Poll Ad、Ad Preloaded、Ad Exhausted、Ad Available Check)逐一搜索,记录所有命中点;
- 若零命中:直接判 N/A("The project doesn't use the ad preloading APIs");
- 若存在命中:读取每个命中点的上下文,对照 3.1 节的 6 条 Fail 模式与 3.2 节的 Warning 条件判定状态;
- 生成报告:按 SKILL.md 的 Final Output 模板,只输出实际检查过的行,格式为:
| Check | Status | Findings | Next Steps |
|---|---|---|---|
| Ad preloading validation checks | Pass / Warning / Fail / N/A | 命中的具体文件、模式与说明 | 修复建议(如"在onAdPreloaded回调中移除startPreload调用,改为在页面初始化时启动") |
六、适用前提与边界说明
- 本文全部判定标准来源于仓库内 ad-preloading.md 与 SKILL.md,适用于任何接入了 GMA SDK(含 Next-Gen SDK,预加载方法签名在两代间基本一致)且使用预加载 API 的工程;
- 各平台 API 关键词表覆盖 Android、iOS、Unity 三端;其他平台(如 Flutter 包装层)不在该表显式覆盖范围内,审计时只能从源码结构推断其最终落到了哪一端的原生 API 上,并据此谨慎套用对应行的规则;
- 迁移映射部分依据的是仓库中迁移技能的映射表(SKILL.md),仅覆盖 Android 侧旧 SDK 到 Next-Gen SDK 的差异;
- 本仓库是只读的 Agent Skills 集合,以上"查看、运行"均指将上述技能文档作为审计规范使用,不涉及修改仓库内容。
【免费下载链接】skillsAgent Skills for Google products and technologies项目地址: https://gitcode.com/GitHub_Trending/skills29/skills
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考