准备工作:
- JDK安装
- Eclipse 安装(包括ADT插件)
- Andorid SDK 下载安装
- Android NDK 下载安装
注:NDK版本在r7以上之后就集成了Cygwin,而且还是十分精简版,已经不需要单独安装Cygwin
第一个Demo
- 新建一个Android工程,然后在工程上右键点击Android Tools->Add Native Support… ,然后给我们的.so文件取个名字,例如我的是:FirstNDK,这时候工程就会多一个jni的文件夹,jni下有Android.mk和FirstNDK.cpp文件。Android.mk是NDK工程的Makefile,FirstNDK.cpp就是NDK的源文件。
(关于 Android.mk 的说明可以参考资料:http://www.cnblogs.com/luxiaofeng54/archive/2011/08/13/2137577.html)
JNI接口的命名规范是:Java_ + 调用该方法的包名(包名的点用代替) + + 调用该接口的类名 + _ + 方法名,对于实例方法,有两个参数是必要的,一个JNI的环境指针JNIEnv *,另一个是调用该方法的Java实例jobject
接下来编辑FirstNDK.cpp文件,写一个FirstNDK的demo,代码如下:
#include <jni.h>
extern "C"{
jstring
Java_com_example_firstndk_MainActivity_getStringFromJNI(JNIEnv* env, jobject thiz)
{
//返回一个字符串给Java层
return env->NewStringUTF("Hello from JNI.");
// return (*env)->NewStringUTF(env, "Hello from JNI.")
}
}
- 然后在MainActivity调用我们刚刚编写的FirstNDK,代码如下:
public class MainActivity extends Activity {
Button btn;
TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button) findViewById(R.id.button);
tv = (TextView) findViewById(R.id.text);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
tv.setText(getStringFromJNI() );
}
});
}
public native String getStringFromJNI();
static {
System.loadLibrary("FirstNdk");
}
}
完成了,然后运行。运行时会先编译NDK,然后在编译JAVA代码。
问题与解决
问题1:编译也许会遇到Unable to launch cygpath. Is Cygwin on the path?
解决方法:
1.工程右键,点Properties->C/C++ Build的Building Settings中去掉Use default build command,然后输入${NDKROOT}/ndk-build.cmd
2.在C/C++ Build中点击Environment,点Add...添加环境变量NDKROOT,值为NDK的根目录
3.再编译,问题就解决啦!
问题2:运行时崩溃,遇到java.lang.UnsatisfiedLinkError
解决方法: 在C++文件中函数定义用extern "C"修饰
原因是:使用extern "C"修饰,编译器会按C语言的方式编译和连接。在C语言中,函数编译之后函数名与C++函数编译之后不同,例如foo(int x, int y),C可能会编译成_foo的名字,而C++因为支持重载,所以会编译成像_foo_int_int这种带参数的函数名。如果是按照C语言的编译方式,调用foo函数是找不到_foo的函数名就会报出函数名找不到的错误。所以要添加extern "C"修饰。
问题3:Method 'NewStringUTF' could not be resolved 问题
因不想使用extern "C"修饰, 所以将FirstNDK.cpp改为FirstNDK.c,
同时将c++写法 env->NewStringUTF("HelloWorld from JNI.") 改为 c写法 (*env)->NewStringUTF(env, "Hello from JNI.")
遇到Method 'NewStringUTF' could not be resolved 问题
解决方法:右键工程 property->C/C++ General->Code Analysis—>配置当前工程(或者workspace)->使 method cannot be resolved 不选中(即此项不进行报错 )