AdMob Android SDK 集成开发详解(2023 最新版) – wiki基地


AdMob Android SDK 集成开发详解(2023 最新版)

前言

随着移动互联网的飞速发展,Android 应用已成为我们生活中不可或缺的一部分。对于开发者而言,如何通过自己的创意和技术获得合理的回报,是实现可持续发展的重要课题。Google AdMob 作为全球领先的移动应用广告平台,为数百万开发者提供了强大的变现工具,通过在应用中展示各种形式的广告,帮助开发者实现收入增长。

本篇文章将详细阐述如何在2023年的最新环境下,将 AdMob Android SDK 集成到你的 Android 应用中,涵盖从项目搭建、广告单元创建、SDK 初始化到各种广告格式(横幅、插页、激励视频、原生、应用开启)的实现,以及测试、优化和最佳实践等方方面面。无论你是一名经验丰富的开发者,还是刚刚踏入移动应用开发领域的新手,本文都将为你提供一份详尽且实用的指南。

第一章:AdMob 平台基础与准备工作

在深入代码之前,我们需要了解 AdMob 的基本概念,并完成一些必要的准备工作。

1.1 什么是 Google AdMob?

Google AdMob 是 Google 旗下的移动应用广告平台,它允许应用开发者在其应用中展示 Google 广告网络中的广告,从而获得广告收入。AdMob 提供了多种广告格式,以适应不同的用户体验和应用场景。

1.2 为什么选择 AdMob?

  • 广泛的广告网络: 接入 Google 庞大的广告生态系统,确保高填充率和广告多样性。
  • 多种广告格式: 支持横幅、插页、激励视频、原生、应用开启等多种广告形式,满足不同变现需求。
  • 智能优化: 利用 Google 强大的机器学习能力,自动优化广告投放,最大化收益。
  • 易于集成: 提供稳定且文档完善的 SDK,集成过程相对简单。
  • 全球覆盖: 适用于全球范围内的应用发布和变现。

1.3 准备工作

在开始集成 AdMob SDK 之前,请确保你已具备以下条件:

  1. Google 账号: 用于注册 AdMob 账户。
  2. AdMob 账户: 访问 AdMob 官网 并注册/登录。
  3. Android Studio: 最新稳定版,推荐使用 Arctic Fox 或更高版本。
  4. Android SDK: 最新稳定版,并确保你的项目 targetSdkVersion 至少为 31(Android 12)或更高,以符合 Google Play 的最新要求。
  5. 一个 Android 项目: 可以是现有项目,也可以是新建的空白项目。
  6. 基础 Android 开发知识: 了解 Activity、Fragment、XML 布局、Gradle 构建系统等。

第二章:AdMob 平台设置与广告单元创建

本章将指导你在 AdMob 平台上设置应用并创建广告单元。这些步骤是获取应用 ID 和广告单元 ID 的关键,它们将在后续的 SDK 集成中用到。

2.1 将应用添加到 AdMob

  1. 登录 AdMob 账户。
  2. 在左侧导航栏中,点击 应用
  3. 点击 添加应用
  4. 选择你的应用是否已在 Google Play 应用商店中发布。
    • 已发布: 搜索并选择你的应用。
    • 未发布: 选择“否”,然后填写应用名称,选择平台为“Android”。你可以在应用发布到商店后再关联。
  5. 按照提示完成应用添加过程。完成后,你将获得一个 AdMob 应用 ID,格式通常为 ca-app-pub-XXXXXXXXXXXXXXXX~XXXXXXXXXX。请务必妥善保存此 ID。

2.2 创建广告单元

为不同类型的广告,你需要在 AdMob 平台中创建相应的广告单元。每个广告单元都有一个唯一的 ID。

  1. 在左侧导航栏中,点击 应用,然后选择你刚刚添加的应用。
  2. 点击 广告单元 选项卡。
  3. 点击 添加广告单元
  4. 选择你想要创建的广告格式。下面是 AdMob 提供的常见广告格式:
    • 横幅广告 (Banner Ad): 以固定大小的矩形区域显示在屏幕顶部或底部。
    • 插页广告 (Interstitial Ad): 全屏广告,通常在应用自然暂停时(如关卡切换、页面跳转)显示。
    • 激励广告 (Rewarded Ad): 用户观看完整视频或与广告互动后获得应用内奖励。
    • 原生广告 (Native Ad): 广告内容与应用界面深度融合,开发者可以自定义其外观。
    • 应用开启广告 (App Open Ad): 在用户打开或切换到应用时显示的全屏广告,用于应用启动变现。
  5. 为每个广告单元设置名称(便于识别),并根据需要配置高级设置。
  6. 点击 创建广告单元
  7. 完成后,你将获得一个或多个 广告单元 ID,格式通常为 ca-app-pub-XXXXXXXXXXXXXXXX/XXXXXXXXXX。请务必妥善保存这些 ID。

重要提示:
* 生产环境 vs. 测试环境: 在开发和测试阶段,请务必使用 AdMob 提供的测试广告单元 ID 或在你自己的 AdMob 账户中将你的设备添加为测试设备。切勿使用真实的广告单元 ID 进行大量的测试点击,这可能导致你的 AdMob 账户被禁用。

