Android JNI配置及入门
2016-04-27 11:38
761 查看
Android JNI配置及入门
JNI是一种可以在Java中调用C/C++代码的技术,也就是说可以在Android上使用C/C++来开发。但是并不能用纯C/C++来开发Android应用,因为这些C/C++代码要通过Java定义的接口来调用。
我试验Android上的JNI时使用的是NDK-R10,不需要Cygin,使用版本较低的NDK时请另寻教程。
NDK的安装与ADT中如何配置NDK
可以到Android Developer官网上去下载最新的NDK工具包,下载下来之后解压到随便一个好找的目录,比如我们解压到了C:\,这样NDK就被安装在了C:\android-ndk-r10目录中。
要在你的Android工程使用NDK还需要进行配置,配置的方法非常简单:
在eclipse ADT中,点开Window->Preference->Andorid->NDK,然后在NDK Location中填入你安装NDK的目录,也就是上面的C:\android-ndk-r10。现在ADT就可以根据你提供的NDK路径自动调用跟构建NDK项目相关的工具了。
试试第一个NDK程序
1. 首先在eclipse ADT中创建一个名为NDKTest的Android项目。
2. 在ADT中你要使用NDK的工程目录上(这里也就是NDKtest目录),鼠标右键后选择Android Tools->Add Native Support...
在弹出的对话框中填入你将要生成的二进制链接库的文件名,这里我们以hello.so为例
然后单击finish,稍等一会儿,就会发现在你的工程目录里多了一叫jni的文件夹。
3. 现在就可以开始写最终起作用那部分的C/C++代码了,这些代码都要写在hello.cpp里面(这个cpp文件的文件名和你刚才要创建的.so的链接库的文件名一样),我们在cpp中写入如下代码:
-----------------------------------开始-------------------------------------------
#include <jni.h>
#include <string.h>
// C/C++定义的方法必须为Java+包名+activity名+你的函数名,每个部分之间要用下划线_来连接,
// 而且参数也是固定的。所以定义C/C++函数的固定格式为:
// Java_PackageName_ActivityName_function(JNIEnv* env, jobject obj) {...}
//
// 这里extern "C"是为了防止C++编译二进制链接库时对函数进行改名,其实加不加都不影响这段实现代码的运行效果,
// 但是如果你的程序因为java.lang.UnsatisfiedLinkError: Native method not found这
// 错误而崩溃的话你还是加上吧。
extern "C" jstring Java_com_example_hellojni_MainActivity_hello(JNIEnv* env, jobject obj) {
return env->NewStringUTF("hello JNI.");
}
---------------------------------------结尾-------------------------------------------------------
代码中的注释已经说明的非常明白了,你定义的C/ C++函数都要按照固定的格式来命名。
在你点击run按钮来运行你的app时ADT会自动调用ndk-build来编译我们的C/C++代码。
4. 要调用我们写好的C/C++代码,需要我们在Java源码中加入如下代码片:
-------------------------------开始---------------------------------------------------------------
public class MainActivity extends Activity {
// 因为static块比其他代码都更优先加载,所以在这里我们导入我们的动态链接库
// 记得之前让你自己填写的.so文件名吧,这里你把文件名写上就可以导入了
static {
System.loadLibrary("hello");
}
// 要使用自己定义的C/C++函数要像这样在Java代码中定义一个空方法
// 返回值和你之前定义的C/C++函数返回的类型一样,函数名和C/C++函数名
// 最后那一部分就可以了,因为最后一部分才是函数名
public native String hello();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = (TextView) findViewById(R.id.tv);
tv.setText(hello());
}
}
-------------------------------结束---------------------------------------------------------------
运行后的效果:
需要注意的是 cpp文件很容易编译报错 可以检查这几个地方是否配置好
1.工程右键,点Properties->C/C++ Build的Building Settings中去掉Use default build command,然后输入${NDKROOT}/ndk-build.cmd
2.在C/C++ Build中点击Environment,点Add...添加环境变量NDKROOT,值为NDK的根目录
3.再编译,问题就解决啦!
运行时崩溃,遇到java.lang.UnsatisfiedLinkError: stringFromJNI错误,解决办法:在C++文件中函数定义前添加extern "C"修饰
原因是:使用extern "C"修饰,编译器会按C语言的方式编译和连接。在C语言中,函数编译之后函数名与C++函数编译之后不同,例如foo(int
x, int y),C可能会编译成_foo的名字,而C++因为支持重载,所以会编译成像_foo_int_int这种带参数的函数名。如果是按照C语言的编译方式,调用foo函数是找不到_foo的函数名就会报出函数名找不到的错误。所以要添加extern "C"修饰。
JNI是一种可以在Java中调用C/C++代码的技术,也就是说可以在Android上使用C/C++来开发。但是并不能用纯C/C++来开发Android应用,因为这些C/C++代码要通过Java定义的接口来调用。
我试验Android上的JNI时使用的是NDK-R10,不需要Cygin,使用版本较低的NDK时请另寻教程。
NDK的安装与ADT中如何配置NDK
可以到Android Developer官网上去下载最新的NDK工具包,下载下来之后解压到随便一个好找的目录,比如我们解压到了C:\,这样NDK就被安装在了C:\android-ndk-r10目录中。
要在你的Android工程使用NDK还需要进行配置,配置的方法非常简单:
在eclipse ADT中,点开Window->Preference->Andorid->NDK,然后在NDK Location中填入你安装NDK的目录,也就是上面的C:\android-ndk-r10。现在ADT就可以根据你提供的NDK路径自动调用跟构建NDK项目相关的工具了。
试试第一个NDK程序
1. 首先在eclipse ADT中创建一个名为NDKTest的Android项目。
2. 在ADT中你要使用NDK的工程目录上(这里也就是NDKtest目录),鼠标右键后选择Android Tools->Add Native Support...
在弹出的对话框中填入你将要生成的二进制链接库的文件名,这里我们以hello.so为例
然后单击finish,稍等一会儿,就会发现在你的工程目录里多了一叫jni的文件夹。
3. 现在就可以开始写最终起作用那部分的C/C++代码了,这些代码都要写在hello.cpp里面(这个cpp文件的文件名和你刚才要创建的.so的链接库的文件名一样),我们在cpp中写入如下代码:
-----------------------------------开始-------------------------------------------
#include <jni.h>
#include <string.h>
// C/C++定义的方法必须为Java+包名+activity名+你的函数名,每个部分之间要用下划线_来连接,
// 而且参数也是固定的。所以定义C/C++函数的固定格式为:
// Java_PackageName_ActivityName_function(JNIEnv* env, jobject obj) {...}
//
// 这里extern "C"是为了防止C++编译二进制链接库时对函数进行改名,其实加不加都不影响这段实现代码的运行效果,
// 但是如果你的程序因为java.lang.UnsatisfiedLinkError: Native method not found这
// 错误而崩溃的话你还是加上吧。
extern "C" jstring Java_com_example_hellojni_MainActivity_hello(JNIEnv* env, jobject obj) {
return env->NewStringUTF("hello JNI.");
}
---------------------------------------结尾-------------------------------------------------------
代码中的注释已经说明的非常明白了,你定义的C/ C++函数都要按照固定的格式来命名。
在你点击run按钮来运行你的app时ADT会自动调用ndk-build来编译我们的C/C++代码。
4. 要调用我们写好的C/C++代码,需要我们在Java源码中加入如下代码片:
-------------------------------开始---------------------------------------------------------------
public class MainActivity extends Activity {
// 因为static块比其他代码都更优先加载,所以在这里我们导入我们的动态链接库
// 记得之前让你自己填写的.so文件名吧,这里你把文件名写上就可以导入了
static {
System.loadLibrary("hello");
}
// 要使用自己定义的C/C++函数要像这样在Java代码中定义一个空方法
// 返回值和你之前定义的C/C++函数返回的类型一样,函数名和C/C++函数名
// 最后那一部分就可以了,因为最后一部分才是函数名
public native String hello();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = (TextView) findViewById(R.id.tv);
tv.setText(hello());
}
}
-------------------------------结束---------------------------------------------------------------
运行后的效果:
需要注意的是 cpp文件很容易编译报错 可以检查这几个地方是否配置好
1.工程右键,点Properties->C/C++ Build的Building Settings中去掉Use default build command,然后输入${NDKROOT}/ndk-build.cmd
2.在C/C++ Build中点击Environment,点Add...添加环境变量NDKROOT,值为NDK的根目录
3.再编译,问题就解决啦!
运行时崩溃,遇到java.lang.UnsatisfiedLinkError: stringFromJNI错误,解决办法:在C++文件中函数定义前添加extern "C"修饰
extern "C" { JNIEXPORT jstring JNICALL Java_com_shamoo_activity_TestActivity_stringFromJNI(JNIEnv *env, jobject thiz); } JNIEXPORT jstring JNICALL Java_com_shamoo_activity_TestActivity_stringFromJNI(JNIEnv *env, jobject thiz) { return env->NewStringUTF("Hello jni"); }
原因是:使用extern "C"修饰,编译器会按C语言的方式编译和连接。在C语言中,函数编译之后函数名与C++函数编译之后不同,例如foo(int
x, int y),C可能会编译成_foo的名字,而C++因为支持重载,所以会编译成像_foo_int_int这种带参数的函数名。如果是按照C语言的编译方式,调用foo函数是找不到_foo的函数名就会报出函数名找不到的错误。所以要添加extern "C"修饰。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android NDK开发之:配置环境的详解
- Android开发的IDE、ADT、SDK、JDK、NDK等名词解释
- Android提高之使用NDK把彩图转换灰度图的方法
- Android使用Jni实现压力锅数据检测效果示例
- JAVA中JNI的简单使用分享
- c++ mk文件出错Jni调用产生java.lang.UnsatisfiedLinkError错误解决方法
- 解析Java的JNI编程中的对象引用与内存泄漏问题
- 探讨:如何在NDK中呼叫Java的class
- 安卓应用开发通过java调用c++ jni的图文使用方法
- Java调用c++库
- Android App 增量更新实例(Smart App Updates)
- 每周总结20130814——Android NDK环境的搭建和使用,YUV420SP格式图像的处理
- Java调用动态链接库
- Mac下用Android Studio运行NDK samples
- Android NDK pthreads详细使用
- Android Studio中NDK开发傻瓜教程(CMake)