Android 集成Cocos 3.8

1,995 阅读12分钟

1.概述

Cocos简介:一款游戏引擎,主要用于游戏互动内容开发平台。同unity,three.js等游戏引擎一样,可以进行构建游戏3D场景,或者进行一些3D内容的开发。支持2D 和 3D 游戏开发,可用于游戏开发、智能座舱、XR、虚拟角色、教育,元宇宙等...

Cocos的主要优势在于开发语言支持Js,那么基本上只要是Web开发从业者,基本上都能够通过Cocos快速上手3D游戏开发,对于一些简单的3D游戏场景的需求来讲那么开发成本将大大降低。构建支持多平台,可以将项目打包到Android,iOS,window,小程序,web等。

Cocos的主要缺点还是在开发语言为Js,在一些内存的细节控制上没办法跟unity相比。

在一些场景下,我们需要在一个原有项目上扩展游戏场景或者3D场景,那么如果采用Cocos方案的话,那么我们就需要将Cocos集成进原有的原生项目中,那么本篇文章就对Android原生项目上集成进行抛砖引玉。

软件的版本

  • Android studio :Android Studio Koala | 2024.1.1
  • Cocos :3.8.3

2.Android项目

首先我们先创建一个简单的Android项目,用来模拟已经存在的原生项目用于集成Cocos项目。 选择Android Empty Views Activity模板,创建,等待。

创建完成等待,编写布局

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


    <androidx.cardview.widget.CardView
        android:id="@+id/card_native"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_margin="8dp"
        app:cardCornerRadius="16dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@id/card_cocos"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:contentDescription="@string/image"
            android:scaleType="fitXY"
            android:src="@drawable/image" />
    </androidx.cardview.widget.CardView>

    <androidx.cardview.widget.CardView
        android:id="@+id/card_cocos"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_margin="8dp"
        app:cardCornerRadius="16dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@id/card_native"
        app:layout_constraintTop_toTopOf="parent">

    </androidx.cardview.widget.CardView>


</androidx.constraintlayout.widget.ConstraintLayout>

运行效果如下:

那么我们的目标就很简单了,将Cocos的3D场景塞进card_cocos这个CardView中,让它与Android项目共存。

3.Cocos项目

a.新建项目

新建一个Cocos的Hello word项目

项目如下:

b.配置打包设置

新建完成之后,我们设置一些打包需要用到的东西。

首先设置Android SDK的目录,然后设置NDK的目录。

二者都可以在Android studio中获取。NDK一般在Android studio中进行下载管理,目录一般在SDK下的子目录。同下图3

  这里NDK的版本选择Cocos官方推荐的版本即可,不要超出Cocos官方建议的范围。

  设置完成后在Cocos中选择Project->Build

  出现如下界面

  基本都是一些基础的设置,这里着重讲一些Android需要关注的设置。

  Debug:这里的Debug的开关开启会在cocos的界面显示帧率,三角面等信息,在调试的时候可以打开,观察性能。

  Package Name:生成的项目包名,如果是在生成的项目的进行二次开发,那么这个比较重要,但是我们是集成进原有的Android项目,这个可以随便填。

  Target API Level:同Android项目中的目标API级别。

  ABI:一般勾选v7a和v8a,如果需要支持模拟器之类的,则可以把x86和x86_64勾选上。

  Render BackEnd:分为VULKAN 和 GLES,一般默认GLES,兼容性比较好。但是性能比VULKAN差一点。

  设置完成后,点击Build进行构建。

c.运行Cocos Hello world

接上面,打开cocos构建的目录,我们先用Android studio打开,然后构建一个apk,看看这个项目先。

目录在Cocos项目下的build目录里面。

打开后,项目结构如下:

我们先直接点击运行,看看效果

效果同上。

4.集成

a.综述

在Android studio项目中打开Cocos生成的项目我们可以发现,这个项目本身和我们平时编写的Android项目有很大的不同,其中一个比较显著的特点就是,项目中有很多的modlue的引入,同时这些moudle还不在同一级的目录下,有些是在Cocos的安装目录下,有些是Cocos项目中,有些则是编译生成的产物。