第三章:Android 项目集成 AdMob SDK

现在我们开始将 AdMob SDK 集成到你的 Android 项目中。

3.1 添加 Gradle 依赖

在你的 build.gradle (Module: app) 文件中,添加 AdMob SDK 的依赖。

“`gradle
// build.gradle (Module: app)

android {
// …
defaultConfig {
// …
minSdkVersion 21 // AdMob SDK 20.0.0+ 要求 minSdkVersion 21
targetSdkVersion 34 // 推荐使用最新的 targetSdkVersion
}
// …
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}

dependencies {
implementation ‘androidx.appcompat:appcompat:1.6.1’ // 确保你的 AndroidX 库是最新版本
implementation ‘com.google.android.material:material:1.10.0’
implementation ‘androidx.constraintlayout:constraintlayout:2.1.4’

// AdMob SDK 依赖 (2023 最新版,请注意查阅官方文档获取最新版本号)
implementation 'com.google.android.gms:play-services-ads:22.6.0' // 替换为最新稳定版

}
“`

注意: 请务必查阅 Google Developers 官网 以获取 play-services-ads 的最新稳定版本号。

3.2 配置 AndroidManifest.xml

AndroidManifest.xml 文件中,你需要添加必要的权限和 AdMob 应用 ID。

  1. 添加权限:

    “`xml

    <!-- 互联网访问权限 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <!-- 访问网络状态权限 (可选,但推荐添加以优化广告加载) -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    
    <application
        <!-- ... -->
    </application>
    


    “`

  2. 添加 AdMob 应用 ID:
    <application> 标签内部,添加 com.google.android.gms.ads.APPLICATION_IDmeta-data 标签。将 YOUR_ADMOB_APP_ID 替换为你之前从 AdMob 平台获取到的真实应用 ID。

    “`xml

    <!-- AdMob 应用 ID (替换为你的真实 ID) -->
    <meta-data
        android:name="com.google.android.gms.ads.APPLICATION_ID"
        android:value="ca-app-pub-XXXXXXXXXXXXXXXX~XXXXXXXXXX" />
    
    <activity android:name=".MainActivity"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <!-- 其他 Activity 或 Service -->
    


    ``
    **重要提示:** 如果缺少此
    meta-data` 标签,AdMob SDK 将无法正常初始化,并在应用启动时抛出崩溃错误。请务必检查并正确配置。

3.3 初始化 Mobile Ads SDK

在你的应用启动时,需要初始化 Mobile Ads SDK。推荐在 MainActivityonCreate() 方法中或在自定义的 Application 类中进行初始化。

“`java
// MainActivity.java 或自定义 Application 类中

import com.google.android.gms.ads.MobileAds;
import com.google.android.gms.ads.initialization.InitializationStatus;
import com.google.android.gms.ads.initialization.OnInitializationCompleteListener;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // 初始化 Mobile Ads SDK
    MobileAds.initialize(this, new OnInitializationCompleteListener() {
        @Override
        public void onInitializationComplete(InitializationStatus initializationStatus) {
            // SDK 初始化完成后的回调
            // 可以在这里开始加载广告
            Log.d("AdMob", "AdMob SDK initialized successfully.");
        }
    });

    // ... 你的其他初始化代码
}

}
``MobileAds.initialize()方法是异步的,当初始化完成时,OnInitializationCompleteListener会被调用。在onInitializationComplete` 回调中,你可以安全地开始加载广告。

3.4 配置测试设备(推荐)

为了在开发过程中安全地测试真实广告,你可以将你的设备注册为测试设备。这样,当你使用真实广告单元 ID 时,你的设备上会显示测试广告,而不会对你的 AdMob 账户造成风险。

“`java
import com.google.android.gms.ads.MobileAds;
import com.google.android.gms.ads.RequestConfiguration;
import java.util.Arrays;
import java.util.List;

// 在 MobileAds.initialize() 之后添加
// 或者在 Application 类中更早的位置
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

    // 获取当前设备的测试 ID (Logcat中会输出)
    // Log.d("AdMob", "Test Device ID: " + YOUR_DEVICE_ID_FROM_LOGCAT);

    // 设置测试设备ID
    List<String> testDeviceIds = Arrays.asList("YOUR_HASHED_DEVICE_ID_1", "YOUR_HASHED_DEVICE_ID_2"); // 替换为你的设备ID
    RequestConfiguration configuration =
            new RequestConfiguration.Builder().setTestDeviceIds(testDeviceIds).build();
    MobileAds.setRequestConfiguration(configuration);

    MobileAds.initialize(this, new OnInitializationCompleteListener() {
        @Override
        public void onInitializationComplete(InitializationStatus initializationStatus) {
            Log.d("AdMob", "AdMob SDK initialized.");
        }
    });
    // ...
}

}
``
当你第一次使用真实广告单元 ID 加载广告时,Logcat 中会打印一条消息,其中包含你的设备 ID 的哈希值。将其复制并添加到
testDeviceIds` 列表中。

第四章:实现各种广告格式

本章将详细介绍如何在应用中实现不同类型的 AdMob 广告。

4.1 横幅广告 (Banner Ads)

