同时加载多个广告
要同时准备多种格式,并发地请求并加载它们。每种格式并行请求和渲染,某种格式没有广告不会影响其他格式:运行你自己的竞价
VideoAd 在渲染前就带着价格,所以你可以和其他广告网络比较后再决定:
price.value 是以 price.currency 计的 CPM。price.precision 说明它是广告主的成交价(EXACT)还是自有需求的预估(ESTIMATED)。
reject 立即告知服务器,服务器告诉广告主其胜出未产生曝光。另一个广告网络以价格胜出时用 Outbid 并带上胜出价格和广告网络,让我们能针对你的流量优化出价;其他任何原因用 NotUsed(默认):时机过了、观众离开了。拒绝是可选的;你从未使用的广告会在过期或你调用 destroy() 时结算。
处理无填充
服务器没有该格式的广告时format() 抛出 VideoAdException.NoFill。这不是失败,SDK 从不自行重试;在之后的时刻再问。
把播放器交给 SDK
每次请求和事件都带有观众在这一集中的位置,叠加广告也会跟随播放:它只在内容播放时展示,观众一暂停就消失。剧集开始播放后,把播放器交给 SDK。 使用 Media3 播放器(ExoPlayer、MediaController)时,添加 so.kontext:video-media3 并直接交给 SDK;SDK 会读取它的时间并监听它的播放。播放器必须运行在主 looper 上:
VideoAdsPlayer:它的位置(毫秒),以及它是否在播放。缓冲和拖动进度都算作播放。
addListener 和 removeListener,并在每次变化时调用 VideoAdsPlayer.Listener(onIsPlayingChanged、onSeek、onContentChanged):观众一暂停叠加广告就会结束。否则叠加广告在屏幕上期间 SDK 每秒检查 isPlaying 四次。SDK 持有适配器直到 destroy() 或下一次 track,所以让适配器弱持有你的播放器。
在这一集开始播放时调用 track,而不是在创建 VideoAds 时:在那之前播放器的时间属于上一集。在那之前 SDK 发送 0,这对预取来说是正确的。
让广告避开你的控件
叠加条幅位于容器的底部或顶部,暂停卡片位于顶部;SDK 让两者都避开与容器重叠的系统栏和屏幕刘海。如果你的播放器在那里绘制自己的控件(标题、进度条、按钮),把它们占用的空间作为insets 传入:
Insets是androidx.core.graphics.Insets,单位为像素。它们叠加在系统栏和刘海之上:从它们的边缘量起,而不是从屏幕边缘。- 广告展示期间它们保持不变,经过改变大小和旋转也是如此。广告在屏幕上时你的控件改变了大小,广告仍保留展示时的 insets。
- 广告仍须能以一半或更大的尺寸放下。insets 会占用空间,所以
ContainerTooSmall包含它们。 - 全屏暂停广告忽略它们:它填满容器,它自己的控件会避开边缘。
下一集
当前一集播放时创建下一集的VideoAds,预取它的广告,观众离开时销毁当前的。任意数量的实例可以同时存在;SDK 让整个应用同一时间最多一个广告在屏幕上。
track,而不是创建时:在那之前播放器的时间属于上一集。
观众是谁
把你知道的信息设置到KontextVideo 上;下一次请求会携带它:
同意信息会自动读取:每次请求时,SDK 都会读取你的同意平台写入默认 见 TCF 与 CMP。
SharedPreferences 的 IAB 键(TCF、GPP、US Privacy)。只有当 SDK 无法检测到某个信号时(你的应用没有这样的平台,或把信号保存在别处),才需要自行设置。你的同意平台写入的值仍然优先。跟随页面的生命周期
VideoAds 属于展示这一集的页面:页面打开时创建它,页面离开时 destroy() 它。
- 在 Activity 中,在
onDestroy()里调用destroy();在 Fragment 中,在onDestroyView()里。 - 线性广告在 SDK 自己的 Activity 中运行,覆盖在你的 Activity 之上:你的 Activity 被停止而不是被销毁,广告结束会在它返回时送达你的监听器。
- 旋转时被重建的 Activity 也会运行
onDestroy(),从而运行destroy()。示例应用用android:configChanges让播放器 Activity 在旋转时保留。 - 广告持有它的监听器直到
onAdEnded运行完毕,所以作为监听器的 Activity 在广告结束前一直可达。
在 Jetpack Compose 中使用
SDK 用 Android View 绘制叠加广告和暂停广告,Compose 通过AndroidView 承载它们。线性广告无需额外操作:show(activity) 会把 SDK 的 Activity 启动在 Compose 当前显示的内容之上。叠加广告和暂停广告需要放进一个 ViewGroup;给它一个覆盖在播放器上的 FrameLayout:
- 只创建一次
FrameLayout并用remember保留:离开窗口的容器会把广告一起带走(INTERRUPTED)。 - 以剧集为键创建
VideoAds,并在DisposableEffect的onDispose中销毁它,这样页面或剧集离开时它也随之离开。 - 对于线性广告,把承载你的 composition 的
Activity传给show(activity)。
从 Java 调用
每个类型都有 builder,每个suspend 调用都有在主线程上送达的回调版本:
show、reject 和 dismiss 声明了 VideoAdException,所以 Java 要求 try。密封类型的值是单例:NoFillReason.NoAdMatch.INSTANCE、VideoAd.RejectReason.NotUsed.INSTANCE。