
在使用 admob 集成插页式广告时,开发者常遇到的一个问题是广告无法显示,调试时发现 interstitialad 对象为 null。这主要是因为广告的加载是一个异步操作,需要一定时间才能完成。当我们在代码中调用加载方法后,广告并不会立即可用。
以下是常见的错误用法示例:
// 在 Activity 中
adsManager = new AdsManager(this);
mInterstitialAd = adsManager.loadInterstatialAd(); // 此处开始加载广告,但尚未完成
if (mInterstitialAd != null) { // 立即检查 mInterstitialAd,此时通常为 null
mInterstitialAd.show(ColoringActivity.this); // 尝试展示一个尚未加载的广告
}在上述代码中,adsManager.loadInterstatialAd() 方法会启动广告加载过程,但由于网络请求和数据处理需要时间,mInterstitialAd 在 loadInterstatialAd() 方法返回时,仍然是 null。只有当广告成功加载后,InterstitialAdLoadCallback 中的 onAdLoaded 方法才会被调用,并在其中将 mInterstitialAd 赋值为已加载的广告实例。因此,在 loadInterstatialAd() 调用之后立即检查并尝试显示广告是无效的。
解决此问题的关键在于理解“预加载”和“事件触发展示”的原则。
我们将对 AdsManager 进行改造,使其负责广告的加载、状态管理以及展示逻辑。loadInterstitialAd 方法将只负责发起加载请求,而不立即返回广告实例。showInterstitialAd 方法则用于检查广告是否已准备好并进行展示。
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import androidx.annotation.NonNull;
import com.google.android.gms.ads.AdError;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.FullScreenContentCallback;
import com.google.android.gms.ads.LoadAdError;
import com.google.android.gms.ads.MobileAds;
import com.google.android.gms.ads.initialization.InitializationStatus;
import com.google.android.gms.ads.initialization.OnInitializationCompleteListener;
import com.google.android.gms.ads.interstitial.InterstitialAd;
import com.google.android.gms.ads.interstitial.InterstitialAdLoadCallback;
public class AdsManager {
private static final String TAG = "AdsManager";
private Context context;
private InterstitialAd mInterstitialAd;
public AdsManager(Context context) {
this.context = context;
MobileAds.initialize(context, new OnInitializationCompleteListener() {
@Override
public void onInitializationComplete(@NonNull InitializationStatus initializationStatus) {
Log.d(TAG, "AdMob 初始化完成.");
}
});
}
// 仅用于加载横幅广告,与插页式广告问题无关,但保留以供参考
// public void createAds (AdView adView) {
// AdRequest adRequest = new AdRequest.Builder().build();
// adView.loadAd(adRequest);
// }
/**
* 加载插页式广告。此方法仅发起加载请求,不立即返回广告实例。
* 广告加载完成后,mInterstitialAd 会被赋值。
*/
public void loadInterstitialAd() {
if (mInterstitialAd != null) {
// 如果已有广告加载,则无需重复加载
Log.d(TAG, "插页式广告已加载,无需重复加载.");
return;
}
AdRequest adRequest = new AdRequest.Builder().build();
InterstitialAd.load(context, "ca-app-pub-3940256099942544/1033173712", // 使用测试广告ID
adRequest, new InterstitialAdLoadCallback() {
@Override
public void onAdFailedToLoad(@NonNull LoadAdError loadAdError) {
super.onAdFailedToLoad(loadAdError);
Log.e(TAG, "插页式广告加载失败: " + loadAdError.getMessage());
mInterstitialAd = null; // 确保加载失败时广告实例为 null
}
@Override
public void onAdLoaded(@NonNull InterstitialAd interstitialAd) {
super.onAdLoaded(interstitialAd);
Log.d(TAG, "插页式广告加载成功.");
mInterstitialAd = interstitialAd; // 广告加载成功,赋值给成员变量
setFullScreenContentCallback(); // 设置全屏内容回调
}
});
}
/**
* 设置插页式广告的全屏内容回调,处理广告的展示、关闭、失败等事件。
*/
private void setFullScreenContentCallback() {
if (mInterstitialAd == null) {
return;
}
mInterstitialAd.setFullScreenContentCallback(new FullScreenContentCallback() {
@Override
public void onAdClicked() {
super.onAdClicked();
Log.d(TAG, "Ad was clicked.");
}
@Override
public void onAdDismissedFullScreenContent() {
super.onAdDismissedFullScreenContent();
Log.d(TAG, "Ad was dismissed.");
mInterstitialAd = null; // 广告关闭后,将实例置为 null,以便下次加载新广告
// 可以在此处预加载下一条广告,以优化用户体验
// loadInterstitialAd();
}
@Override
public void onAdFailedToShowFullScreenContent(@NonNull AdError adError) {
super.onAdFailedToShowFullScreenContent(adError);
Log.e(TAG, "Ad failed to show: " + adError.getMessage());
mInterstitialAd = null; // 展示失败后,将实例置为 null
}
@Override
public void onAdImpression() {
super.onAdImpression();
Log.d(TAG, "Ad recorded an impression.");
}
@Override
public void onAdShowedFullScreenContent() {
super.onAdShowedFullScreenContent();
Log.d(TAG, "Ad showed fullscreen content.");
// 广告展示后,通常将其置为 null,因为一个插页式广告只能展示一次
// mInterstitialAd = null; // 这一步通常在 onAdDismissedFullScreenContent 中处理
}
});
}
/**
* 尝试展示插页式广告。
*
* @param activity 用于展示广告的 Activity。
* @return 如果广告已准备好并成功展示,则返回 true;否则返回 false。
*/
public boolean showInterstitialAd(Activity activity) {
if (mInterstitialAd != null) {
Log.d(TAG, "正在展示插页式广告.");
mInterstitialAd.show(activity);
return true;
} else {
Log.d(TAG, "插页式广告尚未准备好.");
// 可以在此处再次尝试加载广告,以防用户等待时间过长
// loadInterstitialAd();
return false;
}
}
}在 Activity 中,我们将在 onCreate 或更早的生命周期方法中调用 loadInterstitialAd() 来预加载广告。然后,在用户触发某个事件(例如点击“下一关”按钮)时,调用 showInterstitialAd() 来尝试展示广告。
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;
public class ColoringActivity extends AppCompatActivity {
private static final String TAG = "ColoringActivity";
private AdsManager adsManager;
private Button showAdButton; // 假设有一个按钮用于触发广告显示
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_coloring); // 替换为你的布局文件
adsManager = new AdsManager(this);
// 在 Activity 创建时,立即开始加载插页式广告
// 这样可以确保当用户需要时,广告有足够的时间加载完成
adsManager.loadInterstitialAd();
showAdButton = findViewById(R.id.show_ad_button); // 假设你的布局中有一个ID为show_ad_button的按钮
if (showAdButton != null) {
showAdButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "用户点击了展示广告按钮.");
// 当用户点击按钮时,尝试展示广告
if (!adsManager.showInterstitialAd(ColoringActivity.this)) {
// 如果广告尚未准备好,可以给用户一个提示,或者再次尝试加载
Log.d(TAG, "广告尚未准备好,正在尝试重新加载.");
adsManager.loadInterstitialAd(); // 再次尝试加载
}
}
});
}
}
@Override
protected void onResume() {
super.onResume();
// 可以在 onResume 中再次检查并加载广告,确保广告在用户返回应用时可用
// adsManager.loadInterstitialAd();
}
// 其他 Activity 生命周期方法...
}请确保你的布局文件 activity_coloring.xml 中包含一个 Button,其 id 为 show_ad_button,例如:
<!-- activity_coloring.xml -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- 其他UI元素 -->
<Button
android:id="@+id/show_ad_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="显示插页式广告" />
</RelativeLayout><uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
并已在 build.gradle (Module) 中添加 AdMob SDK 依赖:
implementation 'com.google.android.gms:play-services-ads:21.3.0' // 根据实际最新版本调整
同时,AndroidManifest.xml 中也应包含 AdMob 的 APPLICATION_ID:
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-XXXXXXXXXXXXXXXX~YYYYYYYYYY"/> <!-- 替换为你的应用ID -->如果横幅广告能够正常工作,通常说明这些配置是正确的。
AdMob 插页式广告不显示的核心原因在于对异步加载机制的误解。通过将广告加载与展示分离,在应用生命周期早期进行预加载,并在用户触发特定事件时,通过检查广告状态来决定是否展示,可以有效解决此问题。同时,合理利用回调函数进行状态管理和预加载,以及遵循最佳实践,将大大提升广告集成的稳定性和用户体验。
以上就是解决 AdMob 插页式广告不显示问题:异步加载与正确展示时机的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号