横幅广告以固定大小的矩形区域显示在屏幕顶部或底部。

  1. 在布局文件中添加 AdView:

    “`xml

    <!-- 你的其他 UI 元素 -->
    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello AdMob!"
        android:layout_centerInParent="true" />
    
    <!-- AdView 放置在底部 -->
    <com.google.android.gms.ads.AdView
        android:id="@+id/adView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true"
        app:adSize="BANNER" <!-- 广告尺寸 -->
        app:adUnitId="ca-app-pub-3940256099942544/6300978111"> <!-- 测试横幅广告单元ID -->
    </com.google.android.gms.ads.AdView>
    


    ``
    *
    app:adSize:指定广告尺寸。常用的有BANNER(320x50dp),LARGE_BANNER(320x100dp),MEDIUM_RECTANGLE(300x250dp),FULL_BANNER(468x60dp),LEADERBOARD(728x90dp),SMART_BANNER(自适应屏幕宽度)。
    *
    app:adUnitId`:替换为你的横幅广告单元 ID。这里使用的是 AdMob 官方提供的测试 ID。

  2. 在 Activity/Fragment 中加载广告:

    “`java
    // MainActivity.java
    import com.google.android.gms.ads.AdListener;
    import com.google.android.gms.ads.AdRequest;
    import com.google.android.gms.ads.AdView;
    import com.google.android.gms.ads.LoadAdError;

    public class MainActivity extends AppCompatActivity {
    private AdView mAdView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        // ... AdMob SDK 初始化代码
    
        mAdView = findViewById(R.id.adView);
        AdRequest adRequest = new AdRequest.Builder().build();
        mAdView.loadAd(adRequest);
    
        // 监听广告加载事件 (可选)
        mAdView.setAdListener(new AdListener() {
            @Override
            public void onAdLoaded() {
                // 广告加载成功
                Log.d("AdMob", "Banner Ad loaded.");
            }
    
            @Override
            public void onAdFailedToLoad(LoadAdError adError) {
                // 广告加载失败
                Log.e("AdMob", "Banner Ad failed to load: " + adError.getMessage());
            }
    
            @Override
            public void onAdOpened() {
                // 广告打开(用户点击广告)
            }
    
            @Override
            public void onAdClicked() {
                // 广告被点击
            }
    
            @Override
            public void onAdClosed() {
                // 用户从广告返回应用
            }
        });
    }
    
    // 生命周期管理 (推荐)
    @Override
    public void onPause() {
        if (mAdView != null) {
            mAdView.pause();
        }
        super.onPause();
    }
    
    @Override
    public void onResume() {
        super.onResume();
        if (mAdView != null) {
            mAdView.resume();
        }
    }
    
    @Override
    public void onDestroy() {
        if (mAdView != null) {
            mAdView.destroy();
        }
        super.onDestroy();
    }
    

    }
    “`

4.2 插页广告 (Interstitial Ads)

插页广告是全屏广告,通常在应用切换场景时显示。

  1. 加载插页广告:
    插页广告需要在显示之前进行加载。

    “`java
    // InterstitialAdManager.java (自定义类,用于管理插页广告) 或直接在 Activity 中

    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.interstitial.InterstitialAd;
    import com.google.android.gms.ads.interstitial.InterstitialAdLoadCallback;

    public class InterstitialAdManager {
    private InterstitialAd mInterstitialAd;
    private static final String AD_UNIT_ID = “ca-app-pub-3940256099942544/1033173712”; // 测试插页广告单元ID
    private Context mContext;

    public InterstitialAdManager(Context context) {
        this.mContext = context;
    }
    
    public void loadInterstitialAd() {
        AdRequest adRequest = new AdRequest.Builder().build();
        InterstitialAd.load(mContext, AD_UNIT_ID, adRequest,
                new InterstitialAdLoadCallback() {
                    @Override
                    public void onAdLoaded(@NonNull InterstitialAd interstitialAd) {
                        // 广告加载成功
                        mInterstitialAd = interstitialAd;
                        Log.d("AdMob", "Interstitial Ad loaded.");
    
                        mInterstitialAd.setFullScreenContentCallback(new FullScreenContentCallback() {
                            @Override
                            public void onAdDismissedFullScreenContent() {
                                // 广告被关闭(用户已返回应用)
                                Log.d("AdMob", "Interstitial Ad was dismissed.");
                                mInterstitialAd = null; // 清空引用,准备加载下一个
                                // 可以在这里加载下一个广告,或者执行其他逻辑
                                loadInterstitialAd(); // 重新加载下一个广告
                            }
    
                            @Override
                            public void onAdFailedToShowFullScreenContent(@NonNull AdError adError) {
                                // 广告显示失败
                                Log.e("AdMob", "Interstitial Ad failed to show: " + adError.getMessage());
                                mInterstitialAd = null;
                            }
    
                            @Override
                            public void onAdShowedFullScreenContent() {
                                // 广告成功显示
                                Log.d("AdMob", "Interstitial Ad showed.");
                            }
                        });
                    }
    
                    @Override
                    public void onAdFailedToLoad(@NonNull LoadAdError loadAdError) {
                        // 广告加载失败
                        Log.e("AdMob", "Interstitial Ad failed to load: " + loadAdError.getMessage());
                        mInterstitialAd = null;
                    }
                });
    }
    
    public boolean showInterstitialAd(Activity activity) {
        if (mInterstitialAd != null) {
            mInterstitialAd.show(activity);
            return true;
        } else {
            Log.d("AdMob", "Interstitial Ad is not ready yet.");
            return false;
        }
    }
    

    }
    ``
    **注意:**
    FullScreenContentCallback是处理全屏广告生命周期的关键。在onAdDismissedFullScreenContent()` 中,通常会重新加载下一个插页广告。

  2. 在 Activity/Fragment 中使用:

    “`java
    // MainActivity.java
    public class MainActivity extends AppCompatActivity {
    private InterstitialAdManager interstitialAdManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        // ... AdMob SDK 初始化代码
    
        interstitialAdManager = new InterstitialAdManager(this);
        interstitialAdManager.loadInterstitialAd(); // 提前加载广告
    
        findViewById(R.id.next_level_button).setOnClickListener(v -> {
            // 用户点击“下一关”按钮
            if (interstitialAdManager.showInterstitialAd(MainActivity.this)) {
                // 广告显示成功,用户关闭广告后会进入下一关 (在 onAdDismissedFullScreenContent 处理)
            } else {
                // 广告未准备好,直接进入下一关
                startNextLevel();
            }
        });
    }
    
    private void startNextLevel() {
        // 跳转到下一关的逻辑
        Log.d("AdMob", "Starting next level...");
    }
    

    }
    “`

