摘自网上的android生命周期图:
- cocos2dx-2.X前后台切换分析,基于android平台:
- 1、从后台进入前台
- 项目的activity一般继承自Cocos2dxActivity,看过activity生命周期的
- 都知道onCreate,onResume等方法,这些函数是activity生命周期中
- 最重要的函数,具体什么时候调用,可以查看相关资料。
- //刚进入游戏和游戏从后台回到前台会调用
- @Override
- protected void onResume() {
- super.onResume();
- Log.d(TAG,"onResume+++++++++++++++++++++++");
- Cocos2dxHelper.onResume();
- this.mGLSurfaceView.onResume(); --->>
- }
- this.mGLSurfaceView.onResume(); 方法--->>
- @Override
- public void onResume() {
- super.onResume();
- this.setRenderMode(RENDERMODE_CONTINUOUSLY);
- //使用queueEvent方法:主要是从UI线程切换到OpenGL渲染线程
- this.queueEvent(new Runnable() {
- @Override
- public void run() {
- Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleOnResume();
- }
- });
- }
- ------>>>
- public void handleOnResume() {
- //private static native void nativeOnResume();
- //调用了一个native方法,在C++端实现
- Cocos2dxRenderer.nativeOnResume();
- }
- //C++端的实现在Java_org_cocos2dx_lib_Cocos2dxRenderer.cpp文件中:
- JNIEXPORT void JNICALL Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeOnResume() {
- //做个标记(1)这里和我要在下面说的一点有关****
- if (CCDirector::sharedDirector()->getOpenGLView()) {
- CCApplication::sharedApplication()->applicationWillEnterForeground();
- }
- }
- // this function will be called when the app is active again
- //进入前台,我们可以在这里做一些处理
- void AppDelegate::applicationWillEnterForeground()
- {
- CCDirector::sharedDirector()->startAnimation();
- SimpleAudioEngine::sharedEngine()->resumeBackgroundMusic();
- }
- 2、 //从前台进入后台会调用过程
- @Override
- protected void onPause() {
- super.onPause();
- Log.d(TAG,"onPause+++++++++++++++++++++++");
- Cocos2dxHelper.onPause();
- this.mGLSurfaceView.onPause();
- }
- //this.mGLSurfaceView.onPause();--->>
- @Override
- public void onPause() {
- this.queueEvent(new Runnable() {
- @Override
- public void run() {
- Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleOnPause();
- }
- });
- this.setRenderMode(RENDERMODE_WHEN_DIRTY);
- //super.onPause();
- }
- ---->>>mCocos2dxRenderer.handleOnPause:
- public void handleOnPause() {
- Cocos2dxRenderer.nativeOnPause();
- }
- ----->>>native方法,调用C++端的函数:
- private static native void nativeOnPause();
- //C++端的实现在Java_org_cocos2dx_lib_Cocos2dxRenderer.cpp文件中:
- JNIEXPORT void JNICALL Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeOnPause() {
- //进入后台
- CCApplication::sharedApplication()->applicationDidEnterBackground();
- CCNotificationCenter::sharedNotificationCenter()->postNotification(EVENT_COME_TO_BACKGROUND,NULL);
- }
- // This function will be called when the app is inactive. When comes a phone call,it's be invoked too
- //进入后台,我们可以在这里做一些处理。
- void AppDelegate::applicationDidEnterBackground()
- {
- CCDirector::sharedDirector()->stopAnimation();
- SimpleAudioEngine::sharedEngine()->pauseBackgroundMusic();
- }
- 3、我的一点疑惑(已解决)
- 从activity生命周期中我们看到,在第一次进入游戏中时也会调用onResume方法,如果这样,那我们就不能
- 认为调用applicationWillEnterForeground方法的时机是从后台进入前台,如果这样我们在处理游戏从后台进入
- 前台时,就需要注意这个问题。其实,第一次进入游戏applicationWillEnterForeground方法是不会调用的,
- 我们可以不用管上面我说的那个问题。至于为什么,下面分析:
- 3.1、在activity中的onResume方法和Cocos2dxRenderer类中的onSurfaceCreated方法中加入log日志,看下
- 两个地方的执行顺序:
- @Override
- //onSurfaceCreated在surface创建时调用,在这里调用nativeInit方法进行一些初始化。
- //具体整个过程,可以查看cocos2dx启动过程相关的资料。
- public void onSurfaceCreated(final GL10 pGL10,final EGLConfig pEGLConfig) {
- Log.d("","onSurfaceCreated+++++++++++");
- Cocos2dxRenderer.nativeInit(this.mScreenWidth,this.mScreenHeight);
- this.mLastTickInNanoSeconds = System.nanoTime();
- }
- --->>>
- void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit(JNIEnv* env,jobject thiz,jint w,jint h)
- {
- if (!CCDirector::sharedDirector()->getOpenGLView())
- {
- //这里创建才创建CCEGLView,第二个标记(2)*****
- CCEGLView *view = CCEGLView::sharedOpenGLView();
- view->setFrameSize(w,h);
- AppDelegate *pAppDelegate = new AppDelegate();
- CCApplication::sharedApplication()->run();
- }
- else
- {
- //其实这里我有一点疑问?就是这个分支什么时候会被执行,我试了很多次,都没有看到什么时候执行。
- //有待以后学习。
- ccGLInvalidateStateCache();
- CCShaderCache::sharedShaderCache()->reloadDefaultShaders();
- ccDrawInit();
- CCTextureCache::reloadAllTextures();
- CCNotificationCenter::sharedNotificationCenter()->postNotification(EVENT_COME_TO_FOREGROUND,NULL);
- CCDirector::sharedDirector()->setGLDefaultValues();
- }
- }
- activity中的onResume方法和Cocos2dxRenderer类中的onSurfaceCreated方法的执行顺序:
- 看下面的输出信息就可以清楚的知道,onResume方法先执行而onSurfaceCreated方法后执行。
- 05-21 16:03:32.520: D/Cocos2dxActivity(7953): onResume+++++++++++++++++++++++
- 05-21 16:03:32.740: D/(7953): onSurfaceCreated+++++++++++
- 还记的我们做过的(1)和(2)两个标记吗?
- 标记(1):看到这里大家应该明白了吧,这里对是否进入applicationWillEnterForeground函数
- 加了一个判断CCDirector::sharedDirector()->getOpenGLView()即CCEGLView是否存在,
- 按照上面的说明在 onSurfaceCreated -->> Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit -->>
- --->> CCEGLView *view = CCEGLView::sharedOpenGLView() 即在nativeInit方法中才创建CCEGLView类的实例,
- 根据上面说的执行顺序,onResume方法在onSurfaceCreated方法之前执行,就意味着在nativeInit方法之前执行,
- 同样意味着第一次进入游戏时,因为CCDirector::sharedDirector()->getOpenGLView()方法返回NULL,因为还没有
- 实例化,所以applicationWillEnterForeground方法并不会执行。而当游戏从后台切换到前台时,
- CCDirector::sharedDirector()->getOpenGLView()方法返回已经构造的实例变量,所以可以进入
- applicationWillEnterForeground函数。
- JNIEXPORT void JNICALL Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeOnResume() {
- //做个标记(1)这里和我要在下面说的一点有关****
- if (CCDirector::sharedDirector()->getOpenGLView()) {
- CCApplication::sharedApplication()->applicationWillEnterForeground();
- }
- }