菜单

广告探测器-Android 接入说明

  • 本文档面向接入广告 SDK  的开发者,说明如何在开屏/横幅/原生(有容器)插屏/激励视频(无容器) 两种场景下,在展示回调里对广告画面做截帧,用于素材归档、抽检或上报。请结合  广告 SDK  的展示  API  与回调,便于直接落地实现。
  • 下载地址:http://info.appsmartsite.com/Material_monitor/Android_MaterialMonitor.zip

1.  模块能力

能力 说明
截帧 广告  View、全屏/overlay  页面,或原生图片  url-onlymeta.image_url)→ JPEG(≤  可配置  KB,url-only  无本地文件)
元数据 ATAdInfo +  你传入的  AdTimingInput +  设备字段  → meta
上报 POST {baseUploadUrl}/v1/creative/uploadapp_idsignmetaimage
离线队列 SQLite;无网或传输层失败时延后重试(不占  maxUploadAttempts  计数);日配额节流
错误码 端侧  6xxx(§8.1)+  网关  0 / 1xxx ~ 5xxx(§8.4)

2. Gradle  接入

2.1  作为源码子模块(与本  Demo  相同)

在宿主  settings.gradle  中  include ':material-monitor',在  app  模块:

gradle 复制代码
dependencies {
    implementation project(':material-monitor')
    // 广告 SDK 依赖需保留,保证运行时存在 ATAdInfo
}

2.2  权限与要求

  • minSdkVersion:本库  build.gradle  为  21;宿主若更高以宿主为准。

  • Java 8+

  • 网络权限:上报需宿主具备  INTERNET。模块已声明  ACCESS_NETWORK_STATE(用于上传前  是否有可用外网  的预检;合并  manifest  后由系统授予「查看网络连接」类权限)。

    plaintext 复制代码
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android">
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    </manifest>

3.  初始化

在首个  Activity.onCreate  调用(内部会注册生命周期回调以跟踪前台  Activity,  参考 demo):

java 复制代码
import com.github.material.monitor.MaterialMonitor;
import com.github.material.monitor.MaterialMonitorConfig;

public class FirstActivity extends Activity {
    @Override
    public void onCreate() {
        super.onCreate();
        // 开发者用户协议允许之后自行获取和填充设备信息
        MaterialMonitor.init(this, new MaterialMonitorConfig.Builder()
                .baseUploadUrl("https://your-gateway-host")   // 上传地址
                .appId("YOUR_APP_ID")
                .appKey("YOUR_APP_KEY")                      // 请勿泄漏
                .oaid(oaidString)
                .androidId(androidIdString)
                .gaid(gaidString)
                // .imei(...).mac(...)
                // .maxUploadAttempts(3)
                // .retryDelayMs(3000L, 10000L)
                // .connectTimeoutMs(15000).readTimeoutMs(30000)
                // .debugPerfLogging(BuildConfig.DEBUG)
                .build());
    }
}

3.1 MaterialMonitorConfig.Builder  参数一览

类路径:com.github.material.monitor.MaterialMonitorConfig。构建后可通过 MaterialMonitor.get().getConfig()  读取;isUploadConfigured() 在  baseUploadUrlappIdappKey  三者均非空时为  true(自动入队上报的前置条件)。

