开屏广告

开屏广告是一种特殊的广告格式,用于通过应用加载屏幕变现。这些广告可以随时关闭,并且旨在当用户将您的应用带到前台时(无论是在启动时还是从后台返回时)投放。

本指南介绍如何在 Compose Multiplatform 应用中集成开屏广告,除代码示例外,还提供格式使用建议与延伸阅读链接。

注意

开屏广告只能在垂直方向的应用中投放。对于水平方向的应用,广告将不会显示。

版式

开屏广告包含 Go to the app 按钮,让用户知道仍在您的应用中并可关闭广告。 广告示例如下。

前提条件

  1. 请按快速入门完成 Yandex Mobile Ads Compose Multiplatform 插件集成。
  2. 请使用最新的 Yandex Mobile Ads Compose Multiplatform 插件版本。若使用聚合,请同时使用最新的统一构建版本。

术语

  • 冷启动:应用不在内存中,启动并创建新会话。
  • 热启动:应用暂停在内存中,从后台回到前台。

实现

  1. 在 Composable 作用域内通过 rememberAppOpenAdLoader() 获取加载器。
  2. 使用 Yandex Advertising Network 界面中的 adUnitId 构建 AdRequest
  3. 在协程中调用 loadAd(AdRequest) 加载广告,并在展示前保留 AppOpenAd 引用。
  4. 如需在 show() 前监听展示、关闭与曝光,请连接 AppOpenAdEventListener
  5. 按下方建议,在应用回到前台或启动流程结束时调用 AppOpenAd.show()

主要步骤

  1. 创建 AppOpenAdLoader 广告加载器

    @Composable
    fun AppOpenRoot() {
        val loader = rememberAppOpenAdLoader()
        // ...
    }
    
  2. 配置广告请求

    val adUnitId = "demo-appopenad-yandex" // 替换为 "R-M-XXXXXX-Y"
    val request = AdRequest(adUnitId = adUnitId)
    

    adUnitId:在 Yandex Advertising Network 界面中分配的唯一标识,格式为 R-M-XXXXXX-Y。

    提示

    测试可使用演示广告位 ID "demo-appopenad-yandex"。发布前请替换为真实广告位 ID。

    可通过 AdRequest 扩展请求(targetingparameterspreferredTheme 等)。补充上下文有助于提升质量,详见广告定向

  3. 在绑定到 UI 作用域的后台调度器上加载广告

    val scope = rememberCoroutineScope()
    var appOpenAd by remember { mutableStateOf<AppOpenAd?>(null) }
    var isLoading by remember { mutableStateOf(false) }
    
    fun loadAppOpen() {
        isLoading = true
        scope.launch {
            try {
                val ad = loader.loadAd(request)
                appOpenAd = ad
                isLoading = false
            } catch (e: Exception) {
                isLoading = false
                // Ad failed to load with error
                // Attempting to load a new ad from the OnAdFailedToLoad event is strongly discouraged.
            }
        }
    }
    
  4. 决定展示时机。Compose Multiplatform 中通常连接平台生命周期信号(如 Android ProcessLifecycleOwner、iOS scenePhase 或 expect/actual 封装),在应用进入前台时协调 loadAppOpen() / show()。请挂接到您已区分冷/热启动的位置。

  5. 注册面向用户可见事件的监听器

    val ad = appOpenAd ?: return
    ad.setAdEventListener(
        object : AppOpenAdEventListener {
            override fun onAdShown() {
                // Called when an ad is shown.
            }
    
            override fun onAdFailedToShow(adError: AdError) {
                // Called when an ad failed to show.
                appOpenAd = null
                // Preload the next ad if appropriate.
            }
    
            override fun onAdDismissed() {
                // Called when an ad is dismissed.
                appOpenAd = null
                // Preload the next ad if appropriate.
            }
    
            override fun onAdClicked() {
                // Called when a click is recorded for an ad.
            }
    
            override fun onAdImpression(impressionData: ImpressionData?) {
                // Called when an impression is recorded for an ad.
            }
        },
    )
    ad.show()
    
  6. show() 之后,仅在广告在屏期间保留 AppOpenAd 实例。关闭回调后释放引用,再加载新素材。

  7. 若不再需要已加载广告,将可空引用置空以便回收。

    appOpenAd = null
    

完整代码示例

公开示例应用在专用界面演示加载与展示。下面将相同流程集中到单个 Composable 供参考。

