写在前面

本篇内容主要是关于用cocoscreator构建的Android工程,在运行apk时候的启动流程。
CocosCreator版本:2.3.1

正文

1、主Activity入口在AndroidMainifest.xml中定义

<activity>            android:name="org.cocos2dx.javascript.AppActivity"            ...activity>            

2、Cocos2dxActivity的onCreate()方法

AppActivity继承Cocos2dxActivity,在它的onCreate()方法并没有处理太多东西,而是调用了父类的onCreate()方法。代码如下:

    @Override    protected void onCreate(final Bundle savedInstanceState) {        Log.d(TAG, "Cocos2dxActivity onCreate: " + this + ", savedInstanceState: " + savedInstanceState);        super.onCreate(savedInstanceState);        // Workaround in https://stackoverflow.com/questions/16283079/re-launch-of-activity-on-home-button-but-only-the-first-time/16447508        if (!isTaskRoot()) {            // Android launched another instance of the root activity into an existing task            //  so just quietly finish and go away, dropping the user back into the activity            //  at the top of the stack (ie: the last state of this task)            finish();            Log.w(TAG, "[Workaround] Ignore the activity started from icon!");            return;        }        Utils.setActivity(this);        Utils.hideVirtualButton();        Cocos2dxHelper.registerBatteryLevelReceiver(this);        // 把工程中libs下面的so文件load进来,定义在AndroidManifest, meta-data标签下,android.app.lib_name. 最终在包的data/data/com.XXX.XXX/lib下面        onLoadNativeLibraries();        sContext = this;        this.mHandler = new Cocos2dxHandler(this);  // 处理安卓的弹窗等                Cocos2dxHelper.init(this);        CanvasRenderingContext2DImpl.init(this);                this.mGLContextAttrs = getGLContextAttrs(); // 获取OpenGLES相关属性        this.init(); // 初始化        if (mVideoHelper == null) {            mVideoHelper = new Cocos2dxVideoHelper(this, mFrameLayout);        }        if(mWebViewHelper == null){            mWebViewHelper = new Cocos2dxWebViewHelper(mFrameLayout);        }        Window window = this.getWindow();        window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);        this.setVolumeControlStream(AudioManager.STREAM_MUSIC);    }
    protected void onLoadNativeLibraries() {        try {            ApplicationInfo ai = getPackageManager().getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA);            Bundle bundle = ai.metaData;            // 获取在AndroidManifest.xml中定义.so文件名,并调用System.loadLibrary加载            String libName = bundle.getString("android.app.lib_name");            System.loadLibrary(libName);        } catch (Exception e) {            e.printStackTrace();        }    }

在AndroidManifest.xml的定义:

                <meta-data android:name="android.app.lib_name"                   android:value="cocos2djs" />

3、Cocos2dxActivity的init()方法

    public void init() {        ViewGroup.LayoutParams frameLayoutParams =                new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,                                           ViewGroup.LayoutParams.MATCH_PARENT);        mFrameLayout = new FrameLayout(this);        mFrameLayout.setLayoutParams(frameLayoutParams);        // 添加一个surfaceView,surfaceView是什么,下面讲        Cocos2dxRenderer renderer = this.addSurfaceView();        this.addDebugInfo(renderer);        // Should create EditBox after adding SurfaceView, or EditBox will be hidden by SurfaceView.        mEditBox = new Cocos2dxEditBox(this, mFrameLayout);        // Set frame layout as the content view        setContentView(mFrameLayout);    }

addSurfaceView():

    private Cocos2dxRenderer addSurfaceView() {        // 创建一个surfaceView        this.mGLSurfaceView = this.onCreateView();        this.mGLSurfaceView.setPreserveEGLContextOnPause(true);        // Should set to transparent, or it will hide EditText        // https://stackoverflow.com/questions/2978290/androids-edittext-is-hidden-when-the-virtual-keyboard-is-shown-and-a-surfacevie        mGLSurfaceView.setBackgroundColor(Color.TRANSPARENT);        // Switch to supported OpenGL (ARGB888) mode on emulator        if (isAndroidEmulator())            this.mGLSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);        // 注册自主实现的渲染器,渲染器又用来干嘛的,下面讲        Cocos2dxRenderer renderer = new Cocos2dxRenderer();        this.mGLSurfaceView.setCocos2dxRenderer(renderer);        // 将新建的surfaceView添加到mFrameLayout中        mFrameLayout.addView(this.mGLSurfaceView);        return renderer;    }        public Cocos2dxGLSurfaceView onCreateView() {    // Cocos2dxGLSurfaceView 继承于 android.opengl.GLSurfaceView        Cocos2dxGLSurfaceView glSurfaceView = new Cocos2dxGLSurfaceView(this);        //this line is need on some device if we specify an alpha bits        if(this.mGLContextAttrs[3] > 0) glSurfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT);        Cocos2dxEGLConfigChooser chooser = new Cocos2dxEGLConfigChooser(this.mGLContextAttrs);        glSurfaceView.setEGLConfigChooser(chooser);        return glSurfaceView;    }

4、GLSurfaceView和GLSurfaceView.Render

Android提供了两个基本的类GLSurfaceViewGLSurfaceView.Render来让我们使用OpenGL ES API来创建和操纵图形。

GLSurfaceView

它是一个视图类,你可以调用OpenGL API在上面绘制图形和操纵物体,功能和SurfaceView相似。其中Cocos2dxGLSurfaceView 就是继承这个类,并且扩展这个类重写onTouchEvent、onKeyDown、onKeyUp等函数。

GLSurfaceView.Render

这个接口定义了在一个OpenGL的GLSurfaceView中绘制图形所需要的的方法,我们必须在一个单独的类中为这些接口提供实现,并使用GLSurfaceView.setRenderer()方法将它依附到GLSurfaceView实例对象上。Cocos2dxRenderer就是继承此类。
我们需要实现GLSurfaceView.Render的以下方法:

  • onSurfaceCreated():系统在创建GLSurfaceView时调用它一次。我们可以使用它来设置OpenGL的环境变量,或是初始化OpenGL的图形物体。
  • onSurfaceChanged():系统在GLSurfaceView的几何属性发生改变时调用该方法,包括大小或是设备屏幕的方向发生变化。例如,系统在屏幕从直立变为水平使调用它。这个方法主要用来对GLSurfaceView容器的变化进行响应。
  • onDrawFrame():系统在每次重绘GLSurfaceView时调用这个方法。这个方法主要完成绘制图形的操作。

接下来继续看Cocos2dxRenderer类

    @Override    public void onSurfaceCreated(final GL10 GL10, final EGLConfig EGLConfig) {        mNativeInitCompleted = false;        // 这里调用了一个定义为native的函数,它是通过jni来访问c++实现的方法,具体下面讲        Cocos2dxRenderer.nativeInit(this.mScreenWidth, this.mScreenHeight, mDefaultResourcePath);        mOldNanoTime = System.nanoTime();        this.mLastTickInNanoSeconds = System.nanoTime();        mNativeInitCompleted = true;        if (mGameEngineInitializedListener != null) {            Cocos2dxHelper.getActivity().runOnUiThread(new Runnable() {                @Override                public void run() {                    mGameEngineInitializedListener.onGameEngineInitialized();                }            });        }    }
    @Override    public void onSurfaceChanged(final GL10 GL10, final int width, final int height) {        // 同样的调用了c++的方法        Cocos2dxRenderer.nativeOnSurfaceChanged(width, height);    }
    @Override    public void onDrawFrame(final GL10 gl) {        if (mNeedToPause)            return;        if (mNeedShowFPS) {            /////////////////////////////////////////////////////////////////////            //IDEA: show FPS in Android Text control rather than outputing log.            ++mFrameCount;            long nowFpsTime = System.nanoTime();            long fpsTimeInterval = nowFpsTime - mOldNanoTime;            if (fpsTimeInterval > 1000000000L) {                double frameRate = 1000000000.0 * mFrameCount / fpsTimeInterval;                Cocos2dxHelper.OnGameInfoUpdatedListener listener = Cocos2dxHelper.getOnGameInfoUpdatedListener();                if (listener != null) {                    listener.onFPSUpdated((float) frameRate);                }                mFrameCount = 0;                mOldNanoTime = System.nanoTime();            }            /////////////////////////////////////////////////////////////////////        }        /*         * No need to use algorithm in default(60 FPS) situation,         * since onDrawFrame() was called by system 60 times per second by default.         */        if (sAnimationInterval <= INTERVAL_60_FPS) {            // 同样的调用了c++的方法            Cocos2dxRenderer.nativeRender();        } else {            final long now = System.nanoTime();            final long interval = now - this.mLastTickInNanoSeconds;            if (interval < Cocos2dxRenderer.sAnimationInterval) {                try {                    Thread.sleep((Cocos2dxRenderer.sAnimationInterval - interval) / Cocos2dxRenderer.NANOSECONDSPERMICROSECOND);                } catch (final Exception e) {                }            }            /*             * Render time MUST be counted in, or the FPS will slower than appointed.            */            this.mLastTickInNanoSeconds = System.nanoTime();            Cocos2dxRenderer.nativeRender();        }    }

5、c++中实现的nativeInit函数

可以看出,上述说的三个方法关键的地方就是分别调用了nativeInitnativeOnSurfaceChangednativeRender,这些方法都是在C++定义和实现的,这些方法的实现放在frameworks/cocos2d-x/cocos/platform/android/jni/JniImp.cpp中。

    JNIEXPORT void JNICALL JNI_RENDER(nativeInit)(JNIEnv*  env, jobject thiz, jint w, jint h, jstring jDefaultResourcePath)    {        g_width = w;        g_height = h;                // 这个方法new了一个AppDelegate        // auto app = new AppDelegate(width, height);        g_app = cocos_android_app_init(env, w, h);        g_isGameFinished = false;        ccInvalidateStateCache();        std::string defaultResourcePath = JniHelper::jstring2string(jDefaultResourcePath);        LOGD("nativeInit: %d, %d, %s", w, h, defaultResourcePath.c_str());                if (!defaultResourcePath.empty())            FileUtils::getInstance()->setDefaultResourceRootPath(defaultResourcePath);        se::ScriptEngine* se = se::ScriptEngine::getInstance();        se->addRegisterCallback(setCanvasCallback);        EventDispatcher::init();// 程序开始运行,android的Application实现放在CCApplication-android.cpp中,start的代码如下:        g_app->start();        g_isStarted = true;    }
void Application::start(){// applicationDidFinishLaunching具体的实现在frameworks/runtime-src/Classes/AppDelegate.cpp中    if(!applicationDidFinishLaunching())        return;}
bool AppDelegate::applicationDidFinishLaunching(){    se::ScriptEngine* se = se::ScriptEngine::getInstance();    jsb_set_xxtea_key("65dd8463-fe52-43");    jsb_init_file_operation_delegate();#if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0)    // Enable debugger here    jsb_enable_debugger("0.0.0.0", 6086, false);#endif    se->setExceptionCallback([](const char* location, const char* message, const char* stack){        // Send exception information to server like Tencent Bugly.    });    jsb_register_all_modules();    se->start();    se::AutoHandleScope hs;    // 通过jsb调用js脚本,main.js是入口脚本    jsb_run_script("jsb-adapter/jsb-builtin.js");    jsb_run_script("main.js");    se->addAfterCleanupHook([](){        JSBClassType::destroy();    });    return true;}

以上就是CocosCreator2.3.1版本构建的Android工程启动的流程,如果有哪里不对的欢迎指出!

参考链接:
https://www.cnblogs.com/Monte/p/6735061.html
https://www.jb51.net/article/96074.htm

更多相关文章

  1. android对sqlite数据库操作(创建 增 删 改 查)
  2. Android:INSTALL_FAILED_UPDATE_INCOMPATIBLE 错误解决方法
  3. 【IMOOC学习笔记】多种多样的App主界面Tab实现方法(一)
  4. Android8.0源码解析——Activity的启动过程
  5. Android(安卓)各版本关闭 Selinux 的方法
  6. android中的提示方法
  7. android 入门学习笔记 取得文件架构、打开文件、判断文件MimeTyp
  8. Android(安卓)对话框(三)自定义对话框
  9. Android(安卓)View动画——自定义View动画

随机推荐

  1. php基础知识考察点之正则表达式
  2. PHP+Ajax实现文章心情投票功能(代码实例)
  3. php实现微信企业付款到零钱
  4. 关于CentOS6.x/6.5/6.4/6.3/6.2/7.x 64位
  5. 正则表达式中模式修正符作用详解
  6. PHP中的global关键字用法
  7. 深入理解PHP中七个预定义接口
  8. PHP自定义函数+系统函数库(代码示例)
  9. 关于PHP框架中.env文件的加载过程
  10. php中比较两个数组差异的方法