cocosjs與安卓原生集成



@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
    }
}
之後重新編譯。就應該可以了。







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章