4.3 激励广告 (Rewarded Ads)

激励广告通过观看广告或互动,为用户提供应用内奖励。

  1. 加载激励广告:

    “`java
    // RewardedAdManager.java (自定义类)

    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.OnUserEarnedRewardListener;
    import com.google.android.gms.ads.rewarded.RewardItem;
    import com.google.android.gms.ads.rewarded.RewardedAd;
    import com.google.android.gms.ads.rewarded.RewardedAdLoadCallback;

    public class RewardedAdManager {
    private RewardedAd mRewardedAd;
    private static final String AD_UNIT_ID = “ca-app-pub-3940256099942544/5224354917”; // 测试激励广告单元ID
    private Context mContext;
    private OnRewardEarnedListener mRewardEarnedListener;

    public interface OnRewardEarnedListener {
        void onRewardEarned(String rewardType, int rewardAmount);
    }
    
    public RewardedAdManager(Context context, OnRewardEarnedListener listener) {
        this.mContext = context;
        this.mRewardEarnedListener = listener;
    }
    
    public void loadRewardedAd() {
        AdRequest adRequest = new AdRequest.Builder().build();
        RewardedAd.load(mContext, AD_UNIT_ID, adRequest,
                new RewardedAdLoadCallback() {
                    @Override
                    public void onAdLoaded(@NonNull RewardedAd rewardedAd) {
                        mRewardedAd = rewardedAd;
                        Log.d("AdMob", "Rewarded Ad loaded.");
    
                        mRewardedAd.setFullScreenContentCallback(new FullScreenContentCallback() {
                            @Override
                            public void onAdShowedFullScreenContent() {
                                Log.d("AdMob", "Rewarded Ad showed.");
                            }
    
                            @Override
                            public void onAdFailedToShowFullScreenContent(@NonNull AdError adError) {
                                Log.e("AdMob", "Rewarded Ad failed to show: " + adError.getMessage());
                                mRewardedAd = null;
                                loadRewardedAd(); // 尝试重新加载
                            }
    
                            @Override
                            public void onAdDismissedFullScreenContent() {
                                Log.d("AdMob", "Rewarded Ad was dismissed.");
                                mRewardedAd = null;
                                loadRewardedAd(); // 尝试重新加载下一个广告
                            }
                        });
                    }
    
                    @Override
                    public void onAdFailedToLoad(@NonNull LoadAdError loadAdError) {
                        Log.e("AdMob", "Rewarded Ad failed to load: " + loadAdError.getMessage());
                        mRewardedAd = null;
                    }
                });
    }
    
    public boolean showRewardedAd(Activity activity) {
        if (mRewardedAd != null) {
            mRewardedAd.show(activity, new OnUserEarnedRewardListener() {
                @Override
                public void onUserEarnedReward(@NonNull RewardItem rewardItem) {
                    // 用户获得奖励的回调
                    String rewardType = rewardItem.getType();
                    int rewardAmount = rewardItem.getAmount();
                    Log.d("AdMob", "User earned reward: " + rewardAmount + " " + rewardType);
                    if (mRewardEarnedListener != null) {
                        mRewardEarnedListener.onRewardEarned(rewardType, rewardAmount);
                    }
                }
            });
            return true;
        } else {
            Log.d("AdMob", "Rewarded Ad is not ready yet.");
            // 可以在这里再次尝试加载广告
            loadRewardedAd();
            return false;
        }
    }
    

    }
    ``
    **重要提示:** 用户奖励逻辑必须在
    onUserEarnedReward()` 回调中实现。切勿在广告显示前或关闭后立即给予奖励。

  2. 在 Activity/Fragment 中使用:

    “`java
    // MainActivity.java
    public class MainActivity extends AppCompatActivity implements RewardedAdManager.OnRewardEarnedListener {
    private RewardedAdManager rewardedAdManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        // ... AdMob SDK 初始化代码
    
        rewardedAdManager = new RewardedAdManager(this, this);
        rewardedAdManager.loadRewardedAd(); // 提前加载广告
    
        findViewById(R.id.watch_ad_for_reward_button).setOnClickListener(v -> {
            // 用户点击“观看广告获取奖励”按钮
            rewardedAdManager.showRewardedAd(MainActivity.this);
        });
    }
    
    @Override
    public void onRewardEarned(String rewardType, int rewardAmount) {
        // 在这里处理用户获得的奖励
        Toast.makeText(this, "你获得了 " + rewardAmount + " " + rewardType + "!", Toast.LENGTH_SHORT).show();
        // 更新应用内货币、生命值等
    }
    

    }
    “`

