上一次用到NDK还是在2011年,我还记得那年接了个外包,需求是将一些指令通过C写到SD卡上,那会用的还是cgwin编译的,再加上自己又不会C/C++,弄起来特费劲。
当时还写了篇文章Android调用jni全过程,方便以后操作。现在再看,写的太简单了。根本不能做参考。
于是硬着头皮,重新来一遍。这次将整个过程记录下来,好记性不如烂笔头,下次再需要时就不操心了。
来不及解释了,老司机要开车了:
- 首先google下吧,几乎都是11年到13年的帖子,太老了,不太有参考性,要是还让我用cgwin来编译,那我要抓狂了。
- 记得去年的I/O大会,说是Studio添加了对NDK的支持。那还是去android官网看看吧。搜下ndk,找到一个ndk preview,嗯,一年过去了,还只是preview,需要studio 1.3+, gradle 2.5+, SdkManager中的ndk-bundle。如果这些还没有,那先准备下。
- ndk-bundle里的samples居然还是eclipse版本的,还好android提供了一套studio版的samples,github上有:https://github.com/googlesamples/android-ndk.git 下载下来直接打开,等gradle sync吧。这个过程相当之慢。
- 先把官网的preview文档看完。基本上是知道怎么做了吧。等待是漫长的,还是多google下,看看其他人碰到什么坑吧。
- 突然发现原来eclipse也能直接编译的,ndk builder in eclipse那也试试吧。当然还得给装个CDT。按照文档配置一下,用eclipse编译也还是挺方便的。
- gradle终于sync完了。跑一遍没什么问题。很好。可以开车了。
- eclipse跟studio都差不多,区别不大,eclipse中的Android.mk和Application.mk改到studio中的build.gradle中配置。
-
如果直接用studio,那定义好native方法,ide会报错,提示你该创建对应的c方法。然后就自动帮你生成了。。真心方便。如果用eclipse,那你得先用jni生成.h文件,再自己写.c或.cpp文件。
-
这个.h文件可以不要的,像studio直接就帮你创建了.c文件。jni这一步只是帮你将native声明的方法转换成c的方法,你可以理解为interface。一般来说,需要C/C++的地方,都不会太简单,所以不大可能一个文件就搞定,所以,最好不要在转换的那个c文件中写具体实现。你可以把它当作proxy,桥接你的java方法与C方法。
-
这次用的C++,编译的时候碰到了不少坑,比如要额外的导入一些包。
这些都是我google别人的配置,至于为什么,其实我也搞不清楚。
- 最坑的还是jni的参数类型要转成相应的C/C++类型。基本类型还好。当出现一个jcharArray转C++的char*和char[],我整个人都是崩溃的。还有多维数组在jni看来都是jObjectArray,你得手动转成多维数组再去调C++,比iOS要麻烦太多了。还好我机智,没答应去支持传对象。
- 当然中间出了很多小坑,因为沟通不当,两边都没有提前定义好方法参数,导致我一直要改jni方法,以及jni对象转换。有些C++需要额外define引用,不然编译不通过。还有什么std::,真是恶心。
就说这么多吧,我做的功能是通过GPS与Sensor数据来判断车主驾驶习惯,比如急刹车,急加速,急转弯。等等。手机能拿到的数据纬度比较少,判断的还不是很准确,而且GPS还经常乱漂,我走路都能有9.1m/s,太夸张了。还需要再优化。
还有以前的同事也在做ndk,他做的是相机取景的边缘检测,比如说拍一张名片,要把名片边缘描出来。可惜他还没从坑里跳出来。等他跳出来了再看看他的小结吧。
其实我不会C/C++,我一直给自己灌输的是,没搞不定的问题,只有搞不定的人。当遇到你搞不定的问题时,别担心,别到处求人会不会NDK,不然会进入一个死胡同。
先分析业务,罗列可能用到的技术点,通过TODO伪代码串联起来,mock测试通过后,再对每个难点单点击破,不会的去google,最最重要的是,API都有官方说明,不要随便相信博客转载的文章!(重要的事情说三遍)
相关参考: