Android JNI加载 Linux动态库

作为Android开发者而言,提及“.so”文件就会想到Android NDK技术,其实它也是Linux下的动态链接库。刚开始接到项目时,就丢了一份so库和test.c文件,也是摸不着头脑。知道上网查了dlopen,才明白是属于linux下的动态链接库。本文只介绍其使用方法和调试过程中遇到的问题,至于linux下的动态链接库与NDK的so库有什么区别,看这两位大神的博客就清楚了:

Linux静态库和动态库的区别:https://blog.csdn.net/llzk_/article/details/55519242

Android so文件知识:https://blog.csdn.net/haimo_free/article/details/76546568

加载Linux动态库,主要用到以下几个方法:dlopen、dlerror、dlsym。具体使用如下:

//函数指针,用于指向动态链接库中要调用的函数
typedef int (*GET_REPORT_FUNC)(char **buff, int *bufflen, const char *meid, const char *imei1, const char *imei2);

      char *buff;
      void *handle = NULL;//动态链接库文件句柄
      GET_REPORT_FUNC func_ptr;
      const char *error;
      int ret = -1;
      int bufflen = 0;

      LOGD("open file path=%s", LIB_CACULATE_PATH);
//打开动态链接库,打开模式如下:
//RTLD_LAZY 暂缓决定,等有需要时再解出符号 
//RTLD_NOW 立即决定,返回前解除所有未决定的符号。
      handle = dlopen(LIB_CACULATE_PATH, RTLD_LAZY);
      if(!handle){
          LOGE("can not open .so library\n");
          return NULL;
      }
      dlerror();//清除之前的错误
      LOGD("start to dlsym get_credible_report");
//通过dlsym映射函数
      func_ptr = (GET_REPORT_FUNC)dlsym(handle, "get_credible_report");
      if ((error = dlerror()) != NULL)  {//判断是否发生错误
          LOGE("there is some error in dlsym:%s\n", error);
          return NULL;
      }

      LOGD("start to func_ptr");
      func_ptr(&buff, &bufflen, meid, imei1, imei2);//调用函数

通过以上几个函数配合使用,就可以调用Linux动态链接库中函数。

使用问题:

在调用动态链接库的过程中,主要遇到一个问题,在Android加载动态库的时候报.so加载不到。

E/linker: library "/oem/app/xxx.xxx.xxx/lib/arm64/libthird_report.so" ("/oem/app/xxx/lib/arm64/libthird_report.so") needed or dlopened by "/data/app/xxx.xxx.xxx-2/lib/arm64/libtrust_report.so" is not accessible for the namespace: [name="classloader-namespace", ld_library_paths="", default_library_paths="/data/app/xxx.xxx.xxx-2/lib/arm64:/system/fake-libs64:/data/app/xxx.xxx.xxx-2/base.apk!/lib/arm64-v8a", permitted_paths="/data:/mnt/expand:/data/data/xxx.xxx.xxx"]
E/trust_report: can not open .so library

测试的时候是将动态链接库push到data/data/目录下,apk可以成功加载。由于目标apk需要作为system app集成到系统中。再将路径改为system/app/下时,就提示找不到.so文件。起初以为是库的访问权限问题,但用ls -l查看后发现改文件的读写权限是有的。经过一番折腾以后才发现,在使用NDK加载Linux动态库的时候,需要用System.loadLibrary()现加载一次库。这样才能正常使用。

static {
        //由于通过jni加载linux动态链接库,所以在这里要先加载so库,在jni层用dlopen才阔以
        //这里的加载顺序是按JNI调用的反序加载的
        System.loadLibrary("dwtcsec");//dlopen使用的库关联的库
        System.loadLibrary("third_report");//dlopen打开的库
        System.loadLibrary("trust_report");//Java JNI库
    }

 

 

你可能感兴趣的:(JNI)