自适应内联横幅
自适应内联横幅是一种灵活的横幅广告格式,通过优化每个设备上的广告尺寸,实现最大效率。
这种广告类型允许开发者设置广告的最大允许宽度和高度,但最佳广告尺寸仍然是自动确定的。为了选择最佳广告尺寸,内置自适应横幅使用最大高度而不是固定高度。这为提高广告效果提供了空间。
通常,这种格式在基于内容来源的应用或允许主要关注广告的上下文环境中使用。
本指南展示了如何将自适应内联横幅集成到 Android 应用中。 除了代码示例和说明之外,它还包含特定格式的建议和其他资源的链接。
前提条件
- 按照 快速入门 中描述的 SDK 集成步骤进行操作。
- 提前 初始化 您的广告 SDK。
- 确保您运行的是最新的 Yandex Mobile Ads SDK 版本。如果您使用聚合,请同时确保您运行的是最新版本的 统一构建。
实施
集成自适应内联横幅的关键步骤:
- 创建并配置用于显示横幅广告的视图。
- 注册回调方法监听器。
- 加载广告。
- 如果您使用 Adfox,请传递 其他设置。
自适应内联横幅集成的特点
-
所有调用 Yandex Mobile Ads SDK 方法的操作必须在主线程中完成。
-
要在应用的屏幕上成功展示视频广告,您需要启用 硬件加速。默认情况下启用硬件加速,但某些应用会将其禁用。如果这种情况适用于您的应用,我们建议为使用广告的活动类别启用硬件加速。
-
如果您在
onAdFailedToLoad()
回调中收到错误,请不要尝试再次加载新广告。如果没有其他选项,请限制广告加载重试次数。这将有助于避免出现限制时持续出现不成功的请求和连接问题。 -
为了确保自适应内联横幅正常运行,您需要 使应用布局自适应。否则,您的广告可能无法正确呈现。
-
自适应内联横幅在使用所有可用宽度时效果最佳。通常情况下,这是设备屏幕的全宽度。确保包括适用于您的应用程序的所有内边距和安全显示区域。
-
自适应内联横幅设计用于放置在可滚动内容中。广告的高度可以与设备屏幕相同,也可以限制为最大高度,具体取决于 API。
-
要获取广告尺寸,请使用
BannerAdSize.inlineSize(context, adWidth, maxAdHeight)
方法,该方法接受广告上下文、广告容器的可用宽度以及可接受的最大广告高度作为参数。 -
BannerAdSize
对象是使用BannerAdSize.inlineSize(context, adWidth, maxAdHeight)
方法计算的,其中包含用于在后端选择最有效的广告尺寸的技术数据。广告的高度可能会在每次加载时发生变化。收到广告加载成功消息后即可获取广告的实际宽度和高度。
将广告视图添加到应用布局
要显示横幅广告,您需要将 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" />
...
您还可以通过编程方式创建 BannerAdView
对象:
val bannerAd = BannerAdView(this)
final BannerAdView bannerAd = new BannerAdView(this);
加载和呈现广告
创建BannerAdView
并将其添加到应用屏幕后,需要加载广告。在加载自适应内联横幅之前,还必须针对每个设备计算广告尺寸。
该操作通过 SDK API 自动执行:BannerAdSize.inlineSize(context, adWidth, maxAdHeight)
。
作为参数,传递广告容器的最大允许宽度。建议使用设备屏幕的整个宽度或父容器的宽度。确保包括适用于您的应用的所有内边距和安全显示区域。
private val adSize: BannerAdSize
get() {
val screenHeight = resources.displayMetrics.run { heightPixels / density }.roundToInt()
// 计算广告的宽度,同时考虑广告容器中的内边距。
var adWidthPixels = binding.adContainerView.width
if (adWidthPixels == 0) {
// 如果广告尚未布局,则默认为全屏宽度
adWidthPixels = resources.displayMetrics.widthPixels
}
val adWidth = (adWidthPixels / resources.displayMetrics.density).roundToInt()
val maxAdHeight = screenHeight / 2
return BannerAdSize.inlineSize(context, adWidth, maxAdHeight)
}
@NonNull
private BannerAdSize getAdSize() {
final DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
final int screenHeight = Math.round(displayMetrics.heightPixels / displayMetrics.density);
// 计算广告的宽度,同时考虑广告容器中的内边距。
int adWidthPixels = mBinding.adContainerView.getWidth();
if (adWidthPixels == 0) {
// 如果广告尚未布局,则默认为全屏宽度
adWidthPixels = displayMetrics.widthPixels;
}
final int adWidth = Math.round(adWidthPixels / displayMetrics.density);
// 确定允许的最大广告高度。以当前值为例。
final int maxAdHeight = screenHeight / 2;
return BannerAdSize.inlineSize(this, adWidth, maxAdHeight);
}
要加载广告,您还需要来自 Partner Interface 的活动上下文和广告单元 ID (adUnitId)。
要在广告加载或加载失败时发出通知并跟踪自适应内联横幅的生命周期,请为 BannerAdView
类对象设置 BannerAdEventListener
回调方法监听器。
您可以通过 AdRequest.Builder()
在请求中传递用户兴趣、上下文应用数据、位置详细信息或其他数据来扩展广告请求参数。在请求中提供额外的上下文数据可以显著提高您的广告质量。请参阅广告定位版块了解更多信息。
以下示例展示了如何加载自适应内联横幅。加载成功后,会自动显示横幅:
class AdaptiveInlineBannerAdActivity : AppCompatActivity(R.layout.activity_inline_banner_ad) {
private var bannerAd: BannerAdView? = null
private lateinit var binding: ActivityInlineBannerAdBinding
private val adSize: BannerAdSize
get() {
val screenHeight = resources.displayMetrics.run { heightPixels / density }.roundToInt()
// 计算广告的宽度,同时考虑广告容器中的内边距。
var adWidthPixels = binding.adContainerView.width
if (adWidthPixels == 0) {
// 如果广告尚未布局,则默认为全屏宽度
adWidthPixels = resources.displayMetrics.widthPixels
}
val adWidth = (adWidthPixels / resources.displayMetrics.density).roundToInt()
// 确定允许的最大广告高度。以当前值为例。
val maxAdHeight = screenHeight / 2
return BannerAdSize.inlineSize(context, adWidth, maxAdHeight)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityInlineBannerAdBinding.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 AdaptiveInlineBannerAdActivity extends AppCompatActivity {
@Nullable
private BannerAdView mBannerAd = null;
private ActivityInlineBannerAdBinding mBinding;
public AdaptiveInlineBannerAdActivity() {
super(R.layout.activity_inline_banner_ad);
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBinding = ActivityInlineBannerAdBinding.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();
final int screenHeight = Math.round(displayMetrics.heightPixels / displayMetrics.density);
// 计算广告的宽度,同时考虑广告容器中的内边距。
int adWidthPixels = mBinding.adContainerView.getWidth();
if (adWidthPixels == 0) {
// 如果广告尚未布局,则默认为全屏宽度
adWidthPixels = displayMetrics.widthPixels;
}
final int adWidth = Math.round(adWidthPixels / displayMetrics.density);
// 确定允许的最大广告高度。以当前值为例。
final int maxAdHeight = screenHeight / 2;
return BannerAdSize.inlineSize(this, adWidth, maxAdHeight);
}
@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
如果您在集成横幅广告时遇到问题,您将获得有关问题的详细报告以及如何解决这些问题的建议。
其他资源
-
GitHub 链接。