Builder  方法 默认 必填(上报) 说明
baseUploadUrl(String) "" 网关  根地址,仅  host(可带端口),不含路径。客户端会拼  POST {baseUploadUrl}/v1/creative/upload。示例:https://api.example.com。首尾空白会被  trim。
appId(String) "" TopOn  开发者后台分配的  应用  ID,用于  multipart  表单字段  app_id  与签名。
appKey(String) "" 与  appId  配对的  签名密钥(HMAC-MD5,见网关文档  §3)。写入公开仓库或明文日志;推荐远程下发或加固存储。
oaid(String) "" 建议 写入  meta.device_info.oaid。Android  匿名设备标识;须在  用户同意隐私后  由宿主采集并传入。
androidId(String) "" 可选 写入  meta.device_info.android_id
gaid(String) "" 可选 Google Advertising ID,写入  meta.device_info.gaid
imei(String) "" 可选 写入  meta.device_info.imei;受系统版本与权限限制,多数场景可不传。
mac(String) "" 可选 写入  meta.device_info.mac;合规上通常  不建议  采集。
maxUploadAttempts(int) 3 含首次请求  的单任务最大上传次数(3 = 1  次首发  +  最多  2  次重试)。仅对  网关可重试失败(如  4xxx/5xxx)计数;无网延后(6006)不占此预算(§9.2)。耗尽  → RETRY_EXHAUSTED(6007)。最小值为  1
retryDelayMs(long firstMs, long secondMs) 500015000 第  1、2  次  可重试失败  后的等待毫秒数;第  3  次及以后失败  复用 secondMs。与  4001  限流时  SDK  会取  max(配置延迟, 1s)
connectTimeoutMs(int) 15000 HttpURLConnection  连接超时(毫秒),内部  下限  3000
readTimeoutMs(int) 30000 HttpURLConnection  读超时(毫秒),内部  下限  3000
debugPerfLogging(boolean) false 为  true  时输出  [frame] / [bitmap] / [storage] / [upload]  等分阶段耗时(Logcat tag  含  MaterialLog@ +  模块版本),联调性能用;Release  建议关闭

仅采集、不上传:可MaterialMonitor.init(this)  则使用默认空配置;此时自动入队  / reportFrameRecord  会因未配置完整上传参数而得到  ErrorCodes.NOT_READY(见  §8)。


4.  何时调用、delayMs  建议与特殊场景

4.1  通用原则

在  广告已展示、目标区域已  layout  完成  且仍  attached  的回调里调用(如  onAdShow、Banner  展示回调、原生绑定数据后)。
FrameOptions.delayMs  表示:从调用时刻起再等待多少毫秒  才真正截帧,用于错开白屏、素材或视频首帧未就绪、弱网加载慢等情况。

4.2  因网络与素材加载的延迟建议(推荐默认值)

结合弱网下视频类素材缓冲更慢、静态或  HTML  类相对更快的差异,建议如下(可在远程配置中下发,按流量分层微调):

广告样式 建议  delayMs 说明
激励视频 3000 ~ 5000 ms 视频流与贴片常受网络影响,过短易黑屏或未解码帧;可从  2s  起线上观察完整率,必要时提到  3 ~ 5s
开屏  / Banner /  插屏  /  原生等非激励 约  2000 ms 相对激励视频对「首帧就绪」要求略低,2  秒在多数机型与网络上可兼顾合规画面与体验

以上针对「单次展示只截一帧」的常规监测;与  §4.3  的「激励关闭前多帧」可组合使用。

4.3  激励视频:关闭前按需  0  延时、间隔多帧

为更准确识别  违规画面、异常跳转、结束帧诱导  等,可在  广告即将关闭或用户即将离开  前,在  画面已稳定可见  的节点上,使用  delayMs(0)  做  即时截帧,并按业务间隔  多次调用(例如每隔  5  秒一次)。

注意

  • delayMs(0)  表示  不额外等待,仍要求调用时  View  已  layout  且  仍附着在窗口上;若调用过早仍可能失败(VIEW_INVALID /  黑帧),请把「0  延时调用」放在  生命周期靠后、内容已展示  的回调里。
  • 每一次 collectFrameFrom*  都会生成  新的 FrameRecord.uploadTaskId(队列幂等键),同一广告展示可多次截帧、多次上报;网关侧展示维度仍以  ATAdInfo.getShowId()  等与  meta.event_info  一致。
  • 多帧会增加  流量、队列长度与日配额  消耗,请与产品/合规约定  频次上限。若有多帧截取需求,建议 5 秒一次,按最长边像素(maxLongEdge)1080 标准;若有高频需求,则需降低maxLongEdge标准如 720、540;高频截帧动作会增加 ANR 或内存上涨过高风险。

示例(伪代码:在激励关闭前短间隔再采一帧,delayMs  为  0):

java 复制代码
FrameOptions urgent = new FrameOptions.Builder().delayMs(0).maxSizeKb(300).build();
MaterialMonitor.get().collectFrameFromAdContainer(rewardContainer, adInfo, timing, urgent, callback);

4.4  原生自渲染:按素材类型选择采集  API

