转自:http://www.shaoqun.com/a/105310.aspx

在Android中调用动态库文件(*.so)都是通过jni的方式,而且往往在apk或jar包中调用so文件时,都要将对应so文件打包进apk或jar包,工程目录下图:

以上方式的存在的问题:

  1、缺少灵活性比较类似静态加载了(不是静态加载),能加载的so文件绑定死了;

  2、但so文件很多或很大时,会导致对应的apk和jar包很大;

  3、不能动态的对so文件更新;

Android中加载so文件的提供的API:

void System.load(String pathName);

说明:

  1、pathName:文件名+文件路劲;

  2、该方法调用成功后so文件中的导出函数都将插入的系统提供的一个映射表(类型Map);

看到以上对System.load(String pathName);的函数说明可定有人会想到将so文件放到一个指定的目录然后再通过参数pathName直接引用该目录的路劲和对应的so文件问题不就解决了吗?

这里有个问题被忽略了,那就是System.load只能加载两个目录路劲下的so文件:

  1、/system/lib ;

  2、安装包的路劲,即:/data/data/<packagename>/…

而且这两个路劲又是有权限保护的不能直接访问;

问题解决方法:

先从网络下载so文件到手机目录(如:/test/device/test.so) –> 将test.so加载到内存(ByteArrayOutputStream) –> 然后保存到对用安装包目录;

具体代码如下:

try {             String localPath = Environment.getExternalStorageDirectory() + path;             Log.v(TAG, "LazyBandingLib localPath:" + localPath);             String[] tokens = mPatterns.split(path);             if (null == tokens || tokens.length <= 0                     || tokens[tokens.length - 1] == "") {                 Log.v(TAG, "非法的文件路径!");                 return -3;             }             // 开辟一个输入流             File inFile = new File(localPath);             // 判断需加载的文件是否存在             if (!inFile.exists()) {                 // 下载远程驱动文件                 Log.v(TAG, inFile.getAbsolutePath() + " is not fond!");                 return 1;             }             FileInputStream fis = new FileInputStream(inFile);             File dir = context.getDir("libs", Context.MODE_PRIVATE);             // 获取驱动文件输出流             File soFile = new File(dir, tokens[tokens.length - 1]);             if (!soFile.exists()) {                 Log.v(TAG, "### " + soFile.getAbsolutePath() + " is not exists");                 FileOutputStream fos = new FileOutputStream(soFile);                 Log.v(TAG, "FileOutputStream:" + fos.toString() + ",tokens:"                         + tokens[tokens.length - 1]);                 // 字节数组输出流,写入到内存中(ram)                 ByteArrayOutputStream baos = new ByteArrayOutputStream();                 byte[] buffer = new byte[1024];                 int len = -1;                 while ((len = fis.read(buffer)) != -1) {                     baos.write(buffer, 0, len);                 }                 // 从内存到写入到具体文件                 fos.write(baos.toByteArray());                 // 关闭文件流                 baos.close();                 fos.close();             }             fis.close();             Log.v(TAG, "### System.load start");             // 加载外设驱动             System.load(soFile.getAbsolutePath());             Log.v(TAG, "### System.load End");             return 0;         } catch (Exception e) {             Log.v(TAG, "Exception   " + e.getMessage());             e.printStackTrace();             return -1; }

更多相关文章

  1. Android之JNI和NDK的那些事
  2. AndroidManifest.xml文件的作用和简单使用
  3. 跨进程调用Service(AIDL服务) (附图 附源码)
  4. android中make命令
  5. Android保存List>数据到SD卡及读取
  6. Android中的文件读写全面总结
  7. Android(安卓)学习笔记之 Activity 简介
  8. Android(安卓)7.0 FileProvider简单使用以及冲突处理
  9. 菜鸟与月薪10万大神的差距都在这 : Android、嵌入式Linux开发者

随机推荐

  1. Android系统驱动概述
  2. Android(安卓)Studio 清理缓存clean proj
  3. Android进程so注入Hook java方法
  4. Android(安卓)开发常用代码
  5. android shape实现边框圆角
  6. Android(安卓)JNI使用方法
  7. Android(安卓)配置及adb 命令
  8. Building Android(安卓)Apps with AWS 使
  9. Android(安卓)入门篇
  10. android studio 获取证书指纹 SHA1