欢迎访问移动开发之家(rcyd.net),关注移动开发教程。移动开发之家  移动开发问答|  每日更新
页面位置 : > > > 内容正文

cocos2dx-2.X前后台切换分析,基于android平台

来源: 开发者 投稿于  被查看 26713 次 评论:160

cocos2dx-2.X前后台切换分析,基于android平台


摘自网上的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();
		}
        }


 

用户评论