那么我们需要做的就是,将这些moudle移动到我们原有的项目中,让它作为原有项目中的modlue进行编译。

首先查看Android app模块的build.gradle

核心代码如下

dependencies {
implementation fileTree(dir: '../libs', include: ['*.jar','*.aar'])
    implementation fileTree(dir: 'libs', include: ['*.jar','*.aar'])
    implementation fileTree(dir: "$ { COCOS_ENGINE_PATH } /cocos/platform/android/java/libs", include: ['*.jar'])
    implementation project(':libservice')
    implementation project(':libcocos')
    ...
} 

从上可以中可以看出,app模块主要依赖libservice和libcocos这两个模块,同时引入libs,../libs和$ { COCOS_ENGINE_PATH } /cocos/platform/android/java/libs这三个地方的jar包和aar包。

COCOS_ENGINE_PATH的定义则是在项目根目录下的gradle.properties中。

# Project-wide Gradle settings.

# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.

# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html

# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8

# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
org.gradle.jvmargs=-Xmx4608m -Dfile.encoding=UTF-8
android.useAndroidX=true

android.injected.testOnly=false

android.native.buildOutput=verbose

# Android SDK version that will be used as the compile project
PROP_COMPILE_SDK_VERSION=33

# Android SDK version that will be used as the earliest version of android this application can run on
PROP_MIN_SDK_VERSION=21

# Android SDK version that will be used as the latest version of android this application has been tested on
PROP_TARGET_SDK_VERSION=33

# Android Build Tools version that will be used as the compile project
PROP_BUILD_TOOLS_VERSION=30.0.3

# Android Application Name
PROP_APP_NAME=NewProject

# Instant App
PROP_ENABLE_INSTANT_APP=false

# InputSDK
PROP_ENABLE_INPUTSDK=true

PROP_NDK_PATH=D:\Android\AndroidSDK\ndk\21.4.7075529

# Build variant
PROP_IS_DEBUG=true

# Cocos Engine Path
COCOS_ENGINE_PATH=C:/ProgramData/cocos/editors/Creator/3.8.3/resources/resources/3d/engine/native

# Res path
RES_PATH=D:/Developer/Cocos/CocosProject/NewProject/build/android

# Native source dir
NATIVE_DIR=D:/Developer/Cocos/CocosProject/NewProject/native/engine/android

# Application ID
APPLICATION_ID=com.tao.cocos

# List of CPU Archtexture to build that application with
# Available architextures (armeabi-v7a | arm64-v8a | x86 | x86_64)
# To build for multiple architexture, use the `:` between them
# Example - PROP_APP_ABI=arm64-v8a:armeabi-v7a:x86:x86_64
PROP_APP_ABI=arm64-v8a:armeabi-v7a:x86:x86_64

# fill in sign information for release mode
RELEASE_STORE_FILE=C:/ProgramData/cocos/editors/Creator/3.8.3/resources/tools/keystore/debug.keystore
RELEASE_STORE_PASSWORD=123456
RELEASE_KEY_ALIAS=debug_keystore
RELEASE_KEY_PASSWORD=123456

有上述代码可见COCOS_ENGINE_PATH其实是Cocos安装目录下的东西。

我们下面再来看看libservice和libcocos各自的依赖情况。

Libservice

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar','*.aar'])
    implementation project(':libcocos')
} 

Libcocos

dependencies {
api fileTree(include: ['*.jar'], dir: '../java/libs')
} 

所以我们能够很容易根据上面的信息得出下面的依赖关系

image.png 由此我们首先迁移Libcocos,在Android studio打开libcocos所在的目录。

b.迁移libcocos

查看一下libcocos的build.gradle文件,关键代码如下,那么我们只需要按照这里面的信息去创建一个libcocos的moudle即可,也可以复制源码然后直接include进来,这里我们选择手动创建。

apply plugin: 'com.android.library'

android {
compileSdkVersion PROP_COMPILE_SDK_VERSION.toInteger()
    namespace 'com.cocos.lib'
    defaultConfig {
minSdkVersion PROP_MIN_SDK_VERSION
        targetSdkVersion PROP_TARGET_SDK_VERSION
        versionCode 1
        versionName "1.0"
        consumerProguardFiles 'proguard-rules.pro'
    }
    
sourceSets.main {
aidl.srcDir "../java/src"
        java.srcDir "../java/src"
        manifest.srcFile "AndroidManifest.xml"
    }
    
    ...
}

dependencies {
api fileTree(include: ['*.jar'], dir: '../java/libs')
} 

创建完成后,将对应的代码搬过来。

首先我们得知道build.gradle的位置,如下图,知道位置后我们就知道去哪里搬代码了。

那么我们就可以得出下面几步。

  1. 复制../java/src上的源码,到com.cocos.lib
  2. ../java/libs复制到modlue下的libs目录
  3. 复制资源文件
  4. 修改清单文件
  5. 修改build.gradle文件

那么最终libcocos目录结构如下图所示。

AndroidManifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>

buidl.gradle

plugins {
alias(libs.plugins.android.library)
    alias(libs.plugins.jetbrains.kotlin.android)
}

android {
namespace 'com.cocos.lib'
    compileSdk 34

    defaultConfig {
minSdk 24

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        consumerProguardFiles "consumer-rules.pro"
    }

buildTypes {
release {
minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
 }
kotlinOptions {
jvmTarget = '1.8'
    }
    buildFeatures {
buildConfig = true
    }
}

dependencies {
api(fileTree(includes: ["*.jar"], dir: "libs"))
} 

修改完成后,点击Sync Now同步一下,如果没有报错的话,我们的第一步就完成了。如果有报错,则根据报错进行修改即可。

c.迁移libservice

同样的思路我们迁移libserviece,同样的方法也是先看build.gradle

apply plugin: 'com.android.library'

android {
compileSdkVersion PROP_COMPILE_SDK_VERSION.toInteger()
    namespace 'com.cocos.service'
    defaultConfig {
minSdkVersion PROP_MIN_SDK_VERSION
        targetSdkVersion PROP_TARGET_SDK_VERSION
        versionCode 1
        versionName "1.0"
    }

sourceSets.main {
java.srcDirs "src"
        res.srcDirs 'res'
        jniLibs.srcDirs 'libs'
        manifest.srcFile "AndroidManifest.xml"
    }
    
    ...
}

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar','*.aar'])
    implementation project(':libcocos')
} 

同样的配方,同样的味道。我们也是先创建对应的moudle

同样的步骤,但是路径稍有改变。

  1. 复制src上的源码,到com.cocos.service
  2. 同级目录下没有libs所以我们忽略
  3. 复制资源文件,无,忽略
  4. 修改清单文件,无,忽略
  5. 修改build.gradle文件

修改后结构如下

build.gradle

plugins {
alias(libs.plugins.android.library)
    alias(libs.plugins.jetbrains.kotlin.android)
}

