@autho mucjgm
版本:cocos2dx3.10
背景:公司需要把遊戲整合到一個APP裏面。於是打算通過activity切換的方式實現。但是遊戲退出重進之後總會出現fatal 11線程報錯。於是有了以下修改。我是底層小白。折騰了好久總算鼓搗出一個能用的版本。優化的地方應該有很多。不過就沒去好好優化了。
準備步驟
1.java層。
添加activity互相調用。
以及cocos對應的activity的finish調用函數。(提供給C++去調用。由java自己調用在某些機子上會出現釋放不正確的bug。導致線程無法釋放)
屏蔽底層關閉進程的調用。(集成了只有一個進程。不能關閉)
2.C++層。
添加調用ScriptingCore清除的函數。(每次退出清空js代碼)
添加SctiptingCore初始化中關於是否首次進入的初始化。(sc對象重新註冊)
在director的mainloop中添加退出操作和判定。(由C++去調用java層的finish。)
3.js層。
退出時調用cc.director.end.(由js發起整個退出)
以下上修改代碼。
1.java層。
Cocos2dxHelper.java文件。屏蔽terminateProcess函數內的調用。
Cocos2dxActivity.java文件。添加函數。
public static void selffinish(){
sContext.finish();
}
這裏最好別這麼幹。因爲主activity是繼承Cocos2dxActivity的。直接在這裏finish的話主activity釋放不完全。只是一個調用示例。對應的之後改C++層代碼。
2.C++層。
frameworks/cocos2d-x/cocos/platform/CCApplicationProtocol.h
添加clearSc函數。virtual void clearSc() = 0;
AppDelegate.h
添加clearSc函數。
virtual void clearSc();
AppDelegate.cpp
實現clearSc
void AppDelegate::clearSc(){
ScriptingCore::getInstance()->cleanup();
}
frameworks/cocos2d-x/cocos/scripting/js-bindings/manual/ScriptingCore.h
添加初始化判定。
bool ifFirst = true;
frameworks/cocos2d-x/cocos/scripting/js-bindings/manual/ScriptingCore.cpp修改函數。
void ScriptingCore::start()
{
// for now just this
createGlobalContext();
ifFirst = false;
}
在createGlobalContext添加代碼
void ScriptingCore::createGlobalContext() {
if (_cx && _rt) {
ScriptingCore::removeAllRoots(_cx);
JS_DestroyContext(_cx);
JS_DestroyRuntime(_rt);
_cx = NULL;
_rt = NULL;
}
// Start the engine. Added in SpiderMonkey v25
if (!JS_Init()){
return;
}
if(!ifFirst){//!!!!!!!ADD THIS 添加這個初始化
initRegister();
}
//...............
}
frameworks/cocos2d-x/cocos/base/CCDirector.cpp
添加include#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include "jni/JniHelper.h"
#endif
修改mainloop函數
void DisplayLinkDirector::mainLoop()
{
auto OutJudge = false;
static std::string activity = "org/cocos2dx/lib/Cocos2dxActivity";//此處可以修改爲主activity。也可以通過C++調用js去獲取activity
static std::string fun = "selffinish";
if (_purgeDirectorInNextLoop)
{
_purgeDirectorInNextLoop = false;
//#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)//這是我自己獲取activity和方法的代碼。
//activity = Application::getInstance()->getJavaInfo(1);
//fun = Application::getInstance()->getJavaInfo(2);
//CCLOG("CALLING!!!%s, %s",activity.c_str(), fun.c_str());
//#endif
purgeDirector();
Application::getInstance()->clearSc();
OutJudge = true;
}
else if (_restartDirectorInNextLoop)
{
_restartDirectorInNextLoop = false;
restartDirector();
}
else if (! _invalid)
{
drawScene();
// release the objects
PoolManager::getInstance()->getCurrentPool()->clear();
}
if(OutJudge){
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
JniMethodInfo t;
JniHelper::getStaticMethodInfo(t, activity.c_str(), fun.c_str(), "()V");
t.env->CallStaticVoidMethod(t.classID, t.methodID);
#endif
}
}
之後重新編譯。就應該可以了。