CocosCreator Andorid工程的启动过程
写在前面
本篇内容主要是关于用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提供了两个基本的类GLSurfaceView
和GLSurfaceView.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函数
可以看出,上述说的三个方法关键的地方就是分别调用了nativeInit
、nativeOnSurfaceChanged
、nativeRender
,这些方法都是在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
更多相关文章
- android对sqlite数据库操作(创建 增 删 改 查)
- Android:INSTALL_FAILED_UPDATE_INCOMPATIBLE 错误解决方法
- 【IMOOC学习笔记】多种多样的App主界面Tab实现方法(一)
- Android8.0源码解析——Activity的启动过程
- Android(安卓)各版本关闭 Selinux 的方法
- android中的提示方法
- android 入门学习笔记 取得文件架构、打开文件、判断文件MimeTyp
- Android(安卓)对话框(三)自定义对话框
- Android(安卓)View动画——自定义View动画