自适应粘性横幅

这是一个自动更新的小广告,放置在应用屏幕的顶部或底部。它与主要应用内容不重叠,常用于游戏应用中。

自适应粘性横幅通过优化每个设备上的广告尺寸,实现最大效率。这种广告类型允许开发者设置广告的最大允许宽度,但最佳广告尺寸仍然是自动确定的。自适应粘性横幅的高度不应超过屏幕高度的 15%。

本指南展示了如何将自适应粘性横幅集成到 Android 应用中。 除了代码示例和说明之外,它还包含特定格式的建议和其他资源的链接。

前提条件

  1. 按照 快速入门 中描述的 SDK 集成步骤进行操作。
  2. 提前 初始化 您的广告 SDK。
  3. 确保您运行的是最新的 Yandex Mobile Ads SDK 版本。如果您使用聚合,请同时确保您运行的是最新版本的 统一构建

实施

集成自适应粘性横幅的关键步骤:

  • 创建并配置用于显示横幅广告的视图。
  • 注册回调方法监听器。
  • 加载广告。
  • 如果您使用 Adfox,请传递 其他设置

自适应粘性横幅集成的特点

  1. 所有调用 Yandex Mobile Ads SDK 方法的操作必须在主线程中完成。

  2. 如果您在 onAdFailedToLoad() 回调中收到错误,请不要尝试再次加载新广告。如果没有其他选项,请限制广告加载重试次数。这将有助于避免出现限制时持续出现不成功的请求和连接问题。

  3. 自适应粘性横幅在使用所有可用宽度时效果最佳。通常情况下,这是设备屏幕的全宽度。确保包括适用于您的应用程序的所有内边距和安全显示区域。

  4. 要获取广告尺寸,请使用 BannerAdSize.stickySize(context, adWidth) 方法,该方法接受广告上下文和广告容器的可用宽度作为参数。

  5. BannerAdSize 对象是使用 BannerAdSize.stickySize(context, adWidth) 方法计算的,其中包含相同设备的广告宽度和高度的常量值。在特定设备上测试应用布局后,您可以确定广告尺寸将保持不变。

  6. 自适应粘性横幅的高度不应超过屏幕高度的 15%,并且应至少为 50 dp。

将广告视图添加到应用布局

要显示横幅广告,您需要将 BannerAdView 添加到应用布局中。您可以通过编程方式或使用 XML 文件来完成此操作。

BannerAdView 添加到应用屏幕布局的示例:

# activity.xml
...
<com.yandex.mobile.ads.banner.BannerAdView
        android:id="@+id/banner"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent" />
...

您还可以通过编程方式创建 BannerAdView 对象:

val bannerAd = BannerAdView(this)
final BannerAdView bannerAd = new BannerAdView(this);

加载和呈现广告

创建BannerAdView 并将其添加到应用屏幕后,需要加载广告。在加载自适应粘性横幅之前,还必须针对每个设备计算广告尺寸。

这是通过 SDK API 自动执行的:BannerAdSize.stickySize(context, adWidth)

作为参数,传递上下文和广告容器的最大可接受宽度。建议使用设备屏幕的整个宽度或父容器的宽度。确保包括适用于您的应用的所有内边距和安全显示区域。

private val adSize: BannerAdSize
    get() {
        // 计算广告的宽度,同时考虑广告容器中的内边距。
        var adWidthPixels = binding.adContainerView.width
        if (adWidthPixels == 0) {
            // 如果广告尚未布局,则默认为全屏宽度
            adWidthPixels = resources.displayMetrics.widthPixels
        }
        val adWidth = (adWidthPixels / resources.displayMetrics.density).roundToInt()

        return BannerAdSize.stickySize(this, adWidth)
    }
@NonNull
private BannerAdSize getAdSize() {
    final DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
    // 计算广告的宽度,同时考虑广告容器中的内边距。
    int adWidthPixels = mBinding.adContainerView.getWidth();
    if (adWidthPixels == 0) {
        // 如果广告尚未布局,则默认为全屏宽度
        adWidthPixels = displayMetrics.widthPixels;
    }
    final int adWidth = Math.round(adWidthPixels / displayMetrics.density);

    return BannerAdSize.stickySize(this, adWidth);
}