android {
namespace 'com.cocos.service'
    compileSdk 34

    defaultConfig {
minSdk 24

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        consumerProguardFiles "consumer-rules.pro"
    }

buildTypes {
release {
minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
 }
kotlinOptions {
jvmTarget = '1.8'
    }
}

dependencies {

implementation(project(":libcocos"))
} 

同样Sync Now一下,有报错就改报错。

d.迁移app模块

接下来就是迁移App模块了,这里面内容就比较多了。我们先看build.gradle

import org.apache.tools.ant.taskdefs.condition.Os

apply plugin: 'com.android.application'

RES_PATH = RES_PATH.replace("\", "/")
COCOS_ENGINE_PATH = COCOS_ENGINE_PATH.replace("\", "/")

buildDir = "$ { RES_PATH } /proj/build/$ { project.name ==~ /^[_a-zA-Z0-9-]+$/ ? project.name : 'CocosGame' } "
android {
compileSdkVersion PROP_COMPILE_SDK_VERSION.toInteger()
    buildToolsVersion PROP_BUILD_TOOLS_VERSION
    ndkPath PROP_NDK_PATH
    namespace APPLICATION_ID

    compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
 }

defaultConfig {
applicationId APPLICATION_ID
        minSdkVersion PROP_MIN_SDK_VERSION
        targetSdkVersion PROP_TARGET_SDK_VERSION
        versionCode 1
        versionName "1.0"

        externalNativeBuild {
cmake {
targets "cocos"
                arguments "-DRES_DIR=$ { RES_PATH } ", "-DANDROID_STL=c++_static", "-DANDROID_TOOLCHAIN=clang", "-DANDROID_ARM_NEON=TRUE"
            }
ndk { abiFilters PROP_APP_ABI.split(':') }
}
}

sourceSets.main {
java.srcDirs "../src", "src"
        res.srcDirs "../res", 'res', "$ { RES_PATH } /proj/res"
        jniLibs.srcDirs "../libs", 'libs'
        manifest.srcFile "AndroidManifest.xml"
        assets.srcDir "$ { RES_PATH } /data"
        jniLibs {
// Vulkan validation layer
            // srcDir "${android.ndkDirectory}/sources/third_party/vulkan/src/build-android/jniLibs"
        }
}

externalNativeBuild {
cmake {
version "3.22.1"
            path "../CMakeLists.txt"
            buildStagingDirectory "$ { RES_PATH } /proj/build"
        }
}

signingConfigs {

release {
if (project.hasProperty("RELEASE_STORE_FILE") && !RELEASE_STORE_FILE.isEmpty()) {
                storeFile file(RELEASE_STORE_FILE)
                storePassword RELEASE_STORE_PASSWORD
                keyAlias RELEASE_KEY_ALIAS
                keyPassword RELEASE_KEY_PASSWORD
            }
        }
}

buildTypes {
release {
debuggable false
            jniDebuggable false
            renderscriptDebuggable false
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            if (project.hasProperty("RELEASE_STORE_FILE")) {
                signingConfig signingConfigs.release
            }
                        
            externalNativeBuild {
cmake {
// switch HIDE_SYMBOLS to OFF to skip compilation flag `-fvisibility=hidden`
                    arguments "-DHIDE_SYMBOLS=ON"
                }
}

if (!Boolean.parseBoolean(PROP_IS_DEBUG)) {
                getIsDefault().set(true)
            }

        }

debug {
debuggable true
            jniDebuggable true
            renderscriptDebuggable true
            // resValue  "string", "app_name", "${PROP_APP_NAME}-dbg"
            // applicationIdSuffix ".debug"
        }
}
}

dependencies {
implementation fileTree(dir: '../libs', include: ['*.jar','*.aar'])
    implementation fileTree(dir: 'libs', include: ['*.jar','*.aar'])
    implementation fileTree(dir: "$ { COCOS_ENGINE_PATH } /cocos/platform/android/java/libs", include: ['*.jar'])
    implementation project(':libservice')
    implementation project(':libcocos')
    if (Boolean.parseBoolean(PROP_ENABLE_INPUTSDK)) {
        implementation 'com.google.android.libraries.play.games:inputmapping:1.1.0-beta'
        implementation "org.jetbrains.kotlin:kotlin-stdlib:1.4.10"
    }
    implementation "androidx.appcompat:appcompat:1.0.0"
    implementation "com.google.android.material:material:1.0.0"
} 

我们首先需要关注的地方有三个

  • externalNativeBuild
  • sourceSets.main
  • dependencies

其余地方,在迁移的时候我们原封不动搬过来即可。这里为了简化操作,我们直接在原生项目的app中进行改动,但是如果需要独立成一个moudle也是可以的。

那么根据上面的构建信息,我们先将dependencies 处理一下。通过定位build.gradle的位置,我们可以发现../libs和libs都是不存在,所以我们跳过。对于

 implementation fileTree(dir: "$ { COCOS_ENGINE_PATH } /cocos/platform/android/java/libs", include: ['*.jar'])

我们则需要到COCOS_ENGINE_PATH目录下去找一下,看看目录是否存在。COCOS_ENGINE_PATH在上一节里面有提到

由上图可以看到,里面的东西就是libcocos的依赖包,而在libcocos我们采用的是api的方式添加依赖,这里面的依赖会由libcocos传递给app,所以我们也可以忽略。

那么这里就变得很简单了,我们只需要把我们迁移的moudle作为依赖添加上即可。

接下来我们处理一下sourceSets.main这里面的代码,将代码搬运一下。同时在sourceSets.main中除了代码外,还有data资源文件,我们同样搬运一下到assest目录,没有的话,自己新建一下。

最终如图

其余的res的资源文件,我们用自己的即可。按需修改。

剩下还有一个就是externalNativeBuild,

我们同样复制CMakeLists.txt到app目录下,然后修改build.gradle

plugins {
alias(libs.plugins.android.application)
    alias(libs.plugins.jetbrains.kotlin.android)
}

android {
namespace 'com.tao.cocos'
    compileSdk 34

    defaultConfig {
applicationId "com.tao.cocos"
        minSdk 24
        targetSdk 34
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

        externalNativeBuild {
cmake {
targets "cocos"
                arguments "-DRES_DIR=$ { RES_PATH } ", "-DANDROID_STL=c++_static", "-DANDROID_TOOLCHAIN=clang", "-DANDROID_ARM_NEON=TRUE"
            }
ndk { abiFilters PROP_APP_ABI.split(':') }
}
}

externalNativeBuild {
cmake {
version "3.22.1"
            path "CMakeLists.txt"
        }
}


buildTypes {
release {
debuggable false
            jniDebuggable false
            renderscriptDebuggable false
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

            externalNativeBuild {
cmake {
// switch HIDE_SYMBOLS to OFF to skip compilation flag `-fvisibility=hidden`
                    arguments "-DHIDE_SYMBOLS=ON"
                }
}

if (!Boolean.parseBoolean(PROP_IS_DEBUG)) {
                getIsDefault().set(true)
            }
        }

debug {
debuggable true
            jniDebuggable true
            renderscriptDebuggable true
            // resValue  "string", "app_name", "${PROP_APP_NAME}-dbg"
            // applicationIdSuffix ".debug"
        }
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
 }
kotlinOptions {
jvmTarget = '1.8'
    }
}

dependencies {

implementation(project(":libcocos"))
    implementation(project(":libserviece"))

    if (Boolean.parseBoolean(PROP_ENABLE_INPUTSDK)) {
        implementation 'com.google.android.libraries.play.games:inputmapping:1.1.0-beta'
        implementation "org.jetbrains.kotlin:kotlin-stdlib:1.4.10"
    }

    implementation libs.androidx.core.ktx
    implementation libs.androidx.appcompat
    implementation libs.material
    implementation libs.androidx.activity
    implementation libs.androidx.constraintlayout
    testImplementation libs.junit
    androidTestImplementation libs.androidx.junit
    androidTestImplementation libs.androidx.espresso.core
} 

这里同步的时候,会报错,原因在于我们缺少某些变量的定义,这里的定义就是gradle.properties,我们同样复制一下里面的内容,然后添加到我们自己项目的gradle.properties中。

这里就不做演示了。

修改后,我们Sync now一下,发现出现报错

那么我们就来详细看一下CMakeLists.txt中做了什么

cmake_minimum_required(VERSION 3.8)

option(APP_NAME "Project Name" "NewProject")
project(${APP_NAME} CXX)
set(CC_LIB_NAME cocos)
set(CC_PROJECT_DIR src)
set(CC_PROJ_SOURCES)
set(CC_COMMON_SOURCES)
set(CC_ALL_SOURCES)

include(${CMAKE_CURRENT_LIST_DIR}/../common/CMakeLists.txt)

cc_android_before_target(${CC_LIB_NAME})
add_library(${CC_LIB_NAME} SHARED ${CC_ALL_SOURCES})
cc_android_after_target(${CC_LIB_NAME})

内容很简单,设置了一些变量的值,然后引入另外一个CMakeLists文件,我们定位一下这个文件的位置。

这里我们全局搜索CMAKE_CURRENT_LIST_DIR并没有发现他的位置,那么我们就去Cocos生成的项目上,去找到这个文件,添加打印这个变量数据的方法。

message(STATUS "CMAKE_CURRENT_LIST_DIR = ${CMAKE_CURRENT_LIST_DIR}")

然后运行,我们在build的输出信息里查看这个变量的值

从上面可以看出,他在我们Cocos的项目里面的native/engine/android,定位到位置,那就简单了。代码搬运走起。

进入目录

我们可以看到这里是一些Classes和cmake文件,我们直接复制到项目根目录下。

然后修改cmake引入的位置。

include(../common/CMakeLists.txt)

最终项目结构如下所示。

然后我们先修改一下Android 的清单文件,把启动的Activity改为Cocos的AppActivity

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.CocosDemo"
        tools:targetApi="31">
        <meta-data
            android:name="android.app.lib_name"
            android:value="cocos" />
        <activity
            android:name=".AppActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

尝试运行一下

可以看到能够成功的运行起来。

e.修改布局

目前我们只差最后一步,将Cocos的运行到一个半屏,然后另外一个半屏显示我们的原生的一些界面。

查看AppActivity中的源码,我们可以追踪到,整个布局的设置是在AppActivity的父类GameActivity中的onCreateSurfaceView中设置的,详情看下面的源码

public class GameActivity extends Activity implements SurfaceHolder.Callback2 {

    protected int contentViewId;
    protected SurfaceView mSurfaceView;

    ...
    
    protected void onCreateSurfaceView() {
        this.mSurfaceView = new SurfaceView(this);
        FrameLayout frameLayout = new FrameLayout(this);
        this.contentViewId = View.generateViewId();
        frameLayout.setId(this.contentViewId);
        frameLayout.addView(this.mSurfaceView);
        this.setContentView(frameLayout);
        frameLayout.requestFocus();
        this.mSurfaceView.getHolder().addCallback(this);
    }

    ...

}

所以我们只需要将我们自己写的MainActivity继承AppActivity,然后覆写onCreateSurfaceView方法,即可完成我们的目标。二话不说上代码。

class MainActivity : AppActivity() {

    override fun onCreateSurfaceView() {
        this.mSurfaceView = SurfaceView(this)
        val rootView = LayoutInflater.from(this).inflate(R.layout.activity_main, null)
        val card = rootView.findViewById<CardView>(R.id.card_cocos)
        this.contentViewId = card.id
card.addView(this.mSurfaceView)
        this.setContentView(rootView)
        card.requestFocus()
        mSurfaceView.holder.addCallback(this)
    }
}

修改完我们的MainActivity然后我们就可以修改清单文件里面的启动Activity了,搞定之后运行一下

我们就可以看到,我们自己的界面和Cocos的界面各占一半。

至此我们就可以说成功了99%了,剩下的就是收尾,按照我们自己的需求调整我们的代码结构了。

当Cocos的项目有改动的时候,我们只需要复制Cocos生成的data文件到Android项目下assest目录下,当然这部分可以用脚本来实现。

在上述搬运代码的过程中,我们在gradle.properties添加复制了很多cocos相关的配置,这时候我们就可以一个个进行删除了,这部分大家就可以自行处理即可。

f.GameActivity不支持Android X

在我们完成迁移后发现,我们的Activity不支持Android x了怎么办,像一些Activity的声明周期支持,协程统统都没办法用了,一夜回到Android开发的蛮荒时代,不用慌,这时候我们先定位问题。

问题的根据就在于这个GameActivity,它是直接继承的Activity所以导致很多特性我们没办法去使用,理论上我们直接修改这个继承关系,改成AppCompatActivity就可以解决这个问题,但是这个类在gamesdk这个jar里面,我们没办法直接修改。

那我们有没有办法修改gamesdk这个库呢?

Cocos提供game-sdk的仓库,我们可以Clone下来然后编译成jar,替换我们项目中的jar包即可。

修改方式见下面的链接。

github.com/cocos/googl…

END

友情链接: www.cocos.com/

docs.cocos.com/creator/3.8…

如果对你有帮助的话麻烦点个赞,实践中你有更好的做法或者建议,可以一起在Android 学习交流群讨论交流哦