-
Notifications
You must be signed in to change notification settings - Fork 43
cocos2d x 3.3 017 为android平台提供的封装
cheyiliu edited this page Feb 4, 2015
·
5 revisions
//1. use opengl es 2.0
<uses-feature android:glEsVersion="0x00020000" />
//2. 问题1,在哪里用到的这个so?
<!-- Tell Cocos2dxActivity the name of our .so -->
<meta-data android:name="android.app.lib_name"
android:value="cpp_empty_test" />
//3. 支持的屏幕尺寸
<supports-screens android:anyDensity="true"
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true"/>
- 从Resources拷贝的资源
- 除了make file外, 有个main.cpp, 内容如下
//log相关
#define LOG_TAG "main"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
using namespace cocos2d;
//看起来怪怪的,new了一个AppDelegate之后,就不管了
//对比linux平台的,至少还调用了run方法
//问题2,谁调用的这个方法?
void cocos_android_app_init (JNIEnv* env, jobject thiz) {
LOGD("cocos_android_app_init");
AppDelegate *pAppDelegate = new AppDelegate();
}
- 由于我编译了,这个目录下有对应ABI的so
- AppActivity 代码如下
//看样子,料全在基类了
public class AppActivity extends Cocos2dxActivity {
}
- 留了两个问题待解答,别的没啥
- ControllerManualAdapter //粗略过了下代码,和游戏手柄相关,略
- java代码
//android加速度传感器事件对接。注册监听器后,android产生相应事件并
//回调到Cocos2dxAccelerometer的onSensorChanged再经过
//Cocos2dxGLSurfaceView.queueAccelerometer(x,y,z,sensorEvent.timestamp);
//之后调用到Cocos2dxAccelerometer的本地方法onSensorChanged
//该方法所在位置Java_org_cocos2dx_lib_Cocos2dxAccelerometer.cpp,
//该方法在native层dispatchEvent一个传感器事件
Cocos2dxAccelerometer.java
//java层的图片工具类,简单跟了下代码,调用方向是从native方法调用到java层
Cocos2dxBitmap.java
//自定义了一个编辑对话框,对输入类型,键盘显示隐藏等做了些包装
Cocos2dxEditBoxDialog.java
//自定义编辑框,特殊处理了back按键
Cocos2dxEditText.java
//自定义handler,主要和弹出对话框相关
Cocos2dxHandler.java
//工具类,UserDefault存储相关的jni调用,获取包名,终止进程等
//主要调用方向是native到java
Cocos2dxHelper.java
//数据库存储,主要供native端调用到java
Cocos2dxLocalStorage.java
//lua相关
Cocos2dxLuaJavaBridge.java
//java层的音乐播放相关,包装的MediaPlayer,用来播放长的音乐等
//主要由Cocos2dxHandler.java调用过来
//看样子音乐播放这块多半就是用的java层的播放器了
Cocos2dxMusic.java
//java层的音乐播放相关,包装的用soundpool,
//用来播一些短的反应速度要求高的音效
Cocos2dxSound.java
//输入事件监听相关,配合Cocos2dxGLSurfaceView的工作
Cocos2dxTextInputWraper.java
//Typeface cache相关
Cocos2dxTypefaces.java
//android视频播放器,MediaPlayer+SurfaceView
//对应的helper用来将videoview从父控件动态添加删除,简化调用等
Cocos2dxVideoView.java
Cocos2dxVideoHelper.java
//自定义webview,类似上面的视频播放器的封装
Cocos2dxWebView.java
Cocos2dxWebViewHelper.java
//游戏手柄相关
GameControllerAdapter.java
GameControllerDelegate.java
GameControllerUtils.java
//放后面一起看TODO
Cocos2dxActivity.java
Cocos2dxRenderer.java
Cocos2dxGLSurfaceView.java
- cpp
//application 在android平台相关的实现,跨平台实现细节,针对平台的具体实现
//更多信息请参考 https://github.com/cheyiliu/All-in-One/wiki/cocos2d-x-3.3-015-%E7%A8%8B%E5%BA%8F%E5%85%A5%E5%8F%A3main
CCApplication-android.cpp
CCApplication-android.h
//native层的工具类,通过jni调用到java层弹框等
CCCommon-android.cpp
//native层的工具类,获取dpi,设置加速监听器,图片处理等
CCDevice-android.cpp
//fileUtils的android平台相关的实现,类似application了
CCFileUtils-android.cpp
CCFileUtils-android.h
//一堆和opengl相关的宏等
CCGL-android.h
//glview android平台的相关实现,类似application了
CCGLViewImpl-android.cpp
CCGLViewImpl-android.h
//一些宏定义
CCPlatformDefine-android.h
CCStdC-android.h
//放后面一起看TODO
javaactivity-android.cpp
//各种jni相关的helper类或者方法
//提一提touchesJni.cpp,他是用来对接android touch事件和key事件的
//和上面的加速器事件一样的逻辑, 稍后看具体的事件源头
DPIJni.cpp
DPIJni.h
IMEJni.cpp
IMEJni.h
Java_org_cocos2dx_lib_Cocos2dxAccelerometer.cpp
Java_org_cocos2dx_lib_Cocos2dxBitmap.cpp
Java_org_cocos2dx_lib_Cocos2dxBitmap.h
Java_org_cocos2dx_lib_Cocos2dxHelper.cpp
Java_org_cocos2dx_lib_Cocos2dxHelper.h
Java_org_cocos2dx_lib_Cocos2dxRenderer.cpp
JniHelper.cpp
JniHelper.h
TouchesJni.cpp
- 上面一些非重点的代码java的 c++的,我们都过了一遍,涉及的内容都和jni相关包括事件源头的对接,各种跨平台实现细节和输入弹框等。重点代码则是上面的几个标记为TODO的相关类, 接下来重点分析
A. Cocos2dxActivity.java
1. oncreate
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//这里问题1的得到解答
//在manifest中配置的元数据信息,so库的名称
//该库在这里得到了加载
onLoadNativeLibraries();
sContext = this;
this.mHandler = new Cocos2dxHandler(this);
//helper和这个activity绑定了
Cocos2dxHelper.init(this);
//这里问题2得到解答
//这个native方法的调用过程中
//调用了 cocos_android_app_init(env, thiz);初始化了一个applicaton
this.mGLContextAttrs = getGLContextAttrs();
//初始化,下面细看
this.init();
//接下来的两个helper用来动态往mFrameLayout中添加或删除相应的view
if (mVideoHelper == null) {
mVideoHelper = new Cocos2dxVideoHelper(this, mFrameLayout);
}
if(mWebViewHelper == null){
mWebViewHelper = new Cocos2dxWebViewHelper(mFrameLayout);
}
}
2. init
public void init() {
//创建父容器FrameLayout
// FrameLayout
ViewGroup.LayoutParams framelayout_params =
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
mFrameLayout = new FrameLayout(this);
mFrameLayout.setLayoutParams(framelayout_params);
//添加了一个编辑框,但是是干嘛用的?问题3
// Cocos2dxEditText layout
ViewGroup.LayoutParams edittext_layout_params =
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
Cocos2dxEditText edittext = new Cocos2dxEditText(this);
edittext.setLayoutParams(edittext_layout_params);
// ...add to FrameLayout
mFrameLayout.addView(edittext);
//添加一个glSurfaceView到容器
// Cocos2dxGLSurfaceView
this.mGLSurfaceView = this.onCreateView();
// ...add to FrameLayout
mFrameLayout.addView(this.mGLSurfaceView);
// Switch to supported OpenGL (ARGB888) mode on emulator
if (isAndroidEmulator())
this.mGLSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
//设置glSurfaceView的render
this.mGLSurfaceView.setCocos2dxRenderer(new Cocos2dxRenderer());
this.mGLSurfaceView.setCocos2dxEditText(edittext);
//通过activity展现出来
// Set framelayout as the content view
setContentView(mFrameLayout);
}
B. Cocos2dxGLSurfaceView.java
//这个类的代码就不贴了, 不过看了之后应该一些疑惑就得到了解答
//加速器事件,touch事件,key事件的分发都从这里继续派发
//输入法的弹出或者关闭处理也在这里,这里解答了问题3,用那个编辑框来做输入法弹出相关的逻辑
//因为InputMethodManager的showSoftInput,hideSoftInputFromWindow需要相应的参数
//同时,注意这点在onResume时设置的renderMode, setRenderMode(RENDERMODE_CONTINUOUSLY);
C. Cocos2dxRenderer.java
//这个类关注几个callback就好
1. onSurfaceCreated
这里调用了一个本地方法nativeInit, 负责给导演设置了glview并调用了application的run方法
联想到linux的实现,看样子android的大循环也开启了, 但令人感到奇怪的是,android的application
的run方法只调用了applicationDidFinishLaunching而没哟类似linux的大循环。。。问题4
吼吼,继续走起
2. onSurfaceChanged
//屏幕方向变化等导致的回调
3. onDrawFrame
@Override
public void onDrawFrame(final GL10 gl) {
/*
* No need to use algorithm in default(60 FPS) situation,
* since onDrawFrame() was called by system 60 times per second by default.
*/
//android本身是一秒种onDrawFrame才被调用60次,
//也就是fps大于等于60次的都按fps=60来算了,高了也做不到,受限于onDrawFrame这个方法了
if (sAnimationInterval <= 1.0 / 60 * Cocos2dxRenderer.NANOSECONDSPERSECOND) {
Cocos2dxRenderer.nativeRender();
} else {
//fps小于60的情况
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();
}
}
4. Cocos2dxRenderer.nativeRender
JNIEXPORT void JNICALL Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeRender(JNIEnv* env) {
cocos2d::Director::getInstance()->mainLoop();
}
//豁然开朗
//onDrawFrame相当于一个循环了,mainLoop在这个循环中被调用
//逻辑本质上和linux的分析是一样的
//问题4得到解答
D. javaactivity-android.cpp
//在上面的分析中这个文件已经都涉及到了
- 在proj.androd工程里面,几个注意的细节:manifest里面定义了so库的名称并在cocos提供的Cocos2dxActivity onCreate里得到加载;jni里面的main.cpp里面有个奇怪的方法并在那里new了一个application对象,而这个方法同样是被Cocos2dxActivity onCreate方法间接调用到的。
- 在目录cocos/platform/android/下,有用信息很丰富,包含了:
- 很多跨平台实现细节里面的关于android平台的特地实现,如application, fileUtil, glView等
- 对接android平台的事件源,在java层设置事件监听,监听器被回调,jni调用到native层,native层通过事件分发器发送事件。这个过程基本都和glSurfaceView关联了。这里的事件包括加速器事件,touch事件,key事件。
- 对比linux平台的那个大循环,android的大循环本质思路还是一样的。只是那个大循环被Cocos2dxRenderer.java onDrawFrame代替。关于glSurfaceView GLSurfaceView.Renderer的更多信息请参考扩展阅读里面的链接。
- 提供了android平台上关于音频播放相关的两个封装。而且是供native方法调用的。具体用法暂没细看。
- 提供了android平台上播放视频和打开网页相关的分装,通过动态往Cocos2dxActivity的contentView里面添加删除videoView或者webView来实现。具体用法暂没细看。
- 提供了本地数据库存储的包装实现。
- 提供了很多helper类或者功能,弹出对话框,弹出输入法框,获取应用包名等。
- 提一提android程序是怎么退出的:
menuCloseCallback --> Director::getInstance()->end() --> (android平台的实现)GLViewImpl::end() --> (Java_org_cocos2dx_lib_Cocos2dxHelper.cpp)terminateProcessJNI --> (Cocos2dxHelper.java) terminateProcess --> android.os.Process.killProcess(android.os.Process.myPid());
- 那android程序怎么起来的呢。。。Zygote and fork, that's a long story
- 看这部分代码有个细节要注意,这里涉及到jni,但jni也没那么可怕,记住调用方向就好,java调用c++的方法时该方法要用native修饰,c++调用java一般是通过jnihelper来调用java层的xxHelper的static方法。
- 关于在Cocos2dxActivity contenView里面有一个隐藏的Cocos2dxEditText这里应该还有不少故事。
Just build something.