原生自渲染广告请按  主素材类型  选用  API(Demo  参考  NativeAdActivity  图片、NativePatchVideoActivity  视频):

素材类型 推荐  API 说明
图片(静态大图等) collectFrameFromNativeAdContainer 传入有效  http/https  的  creativeAssetUrl(如  getAdMaterial().getMainImageUrl())时,跳过本地截帧,仅上报  meta.image_url(网关  url-only  路径);无效或非  http(s) URL  会  回退  为对  targetView  截帧
视频 collectFrameFromAdContainer 视频帧在  SurfaceView /  硬件层,需走容器截帧  + PixelCopy不要依赖静态主图  URL
  • creativeAssetUrl:图片场景  有则传;须为  http://  或  https://  开头。空白或非法协议不会失败整次调用,而是回退为截帧。
  • url-only  成功时  FrameRecord.file  为  null,multipart 不含 image part;具体必填规则以网关文档为准。

5. API  参考(入参、返回值与用法)

包名:com.github.material.monitor。以下若无说明,采集相关回调均在主线程(见对外实施方案中的线程说明)。

5.1 MaterialMonitor.init / get / getConfig

方法 说明
static void init(Application application) 使用默认  MaterialMonitorConfig(无上传参数)。仅适合只落盘、不接网关的场景。
static void init(Application application, MaterialMonitorConfig config) 推荐。config  不可为  null  时用  DEFAULT  等价空配置。
static MaterialMonitor get() 获取单例。未  init  或已  shutdown  时返回  idle  占位实例collect*  等为  no-op  并打  warn  日志),不抛异常
static boolean isReady() 是否已  init  且尚未  shutdown(真实实例可在首次  get()  时懒创建)。
static void shutdown() 释放生命周期回调与  worker;待上传  SQLite  行保留,后续可再次  init  续传。
MaterialMonitorConfig getConfig() 读取初始化时的配置;可调用  isUploadConfigured()  判断是否具备  baseUploadUrl + appId + appKey

5.2 collectFrameFromAdContainer

签名

text 复制代码
void collectFrameFromAdContainer(
    View targetView,
    ATAdInfo adInfo,
    AdTimingInput timing,
    FrameOptions options,
    FrameCallback callback
)
参数 类型 可否  null 说明
targetView View 广告实际渲染区域(容器)。延时结束后会检查  仍  attached;延时期间仅  弱引用持有,避免泄漏。
adInfo ATAdInfo 当前展示对应的  TopOn  广告信息,用于  placementIdshowId、样式枚举  MaterialStyle等。
timing AdTimingInput 请求/填充/展示时间(毫秒),写入网关  event_info(库内转秒)。
options FrameOptions 传  null  时使用  FrameOptions.defaults()
callback FrameCallback 传  null  时无采集/上报回调,一般不推荐。

行为:校验通过后  **postDelayed(delayMs),到时截帧  →  压缩写盘  →  主线程  onCollectSuccess →  若上传已配置则  自动 enqueueReport。失败走  onCollectFailure(不会入队)。

样式目录MaterialStyle  由内部根据  ATAdInfo  解析,用于本地子目录名(如  rewarded_video),与网关  ad_type  含义对应,无需调用方传入。

5.3 collectFrameFromAdPage

签名

text 复制代码
void collectFrameFromAdPage(
    Activity hostActivity,
    ATAdInfo adInfo,
    AdTimingInput timing,
    FrameOptions options,
    FrameCallback callback
)
参数 类型 可否  null 说明
hostActivity Activity 调用方  当前页面(展示广告前/承载回调的  Activity,如  Demo  页)。用于在延时截帧时  排除  该窗口,避免透明  overlay  或独立  AdActivity  场景误截到宿主页。无效(null / finishing / destroyed)→ PARAM_INVALID
adInfo / timingoptions / callback 同上 同上 与容器采集一致。

适用:插屏/激励等  无稳定业务侧广告容器、或全屏覆盖难以取子  View  时(Demo:InterstitialAdActivityRewardVideoAdActivity  传入  this)。
失败常见原因:延时后无可用  Activity /  捕获  View → ACTIVITY_INVALID;弱引用  Activity  被回收等。

