引言
在 Cocos Creator 游戏开发中,集成第三方 SDK(如支付、统计、广告、社交分享等)是常见的需求。由于 Cocos Creator 使用 JavaScript/TypeScript 开发,最终通过 JSB(JavaScript Binding)与原生平台通信,因此 SDK 集成涉及到 Android Studio 项目配置、Gradle 构建脚本修改、资源文件处理等多个环节。本文将以 Cocos Creator 2.0.4 为例,详细介绍 Android 平台第三方 SDK 的完整集成流程。
集成流程概览
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| ┌─────────────────────────────────────────────────────────────────────┐ │ Cocos Creator Android SDK 集成流程 │ ├─────────────────────────────────────────────────────────────────────┤ │ │ │ 1. 准备 SDK 文件 │ │ ├── JAR/AAR 库文件 │ │ ├── SO 动态库 │ │ └── 资源文件(assets/res) │ │ │ │ │ ▼ │ │ 2. 配置 Android Studio 项目 │ │ ├── 创建 libs 目录并添加依赖 │ │ ├── 修改 app/build.gradle │ │ └── 配置资源合并规则 │ │ │ │ │ ▼ │ │ 3. JS 调用原生方法 │ │ ├── 编写 Java 桥接类 │ │ ├── 使用 jsb.reflection 调用 │ │ └── 处理回调结果 │ │ │ │ │ ▼ │ │ 4. 打包测试 │ │ ├── 构建 Release 包 │ │ ├── 验证 SDK 功能 │ │ └── 处理签名配置 │ │ │ └─────────────────────────────────────────────────────────────────────┘
|
第一步:添加 JAR 依赖
创建 libs 目录
在 Android Studio 项目的 app 模块中创建 libs 目录:
1 2 3 4 5 6
| proj.android-studio/ └── app/ └── libs/ ← 新建此目录 ├── sdk-core.jar ├── sdk-payment.jar └── sdk-analytics.jar
|
配置 build.gradle
修改 app/build.gradle 文件,确保包含以下依赖配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation fileTree( include: ['*.jar'], dir: 'F:/CocosCreator204/resources/cocos2d-x/cocos/platform/android/java/libs' )
implementation project(':libcocos2dx')
}
|
| 配置项 |
说明 |
fileTree(dir: 'libs') |
自动引入 app/libs 目录下的所有 JAR |
fileTree(dir: '.../java/libs') |
引入 Cocos2d-x 平台依赖 |
implementation project(':libcocos2dx') |
引入引擎模块 |
同步项目
修改完成后,点击 Android Studio 工具栏的 Sync Now 按钮,Gradle 会自动将 libs 目录下的 JAR 文件添加到项目依赖中。
第二步:合并资源文件
很多第三方 SDK 除了 JAR 文件外,还包含额外的资源文件(如配置文件、图片、HTML 页面等),需要打包到 APK 的 assets 目录中。
资源目录结构
1 2 3 4 5 6 7 8 9 10 11
| proj.android-studio/ ├── app/ │ └── build.gradle │ └── treeSDKAssets/ ← SDK 资源目录(与 proj.android-studio 同级) ├── config/ │ └── sdk_config.json ├── html/ │ └── payment_page.html └── images/ └── logo.png
|
配置资源合并
在 app/build.gradle 的 android 块中添加资源合并规则:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| android { compileSdkVersion 24 buildToolsVersion "26.0.2"
defaultConfig { applicationId "com.game.xxx" minSdkVersion 10 targetSdkVersion 23 }
variant.mergeAssets.doLast { copy { from "${buildDir}/../../../../../treeSDKAssets" into "${buildDir}/intermediates/assets/${variant.dirName}/treeSDKAssets" }
} }
|
| 参数 |
说明 |
from |
源资源目录路径 |
into |
目标路径(APK 构建中间目录) |
${variant.dirName} |
构建变体名称(debug/release) |
路径说明
treeSDKAssets 目录位于 proj.android-studio 的上一级目录中,路径关系如下:
1 2 3 4 5 6 7 8 9 10
| 项目根目录/ ├── assets/ # Cocos Creator 默认资源目录 ├── build/ ├── library/ ├── proj.android-studio/ # Android Studio 项目 │ └── app/ │ └── build.gradle # 修改此文件 │ └── treeSDKAssets/ # SDK 资源目录(与 proj.android-studio 同级) └── ...
|
在 build.gradle 中,使用相对路径访问:
1 2 3 4 5 6
| "${buildDir}/../../../../../treeSDKAssets"
|
第三步:JS 与 Java 通信
Java 桥接类编写
在 org/cocos2dx/javascript/ 包下创建桥接类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| package org.cocos2dx.javascript;
import android.util.Log; import org.cocos2dx.lib.Cocos2dxActivity;
public class SdkBridge { private static final String TAG = "SdkBridge";
public static void initSdk(String appId) { Log.d(TAG, "初始化 SDK,appId: " + appId); }
public static String pay(String productId, String amount) { Log.d(TAG, "发起支付,商品: " + productId + ", 金额: " + amount);
return "order_" + System.currentTimeMillis(); }
public static String getDeviceInfo() { return "{\"model\":\"\"" + android.os.Build.MODEL + "\"}"; } }
|
JavaScript 调用原生方法
在 Cocos Creator 中使用 jsb.reflection.callStaticMethod 调用 Java 静态方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| const { ccclass } = cc._decorator;
@ccclass export default class SdkManager {
static init() { if (cc.sys.platform === cc.sys.ANDROID) { jsb.reflection.callStaticMethod( "org/cocos2dx/javascript/SdkBridge", "initSdk", "(Ljava/lang/String;)V", "your_app_id" ); } }
static pay(productId, amount, callback) { if (cc.sys.platform !== cc.sys.ANDROID) { cc.log('非 Android 平台,模拟支付成功'); callback && callback(true, 'mock_order_id'); return; }
const result = jsb.reflection.callStaticMethod( "org/cocos2dx/javascript/SdkBridge", "pay", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", productId, amount.toString() );
cc.log('支付结果:', result); callback && callback(true, result); }
static getDeviceInfo() { if (cc.sys.platform !== cc.sys.ANDROID) { return '{"model":"Editor"}'; }
return jsb.reflection.callStaticMethod( "org/cocos2dx/javascript/SdkBridge", "getDeviceInfo", "()Ljava/lang/String;" ); } }
|
JNI 方法签名规则
| Java 类型 |
JNI 签名 |
示例 |
void |
V |
(I)V |
boolean |
Z |
(Z)Z |
int |
I |
(II)I |
long |
J |
(J)J |
float |
F |
(F)F |
double |
D |
(D)D |
String |
Ljava/lang/String; |
(Ljava/lang/String;)V |
int[] |
[I |
([I)V |
Object |
L完整类名; |
(Lorg/cocos2dx/lib/Cocos2dxActivity;)V |
1 2 3 4 5 6
| 方法签名格式:(参数类型)返回值类型
示例: void init(String) → (Ljava/lang/String;)V String pay(String, String) → (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; int add(int, int) → (II)I
|
第四步:签名配置与打包
配置 Release 签名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| android { signingConfigs { release { if (project.hasProperty("RELEASE_STORE_FILE")) { storeFile file(RELEASE_STORE_FILE) storePassword RELEASE_STORE_PASSWORD keyAlias RELEASE_KEY_ALIAS keyPassword RELEASE_KEY_PASSWORD } } }
buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' if (project.hasProperty("RELEASE_STORE_FILE")) { signingConfig signingConfigs.release } } } }
|
创建签名配置
在项目根目录创建 keystore.properties:
1 2 3 4
| RELEASE_STORE_FILE=../keystore/release.keystore RELEASE_STORE_PASSWORD=your_store_password RELEASE_KEY_ALIAS=your_key_alias RELEASE_KEY_PASSWORD=your_key_password
|
在 build.gradle 中读取配置:
1 2 3 4
| if (project.hasProperty("RELEASE_STORE_FILE")) { }
|
构建 Release 包
1 2 3 4 5 6 7
|
cocos compile -p android --android-studio --app-abi armeabi-v7a
cocos compile -p android --android-studio -m release
|
常见问题排查
问题一:ClassNotFoundException
1
| java.lang.ClassNotFoundException: org.cocos2dx.javascript.SdkBridge
|
原因:JAR 文件未正确引入,或类路径错误。
解决方案:
- 检查
libs 目录下是否有对应的 JAR 文件
- 确认
build.gradle 中 implementation fileTree(dir: 'libs') 已配置
- 点击 Sync Project with Gradle Files
- 检查类包名是否与调用时一致
问题二:资源文件未打包
原因:资源合并配置错误,或路径不正确。
解决方案:
- 检查
mergeAssets.doLast 中的 from 路径是否正确
- 构建后检查
app/build/intermediates/assets/ 目录
- 使用 APK 分析工具检查 assets 内容
问题三:JNI 调用崩溃
1
| JNI ERROR: java.lang.NoSuchMethodError
|
原因:方法签名不匹配,或方法不存在。
解决方案:
- 检查 Java 方法的修饰符是否为
public static
- 核对 JNI 方法签名是否完全正确
- 使用
javap -s 命令获取正确签名:
1
| javap -s org.cocos2dx.javascript.SdkBridge
|
问题四:SDK 初始化失败
原因:SDK 需要在主线程初始化,或缺少必要的权限。
解决方案:
1 2 3 4 5 6 7 8 9 10
| public static void initSdk(final String appId) { final Activity activity = (Activity) Cocos2dxActivity.getContext(); activity.runOnUiThread(new Runnable() { @Override public void run() { ThirdPartySdk.init(activity, appId); } }); }
|
总结
Cocos Creator Android SDK 集成的核心要点:
- JAR 引入:创建
libs 目录,配置 fileTree 自动引入依赖
- 资源合并:使用
variant.mergeAssets.doLast 将 SDK 资源拷贝到 APK
- JS-Java 通信:通过
jsb.reflection.callStaticMethod 调用 Java 静态方法
- 签名配置:在
build.gradle 中配置 Release 签名信息
- 路径关系:理解
treeSDKAssets 与 proj.android-studio 的相对路径关系
- JNI 签名:掌握 Java 类型到 JNI 签名的映射规则
通过规范的集成流程,可以高效地将各种第三方 SDK 接入 Cocos Creator 游戏,实现支付、统计、社交等丰富的原生功能。