cocos2dx:C++层通过JniHelper调用JAVA层代码进而调用Android手机应用接口

首先记录android打包主线流程(Windows平台,cocos2dx-3.6)

首先我们采用官方推荐的方法生成项目 cocos new xxx -p xxx.xxx.xxx -l xxx -d xxx

接着我们需要下载很多东西(当然以下这些肯定也是依照个人环境及需求去下载,仅有jdk是需要安装的,请配置环境变量):

都可以在这个链接中下载:http://www.androiddevtools.cn/

adt-bundle-windows-x86_64-20140702

android-ndk-r9d-windows-x86_64

apache-ant-1.9.4-bin(官网下载)

jdk-8u5-windows-x64(官网下载)

还记得你执行cocos2dx目录中的setup.py脚本时skip的那些 ROOT 目录指向吗?这里把上面的压缩包一一解压,再次执行setup.py脚本,建议先命令行打开cocos2dx目录,再执行setup.py脚本文件,这样你就可以粘贴了。SDK是在 adt-bundle 里面的,还有一点需要注意的是ANT_ROOT指向apache-ant-1.9.4-bin目录里的bin文件夹。

当然你的程序不可能一成不变,这里就要手动改一下proj.android\jni\Android.mk 文件,直接搜索../../Classes/AppDelegate.cpp \,依次写上你所有的cpp源码文件。

接下来就是编译了,打开命令行,进入proj.android文件夹,执行cocos compile -p android -j 4,-p指的是 android平台,-j好像是起多少个任务线程(不清楚),当然你若想深入学习了解的话,大可以执行cocos compile -h进而查看帮助。

若是一切顺利的话,proj.android\bin目录下或proj.android同级bin目录下,都应该已经有apk文件啦。

接下来记录android真机调试流程

右键项目-debug as-android application,若是此时电脑已经连接手机的话,请确保打开 开发者选项-usb调试,eclipse弹出界面就可以直接选择你的手机进行调试。若是你手边没有android手机,想尝试一下非真机调试(万万不推荐),跟着提示流程创建就不说了,你可能会缺少一项:CPU/ABI,不知道该选择什么,网上说的怎样怎样通过eclipse下载,那肯定是没有问题,这里我再提供一个下载方法,直接在上面提到的那个网址下载SDK System images,按照说明操作一下就可以了,至少会很快。

这里就到最关键的地方啦,因为我写的是一个能简单打电话的程序,如何调用Android手机应用接口将成为重点,C++层调用JAVA层也成了拦路虎

这先说一下C++层调用JAVA层相关知识,首先你看一下这篇文章:http://xiaominghimi.blog.51cto.com/2614927/908804,我将在它的基础上展开说明,说的都是我一点一点尝试出来的,也算是它blog的问题。

JniHelper::getStaticMethodInfo(minfo,"org/cocos2dx/cpp/AppActivity","callNumber","(Ljava/lang/String;)V");
public void callNumber(String uriString) {
Uri uri = Uri.parse("tel:10086");
Intent it = new Intent(Intent.ACTION_CALL,uri);
startActivity(it);
}

若是你按着示例来写自己的,得到的结果肯定是程序崩溃,你难道不想想那四个参数分别是什么都一切照搬吗?(我就是这样的),第四个参数虽然最复杂,但是人家讲得也很明白的,类的路径最难发现其中的猫腻,若是你用推荐方法创建的项目的话,那里应该填AppActivity.java的路径,即是org/cocos2dx/cpp/AppActivity。这是第一个需要说明的地方,

第二个说明的地方即是(Ljava/lang/String;)V括号里面的分号,这个我真的说不了什么,这是我试出来的,我这里没有错。

第三个说明的地方是Android手机应用接口大全大家可以看这篇文章:http://jasonshieh.iteye.com/blog/781652,当我在找各种各样错误问题的时候,我曾质疑过这些接口方法对不对啊,但是与其这样不如好好找找自己的逻辑那里出了问题,毕竟就那么三行代码,你说人家怎么错。关于ACTION_DIAL和ACTION_CALL的区别是,CALL直接就弹出提示框是否要拨打电话,而DIAL则是打开手机上的拨号盘,并已经输入好了你要拨打的电话,其实你大可以自己试试的。

第四个说明的地方就是占用我将近一天多的时间,说多了都是泪,首先JniHelper获取静态方法,及后面的调用静态方法,从文章中的第一个示例中大家再加上我给我说明,编译并执行应该并不成问题,虽然C++层如何增加断点真机调试我还不会,但是AppActivity.java里面增加断点,是可以调试的,这样你就可以测试自己的逻辑是否生效,当然不想这样的话,你也可以import android.util.Log;然后通过Log.e("cocos2d-x debug info","hello world");当然之所以写成cocos2d-x debug info是因为这第一个参数在logCat中显示为 tag,这样我就可以把这个日志和cocos2dx的日志一同过滤出来只看它们了。