加载广告还需要活动上下文和来自 Partner Interface (adUnitId) 的广告版位 ID。

要在广告加载或加载失败时发出通知并跟踪自适应粘性横幅的生命周期,请为 BannerAdView 类对象设置 BannerAdEventListener 回调方法监听器。

您可以通过 AdRequest.Builder() 在请求中传递用户兴趣、上下文应用数据、位置详细信息或其他数据来扩展广告请求参数。在请求中提供额外的上下文数据可以显著提高您的广告质量。请参阅广告定位版块了解更多信息。

以下示例展示了如何加载自适应粘性横幅。加载成功后,会自动显示横幅:

class StickyBannerAdActivity : AppCompatActivity(R.layout.activity_sticky_banner_ad) {
    private var bannerAd: BannerAdView? = null
    private lateinit var binding: ActivityStickyBannerAdBinding

    private val adSize: BannerAdSize
        get() {
            // 计算广告的宽度,同时考虑广告容器中的内边距。
            var adWidthPixels = binding.adContainerView.width
            if (adWidthPixels == 0) {
                // 如果广告尚未布局,则默认为全屏宽度
                adWidthPixels = resources.displayMetrics.widthPixels
            }
            val adWidth = (adWidthPixels / resources.displayMetrics.density).roundToInt()

            return BannerAdSize.stickySize(this, adWidth)
        }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityStickyBannerAdBinding.inflate(layoutInflater)
        setContentView(binding.root)

        // 由于我们根据 adContainerView 大小加载横幅,
        // 我们需要等到该视图布局完毕后才能获取宽度
        binding.adContainerView.viewTreeObserver.addOnGlobalLayoutListener(object :
            ViewTreeObserver.OnGlobalLayoutListener {
            override fun onGlobalLayout() {
                binding.adContainerView.viewTreeObserver.removeOnGlobalLayoutListener(this);
                bannerAd = loadBannerAd(adSize)
            }
        })
    }

    private fun loadBannerAd(adSize: BannerAdSize): BannerAdView {
        return binding.banner.apply {
            setAdSize(adSize)
            setAdUnitId("your-ad-unit-id")
            setBannerAdEventListener(object : BannerAdEventListener {
                override fun onAdLoaded() {
                    // 如果此回调发生在活动被销毁之后,您
                    // 必须调用 destroy 和 return,否则可能会出现内存泄漏。
                    // 注意 `isDestroyed` 是活动上的一个方法。
                    if (isDestroyed) {
                        bannerAd?.destroy()
                        return
                    }
                }

                override fun onAdFailedToLoad(adRequestError: AdRequestError) {
                    // 广告加载失败,出现 AdRequestError。
                    // 强烈建议不要尝试通过 onAdFailedToLoad() 方法加载新广告。
                }

                override fun onAdClicked() {
                    // 记录广告点击时调用。
                }

                override fun onLeftApplication() {
                    // 当用户由于点击广告而即将离开应用程序(例如,转到浏览器)时调用。
                }

                override fun onReturnedToApplication() {
                    // 当用户点击后返回应用程序时调用。
                }

                override fun onImpression(impressionData: ImpressionData?) {
                    // 记录广告展示次数时调用。
                }
            })
            loadAd(
                AdRequest.Builder()
                    // 此处可以使用 AdRequest.Builder 类中的方法来指定各个选项设置。
                    .build()
            )
        }
    }
}
public class StickyBannerAdActivity extends AppCompatActivity {
    @Nullable
    private BannerAdView mBannerAd = null;
    private ActivityStickyBannerAdBinding mBinding;

    public StickyBannerAdActivity() {
        super(R.layout.activity_sticky_banner_ad);
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBinding = ActivityStickyBannerAdBinding.inflate(getLayoutInflater());
        setContentView(mBinding.getRoot());

        // 由于我们根据 adContainerView 大小加载横幅,
        // 我们需要等到该视图布局完毕后才能获取宽度
        mBinding.adContainerView.getViewTreeObserver().addOnGlobalLayoutListener(
                new ViewTreeObserver.OnGlobalLayoutListener() {
                    @Override
                    public void onGlobalLayout() {
                        mBinding.adContainerView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                        mBannerAd = loadBannerAd(getAdSize());
                    }
                }
        );
    }