4.4 原生广告 (Native Ads)

原生广告允许开发者完全自定义广告的样式和布局,使其与应用内容无缝融合。这需要更多的自定义布局。

  1. 创建原生广告布局文件 (e.g., ad_unified.xml):
    这个布局将包含原生广告的所有元素,如标题、正文、广告媒体(图片/视频)、图标、CTA 按钮等。根视图必须是 com.google.android.gms.ads.nativead.NativeAdView

    “`xml

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="8dp">
    
        <!-- "Ad" 标签 -->
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Ad"
            android:background="#FFCC66"
            android:paddingLeft="4dp"
            android:paddingRight="4dp"
            android:textColor="#FFFFFF"
            android:textSize="12sp"
            android:layout_gravity="left" />
    
        <!-- 广告标题 -->
        <TextView
            android:id="@+id/ad_headline"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="16sp"
            android:textStyle="bold"
            android:maxLines="2"
            android:ellipsize="end" />
    
        <!-- 广告主图标 -->
        <ImageView
            android:id="@+id/ad_app_icon"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:adjustViewBounds="true"
            android:scaleType="centerInside"
            android:paddingBottom="4dp" />
    
        <!-- 广告正文 -->
        <TextView
            android:id="@+id/ad_body"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="14sp"
            android:maxLines="3"
            android:ellipsize="end" />
    
        <!-- 媒体内容 (图片或视频) -->
        <com.google.android.gms.ads.nativead.MediaView
            android:id="@+id/ad_media"
            android:layout_width="match_parent"
            android:layout_height="180dp"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="8dp" />
    
        <!-- 号召性用语按钮 (Call To Action) -->
        <Button
            android:id="@+id/ad_call_to_action"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="right"
            android:layout_marginTop="8dp"
            android:textSize="14sp" />
    
        <!-- 广告评级 (可选) -->
        <RatingBar
            android:id="@+id/ad_stars"
            style="?android:attr/ratingBarStyleSmall"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:isIndicator="true"
            android:numStars="5"
            android:stepSize="0.5" />
    
        <!-- 广告主名称 (可选) -->
        <TextView
            android:id="@+id/ad_advertiser"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="12sp" />
    
    </LinearLayout>
    


    “`

  2. 加载和显示原生广告:

    “`java
    // NativeAdManager.java 或直接在 Activity 中

    import com.google.android.gms.ads.AdListener;
    import com.google.android.gms.ads.AdLoader;
    import com.google.android.gms.ads.AdRequest;
    import com.google.android.gms.ads.LoadAdError;
    import com.google.android.gms.ads.nativead.NativeAd;
    import com.google.android.gms.ads.nativead.NativeAdOptions;
    import com.google.android.gms.ads.nativead.NativeAdView;

    public class NativeAdManager {
    private NativeAd mNativeAd;
    private Context mContext;
    private ViewGroup mAdContainer; // 放置原生广告的容器

    private static final String AD_UNIT_ID = "ca-app-pub-3940256099942544/2247696110"; // 测试原生高级广告单元ID
    
    public NativeAdManager(Context context, ViewGroup adContainer) {
        this.mContext = context;
        this.mAdContainer = adContainer;
    }
    
    public void loadNativeAd() {
        AdLoader adLoader = new AdLoader.Builder(mContext, AD_UNIT_ID)
                .forNativeAd(new NativeAd.OnNativeAdLoadedListener() {
                    @Override
                    public void onNativeAdLoaded(NativeAd nativeAd) {
                        // 广告加载成功
                        if (mNativeAd != null) {
                            mNativeAd.destroy(); // 销毁旧广告
                        }
                        mNativeAd = nativeAd;
                        Log.d("AdMob", "Native Ad loaded.");
                        displayNativeAd(); // 立即显示或在需要时显示
                    }
                })
                .withAdListener(new AdListener() {
                    @Override
                    public void onAdFailedToLoad(LoadAdError adError) {
                        // 广告加载失败
                        Log.e("AdMob", "Native Ad failed to load: " + adError.getMessage());
                    }
                })
                .withNativeAdOptions(new NativeAdOptions.Builder()
                        // 配置原生广告选项
                        .setVideoOptions(new com.google.android.gms.ads.VideoOptions.Builder()
                                .setStartMuted(true) // 视频静音播放
                                .build())
                        .build())
                .build();
    
        adLoader.loadAd(new AdRequest.Builder().build());
    }
    
    private void displayNativeAd() {
        if (mNativeAd == null) {
            Log.d("AdMob", "Native Ad is null, cannot display.");
            return;
        }
    
        NativeAdView adView = (NativeAdView) LayoutInflater.from(mContext)
                .inflate(R.layout.ad_unified, mAdContainer, false); // 确保 ad_unified.xml 已创建
    
        // 将所有广告视图注册到 NativeAdView
        adView.setHeadlineView(adView.findViewById(R.id.ad_headline));
        adView.setBodyView(adView.findViewById(R.id.ad_body));
        adView.setCallToActionView(adView.findViewById(R.id.ad_call_to_action));
        adView.setIconView(adView.findViewById(R.id.ad_app_icon));
        adView.setMediaView(adView.findViewById(R.id.ad_media));
        adView.setStarRatingView(adView.findViewById(R.id.ad_stars));
        adView.setAdvertiserView(adView.findViewById(R.id.ad_advertiser));
    
        // 填充广告数据
        ((TextView) adView.getHeadlineView()).setText(mNativeAd.getHeadline());
        ((TextView) adView.getBodyView()).setText(mNativeAd.getBody());
        ((Button) adView.getCallToActionView()).setText(mNativeAd.getCallToAction());
    
        if (mNativeAd.getIcon() != null) {
            ((ImageView) adView.getIconView()).setImageDrawable(mNativeAd.getIcon().getDrawable());
            adView.getIconView().setVisibility(View.VISIBLE);
        } else {
            adView.getIconView().setVisibility(View.GONE);
        }
    
        if (mNativeAd.getMediaContent() != null) {
            ((MediaView) adView.getMediaView()).setMediaContent(mNativeAd.getMediaContent());
            adView.getMediaView().setVisibility(View.VISIBLE);
        } else {
            adView.getMediaView().setVisibility(View.GONE);
        }
    
        if (mNativeAd.getStarRating() != null) {
            ((RatingBar) adView.getStarRatingView())
                    .setRating(mNativeAd.getStarRating().floatValue());
            adView.getStarRatingView().setVisibility(View.VISIBLE);
        } else {
            adView.getStarRatingView().setVisibility(View.GONE);
        }
    
        if (mNativeAd.getAdvertiser() != null) {
            ((TextView) adView.getAdvertiserView()).setText(mNativeAd.getAdvertiser());
            adView.getAdvertiserView().setVisibility(View.VISIBLE);
        } else {
            adView.getAdvertiserView().setVisibility(View.GONE);
        }
    
        adView.setNativeAd(mNativeAd); // 注册原生广告对象到视图
    
        // 清除容器中旧的广告视图并添加新广告
        mAdContainer.removeAllViews();
        mAdContainer.addView(adView);
    }
    
    public void destroyNativeAd() {
        if (mNativeAd != null) {
            mNativeAd.destroy();
            mNativeAd = null;
        }
    }
    

    }
    “`

  3. 在 Activity/Fragment 中使用:

    “`java
    // MainActivity.java
    public class MainActivity extends AppCompatActivity {
    private NativeAdManager nativeAdManager;
    private LinearLayout nativeAdPlaceholder; // 用于放置原生广告的布局

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        // ... AdMob SDK 初始化代码
    
        nativeAdPlaceholder = findViewById(R.id.native_ad_placeholder); // 在你的布局文件中添加一个 LinearLayout
        nativeAdManager = new NativeAdManager(this, nativeAdPlaceholder);
        nativeAdManager.loadNativeAd(); // 加载并显示原生广告
    }
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (nativeAdManager != null) {
            nativeAdManager.destroyNativeAd(); // 销毁原生广告以防止内存泄漏
        }
    }
    

    }
    在 `activity_main.xml` 中添加 `LinearLayout` 作为原生广告的占位符:xml


    “`