@Composable
fun AppOpenSample(adUnitId: String) {
    val loader = rememberAppOpenAdLoader()
    val scope = rememberCoroutineScope()
    var appOpenAd by remember { mutableStateOf<AppOpenAd?>(null) }
    var isLoading by remember { mutableStateOf(false) }

    Column {
        Button(
            onClick = {
                isLoading = true
                scope.launch {
                    try {
                        appOpenAd = loader.loadAd(AdRequest(adUnitId = adUnitId))
                    } catch (e: Exception) {
                        // Ad failed to load with AdRequestError.
                        // Attempting to load a new ad from the onAdFailedToLoad() method is strongly discouraged.
                    }
                    isLoading = false
                }
            },
            enabled = !isLoading,
        ) {
            Text(if (isLoading) "加载中…" else "加载开屏")
        }

        Button(
            onClick = { appOpenAd?.show(); appOpenAd = null },
            enabled = appOpenAd != null,
        ) {
            Text("展示开屏")
        }
    }
}

生产环境请将加载/展示挂接到真实生命周期入口,而非按钮。

集成开屏广告时的特点

  1. 加载可能耗时,若广告尚未就绪,请勿延长冷启动时间。
  2. 热启动要展示的广告请提前预加载。
  3. 不建议在应用启动瞬间同时加载开屏与其他格式;此时运营数据与设备/网络繁忙,加载可能变慢。
  4. 加载出错时请勿立即再次请求新广告。若必须重试,请限制重试次数,以免在触发限制时出现持续失败请求与连接问题。

运行时集成测试

使用演示广告单元进行广告测试

我们建议使用测试广告来测试开屏广告集成和应用本身。

为了保证为每个广告请求返回测试广告,我们创建了一个特殊的演示广告版位 ID。用它来检查您的广告集成。

演示广告单元 ID:demo-appopenad-yandex

重要

在商店中发布您的应用程序之前,确保将演示版位 ID 替换为您在 Yandex Advertising Network 界面中获得的真实 ID。

您可以在 用于测试的演示广告单元 版块找到可用的演示广告版位 ID 列表。

测试广告集成

您可以使用 SDK 的内置分析器检查开屏广告集成。

该工具可确保您的开屏广告正确集成,并向日志输出详细报告。 要查看报告,请在用于 Android 应用调试的 Logcat 工具中搜索“YandexAds”关键字。

adb logcat -v brief '*:S YandexAds'

如果集成成功,您将看到以下消息:

adb logcat -v brief '*:S YandexAds'
mobileads$ adb logcat -v brief '*:S YandexAds'
I/YandexAds(13719): [Integration] Ad type App Open Ad was integrated successfully

如果您在集成广告时遇到问题,您将获得有关问题的详细报告以及如何解决这些问题的建议。

使用演示广告单元进行广告测试

我们建议使用测试广告来测试开屏广告集成和应用本身。

为了保证为每个广告请求返回测试广告,我们创建了一个特殊的演示广告版位 ID。用它来检查您的广告集成。

演示广告单元 ID:demo-appopenad-yandex

重要

在商店中发布您的应用程序之前,确保将演示版位 ID 替换为您在 Yandex Advertising Network 界面中获得的真实 ID。

您可以在 用于测试的演示广告单元 版块找到可用的演示广告版位 ID 列表。

验证广告集成

您可以使用本机控制台工具测试广告集成。

要查看详细日志,请调用 YMAMobileAds 类的 enableLogging 方法。

YMAMobileAds.enableLogging()

要查看 SDK 日志,请前往控制台工具并设置 Subsystem = com.mobile.ads.ads.sdk。您还可以按类别和错误级别过滤日志。

如果您在集成广告时遇到问题,您将获得有关问题的详细报告以及如何解决这些问题的建议。

建议

  1. 不要在启动画面之前展示开屏广告。

    先显示启动画面可改善体验,并让用户确认打开了正确应用。可在同一界面提示即将展示广告。用加载指示或简短文案说明广告结束后将回到内容。

  2. 若请求与渲染之间存在延迟,用户可能短暂看到应用后又看到与内容无关的广告。为避免此情况,请在主内容之前在启动画面中开始渲染。若启动画面后直接显示内容,最好不要渲染广告。

  3. 新用户应在多次使用应用后再看到开屏广告。仅向满足特定条件(如完成关卡、达到使用次数、未参与奖励等)的用户展示,安装后不要立即展示。

  4. 根据用户行为调节展示频率,不要在每次冷/热启动都展示。

  5. 仅在应用在后台停留超过一定时长(如 30 秒、2 分钟、15 分钟)后再展示。

  6. 最佳策略因应用而异,请充分测试。用户行为会变化,建议定期复查开屏策略。

延伸阅读

可在此查看完整集成示例: