一、序言
NDK开发需要用到jni,项目中的第三方库经常有个.so文件有什么用,为啥加密不用java写呢?等等,我不知道...即使知道也仅仅是概念性的。现在我知道了!!
二、JNI的好处
两个字“装逼!!”,学了之后在同行看来会有种高大上的感觉,虽然自己心里知道很简单的,但是别人不会的东西,在他们眼里,就是高大上的。我有时很赞同:装逼就是一直学习新技术的动力。也是为了升职加薪,努力为以后的白富美创造更多幸福!!
三、环境搭建
参考:http://blog.csdn.net/u011176685/article/details/50450585
里面是针对64位操作系统的,去云盘下载一下本地安装就行。个人不推荐在线安装。因为我被那个在线安装折腾死了。
四、Java代码调用C代码
1.在MainActivity里面定义一个C方法的接口,相当于在java代码中定义一个接口,接口的实现方法是通过C语言实现的
public native String helloWorldFromC()
2.C语言实现接口方法,方法的命名严格按照jni规范来(env指向java虚拟机的环境,obj代表对象)
Java_com_example_helloworldformc_MainActivity_helloWorldFromC(JNIEnv* env,jobject obj){}
3.在项目文件创建jni文件夹,生成.mk文件。.mk文件主要用于告诉编译器如何把C代码打包成函数库
Hello.c为刚才创建的实现接口方法的文件
LOCAL_PATH := $(call my-dir) // 返回当前c代码目录
include $(CLEAR_VARS)
LOCAL_MODULE := hello // 库函数的名字 严格遵守makefile 格式 lib .so 如果前面加lib 不会自动生成了
LOCAL_SRC_FILES := Hello.c
include $(BUILD_SHARED_LIBRARY) // 加入库函数
4.交叉编译,利用前面安装的软件cygwin,把c代码打包成函数库.so文件
5.在java代码中引入库函数,注意事项去掉前面的lib 后面的.so
System.loadLibrary("hello");
6.使用方法
System.out.println(helloWorldFromC()
7.小总结:jni其实就相当于java和c语言的翻译器,在android-ndk-r8c里面的jni.h头文件,有两者相互对应的方法,类型等等。在编程中可以进行查找参考。
五、C语言回调Java方法(java中开发好的方法,c语言调用
1.原理:通过反射调用java代码(在java里面调用java类DataProvider里面的helloFromJava方法)
Class<?> forName = Class.forName("com.example.ndkcallback.DataProvider");
Method declaredMethod = forName.getDeclaredMethod("helloFromJava", new Class[]{});
declaredMethod.invoke(forName.newInstance(), new Object[]{});
2.C代码中,其实就是通过jni把那个方法翻译过来
注意“()V”是方法的签名,cmd命令窗口cd到 D:\workspace\HelloWorldFromC2\bin\classes ,你的工程文件存放class的地方,然后javap -s 打印方法的签名,需要传完整的包名。
jclass clazz=(*env)->FindClass(env,"com/example/ndkcallback/DataProvider");
// 方法签名 参数和返回值
jmethodID methodId=(*env)->GetMethodID(env,clazz,"helloFromJava","()V");
(*env)->CallVoidMethod(env,jobject,methodId);
3.然后就是java中调用C方法,c回调java方法
六、jni常见错误
1.错误1 忘记方法的参数
2.错误2 E/AndroidRuntime(821): java.lang.UnsatisfiedLinkError: Native method not found:
3.错误3 一般没有日志打印 直接报错工程停止 一般c代码有运行错误
4.错误4 在交叉编译的工具链上报错 c代码有编译错误 比如 一些函数没有声明 一些类型没有声明 少符号
5.错误5 没有Android.mk 文件
6.错误6 Android.mk 文件有错
7.错误7 引用别人.so 函数库 需要你自己native方法对应类的包名 和之前打包成.so函数库的包名一致
七、本人是攻城狮一只,正在拼命努力的向更高的地方跑。有兴趣的话可以加QQ群:494364346。大家一起努力奋斗,相互分享。
转载请注明转自:http://blog.csdn.net/u011176685/article/details/50455030
欢迎关注个人微信公众号,专注于Android深度文章和移动前沿技术分享