原文连接:http://blog.csdn.net/codezjx/article/details/8879670html
前言:Android NDK r7及以上的版本已经集成了Cygwin编译环境,也就是说,咱们彻底能够抛弃庞大的Cygwin了。java
r6及如下版本,也能够抛弃几个G的完整版,使用精简过的Mini-Cygwin来编译,解压后大小仅9M,但短小巧精悍,彻底能够知足Android NDK的开发。android
下载地址:https://code.google.com/p/mini-cygwin/c++
Eclipse集成Cygwin编译环境能够参考个人这篇贴:http://blog.csdn.net/codezjx/article/details/8858825windows
下面进入正题,r7及以上版本,跟着个人这篇帖子,完成环境的升级吧!!!app
参考官网:http://tools.android.com/recent/usingthendkplugineclipse
一、首先确认本身的ADT版本,NDK plugin的支持是在ADT 20及之后的版本。ide
二、安装Android Native Development Tools(该组件集成C/C++开发环境),既在安装ADT工具的时候勾选NDK组件,一路next后重启Eclipse使插件生效。函数
三、下载NDK工具http://developer.android.com/tools/sdk/ndk/index.html,我使用的是最新的android-ndk-r8e-windows-x86.zip,下载完后解压缩。工具
四、Eclipse -> Window -> Preferences -> Android -> NDK,设置NDK为刚刚解压缩的工具包路径。
侯注:作到这里时,控制台报出了一个错误:“Unable to launch cygpath. Is Cygwin on the path”,由于个人ndk是以前安装的,并无专门设置环境变量。按照这个连接中的引导解决:
Head to the project's properties. If you're using Windows, the shortcut is Alt + Enter
; or simply right-click the project name to find its properties.
Go to the C/C++ Build
section; under Builder Settings
tab in Build command:
text box you're likely to find something similar to that below, if it's empty then type in the similar text - namely:${NDKROOT}/ndk-build.cmd
where NDKROOT
, as its name implies, refers to the path where your NDK root folder exists.
Now you must inform eclipse what NDKROOT
equates to; as in, where is the NDK root path. You can do this by heading to (in your project's properties) C/C++ Build
> Environment
> press Add…
Now add your environment variable named NDKROOT (the Name
) with the relevant path (Value
). Note that you're to repeat this per NDK project. You would get a window similar to that below.
Press OK
to the New variable input window and then OK
again to the properties window.
五、NDK环境基本上已经搭建好,新建一个普通Android项目测试NDK支持。项目右键->Android Tools->Add Native Support...,输入.so库名字后点击Finish
(注意:若项目已是一个Jni项目,例如NDK example里面的HelloJni,这一步中.so库名字不用填)
六、如今已经能够Build咱们的Jni项目了,选择项目,Project->Build Project,编译咱们的c/c++代码,此时项目结构以下,NDK plugin已经为咱们添加好了include,已经为咱们生成了相应的Android.mk以及 cpp文件。(注意:这里插件为咱们生成的是cpp文件,若你不喜欢能够改回.c,并在mk文件中进行相应更改)
七、这时,Android NDK环境已经完美搭建好,咱们能够在cpp文件中流畅地书写咱们的c/c++代码。
(并且当你Alt+/时,已经可使用自动提示,各类爽歪歪有木有。若你不是用NDK plugin来构建JNI项目,而是选择手动方式,Alt+/是不会提示的)
八、关于编译,默认状况下:选择项目,Project->Build Project,来从新编译咱们的代码。并且每次run项目的时候,也会自动编译.so库。
一些问题与解决方法:
问题一:Android NDK: WARNING: APP_PLATFORM android-14 is larger than android:minSdkVersion 8 in ./AndroidManifest.xml (这个是NDK工具的一个BUG,若build Target大于minSdkVersion,则会报这个错误,致使没法运行)
解决方法:
android-ndk-r8e/build/core/add-application.mk第128行把__ndk_warning改成__ndk_info;而后从新build一次项目便可消除错误。
原文:
this problem may be safely fixed by changing this line in add-application.mk from __ndk_warning to __ndk_info
连接:
https://code.google.com/p/android/issues/detail?id=39752
问题二:使用c++来编写本地库,会有一些兼容问题。
(1)直接黏贴HelloJni的stringFromJNI函数过来测试,提示Method 'NewStringUTF' could not be resolved
解决方法:
改成:将(*env)->NewStringUTF(env, "Hello from JNI !")改成return env->NewStringUTF("Hello from JNI !")便可
缘由是:
NDK plugin默认为咱们生成的是cpp文件,而C与C++调用函数的参数不一致,所以找不到函数,具体参考jni.h中的定义。cpp文件中形如(*env)->Method(env, XXX)改为env->Method(XXX)便可。
(2)运行c++生成的.so库,若报如下错误:(既找不到函数)
No implementation found for native Lcom/dgut/android/MainActivity;.stringFromJNI ()Ljava/lang/String;
java.lang.UnsatisfiedLinkError: stringFromJNI
at com.dgut.android.MainActivity.stringFromJNI(Native Method)
解决方法:
为供Java调用的c++函数前加入extern "C" 修饰,如:(NDK example里面的cpp文件也是这么声明的,参考hello-gl2)
被extern "C"修饰的变量和函数是按照C语言方式编译和链接的。
首先看看C++中对相似C的函数是怎样编译的:做为一种面向对象的语言,C++支持函数重载,而过程式语言C则不支持。函数被C++编译后在符号库中的名字与C语言的不一样。例如,假设某个函数的原型为:void foo( int x, int y );该函数被C编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字(不一样的编译器可能生成的名字不一样,可是都采用了相同的机制,生成的新名字称为“mangled name”)。_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来实现函数重载的。例如,在C++中,函数voidfoo( int x, int y )与void foo( int x, float y )编译生成的符号是不相同的,后者为_foo_int_float。
一样地,C++中的变量除支持局部变量外,还支持类成员变量和全局变量。用户所编写程序的类成员变量可能与全局变量同名,咱们以"."来区分。而本质上,编译器在进行编译时,与函数的处理类似,也为类中的变量取了一个独一无二的名字,这个名字与用户程序中同名的全局变量名字不一样。
所以,若咱们没有使用extern "C"修饰函数,按照C语言方式编译和链接,Jni调用将可能找不到该函数。