1. package com.wsc.utils;
  2.  
  3. import android.content.Context;
  4.  
  5. import com.wsc.common.Entrance;
  6. import com.wsc.common.SDKCommon;
  7.  
  8. import java.io.ByteArrayOutputStream;
  9. import java.io.File;
  10. import java.io.FileInputStream;
  11. import java.io.FileOutputStream;
  12.  
  13. /**
  14. * so库从sd卡拷贝到app的私有目录下,并进行比对验证和加载<p></p>
  15. * Created by win10-JYcainiao on 2018/1/24.
  16. */
  17.  
  18. public class LoadSoFileUtils {
  19. private static final String TAG = LoadSoFileUtils.class.getSimpleName();
  20.  
  21. /**
  22. * 加载 so 文件
  23. *
  24. * @param context
  25. * @param soPath 下载到得sdcard目录
  26. */
  27. public static void loadSoFile(Context context, String soPath, LoadSoFileListener loadSoFileListener) throws Exception {
  28. if (Entrance.loacSo) {
  29. KLog.d(TAG, "so已经加载过了");
  30. return;
  31. }
  32. //存放so文件的私有目录
  33. File appLibs = context.getApplicationContext().getDir("libs", Context.MODE_PRIVATE);
  34. //需要加载的so文件
  35. File soDir = new File(soPath);
  36. File[] soFiles = null;
  37. //获取so来源文件夹下的所有so文件
  38. if (soDir.exists() && soDir.isDirectory()) {
  39. soFiles = soDir.listFiles();
  40. }
  41. //看看需要加载的so文件
  42. if (!soFileExisted(appLibs, soFiles) && soFiles != null) {
  43. copy(soPath, appLibs.getAbsolutePath());
  44. }
  45. //获取app私有目录下的文件列表
  46. File[] currentFiles = appLibs.listFiles();
  47. if (!loadSoFileListener.compareSo(currentFiles)) {
  48. KLog.d(TAG, "so验证未通过");
  49. loadSoFileListener.onError();
  50. return;
  51. }
  52. //记录加载的so个数
  53. int loacSoFileCount = 0;
  54. //根据so文件名称加载so文件
  55. for (int i = 0; i < currentFiles.length; i++) {
  56. for (int j = 0; j < SDKCommon.soFileNames.length; j++) {
  57. if (currentFiles[i].getName().contains(SDKCommon.soFileNames[j])) {
  58. try {
  59. System.load(currentFiles[i].getAbsolutePath());
  60. loacSoFileCount++;
  61. } catch (Exception e) {
  62. throw new Exception("加载so库失败,soName = " + currentFiles[i].getName());
  63. }
  64. }
  65. }
  66. }
  67. //判断需要加载的so是否加载完全
  68. if (loacSoFileCount == SDKCommon.soFileNames.length) {
  69. Entrance.loacSo = true;
  70. loadSoFileListener.onSuccess();
  71. } else {
  72. loadSoFileListener.onError();
  73. }
  74. }
  75.  
  76. /**
  77. * 判断 so 文件是否存在
  78. *
  79. * @param soFolder 需要存放so库的app私有文件夹
  80. * @param soFiles 需要动态加载的so文件
  81. * @return 需要加载的so文件是否存在
  82. */
  83. private static boolean soFileExisted(File soFolder, File... soFiles) {
  84. int count = 0;
  85. if (soFolder.exists()) {
  86. File[] files = soFolder.listFiles();
  87. if (files != null && files.length > 0) {
  88. for (int i = 0; i < files.length; i++) {
  89. for (int j = 0; j < soFiles.length; j++) {
  90. if (files[i].getName().equals(soFiles[j].getName()) && files[i].length() == soFiles[j].length()) {
  91. count++;
  92. }
  93. }
  94. }
  95. }
  96. }
  97. if (count == 6) {
  98. return true;
  99. }
  100. return false;
  101. }
  102.  
  103. /**
  104. * @param fromFile 指定的下载目录
  105. * @param toFile 应用的包路径
  106. * @return
  107. */
  108. private static int copy(String fromFile, String toFile) {
  109. //要复制的文件目录
  110. File[] currentFiles;
  111. File root = new File(fromFile);
  112. //如同判断SD卡是否存在或者文件是否存在,如果不存在则 return出去
  113. if (!root.exists()) {
  114. return -1;
  115. }
  116. //如果存在则获取当前目录下的全部文件 填充数组
  117. currentFiles = root.listFiles();
  118. //目标目录
  119. File targetDir = new File(toFile);
  120. //创建目录
  121. if (!targetDir.exists()) {
  122. targetDir.mkdirs();
  123. }
  124. //遍历要复制该目录下的全部文件
  125. for (int i = 0; i < currentFiles.length; i++) {
  126. if (currentFiles[i].isDirectory()) {
  127. //如果当前项为子目录 进行递归
  128. copy(currentFiles[i].getPath() + "/", toFile + currentFiles[i].getName() + "/");
  129. } else {
  130. //如果当前项为文件则进行文件拷贝
  131. if (currentFiles[i].getName().contains(".so")) {
  132. int id = copySdcardFile(currentFiles[i].getPath(), toFile + File.separator + currentFiles[i].getName());
  133. KLog.d(TAG, currentFiles[i].getName());
  134. }
  135. }
  136. }
  137. return 0;
  138. }
  139.  
  140. //文件拷贝
  141. //要复制的目录下的所有非子目录(文件夹)文件拷贝
  142. private static int copySdcardFile(String fromFile, String toFile) {
  143. try {
  144. FileInputStream fosfrom = new FileInputStream(fromFile);
  145. FileOutputStream fosto = new FileOutputStream(toFile);
  146. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  147. byte[] buffer = new byte[1024];
  148. int len = -1;
  149. while ((len = fosfrom.read(buffer)) != -1) {
  150. baos.write(buffer, 0, len);
  151. }
  152. // 从内存到写入到具体文件
  153. fosto.write(baos.toByteArray());
  154. // 关闭文件流
  155. baos.close();
  156. fosto.close();
  157. fosfrom.close();
  158. return 0;
  159. } catch (Exception ex) {
  160. return -1;
  161. }
  162. }
  163.  
  164. public interface LoadSoFileListener {
  165. void onSuccess();
  166.  
  167. void onError();
  168.  
  169. /**
  170. * 验证so
  171. *
  172. * @param loadSofile 需要验证的so
  173. */
  174. boolean compareSo(File... loadSofile);
  175. }
  176. }

  

