Cocoscreator官方插件集成Admob只做了3.7.x的版本,并且Android 35还不能用...无力吐槽下准备自己做,先从比较多项目使用的2.4.x版本做集成。
将 Cocos Creator 项目适配到最新 Android SDK 35 并集成 AdMob 激励广告是一项复杂但必要的工作。本文详细记录了从环境配置到广告集成的完整流程,涵盖 Gradle 配置、AndroidX 支持、Java 原生接口开发以及 JavaScript 交互等关键步骤,旨在为开发者提供可操作的参考模板。特别针对 Cocos Creator 2.4.14 版本,结合 Android Studio JDK 设置和 JavaScript 调用调整,提供优化后的实现方案。环境准备基础环境
Cocos Creator:2.4.14
Android Studio:最新版本
Android SDK:35
Java:17(必需)
Gradle:8.5
项目结构Cocos Creator 2.4.14 默认生成的 Android 项目结构如下:
proj.android-studio/
├── app/
│ ├── build.gradle
│ ├── AndroidManifest.xml
│ └── src/org/cocos2dx/javascript/
│ └── CocosPlatformHelper.java
├── build.gradle
├── gradle.properties
└── gradle/wrapper/gradle-wrapper.properties
第一步:配置 Gradle JDKAndroid Gradle Plugin (AGP) 8.1.4 要求 Java 17,因此需要正确配置 Gradle JDK。以下是基于 Android Studio 的配置步骤:
打开 Android Studio 设置:
Windows:File → Settings
macOS:Android Studio → Preferences
导航到 Gradle 设置:
Build, Execution, Deployment → Build Tools → Gradle
配置 Gradle JDK:
在 “Gradle JDK” 下拉菜单中选择 “Embedded JDK” 或指向 Java 17 的路径(如图所示,当前使用 jbr-21 JetBrains Runtime 21.0.6)。
确保 “Distribution” 设置为 “Wrapper”。
点击 “Apply” 和 “OK”。
参考截图: Android Studio JDK 设置注意:通过 Android Studio 配置 Gradle JDK 比直接修改配置文件更安全,避免路径或版本兼容性问题。第二步:升级 Gradle 和 Android Gradle Plugin2.1 更新根目录 build.gradle修改根目录下的 build.gradle,确保支持 Android SDK 35:
gradle
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.1.4'
}
}
allprojects {
repositories {
google()
mavenCentral()
flatDir {
dirs 'libs'
}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
2.2 更新 Gradle Wrapper修改 gradle/wrapper/gradle-wrapper.properties,使用 Gradle 8.5:
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
networkTimeout=10000
validateDistributionUrl=true
第三步:配置 gradle.properties为适配 Android 35 和 AdMob,需启用 AndroidX 并设置相关 SDK 版本:
PROP_COMPILE_SDK_VERSION=35
PROP_MIN_SDK_VERSION=21
PROP_TARGET_SDK_VERSION=35
PROP_BUILD_TOOLS_VERSION=34.0.0
PROP_APP_ABI=armeabi-v7a:arm64-v8a
RELEASE_STORE_FILE=D:/Soft/cocos/editors/Creator/2.4.14/resources/static/build-templates/native/debug.keystore
RELEASE_STORE_PASSWORD=123456
RELEASE_KEY_ALIAS=debug_keystore
RELEASE_KEY_PASSWORD=123456
android.injected.testOnly=false
android.enableJetifier=true
android.useAndroidX=true
关键点:
移除 org.gradle.java.home,通过 Android Studio 配置更可靠。
android.enableJetifier=true 和 android.useAndroidX=true 是 AdMob 集成的必要条件。
SDK 版本升级到 35,确保兼容性。
第四步:添加 AdMob 依赖在 app/build.gradle 中添加 AdMob SDK 依赖:
dependencies {
implementation fileTree(dir: '../libs', include: ['*.jar','*.aar'])
implementation fileTree(dir: 'libs', include: ['*.jar','*.aar'])
implementation fileTree(dir: "D:/Soft/cocos/editors/Creator/2.4.14/resources/cocos2d-x/cocos/platform/android/java/libs", include: ['*.jar'])
implementation project(':libcocos2dx')
implementation 'com.google.android.gms:play-services-ads:22.6.0'
}
第五步:配置 AndroidManifest.xml在 app/AndroidManifest.xml 中添加网络权限和 AdMob 配置:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="auto">
<uses-feature android:glEsVersion="0x00020000" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<application
android:allowBackup="true"
android:label="@string/app_name"
android:usesCleartextTraffic="true"
android:icon="@mipmap/ic_launcher">
<meta-data android:name="android.app.lib_name" android:value="cocos2djs" />
<meta-data android:name="com.google.android.gms.ads.APPLICATION_ID" android:value="ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy" />
<activity
android:name="org.cocos2dx.javascript.AppActivity"
android:screenOrientation="portrait"
android:configChanges="orientation|keyboardHidden|screenSize|screenLayout|uiMode"
android:label="@string/app_name"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:launchMode="singleTask"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
注意:
将 ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy 替换为真实的 AdMob 应用 ID。
网络权限对广告加载至关重要。
保留 Cocos Creator 2.4.14 的默认配置。
第六步:开发 AdMob 原生接口创建 CocosPlatformHelper.java 实现 AdMob 激励广告的加载和显示逻辑:
package org.cocos2dx.javascript;
import android.app.Activity;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.LoadAdError;
import com.google.android.gms.ads.MobileAds;
import com.google.android.gms.ads.FullScreenContentCallback;
import com.google.android.gms.ads.AdError;
import com.google.android.gms.ads.rewarded.RewardedAd;
import com.google.android.gms.ads.rewarded.RewardedAdLoadCallback;
import com.google.android.gms.ads.OnUserEarnedRewardListener;
import com.google.android.gms.ads.rewarded.RewardItem;
import androidx.annotation.NonNull;
public class CocosPlatformHelper {
private static final String TAG = "CocosPlatformHelper";
private static Activity activity;
private static RewardedAd rewardedAd;
private static boolean isLoading = false;
private static boolean showSuccess = false;
private static Handler handler = new Handler(Looper.getMainLooper());
private static final String REWARDED_AD_UNIT_ID = "ca-app-pub-xxxxxxxxxxxxxxxx/zzzzzzzzzz";
public static void init(Activity mainActivity) {
Log.d(TAG, "Initializing CocosPlatformHelper");
activity = mainActivity;
if (activity == null) {
Log.e(TAG, "Activity is null during initialization");
return;
}
try {
Log.d(TAG, "Starting AdMob SDK initialization...");
MobileAds.initialize(activity, initializationStatus -> {
Log.d(TAG, "AdMob SDK initialized successfully");
loadRewardedAd();
});
} catch (Exception e) {
Log.e(TAG, "Failed to initialize AdMob SDK: " + e.getMessage());
}
}
private static void loadRewardedAd() {
if (activity == null || isLoading) {
Log.d(TAG, activity == null ? "Cannot load ad: activity is null" : "Ad is already loading");
return;
}
try {
Log.d(TAG, "Loading rewarded ad...");
isLoading = true;
AdRequest adRequest = new AdRequest.Builder().build();
RewardedAd.load(activity, REWARDED_AD_UNIT_ID, adRequest, new RewardedAdLoadCallback() {
@Override
public void onAdFailedToLoad(@NonNull LoadAdError loadAdError) {
Log.e(TAG, "Rewarded ad failed to load: " + loadAdError.getMessage());
rewardedAd = null;
isLoading = false;
}
@Override
public void onAdLoaded(@NonNull RewardedAd ad) {
Log.d(TAG, "Rewarded ad loaded successfully");
rewardedAd = ad;
isLoading = false;
ad.setFullScreenContentCallback(new FullScreenContentCallback() {
@Override
public void onAdDismissedFullScreenContent() {
Log.d(TAG, "Ad was dismissed");
if (showSuccess) {
postMessageToJs("2");
showSuccess = false;
}
rewardedAd = null;
loadRewardedAd();
}
@Override
public void onAdFailedToShowFullScreenContent(@NonNull AdError adError) {
Log.e(TAG, "Ad failed to show: " + adError.getMessage());
postMessageToJs("2");
}
@Override
public void onAdShowedFullScreenContent() {
Log.d(TAG, "Ad showed fullscreen content");
showSuccess = true;
}
});
}
});
} catch (Exception e) {
Log.e(TAG, "Exception while loading rewarded ad: " + e.getMessage());
isLoading = false;
}
}
public static void ShowRewardAD() {
Log.d(TAG, "ShowRewardAD called from JS");
if (activity == null) {
Log.e(TAG, "Activity is null, cannot show ad");
return;
}
activity.runOnUiThread(() -> {
if (rewardedAd != null) {
Log.d(TAG, "Showing rewarded ad");
showSuccess = false;
rewardedAd.show(activity, rewardItem -> {
Log.d(TAG, "User earned reward: " + rewardItem.getAmount() + " " + rewardItem.getType());
showSuccess = false;
postMessageToJs("1");
});
} else {
Log.d(TAG, "The rewarded ad wasn't ready yet");
postMessageToJs("2");
if (!isLoading) {
loadRewardedAd();
}
}
});
}
public static void LoadRewardAD() {
Log.d(TAG, "LoadRewardAD called from JS");
if (!isLoading) {
loadRewardedAd();
}
}
public static boolean IsRewardAdReady() {
boolean isReady = rewardedAd != null;
Log.d(TAG, "IsRewardAdReady: " + isReady);
return isReady;
}
// 使用 Cocos2dxHelper 适配 Cocos Creator 2.4.14
private static void postMessageToJs(final String msg) {
Cocos2dxHelper.runOnGLThread(new Runnable() {
@Override
public void run() {
Log.v(TAG, "[Android] postMessageToJs:" + msg);
String script = String.format("AndroidReceiveNative(%s);", msg);
Cocos2dxJavascriptJavaBridge.evalString(script);
}
});
}
}
关键点:
将 REWARDED_AD_UNIT_ID 替换为真实的 AdMob 激励广告单元 ID。
使用 showSuccess 标志确保广告状态准确。
postMessageToJs 方法已调整为使用 Cocos2dxHelper.runOnGLThread,适配 Cocos Creator 2.4.14 的线程模型。
第七步:初始化 AdMob在 AppActivity.java 中初始化 AdMob:
package org.cocos2dx.javascript;
import org.cocos2dx.lib.Cocos2dxActivity;
public class AppActivity extends Cocos2dxActivity {
@Override
protected void onCreate(android.os.Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CocosPlatformHelper.init(this);
}
}
第八步:JavaScript 端集成在 JavaScript 代码中添加回调和调用逻辑:
window.AndroidReceiveNative = function(msg) {
console.log("Received from Android:", msg);
if (msg === "1") {
console.log("User earned reward");
// 处理奖励逻辑,例如增加金币或道具
} else if (msg === "2") {
console.log("Ad failed or closed");
// 处理广告失败或关闭逻辑
}
};
window.showRewardAd = function() {
if (cc.sys.os === cc.sys.OS_ANDROID) {
jsb.reflection.callStaticMethod("org/cocos2dx/javascript/CocosPlatformHelper", "ShowRewardAD", "()V");
}
};
window.isRewardAdReady = function() {
if (cc.sys.os === cc.sys.OS_ANDROID) {
return jsb.reflection.callStaticMethod("org/cocos2dx/javascript/CocosPlatformHelper", "IsRewardAdReady", "()Z");
}
return false;
};
window.loadRewardAd = function() {
if (cc.sys.os === cc.sys.OS_ANDROID) {
jsb.reflection.callStaticMethod("org/cocos2dx/javascript/CocosPlatformHelper", "LoadRewardAD", "()V");
}
};
第九步:构建与测试
9.1 构建项目
9.2 测试流程
安装生成的 APK 到测试设备。
使用 adb logcat 查看 AdMob 相关日志。
在游戏中调用 showRewardAd() 测试广告显示。
验证 JavaScript 回调是否正常触发。
常见问题与解决方案
Gradle JDK 配置错误
错误:Invalid Gradle JDK configuration found
解决:在 Android Studio 中选择 “Embedded JDK” 或 Java 17 路径。
Android 资源链接失败
错误:Android resource linking failed
解决:确保 SDK 版本和构建工具版本正确。
JavaScript 调用崩溃
错误:crash_dump64
解决:
确保 JavaScript 回调函数正确定义。
使用 Cocos2dxHelper.runOnGLThread 确保主线程调用。
添加异常处理。
广告加载失败
解决:
检查网络连接。
验证 AdMob 广告单元 ID。
将设备添加到 AdMob 测试设备列表。
注意事项
版本兼容性:Android SDK 35 要求 AGP 8.1.4+ 和 Java 17。
AndroidX 支持:AdMob 依赖 AndroidX,必须启用 Jetifier。
网络权限:确保 AndroidManifest.xml 中包含网络权限。
测试广告:开发阶段使用 AdMob 测试广告单元 ID。
线程安全:Cocos Creator 2.4.14 需使用 Cocos2dxHelper.runOnGLThread 处理 UI 操作。
Gradle JDK 配置:优先使用 Android Studio 界面配置。
总结通过以上步骤,我们成功将 Cocos Creator 2.4.14 Android 项目适配到 Android SDK 35 并集成了 AdMob 激励广告。关键在于合理的版本管理、适配 Cocos Creator 线程模型的原生接口设计以及可靠的 JavaScript 交互机制。本指南可作为其他 Cocos Creator 2.4.14 项目集成广告功能的模板,帮助开发者高效实现类似需求。
评论区