4.5 应用开启广告 (App Open Ads)

应用开启广告在用户打开应用或从后台切换到应用时显示,适合在启动时进行变现。

  1. 加载和显示应用开启广告:
    通常在 Application 类中管理应用开启广告,监听 ProcessLifecycleOwner 的生命周期事件。

    “`java
    // AppOpenAdManager.java (自定义类)

    import android.app.Activity;
    import android.app.Application;
    import android.os.Bundle;
    import android.util.Log;

    import androidx.annotation.NonNull;
    import androidx.lifecycle.LifecycleObserver;
    import androidx.lifecycle.OnLifecycleEvent;
    import androidx.lifecycle.ProcessLifecycleOwner;

    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.appopen.AppOpenAd;

    import java.util.Date;

    import static androidx.lifecycle.Lifecycle.Event.ON_START;

    public class AppOpenAdManager implements LifecycleObserver, Application.ActivityLifecycleCallbacks {
    private static final String LOG_TAG = “AppOpenAdManager”;
    private static final String AD_UNIT_ID = “ca-app-pub-3940256099942544/3419835294”; // 测试应用开启广告单元ID
    private AppOpenAd appOpenAd = null;
    private Application myApplication;
    private Activity currentActivity;
    private static boolean isShowingAd = false; // 防止同时显示多个应用开启广告
    private long loadTime = 0; // 记录广告加载时间,用于控制显示频率

    public AppOpenAdManager(Application myApplication) {
        this.myApplication = myApplication;
        this.myApplication.registerActivityLifecycleCallbacks(this);
        ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
    }
    
    /**
     * 加载应用开启广告。
     */
    public void loadAd() {
        if (isLoadingAd() || isAdAvailable()) {
            return;
        }
    
        AdRequest request = new AdRequest.Builder().build();
        AppOpenAd.load(
                myApplication,
                AD_UNIT_ID,
                request,
                AppOpenAd.APP_OPEN_AD_ORIENTATION_PORTRAIT, // 广告方向
                new AppOpenAd.AppOpenAdLoadCallback() {
                    @Override
                    public void onAdLoaded(@NonNull AppOpenAd ad) {
                        appOpenAd = ad;
                        loadTime = (new Date()).getTime();
                        Log.d(LOG_TAG, "App Open Ad loaded successfully.");
                    }
    
                    @Override
                    public void onAdFailedToLoad(@NonNull LoadAdError loadAdError) {
                        Log.e(LOG_TAG, "App Open Ad failed to load: " + loadAdError.getMessage());
                    }
                });
    }
    
    /**
     * 检查广告是否准备好显示。
     */
    private boolean isAdAvailable() {
        return appOpenAd != null && wasLoadTimeLessThanNHoursAgo(4); // 4小时内加载的广告才有效
    }
    
    /**
     * 检查广告是否还在有效期内。
     */
    private boolean wasLoadTimeLessThanNHoursAgo(long numHours) {
        long dateDifference = (new Date()).getTime() - loadTime;
        long numMilliSecondsPerHour = 3600000;
        return (dateDifference < (numMilliSecondsPerHour * numHours));
    }
    
    /**
     * 在应用从后台回到前台时调用。
     */
    @OnLifecycleEvent(ON_START)
    public void onMoveToForeground() {
        // 当应用从后台进入前台时显示应用开启广告
        Log.d(LOG_TAG, "onMoveToForeground");
        showAdIfAvailable();
    }
    
    /**
     * 如果广告可用,则显示应用开启广告。
     */
    public void showAdIfAvailable() {
        if (!isShowingAd && isAdAvailable()) {
            Log.d(LOG_TAG, "Will show ad.");
            FullScreenContentCallback fullScreenContentCallback =
                    new FullScreenContentCallback() {
                        @Override
                        public void onAdDismissedFullScreenContent() {
                            // 广告被关闭。
                            appOpenAd = null;
                            isShowingAd = false;
                            loadAd(); // 重新加载下一个广告
                            Log.d(LOG_TAG, "App Open Ad dismissed.");
                        }
    
                        @Override
                        public void onAdFailedToShowFullScreenContent(@NonNull AdError adError) {
                            // 广告显示失败。
                            appOpenAd = null;
                            isShowingAd = false;
                            Log.e(LOG_TAG, "App Open Ad failed to show: " + adError.getMessage());
                            loadAd(); // 尝试重新加载
                        }
    
                        @Override
                        public void onAdShowedFullScreenContent() {
                            // 广告成功显示。
                            Log.d(LOG_TAG, "App Open Ad showed.");
                            isShowingAd = true;
                        }
                    };
            appOpenAd.setFullScreenContentCallback(fullScreenContentCallback);
            currentActivity.runOnUiThread(() -> appOpenAd.show(currentActivity)); // 确保在UI线程显示
        } else {
            Log.d(LOG_TAG, "Can not show ad.");
            loadAd(); // 广告不可用,尝试加载新广告
        }
    }
    
    private boolean isLoadingAd() {
        return appOpenAd == null && loadTime == 0; // 简单的判断是否正在加载
    }
    
    @Override
    public void onActivityCreated(@NonNull Activity activity, Bundle savedInstanceState) {}
    
    @Override
    public void onActivityStarted(@NonNull Activity activity) {
        currentActivity = activity;
    }
    
    @Override
    public void onActivityResumed(@NonNull Activity activity) {
        currentActivity = activity;
    }
    
    @Override
    public void onActivityPaused(@NonNull Activity activity) {}
    
    @Override
    public void onActivityStopped(@NonNull Activity activity) {}
    
    @Override
    public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {}
    
    @Override
    public void onActivityDestroyed(@NonNull Activity activity) {
        currentActivity = null;
    }
    

    }
    “`

  2. 在自定义 Application 类中集成:

    “`java
    // MyApplication.java (在你的项目中创建一个继承自 Application 的类)

    import android.app.Application;
    import com.google.android.gms.ads.MobileAds;
    import com.google.android.gms.ads.initialization.InitializationStatus;
    import com.google.android.gms.ads.initialization.OnInitializationCompleteListener;

    public class MyApplication extends Application {
    private AppOpenAdManager appOpenAdManager;

    @Override
    public void onCreate() {
        super.onCreate();
    
        MobileAds.initialize(this, new OnInitializationCompleteListener() {
            @Override
            public void onInitializationComplete(InitializationStatus initializationStatus) {
                // AdMob SDK 初始化完成
                Log.d("AdMob", "AdMob SDK initialized.");
                appOpenAdManager = new AppOpenAdManager(MyApplication.this);
            }
        });
    }
    
    public AppOpenAdManager getAppOpenAdManager() {
        return appOpenAdManager;
    }
    

    }
    ``
    **注意:** 别忘了在
    AndroidManifest.xml标签中指定你的MyApplication类:`

