羽毛先生
2022/06/11阅读:17主题:全栈蓝
CocosCreator原生二次开发的正确姿势
开发环境
❝❞
「cocos creator 3.4.2」 「Android Studio Bumblebee | 2021.1.1 Patch 3」 「ndk r21」
前言
本文主要介绍基于Cocos Creator 3.4.2的android原生二次开发流程以及JSB进行Android层与cocos ts/js层进行相互调用的过程。为开发的小伙伴提供一些参考。
文章介绍了背景及分析过程,只需要结论的同学请直接跳转到「“接入流程”」标题处。
点击上文卡片或文末扫描二维码关注公众号后,后台回复”「3.x安卓demo」“获取demo源码
背景
❝最近在开发的一个游戏进入到了安卓sdk接入的相关工作,这类工作较为简单,根据以往经验做起来应当是行云流水毫无障碍的——「“今晚肯定不用加班了!可以跟小花约会了!”」
❞
但是构建安卓工程后,发现结构跟以往的jsb-link差别比较大,跟以往的项目目录结构有所不同。
「心头一慌:我该不会要加班了吧?」
搜索论坛也有同学认真地发了帖子但还是未得到解决(提问日期为3月17日),问题主要概括为:不知道安卓二次开发的流程,不知道该打开哪个工程,如何修改文件,帖子如下: 【求助帖】请教一下关于使用Cocos Creator 进行Android 原生开发的正确姿势
分析过程
翻阅官方文档
注意事项
查看本地文件
「/build/android/proj 目录」
-
查看/build/android/proj 未发现AppActitivy.java等文件,但是存在build.gradle等安卓相关文件 -
使用Android Studio 打开目录,「可以成功打开并编译」
「native 目录」
-
查看 /native/engine/android/app目录,存在AndroidMainfest.xml,build.gradle等文件。
-
查看 /native/engine/android/app/com/cocos/game,可以看到有AppActitivy.java 发现以上是熟悉的安卓工程目录结构,
-
使用Android Studio 打开目录,「报错」
-

-
跟随文档,使用Android Studio打开「build/android/proj」,发现找不到上述的AndroidMainfest.xml,build.gradle,以及/native/engine/android/app/com/cocos/game/Appactivity,这时候只要切换一下显示模式为「Android」即可

切换后即可看到相关的原生文件

通过android studio中使用windows资源管理器打开 AppActivty.java可以发现AppActivity.java位于「native」/engine/android/app/src/com/cocos/game目录中


总结:在build/android/proj使用as进行开发,生效文件位于native/engine/android中,对native目录做版本管理,同时需去除native下的build目录(编译过程临时生成内容)。 build/android目录中为creator配置的service内容,随工程改变,不需要做单独的版本管理。
接入流程
Talking Data完整接入示例
接下来以TalkingData Sdk为例,介绍一下完整的安卓原生工程二次开发流程。下载好sdk后打开sdk文档: tdsdk 接入文档,参照文档指引进行接入。
1.在编辑器中进行安卓原生构建,构建的相关选项请参考官方文档,这部分介绍的还比较详细

2.构建完成后,可在工程目录下看到native、build/android两个目录


3. 使用Android Studio打开build/android/proj并且切换到Android显示模式