    @NonNull
    private BannerAdSize getAdSize() {
        final DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
        // 计算广告的宽度,同时考虑广告容器中的内边距。
        int adWidthPixels = mBinding.adContainerView.getWidth();
        if (adWidthPixels == 0) {
            // 如果广告尚未布局,则默认为全屏宽度
            adWidthPixels = displayMetrics.widthPixels;
        }
       final int adWidth = Math.round(adWidthPixels / displayMetrics.density);

        return BannerAdSize.stickySize(this, adWidth);
    }

    @NonNull
    private BannerAdView loadBannerAd(@NonNull final BannerAdSize adSize) {
        final BannerAdView bannerAd = mBinding.banner;
        bannerAd.setAdSize(adSize);
        bannerAd.setAdUnitId("your-ad-unit-id");
        bannerAd.setBannerAdEventListener(new BannerAdEventListener() {
            @Override
            public void onAdLoaded() {
                // 如果此回调发生在活动被销毁之后,您
                // 必须调用 destroy 和 return,否则可能会出现内存泄漏。
                // 注意 `isDestroyed` 是活动上的一个方法。
                if (isDestroyed() && mBannerAd != null) {
                    mBannerAd.destroy();
                }
            }

            @Override
            public void onAdFailedToLoad(@NonNull final AdRequestError adRequestError) {
                // 广告加载失败,出现 AdRequestError。
                // 强烈建议不要尝试通过 onAdFailedToLoad() 方法加载新广告。
            }

            @Override
            public void onAdClicked() {
                // 记录广告点击时调用。
            }

            @Override
            public void onLeftApplication() {
                // 当用户由于点击广告而即将离开应用程序(例如,转到浏览器)时调用。
            }

            @Override
            public void onReturnedToApplication() {
                // 当用户点击后返回应用程序时调用。
            }

            @Override
            public void onImpression(@Nullable ImpressionData impressionData) {
                // 记录广告展示次数时调用。
            }
        });
        final AdRequest adRequest = new AdRequest.Builder()
                // 此处可以使用 AdRequest.Builder 类中的方法来指定各个选项设置。
                .build();
        bannerAd.loadAd(adRequest);
        return bannerAd;
    }
}

释放资源

如果在活动生命周期结束后调用回调方法,请通过调用广告对象的 destroy() 函数来释放资源:

private fun loadBannerAd(adSize: BannerAdSize): BannerAdView {
    return binding.banner.apply {
        setBannerAdEventListener(object : BannerAdEventListener {
            override fun onAdLoaded() {
                // 如果此回调发生在活动被销毁之后,您
                // 必须调用 destroy 和 return,否则可能会出现内存泄漏。
                // 注意 `isDestroyed` 是活动上的一个方法。
                if (isDestroyed) {
                    bannerAd?.destroy()
                    return
                }
            }
            ...
        })
        ...
    }
}
@NonNull
private BannerAdView loadBannerAd(@NonNull final BannerAdSize adSize) {
    final BannerAdView bannerAd = mBinding.banner;
    bannerAd.setBannerAdEventListener(new BannerAdEventListener() {
        @Override
        public void onAdLoaded() {
            // 如果此回调发生在活动被销毁之后,您
            // 必须调用 destroy 和 return,否则可能会出现内存泄漏。
            // 注意 `isDestroyed` 是活动上的一个方法。
            if (isDestroyed() && mBannerAd != null) {
                mBannerAd.destroy();
            }
        }
        ...
    });
    ...
    return bannerAd;
}

测试自适应粘性横幅集成

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

我们建议使用测试广告来测试您的自适应粘性横幅集成和应用本身。

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

演示广告单元 ID:demo-banner-yandex.

重要

在商店中发布您的应用之前,请确保将演示广告版位 ID 替换为从 Partner Interface 获取的真实广告版位 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 banner was integrated successfully

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

其他资源