本篇内容主要是关于用cocoscreator构建的Android工程,在运行apk时候的启动流程。
CocosCreator版本:2.3.1
<activity>
android:name="org.cocos2dx.javascript.AppActivity"
...
activity>
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" />
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;
}
Android提供了两个基本的类GLSurfaceView
和GLSurfaceView.Render
来让我们使用OpenGL ES API来创建和操纵图形。
它是一个视图类,你可以调用OpenGL API在上面绘制图形和操纵物体,功能和SurfaceView相似。其中Cocos2dxGLSurfaceView 就是继承这个类,并且扩展这个类重写onTouchEvent、onKeyDown、onKeyUp等函数。
这个接口定义了在一个OpenGL的GLSurfaceView中绘制图形所需要的的方法,我们必须在一个单独的类中为这些接口提供实现,并使用GLSurfaceView.setRenderer()方法将它依附到GLSurfaceView实例对象上。Cocos2dxRenderer就是继承此类。
我们需要实现GLSurfaceView.Render的以下方法:
@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();
}
}
可以看出,上述说的三个方法关键的地方就是分别调用了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