http://jingyan.baidu.com/article/3ea51489e7a9bd52e61bbac7.html
http://blog.csdn.net/houshunwei/article/details/17217695
NDK开发:http://blog.csdn.net/ikerpeng/article/details/45393223
http://www.cnblogs.com/devinzhang/archive/2012/02/29/2373729.html
一. Android SDK Android NDK Android Studio 官方下载地址:http://www.cnblogs.com/yaotong/archive/2011/01/25/1943615.html
二. 将下载下来的“android-ndk-r10c-windows-x86_64.exe”放到
“D:\Android“目录下面,然后双击安装,便会自动解压到"D:\Android"
下面
三. 选择菜单栏上的[Window->Perferences->Android->NDK]设置 NDK Loaction 为D:\Android\android-ndk-r10c;
四. 设置环境变量。按照这个链接中的引导解决:
-
环境变量中新增变量名:NDK_ROOT,变量值:E:\android\android-ndk-r10。Path中添加;%NDK_ROOT%
-
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; underBuilder Settings
tab inBuild 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
whereNDKROOT
, 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
> pressAdd…
-
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 thenOK
again to the properties window.
(注意:若项目已经是一个Jni项目,例如NDK example里面的HelloJni,这一步中.so库名字不用填)
六.现在已经可以Build我们的Jni项目了,选择项目,Project->Build Project,编译我们的c/c++代码,此时项目结构如下,NDK plugin已经为我们添加好了include,已经为我们生成了相应的Android.mk以及 cpp文件。(注意:这里插件为我们生成的是cpp文件,若你不喜欢可以改回.c,并在mk文件中进行相应更改)
7、这时,Android NDK环境已经完美搭建好,我们可以在cpp文件中流畅地书写我们的c/c++代码。
(而且当你Alt+/时,已经可以使用自动提示,各种爽歪歪有木有。若你不是用NDK plugin来构建JNI项目,而是选择手动方式,Alt+/是不会提示的)
8、关于编译,默认情况下:选择项目,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" {
- JNIEXPORT jstring JNICALL Java_com_dgut_android_MainActivity_stringFromJNI( JNIEnv* env, jobject thiz );
- }
- JNIEXPORT jstring JNICALL Java_com_dgut_android_MainActivity_stringFromJNI( JNIEnv* env, jobject thiz )
- {
- return env->NewStringUTF("Hello from JNI bear c++");
- }
被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调用将可能找不到该函数。
还可以在cygwin环境下编译NDK
下载安装cygwin
http://www.cnblogs.com/devinzhang/archive/2012/02/29/2373729.html
由于NDK编译代码时必须要用到make和gcc,所以你必须先搭建一个linux环境, cygwin是一个在windows平台上运行的unix模拟环境,它对于学习unix/linux操作环境,或者从unix到windows的应用程序移植,非常有用。通过它,你就可以在不安装linux的情况下使用NDK来编译C、C++代码了。下载地址:http://www.cygwin.com
1)然后双击运行吧,运行后你将看到安装向导界面。
2)点击下一步,此时让你选择安装方式:
- Install from Internet:直接从Internet上下载并立即安装(安装完成后,下载好的安装文件并不会被删除,而是仍然被保留,以便下次再安装)。
- Download Without Installing:只是将安装文件下载到本地,但暂时不安装。
- Install from Local Directory:不下载安装文件,直接从本地某个含有安装文件的目录进行安装。
3)选择第一项,然后点击下一步。
4)选择要安装的目录,注意,最好不要放到有中文和空格的目录里,似乎会造成安装出问题,其它选项不用变,之后点下一步:
5)上一步是选择安装cygwin的目录,这个是选择你下载的安装包所在的目录,默认是你运行setup.exe的目录,直接点下一步就可以:
6)此时你共有三种连接方式选择:
- Direct Connection:直接连接。
- Use IE5 Settings:使用IE的连接参数设置进行连接。
- Use HTTP/FTP Proxy:使用HTTP或FTP代理服务器进行连接(需要输入服务器地址、端口号)。
用户可根据自己的网络连接的实情情况进行选择,一般正常情况下,均选择第一种,也就是直接连接方式。然后再点击“下一步”。
7)这是选择要下载的站点,选择后点下一步。
8)此时会下载加载安装包列表
9)Search是可以输入你要下载的包的名称,能够快速筛选出你要下载的包。那四个单选按钮是选择下边树的样式,默认就行,不用动。View默认是Category,建议改成full显示全部包再查,省的一些包被隐藏掉。左下角那个复选框是是否隐藏过期包,默认打钩,不用管它就行,下边开始下载我们要安装的包吧,为了避免全部下载,这里列出了后面开发NDK用得着的包:autoconf2.1、automake1.10、binutils、gcc-core、gcc- g++、gcc4-core、gcc4-g++、gdb、pcre、pcre-devel、gawk、make共12个包
10)然后开始选择安装这些包吧,点skip,把它变成数字版本格式,要确保Bin项变成叉号,而Src项是源码,这个就没必要选了。
11)下面测试一下cygwin是不是已经安装好了。
运行cygwin,在弹出的命令行窗口输入:cygcheck -c cygwin命令,会打印出当前cygwin的版本和运行状 态,如果status是ok的话,则cygwin运行正常。
然后依次输入gcc –version,g++ --version,make –version,gdb –version进行测试,如果都打印出版本信息和一些描述信息,则cygwin安装成功!
3.配置 NDK 环境变量
http://www.cnblogs.com/shangdahao/archive/2013/04/17/3025429.html
新增CYGWIN_HOME键,值为Cygwin的安装目录。在Path末尾增加;%CYGWIN_HOME%\bin
4.用 NDK 来编译程序
a.现在我们用安装好的 NDK 来编译一个简单的程序吧,我们选择 ndk 自带的例子 hello-jni ,我的位于E:\android-ndk-r5\samples\hello-jni( 根据你具体的安装位置而定 ) ,
b.运行 cygwin ,输入命令 cd /cygdrive/e/android-ndk-r5/samples/hello-jni ,进入到 E:\android-ndk-r5\samples\hello-jni 目录。
c.输入 $NDK/ndk-build ,执行成功后,它会自动生成一个 libs 目录,把编译生成的 .so 文件放在里面。 ($NDK是调用我们之前配置好的环境变量, ndk-build 是调用 ndk 的编译程序 )
d.此时去 hello-jni 的 libs 目录下看有没有生成的 .so 文件,如果有,你的 ndk 就运行正常啦!
NDK编译第三方库.so
方法一:
http://www.xuebuyuan.com/1449225.html
第一次在Android NDK的C++代码中调用第三方so文件时吃了点亏, 以为只用把.so文件放到libs/armeabi目录下即可, 没想
到一ndk-build, 该so就被删除了, 报告链接错误. 通过了解, 发现NDK下调用.so时需要对其作PREBUILT处理, 步骤如下:
1.在project/jni目录下创建prebuilt子目录(目录名可自定义).
2.将第三方.so放到prebuilt中,并创建Android.mk, 内容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := xxx
LOCAL_SRC_FILES := libxxx.so
include $(PREBUILT_SHARED_LIBRARY)
3.在project/jni/Android.mk中加入
LOCAL_SHARED_LIBRARIES := xxx
4.在project/jni/android.mk的最后加入
include $(LOCAL_PATH)/prebuilt/Android.mk
5.运行cygwin, 到project目录下, 运行ndk-build
方法二:只有一个Android.mk文件
http://blog.csdn.net/vrix/article/details/7097794
1.将第三方.so放到project/jni目录下
2.在project/jni/Android.mk中修改
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := rmdradec
LOCAL_SRC_FILES := librmdradec.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := rmDraDecSample
#LOCAL_SHARED_LIBRARY := my-init #应该用复数形式,否则连接不上第三方库中的函数
LOCAL_SHARED_LIBRARIES := rmdradec
LOCAL_SRC_FILES := rmDraDecSample.c
include $(BUILD_EXECUTABLE)
以上是将NDK编译出来的文件作为可在android上直接运行的可执行文件,所以最后一行是include $(BUILD_EXECUTABLE) ,如果希望编译出来的是.so文件,改回include $(BUILD_SHARED_LIBRARY)即可。
执行编译出来的可执行文件:
如果是include $(BUILD_EXECUTABLE)编译出来的可执行文件,在android真机上怎么运行,由于我的手机没有root权限,无法运行编译出来的文件,这里用模拟器代替:
a. cmd进入dos窗口
b. 将可执行文件adb push到模拟器
c. adb shell E:\eclipse\workspace\LizmFileExplorer\libs\armeabi\rmDraDecSample /data
d. adb shell E:\eclipse\workspace\LizmFileExplorer\libs\armeabi\librmdradec.so /data
e. #cd /data 进入到文件push到的目录
f. #chmod 777 rmDraDecSample 加入文件权限,否则提示permision dinied
g. #LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/data ./rmDraDecSample 直接./rmDraDecSample会提示CANNOT LINK EXECUTABLE: could not load library "libktest.so" needed by "./testlo
ad"; caused by library "libktest.so" not found,文件运行阶段找不到库,加上LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/data可以解决,/data是执行文件所在的目录。NDK开发环境搭建 http://zengwu3915.blog.163.com/blog/static/2783489720137252525579/