第五个要说明的地方是承接上个说明,若是想访问非静态方法呢,你可以看我上面提到那篇文章的下一篇的最后一个示例,其实我一开始急功近利,我没有看到,导致我瞎试,浪费时间。请擦亮你们的钛合金双眼结合上一篇好好注意一下调用非静态方法第一个参数是什么?CallVoidMethod(jobj,methodID);是一个jobject的对像啊,千万别想当然的认为像调用静态方法那样,不然各种没有反应,你都不知道你的函数为什么调用不到,然后你就各种猜测吧。它最后一个示例的java代码有问题。我仅是大学里面学过java,所以我暂且认为它有问题,它的整体思想我们应该都能理解的,想把Activity的对像返回到C++层,当参数传递进行调用,但是它的方法有问题,actInstance= null,程序应该还是没有反应不去调用任何函数的,而且他加的那行注释我也不想说什么了,//定义单例,我还在想是不是他想定义单例然后没有写成呢,我就傻乎乎的百度了一下java如何实现单例模式,给套进去了,然后让我又一次陷入了一个不懂的难题,下面这段代码是错误的啊。

public static AppActivity instance = new AppActivity();
public static Object getInstance() {
	return instance;
}

这里不去理会我的单例是如何实现的啦,因为这样总是错的。程序的现象就是运行到startActivity 程序就崩溃,logCat输出日志是这样的

05-26 16:42:31.170: E/AndroidRuntime(655): FATAL EXCEPTION: GLThread 9269
05-26 16:42:31.170: E/AndroidRuntime(655): java.lang.NullPointerException
05-26 16:42:31.170: E/AndroidRuntime(655): 	at android.app.Activity.startActivityForResult(Activity.java:3388)
05-26 16:42:31.170: E/AndroidRuntime(655): 	at android.app.Activity.startActivityForResult(Activity.java:3349)
05-26 16:42:31.170: E/AndroidRuntime(655): 	at android.app.Activity.startActivity(Activity.java:3584)
05-26 16:42:31.170: E/AndroidRuntime(655): 	at android.app.Activity.startActivity(Activity.java:3552)
05-26 16:42:31.170: E/AndroidRuntime(655): 	at org.cocos2dx.cpp.AppActivity.callNumber(AppActivity.java:66)
05-26 16:42:31.170: E/AndroidRuntime(655): 	at org.cocos2dx.lib.Cocos2dxRenderer.nativeTouchesEnd(Native Method)
05-26 16:42:31.170: E/AndroidRuntime(655): 	at org.cocos2dx.lib.Cocos2dxRenderer.handleActionUp(Cocos2dxRenderer.java:130)
05-26 16:42:31.170: E/AndroidRuntime(655): 	at org.cocos2dx.lib.Cocos2dxGLSurfaceView$9.run(Cocos2dxGLSurfaceView.java:257)
05-26 16:42:31.170: E/AndroidRuntime(655): 	at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1462)
05-26 16:42:31.170: E/AndroidRuntime(655): 	at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)

其实我也一直忽略了logCat的日志,毕竟java在崩溃前被断住了,唉,后来的后来才看到日志,初学的我还不知如何更好的看这个日志,反正就是错误,把日志拿去百度了好长时间都没有解决问题,不是我的这个问题是多么的高级,而是这是一个低级错误,最后截屏源代码问我一经验非常丰富的朋友得出的结论是:android的activity都是系统实例化的不能自己new,重写activity的onCreate方法,然后在里面把instance=this,然后就好了。

最后我的程序需要访问手机相册,选取图片,返回图片的真实路径,首先startActivity这块,大家直接看我的源码或是百度一下应该就差不多了,但是很少有说明如何给出真实图片路径的,大家可以参考这个文章:http://ask.csdn.net/questions/293,之后你就会发现你现在需要JAVA调用C++啦,因为取到路径怎么派上用场呢,这点你可以参看这篇文章:http://www.who1753.com/java-call-cpp-by-jni-in-cocos2dx.html,但是JAVA调用C++我传的参数是String类型,这样以来jstring转char*又是一个我不会的问题啦,这可以参考这篇文章:http://blog.csdn.net/r_hgt/article/details/20942245。这个问题整体描述的都是别人的链接地址,相信你认真话也会搜到合适的解决方案。

这里说的最多的只是C++层调用JAVA层遇到的状况,因为它是我程序写到最后碰到的问题,其它的都是用主线一笔代过,并不是碰见的问题不多啊,但是细心百度总会有解决方案的,我大约用一周多的时间了解Cocos2dx客户端开发的整体流程,学的自我感觉不慢,因为我有一强力朋友一直再手把手的指导,学习过程中产生两个小项目,已经上传至github,供大家下载学习:

board:https://github.com/panshiqu/board

mother:https://github.com/panshiqu/mother


最后说明一下,这篇文章是几天断断续续写成的,所以请大家见谅...

相关文章

    本文实践自 RayWenderlich、Ali Hafizji 的文章《...
Cocos-code-ide使用入门学习地点:杭州滨江邮箱:appdevzw@1...
第一次開始用手游引擎挺激动!!!进入正题。下载资源1:从C...
    Cocos2d-x是一款强大的基于OpenGLES的跨平台游戏开发...
1.  来源 QuickV3sample项目中的2048样例游戏,以及最近《...
   Cocos2d-x3.x已经支持使用CMake来进行构建了,这里尝试...