第五章:测试、优化与最佳实践

5.1 测试广告

在应用发布之前,彻底测试广告是至关重要的。

  • 使用测试广告单元 ID: AdMob 提供了专门的测试广告单元 ID,它们永远不会产生收入,也不会导致账户被禁用。在开发阶段,始终使用这些测试 ID。
    • 横幅:ca-app-pub-3940256099942544/6300978111
    • 插页:ca-app-pub-3940256099942544/1033173712
    • 激励:ca-app-pub-3940256099942544/5224354917
    • 原生高级:ca-app-pub-3940256099942544/2247696110
    • 应用开启:ca-app-pub-3940256099942544/3419835294
  • 注册测试设备: 如果你需要用自己的真实广告单元 ID 测试,请务必在 RequestConfiguration 中添加你的设备 ID,确保只收到测试广告。
  • Logcat 检查: 仔细查看 Logcat 输出,AdMob SDK 会打印加载和显示广告的状态信息及错误。

5.2 用户隐私与同意(GDPR & CCPA)

2023年,用户隐私是重中之重。针对欧洲经济区 (EEA) 和英国的 GDPR,以及加利福尼亚州的 CCPA,你必须获取用户的同意。

  • Google 用户信息法规同意平台 (UMP SDK): Google 推荐使用其 UMP SDK 来收集用户同意。你需要集成 UMP SDK,并在初始化 AdMob SDK 之前,确保用户已做出同意选择。
  • 个性化与非个性化广告: 根据用户的同意状态,你可以选择加载个性化广告或非个性化广告。
  • 未成年人保护 (COPPA): 如果你的应用面向儿童,必须遵守 COPPA 法规,将请求标记为面向儿童,并禁用个性化广告。