示例

java 复制代码
MaterialMonitor.get().collectFrameFromAdPage(
        InterstitialAdActivity.this, adInfo, timing,
        new FrameOptions.Builder().delayMs(3000).build(), callback);

5.4 onAdClosed

签名

text 复制代码
void onAdClosed(ATAdInfo adInfo)
参数 说明
adInfo 当前关闭的广告;按  ATAdInfo.getShowId()  匹配仍在  delayMs  等待中的采集任务。

行为:若同一  showId  的  collectFrameFromAdContainer  或  collectFrameFromAdPage  尚未执行截帧,则  取消  本次采集并回调  onCollectFailure(COLLECT_CANCELLED, …),避免广告已关仍截到空白或宿主页。

何时调用:在广告  关闭回调  中调用(Demo:onInterstitialAdCloseonRewardedVideoAdClosed)。Dialog / overlay /  宿主  Activity  上展示的插屏  建议必调;独立全屏  AdActivity  且生命周期已足够时可省略。

java 复制代码
@Override
public void onInterstitialAdClose(ATAdInfo adInfo) {
    MaterialMonitor.get().onAdClosed(adInfo);
}

5.5 reportFrameRecord

签名

text 复制代码
void reportFrameRecord(FrameRecord record, ATAdInfo adInfo)
void reportFrameRecord(FrameRecord record, ATAdInfo adInfo, ReportCallback callback)
参数 说明
record 截帧路径须含  已存在  的本地  JPEG file;url-only  采集时  file  为  null,由  collectFrameFromNativeAdContainer  自动入队,一般无需手动调用。uploadTaskId  为空时入队会生成   task_id
adInfo 与当时展示一致,用于组装  meta  中广告字段。
callback 仅上报结果:onReportSuccess / onReportSkip / onReportFailure(无  onCollect)。

典型用途:先采集落盘、后择机上传;或采集成功但此前上传失败后的补传(注意  uploadTaskId  与重复入队语义)。

5.6 flushPendingFrames

text 复制代码
void flushPendingFrames()

作用:主动请求模块  尽快处理一次 SQLite  中仍存在的  待上传任务(内部会调度上传执行器里的  drain,与「新任务入队」触发的处理同源)。可从任意线程调用,内部会切到上传线程与主线程  Handler,不会在调用线程上做  HTTP。

典型使用场景(按需选用;与「新任务入队自动  drain」叠加一般无害):

场景 说明
网络从不可用到可用 无网、NETWORK_ERROR  延后路径下任务仍在库中;在  NetworkCallback.onAvailable、或自建「已联网」判断里调用,可缩短等到下一次  约  30s  定时探测的间隔。
用户打开  Wi‑Fi /  蜂窝后回到  App 在  onResume  或网络回调里  flushPendingFrames()
日配额  /  限流解除后 封禁窗口过后可配合业务判断再  flush

一般不必:仅依赖进程内  入队  / init  时的自动  drain  也能在恢复网络后陆续上传;无全局网络监听时,至少在  网络可用回调  +  主  Activity onResume  调用即可。

与「无网延后」的关系flush  只唤醒上传队列,不重新截帧;无网时  drain  内仍会预检失败并再次排程,但比干等定时器更及时。

注意flush 绕过日配额门;本地文件已删或任务已终态则无上传可做。无网延后、回调语义等见  §9


6. FrameOptions  与  AdTimingInput

6.1 FrameOptions.Builder

方法  /  字段 默认 说明
delayMs(long) 500 ≥ 0。建议按  §4.2  调整:激励  2 ~ 5s,其他  约  2s;关闭前定点可用  0
maxSizeKb(int) 300 输出  JPEG  上限,与网关「单图  ≤300KB」对齐;允许范围  80, 300(超出会被  clamp)。
maxLongEdge(int) 1080 最长边像素上限;允许  540, 1440(超出会被  clamp)。默认  1080  在  300KB  网关限制与审核可读性之间折中;识别要求更高可调至  1440  并验证  JPEG  体积。若截帧频率高则倾向 720  或   更低
keepQualityFirst(boolean) true 优先较高  JPEG  质量再降质量/缩小,直到满足  maxSizeKb