4. 根据sdk接入文档进行接入
-
1.导入sdk
❝❞
在native/engine/android/app/目录下新建libs目录(可在android studio中通过show in explore使用windows资源管理器打开,自动跳转到该目录),
在\native\engine\android\app下创建libs目录,复制sdk中的aar等文件到libs下,并在app module所属的build.gradle中添加依赖
此处需要注意libs目录的中的aar/jar文件并非talkingdata接入文档中的「TalkingdataSDK.jar」,而是「SaaS_TalkingDataSDK_Android_V5.0.3.jar」(下载sdk时提供的文件名),在接入其他的sdk中也常常会有这样的细节问题,需要注意以免被坑,「导致加班而耽误了跟小花的约会」。
2.配置混淆规则
❝❞
打开app module所属proguard-rules.pro添加混淆规则
-
如上同理按照文档要求进行权限配置
-
sdk初始化,接口实现等,内容相似,则不赘述了。这里提供关键性的代码,详细内容可以文末关注公众号后,后台回复 「“3.x安卓demo”」 获取demo源码
TDSDK.java
package com.cocos.sdk;
import android.util.Log;
import com.cocos.game.AppActivity;
import com.cocos.lib.CocosHelper;
import com.cocos.lib.CocosJavascriptJavaBridge;
import com.tendcloud.tenddata.TalkingDataProfile;
import com.tendcloud.tenddata.TalkingDataProfileType;
import com.tendcloud.tenddata.TalkingDataSDK;
public class TDSDK {
static String AppID = "xxxxxxxxx";
static String Chanel = "test_channel";
static TDSDK s_self = null;
public static TDSDK getInstance(){
if (s_self == null){
s_self = new TDSDK();
}
return s_self;
}
public void init(){
TalkingDataSDK.init(AppActivity.getContext(),AppID,Chanel, "");
}
public static void onResgister(String accountId){
if (accountId==""){
accountId = TalkingDataSDK.getDeviceId(AppActivity.getContext());
}
TalkingDataProfile profile = TalkingDataProfile.createProfile();
profile.setName("");
profile.setType(TalkingDataProfileType.ANONYMOUS);
TalkingDataSDK.onRegister(accountId, profile,"");
}
public static String js2JavaTest(String str1, String str2){
Log.d("TDSDK", String.format( "js2JavaTest Success param1:%s param2: %s",str1, str2));
if (s_self!= null) s_self.java2js();
return "Java Test Success";
}
public void java2js(){
CocosHelper.runOnGameThread (new Runnable() {
@Override
public void run() {
String str1 = "param3";
String str2 = "param4";
String funcStr = String.format("window.tdsdk.java2js('%s','%s')",str1,str2);
Log.d("-----------------------", "Start Java2Js");
CocosJavascriptJavaBridge.evalString(funcStr);
Log.d("----------------------", "End Java2Js");
}
});
}
}
Appactivity.java,建议可以简单了解下android各个生命周期函数执行时机以及机制。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// DO OTHER INITIALIZATION BELOW
SDKWrapper.shared().init(this);
TDSDK.getInstance().init();
}
❝❞
接入完成后可以直接在 as(android studio,以下统一简称as)中进行打包, apk 生成路径:android-001\proj\build\sdkDemo\outputs\apk
android-001为在creator构建界面的构架任务名
❝❞
也可以在ccc构建工具中点击生成进行打包。 apk 生成路径:\build\android-001\publish android-001为在creator构建界面的构架任务名
❝❞
如果进行了js层代码修改,则还需要通过编辑器的构建流程进行工程构建,然后再进行生成,使代码生效。 按照引擎设计,native目录生成后,再次构建将跳过这部分的生成,避免影响已经开发的android sdk、native C++等原生定制的内容,在此也建议「将native目录加入git/svn版本控制」。
-
打包测试,运行成功,后台可收到激活设备, 大功告成!!!
JS/TS与Android方法互调
「Android层接入完毕后,则需要实现java与ts的互调。」
❝❞
官方文档: 1. Java反射
概括:ts 调用java:jsb.reflection.callStaticMethod java 调用 ts,使用evalString,「请注意观察示例代码中的evalString函数中参数的单引号双引号使用,避免出错。」
示例:
-
cocos creator ts代码:
const classPath = "com/cocos/sdk/TDSDK";
@ccclass('tdsdk')
export class tdsdk {
private static _instance = null;
static getInstance(): tdsdk {
if (tdsdk._instance == null) {
tdsdk._instance = new tdsdk();
}
return tdsdk._instance;
}
//js调用Java
js2Java() {
if (JSB) {
log("********************start js2Java param1: title param2: content********************");
let res = jsb.reflection.callStaticMethod(classPath, "js2JavaTest", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", "title", "content");
log("返回值", res);
log("********************end js2Java param1: title param2: content********************");
}
}
//java调用js
java2js(param1: string, param2: string) {
if (!JSB) {
}
log("java2js success param3: %s param4:%s ", param1, param2);
}
}
window.tdsdk = tdsdk.getInstance();
请注意代码末尾将tdsdk挂在window上,并且在cocos creator 根目录创建.d.ts文件对tdsdk进行全局声明(文件名随意,不跟已有的冲突即可)方便别处调用时可以进行代码提示(「优雅永不过时」) global.d.ts:
import { tdsdk } from "./assets/script/tdsdk";
declare global {
interface Window {
tdsdk: tdsdk
}
}
-
Java代码
public static String js2JavaTest(String str1, String str2){
Log.d("TDSDK", String.format( "js2JavaTest Success param1:%s param2: %s",str1, str2));
if (s_self!= null) s_self.java2js();
return "Java Test Success";
}
public void java2js(){
CocosHelper.runOnGameThread (new Runnable() {
@Override
public void run() {
String str1 = "param3";
String str2 = "param4";
String funcStr = String.format("window.tdsdk.java2js('%s','%s')",str1,str2);
Log.d("-----------------------", "Start Java2Js");
CocosJavascriptJavaBridge.evalString(funcStr);
Log.d("----------------------", "End Java2Js");
}
});
}
注意在java调用js代码时,如果需要操作ui,请在规定线程中调用(「runOnGameThread」),避免崩溃,这里建立规范统一在规定线程中调用
运行结果
❝❞
更高级的互调方式,请观摩「腾讯在线教育部技术博客」的自动绑定方案文章,主要介绍了C++与js互调:
总结
以上介绍完成了sdk接入以及java、ts互调的相关用法,掌握后应该可以完成大部分安卓sdk的接入工作了。「羽毛也要跟小花去约会了。」
更多
❝ ❞
今日技能你学废了吗?
更多精彩欢迎关注微信公众号


作者介绍