羽毛先生

V1

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 打开目录,报错

  1. 跟随文档,使用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添加混淆规则

  1. 如上同理按照文档要求进行权限配置

  2. 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版本控制
  1. 打包测试,运行成功,后台可收到激活设备, 大功告成!!!

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互调:

JSB自动绑定

总结

以上介绍完成了sdk接入以及java、ts互调的相关用法,掌握后应该可以完成大部分安卓sdk的接入工作了。羽毛也要跟小花去约会了。

更多

.简单性能优化(一):从认识与方法出发

.在编辑器上声明自定义数据数组

.包体优化指南

不规则3D地形行走

基于creator3.0的3D换装

快速实现3d抛物线绘制

奇形怪状-不规则按钮实现

今日技能你学废了吗?

更多精彩欢迎关注微信公众号

分类:

移动端开发

标签:

移动端开发

作者介绍

羽毛先生
V1