目前我所知道的jni有两种方式编译,一种是使用ndk-build(也就是要写Android.mk,Application.mk来实现编译so,这也是之前安卓平台一直使用的一种比较老的方式),一种是cmake编译的方式。之前遇到一个莫名崩溃的问题,使用cmake的方式实现的一直没有找到原因来解决,后面直接使用ndk-build的方式就OK了,这里也记录一下,就是遇到莫名其妙的问题的时候,获取换一种编译环境也许能解决问题。
另外还有一个问题也困扰了我一段时间,就是在jni代码中调用第三方含有c++ stl库的so的问题(比如vector,string等),这里一定要注意的是,你的jni配置的stl库一定要和第三方so配置的是一样的,否则肯定会出现undefined reference to XXX之类的编译问题,因为不同版本的stl的命名空间不一样,直接调用肯定会链接不过去,导致编译出错。你也可以通过ndk的readelf 工具来查看第三方so依赖的是libc++.so还是libstdc++.so等来判断,不过这种方式只能判断个大概,就是说明你是gnustl还是c++_shared等等,并不能说明具体是哪一种,最好的方式是直接问下第三方so的提供者,他是用哪一种stl进行编译的。
这里引用ndk指南中的原文来说明一下:
关于jni传递基本类型这种,很简单。也做下记录备忘。
基本上java层传int,byte,char,short,long,jstring等数据到jni的时候,jni层都会有对应的jint,jbyte,jchar,jshort,jlong,jstring来负责接收这些基本数据类型,同样的jni调用c++文件的时候,又可以直接将这些基本类型转化为c++的基本类型。
java传递对象,list到jni的时候就需要,jni就需要使用jobject来接收了,收到jobject之后根据java传下来的具体的类来进行解析。
c++回调java实现:1.首先找到类jclass cls = env->FindClass(g_JavaClassName); 2获取方法id以及返回值类型.jmethodID mid = env->GetMethodID(cls, "function", "(III)V");3.将参数回调回去 env->CallVoidMethod(obj, mid, arg1, arg2);或者回调静态方法CallStaticVoidMethod