5.3 优化建议

  • 预加载广告: 对于插页广告和激励广告,在需要显示之前提前加载,可以减少用户等待时间,提高用户体验。
  • 合理安排广告展示时机: 广告应在应用流程的自然暂停点出现,避免打断用户体验。例如,游戏结束后、关卡切换时、内容加载期间。
  • 控制广告频率: 过多的广告会令用户感到厌烦。使用 AdMob 后台的广告频率上限设置,或在代码中自行控制,避免短时间内重复显示同类广告。
  • 错误处理: 始终实现 onAdFailedToLoadonAdFailedToShowFullScreenContent 回调,以便在广告加载或显示失败时优雅地处理,例如显示备用内容或记录日志。
  • 内存管理: 对于原生广告,在 Activity/Fragment 销毁时,记得调用 nativeAd.destroy() 来释放资源。对于其他广告,确保在不使用时将其置为 null
  • 适配不同屏幕尺寸: 对于横幅广告,考虑使用 SMART_BANNER 或根据屏幕宽度动态计算 AdSize,以确保在不同设备上都能良好显示。

5.4 混淆规则 (Proguard/R8)

通常情况下,当你使用 play-services-ads 依赖时,SDK 已经包含了所需的 Proguard 规则。你不需要手动添加额外的规则。但是,如果你遇到与 AdMob 相关的混淆问题,可以尝试在 proguard-rules.pro 中添加以下规则:

proguard
-keep public class com.google.android.gms.ads.** { *; }
-keep public class com.google.ads.** { *; }
-keep public class com.google.android.gms.ads.formats.** { *; }
-keep public class com.google.android.gms.ads.admanager.** { *; }
-keep class * implements com.google.android.gms.ads.mediation.MediationAdapter
-keep class * implements com.google.android.gms.ads.mediation.NetworkExtras
-keep class * implements com.google.android.gms.ads.mediation.customEvent.CustomEvent

5.5 政策合规

在发布应用之前,务必仔细阅读并遵守 AdMob 和 Google Play 的开发者政策。违反政策可能导致广告投放受限甚至账户被禁用。常见的违规行为包括:
* 无效点击: 开发者或鼓励用户点击广告。
* 强制广告: 广告展示方式影响用户体验,如欺骗性点击、无法关闭。
* 内容违规: 应用内容不符合 Google 政策。
* 未披露广告: 未明确标示广告为广告(尤其是原生广告)。

总结

AdMob Android SDK 为开发者提供了强大的应用变现能力。通过本篇详尽的指南,你应该已经掌握了 AdMob SDK 的最新集成方法,从 AdMob 平台设置到各种广告格式的实现,再到测试和优化技巧。

在集成过程中,请始终关注用户体验,确保广告与你的应用内容和谐共存,避免过度干扰用户。同时,密切关注 AdMob 官方文档的更新,因为 SDK 和政策可能会随着时间而变化。通过精心设计和合理部署广告,你将能够有效地实现应用变现,为你的开发事业带来持续的成功。祝你在 AdMob 的旅程中一切顺利!


发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部