动态加载sd卡或者手机内置存储卡的so库的更多相关文章

  1. Android加载SD卡目录,文件夹遍历,图片设置,设置文件对应打开方式等

    此案例主要说的是Android使用GridView加载SD卡下所有目录,文件夹多层遍历,文件图标修改,设置文件对应打开方式等功能. 如图: 代码: public class GridViewFile ...

  2. Android 操作手机内置存储卡中的文件

    场景:需要读取指定文件的内容,此文件是手动存储到手机内置存储卡中的,且手机上不存在SD卡. 对于android通过activity提供的openFileOutput和openFileInput可以直接 ...

  3. Android NDK加载SD卡中的so

    最近公司框架刚移植完成,由于框架程序要调用子程序,每个子程序都是一个so文件,有好几百个,把所有的so和apk打包不现实,及时可以升级维护也很麻烦.所以需要放SD卡中.考虑两种方式 1 放到设备中的 ...

  4. listview异步加载sd卡图片

    package com.example.gridview; import java.io.File; import java.io.FileOutputStream; import java.io.I ...

  5. 把外置sd卡映射为内置sd卡地一个目录

    教程:1.已root机器运行re浏览器2.在/sdcard卡上创建目录sd-ext3.找到/etc/rc.local,长按选编辑4.拉到文件最后,在最后一行exit 0前行添加:     (sleep ...

  6. Android 动态加载 (二) 态加载机制 案例二

    探秘腾讯Android手机游戏平台之不安装游戏APK直接启动法 重要说明 在实践的过程中大家都会发现资源引用的问题,这里重点声明两点: 1. 资源文件是不能直接inflate的,如果简单的话直接在程序 ...

  7. Android应用开发提高系列(4)——Android动态加载(上)——加载未安装APK中的类

    前言 近期做换肤功能,由于换肤程度较高,受限于平台本身,实现起来较复杂,暂时搁置了该功能,但也积累了一些经验,将分两篇文章来写这部分的内容,欢迎交流! 关键字:Android动态加载 声明 欢迎转载, ...

  8. android动态加载

    转载自: http://www.cnblogs.com/over140/archive/2012/03/29/2423116.html http://www.cnblogs.com/over140/a ...

  9. QEMU 运行uboot,动态加载内核与文件系统

    背景 上一讲我们完成了 编译 QEMU 以及简单地做了仿真.这一讲在 启动uboot 的基础上进行,以加强对于 运行地址,加载地址等理解. 有关资料: uboot 与 代码重定位 有这样的约定,ubo ...

随机推荐

  1. C++的函数重载与C参数个数不一致时的编译

    C++的函数重载意味着函数名和返回值类型相同,但是参数个数和/或类型不同.在编译过程中编译器一般会把各个参数的类型连接到函数名内组成新的函数名,以区分各个重载函数. C语言不支持函数重载.但是有时候虽 ...

  2. python2和python3中的range区别

    python2中的range返回的是一个列表 python3中的range返回的是一个迭代值 for i in range(1,10)在python2和python3中都可以使用,但是要生成1-10的 ...

  3. 三台主机搭建LAMP(apache、mariadb、php)

    实验环境:均是CentOS7 httpd:172.16.254.88   2.4.6 PHP:172.16.250.140 5.4.16 mariadb:172.16.250.94 5.5.52 第三 ...

  4. netstat -st输出解析(二)

    转自:http://perthcharles.github.io/2015/11/10/wiki-netstat-proc/ netstat -st输出的两个重要信息来源分别是/proc/net/sn ...

  5. plsql&nbsp;分页

     select * from (select rownum rn,ps.* from (select * from user_t) ps ) where rn>=1 and rn<=10 ...

  6. CodeForces 484A Bits(水题)

    A. Bits time limit per test 1 second memory limit per test 256 megabytes input standard input output ...

  7. c++控制台 对齐 域宽

    包含在头文件  iomanip 设置对齐: cout<<setiosflags(ios::xxx); xxx内填参数 left左对齐 right右对齐 setiosflags还有其他选项, ...

  8. 解决 Ajax 发送 post 请求出现 403 Forbidden 的三种方式

    众所周知前端向后台发送 post 请求时,必须验证 csrf,否则会报错 403 Forbidden.使用 Django Form 表单可以直接在表单里面添加 {% csrf_token %} 即可, ...

  9. 数据库路由中间件MyCat - 源代码篇(12)

    此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. NodeList ruleNodes = e.getElementsByTagName("rule ...

  10. Python 绘制你想要的数学函数图形

    Python 非常热门,但除非工作需要没有刻意去了解更多,直到有个函数图要绘制,想起了它.结果发现,完全用不着明白什么是编程,就可以使用它完成很多数学函数图的绘制. 通过以下两个步骤,就可以进行数学函 ...