构建:new FrameOptions.Builder().delayMs(2000).maxSizeKb(300).build()

6.2 AdTimingInput

构造  /  工厂 说明
new AdTimingInput(requestTimeMs, fillTimeMs, showTimeMs) requestTimeMs:广告请求时机、fillTimeMs:广告填充时机、showTimeMs:广告展示时机,毫秒;写入  meta.event_info  时转为秒。

网关对  request_ts / fill_ts / show_ts  的必填语义以对接文档为准;库内对  ≤0  的项会按  show_ts  等同秒做回填(见  CreativeMetaBuilder),生产环境仍建议传入真实三阶段时间


7.  回调说明(FrameCallback / AbstractFrameCallback

java 复制代码
AbstractFrameCallback() {
            @Override
            public void onCollectSuccess(FrameRecord record) {
                // 主线程:截帧成功时 file 已写好;url-only 时 file 为 null、仅带 image_url
            }

            @Override
            public void onCollectFailure(int errorCode, String message, Throwable cause) {
                // 主线程:未入队上传
            }

            @Override
            public void onReportSuccess(FrameRecord record) {
                // 主线程:上传成功;record.getFile() 通常为 null(库已删 JPEG)
            }

            @Override
            public void onReportSkip(FrameRecord record, String reason) {
                // 主线程:重复 task、配额封禁等
            }

            @Override
            public void onReportFailure(int errorCode, String message, FrameRecord record, Throwable cause) {
                // 主线程:record 可能为 null(终端失败且已清理)
            }
        }
java 复制代码
MaterialMonitor.get().collectFrameFromAdContainer(target, adInfo, AdTimingTracker.mock(), options,
                MaterialMonitorHelper.demoFrameCallback(this));

frameCallback需要持有 activity,为避免内存泄漏推荐两种使用路径:

  1. static  内部类  +  引用  Activity.this 方式:参考MaterialMonitorHelper.demoFrameCallback(activity)  弱引用持有 activity;
  2. 匿名  /  非  static  内部类  +  强引用 Activity.this 方式:可在 activity onDestroy  对接  传入与 collect 的同一实例 frameCallback
java 复制代码
  MaterialMonitor.get().detachCallback(frameCallback);

8.  错误码速查(com.github.material.monitor.ErrorCodes

SDK  回调里的  errorCode  均为  6xxx  端侧码,与网关  HTTP  响应  JSON  的 code(1xxx ~ 5xxx)不是同一套数值**。排查网关问题时,请看失败  message  里的  gateway NNNN: …  前缀,并对照  CreativeAuditGateway - SDK对接文档

8.1  端侧错误码一览

常量 回调 终端 含义与处理建议
6001 VIEW_INVALID onCollectFailure 容器为空、未  attach,或  delayMs  后  View  已销毁  →  在  展示且仍  attached  的回调里调用;适当增大  delayMs
6002 ACTIVITY_INVALID onCollectFailure 全屏采集延时后无可用页面  → collectFrameFromAdPage  传入有效  hostActivity;确认广告页仍在前台
6003 COLLECTION_FAILED onCollectFailure 截帧失败(含  PixelCopy  失败)→  视频类用容器  API;低版本可能只能  View.draw,可增大  delayMs
6004 COMPRESS_FAILED onCollectFailure JPEG  超  maxSizeKb  预算  →  降低  maxLongEdge  或  maxSizeKb,或缩小截帧区域
6005 PARAM_INVALID onCollectFailure / onReportFailure 入参不合法(adInfo/timing/hostActivity  等)或  reportFrameRecord  时本地文件不存在
6006 NETWORK_ERROR onReportFailure 无网或传输失败;任务仍排队,不占重试上限  →  恢复网络后  flushPendingFrames()(§9.2);成功后仍可能  onReportSuccess
6007 RETRY_EXHAUSTED onReportFailure 上传重试耗尽  →  查  message  中网关码;需补传时用新  uploadTaskId  重新  reportFrameRecord  或重新采集
6008 NOT_READY onCollectFailure / onReportFailure 未  init、已  shutdown,或  baseUploadUrl/appId/appKey  未配齐
6009 COLLECT_CANCELLED onCollectFailure 延时未截帧前广告已关(onAdClosed)→ 预期行为;关闭回调中调用  onAdClosed  可避免误采

8.2  回调与错误码

回调 说明
onCollectFailure 采集/写盘失败,或  onAdClosed  取消;不会自动入队上传
onReportFailure 上报链失败;6006  为非终端,其余多为终端(本地任务可能已清理)
onReportSkip 不是错误码;如日配额封禁、重复  uploadTaskId,看  reason  字符串

采集  vs  上报:6001 ~ 6004、6009  只出现在  onCollectFailure;6005 ~ 6008  主要出现在  onReportFailure(6005  也可能在采集入口触发)。

8.3  网关  code  与端侧  errorCode

你看到的 说明
回调  errorCode(6xxx) SDK 采集链及无  HTTP  响应时的上报错误(如  6006  无网)
回调  errorCode(1xxx ~ 5xxx) 部分  网关终态失败  时,errorCode  可能与响应  body  的  code  相同;仍建议以 message 为准
message  中  gateway NNNN: 网关原始协议码与文案,联调时  优先解析此字段
响应  body trace_id 成功/失败均可能返回,联系  TopOn  技术支持时一并提供

不要把  6xxx  端侧码与网关  1xxx ~ 5xxx  混在同一套埋点枚举里。网关码完整表见  §8.4

8.4  网关响应错误码(CreativeAuditGateway)

上传接口  POST …/v1/creative/upload  返回  JSON,code == 0 表示成功(HTTP  通常为  200)。失败时  code  为非  0,且  trace_id 在成功与失败时均可能返回,请失败时落日志便于排查。

以下与  document/CreativeAuditGateway - SDK对接文档.md §八  一致;若网关版本有增删,以在线接口说明为准。

8.4.1  成功

code msg(示例) 说明
0 ok 上传成功;同一  event_info.show_id  重复上报也返回  0(幂等,不重复扣配额)

8.4.2 1xxx —  鉴权错误(不可重试)

code HTTP msg(示例) 说明 建议处理
1001 401 unauthorized 签名校验失败或  app_id  无效 检查  appKey、签名算法、appId
1002 403 forbidden 未开通素材监测能力 联系  TopOn  运营开通

8.4.3 2xxx —  参数  /  图片错误(不可重试)

code HTTP msg(示例) 说明 建议处理
2001 400 invalid params meta  必填字段缺失或格式错误 核对  ATAdInfoAdTimingInput、设备字段
2002 400 image too large JPEG  超过  300KB 降低  maxSizeKb / maxLongEdge
2003 400 invalid image format 非  JPEG 确认截帧输出为  JPEG
2005 400 request body too large 整包超过  512KB 缩小图片或走  url-only

8.4.4 3xxx —  配额错误(当日不再上报)

code HTTP msg(示例) 说明 建议处理
3001 429 account quota exceeded 帐户每日配额用完 当天停止上报;响应或  onReportSkip/reason  中可能有  daily_quota_reset_at
3002 429 app quota exceeded App  每日配额用完 同上,针对单个  App

8.4.5 4xxx —  限流(可重试)

code HTTP msg(示例) 说明 建议处理
4001 429 rate limit exceeded 请求频率过高 等待响应  Header Retry-After(通常  ≥1s)后重试

8.4.6 5xxx —  服务端错误(可重试)

code HTTP msg(示例) 说明 建议处理
5001 500 upload failed 服务端存储异常 SDK  自动重试;仍失败则  RETRY_EXHAUSTED(6007)
5002 500 internal error 服务端内部错误 同上
5003 502 image download failed meta.image_url  下载失败 检查  URL  可访问性(原生  url-only)
5004 503 service unavailable 服务暂不可用 稍后重试

8.4.7 material-monitor  对网关码的处理

网关  code SDK  行为 宿主回调
0 删本地  JPEG  与队列行 onReportSuccess
1001 ~ 1002、2001 ~ 2005 终端失败,清理本地任务 onReportFailuremessage  含  gateway NNNN: …
3001 ~ 3002 写入日配额封禁窗口,清理当前任务 onReportFailure  或后续新任务  onReportSkipreason  含  daily_quota_reset_at
4001、5001 ~ 5004 按  maxUploadAttempts  自动重试(4001  至少等待  1s) 重试期间通常    失败回调;耗尽后  onReportFailure(6007, …)
无  HTTP  响应  /  无网 延后约  30s  再试,不占重试次数 onReportFailure(6006, …)  至多一次;恢复网后可  onReportSuccess

9.  网络、无网延后与队列

9.1  队列与线程

  • 采集成功且上传已配置时,任务写入  SQLite,由  单线程 uploadExecutor  顺序上传。
  • 日配额(3001/3002):可能  onReportSkipreason  含  daily_quota_reset_at(见网关文档)。

9.2  无网  /  传输层失败(NETWORK_ERROR = 6006)

上传线程在  真正发起  HTTP  之前  会调用  NetworkReachability.hasInternet(需  ACCESS_NETWORK_STATE,由本模块  manifest  合并进宿主):

  • Android M(API 23)及以上:当前默认网络须具备  NET_CAPABILITY_INTERNET  且  NET_CAPABILITY_VALIDATED(系统已判定可上网),否则视为无网。
  • 更低版本NetworkInfo.isConnected()  为真才继续。

若预检判定无网,或  HttpURLConnection 在收到  HTTP  状态行之前失败(超时、UnknownHost、无路由等,上传结果表现为  httpCode==0  且  gatewayCode==-1),进入  延后路径

行为
重试计数 增加  retry_count不计入 MaterialMonitorConfig.getMaxUploadAttempts()  的「可重试失败」预算)
数据 保留 DB  行与本地  JPEG
定时再试 约  30  秒  后再次调度  processNextUploadTask  探测队列
onReportFailure 同一  uploadTaskId  在「持续处于延后状态」期间,NETWORK_ERROR  只回调一次,避免日志/埋点刷屏
ReportCallback  生命周期 因该次失败而移除;后续同一任务上传成功时,仍可收到  onReportSuccess(与「先失败后成功」不矛盾,详见  ReportCallback JavaDoc)

宿主可在  NetworkCallback.onAvailable、回到前台的  onResume  等处调用  MaterialMonitor.get().flushPendingFrames(),缩短「等  30  秒」的空窗(与内部定时叠加无害)。

9.3 flushPendingFrames(摘要)

java 复制代码
MaterialMonitor.get().flushPendingFrames();

主动唤醒一次队列  drain;可从任意线程调用。典型场景见  §5.7  表格。


10.  隐私与合规建议

  • 只截取  广告相关区域  的  View,避免把个人敏感界面截进去。
  • 设备标识(OAID、GAID  等)请遵守当地法律与平台政策。
  • appKey  不建议硬编码在公开的地方。

11.  排错清单

现象 可能错误码 检查项
调用无效果  / warn not initialized 是否已  MaterialMonitor.init;未  init  时  get()  为  idle  实例
延时后采集失败 6001 View  是否仍  attached;调用时机是否过早
插屏/激励全屏失败 6002 collectFrameFromAdPage  是否传入  hostActivity;延时后广告页是否仍可见
黑屏  /  视频画面不对 6003 视频用  collectFrameFromAdContainer;增大  delayMs(§4.2)
图片过大无法压缩 6004 降低  maxLongEdge(540 ~ 1440)或  maxSizeKb
广告关后仍想采帧却失败 6009 属预期;未关前应完成采集,或不要调  onAdClosed
一直  NOT_READY 6008 baseUploadUrlappIdappKey  是否齐全
NETWORK_ERROR  后仍  pending 6006 延后上传(§9.2);恢复网络后  flushPendingFrames()
多次失败终态 6007 /  网关码 查  message  中  gateway NNNN:  与  trace_id(§8.4)
重复上报 —(onReportSkip 同一  uploadTaskId  只入队一次
想重新上传同一文件 使用  uploadTaskId  为空的  FrameRecord  调  reportFrameRecord,或重新采集
原生图片无本地  JPEG 有效  URL  走  url-only;视频类用  collectFrameFromAdContainer
插屏截到宿主页 6002 / 6003 传入  hostActivity;关闭时调  onAdClosed

完整错误码表见  §8


最近修改: 2026-08-13Powered by