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')
}
所以我们能够很容易根据上面的信息得出下面的依赖关系
由此我们首先迁移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的位置,如下图,知道位置后我们就知道去哪里搬代码了。
那么我们就可以得出下面几步。
- 复制../java/src上的源码,到com.cocos.lib
- ../java/libs复制到modlue下的libs目录
- 复制资源文件
- 修改清单文件
- 修改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
同样的步骤,但是路径稍有改变。
- 复制src上的源码,到com.cocos.service
- 同级目录下没有libs所以我们忽略
- 复制资源文件,无,忽略
- 修改清单文件,无,忽略
- 修改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包即可。
修改方式见下面的链接。
END
友情链接: www.cocos.com/
如果对你有帮助的话麻烦点个赞,实践中你有更好的做法或者建议,可以一起在Android 学习交流群讨论交流哦