动态加载sd卡或者手机内置存储卡的so库
package com.wsc.utils; import android.content.Context; import com.wsc.common.Entrance; import com.wsc.common.SDKCommon; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; /** * so库从sd卡拷贝到app的私有目录下,并进行比对验证和加载<p></p> * Created by win10-JYcainiao on 2018/1/24. */ public class LoadSoFileUtils { private static final String TAG = LoadSoFileUtils.class.getSimpleName(); /** * 加载 so 文件 * * @param context * @param soPath 下载到得sdcard目录 */ public static void loadSoFile(Context context, String soPath, LoadSoFileListener loadSoFileListener) throws Exception { if (Entrance.loacSo) { KLog.d(TAG, "so已经加载过了"); return; } //存放so文件的私有目录 File appLibs = context.getApplicationContext().getDir("libs", Context.MODE_PRIVATE); //需要加载的so文件 File soDir = new File(soPath); File[] soFiles = null; //获取so来源文件夹下的所有so文件 if (soDir.exists() && soDir.isDirectory()) { soFiles = soDir.listFiles(); } //看看需要加载的so文件 if (!soFileExisted(appLibs, soFiles) && soFiles != null) { copy(soPath, appLibs.getAbsolutePath()); } //获取app私有目录下的文件列表 File[] currentFiles = appLibs.listFiles(); if (!loadSoFileListener.compareSo(currentFiles)) { KLog.d(TAG, "so验证未通过"); loadSoFileListener.onError(); return; } //记录加载的so个数 int loacSoFileCount = 0; //根据so文件名称加载so文件 for (int i = 0; i < currentFiles.length; i++) { for (int j = 0; j < SDKCommon.soFileNames.length; j++) { if (currentFiles[i].getName().contains(SDKCommon.soFileNames[j])) { try { System.load(currentFiles[i].getAbsolutePath()); loacSoFileCount++; } catch (Exception e) { throw new Exception("加载so库失败,soName = " + currentFiles[i].getName()); } } } } //判断需要加载的so是否加载完全 if (loacSoFileCount == SDKCommon.soFileNames.length) { Entrance.loacSo = true; loadSoFileListener.onSuccess(); } else { loadSoFileListener.onError(); } } /** * 判断 so 文件是否存在 * * @param soFolder 需要存放so库的app私有文件夹 * @param soFiles 需要动态加载的so文件 * @return 需要加载的so文件是否存在 */ private static boolean soFileExisted(File soFolder, File... soFiles) { int count = 0; if (soFolder.exists()) { File[] files = soFolder.listFiles(); if (files != null && files.length > 0) { for (int i = 0; i < files.length; i++) { for (int j = 0; j < soFiles.length; j++) { if (files[i].getName().equals(soFiles[j].getName()) && files[i].length() == soFiles[j].length()) { count++; } } } } } if (count == 6) { return true; } return false; } /** * @param fromFile 指定的下载目录 * @param toFile 应用的包路径 * @return */ private static int copy(String fromFile, String toFile) { //要复制的文件目录 File[] currentFiles; File root = new File(fromFile); //如同判断SD卡是否存在或者文件是否存在,如果不存在则 return出去 if (!root.exists()) { return -1; } //如果存在则获取当前目录下的全部文件 填充数组 currentFiles = root.listFiles(); //目标目录 File targetDir = new File(toFile); //创建目录 if (!targetDir.exists()) { targetDir.mkdirs(); } //遍历要复制该目录下的全部文件 for (int i = 0; i < currentFiles.length; i++) { if (currentFiles[i].isDirectory()) { //如果当前项为子目录 进行递归 copy(currentFiles[i].getPath() + "/", toFile + currentFiles[i].getName() + "/"); } else { //如果当前项为文件则进行文件拷贝 if (currentFiles[i].getName().contains(".so")) { int id = copySdcardFile(currentFiles[i].getPath(), toFile + File.separator + currentFiles[i].getName()); KLog.d(TAG, currentFiles[i].getName()); } } } return 0; } //文件拷贝 //要复制的目录下的所有非子目录(文件夹)文件拷贝 private static int copySdcardFile(String fromFile, String toFile) { try { FileInputStream fosfrom = new FileInputStream(fromFile); FileOutputStream fosto = new FileOutputStream(toFile); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len = -1; while ((len = fosfrom.read(buffer)) != -1) { baos.write(buffer, 0, len); } // 从内存到写入到具体文件 fosto.write(baos.toByteArray()); // 关闭文件流 baos.close(); fosto.close(); fosfrom.close(); return 0; } catch (Exception ex) { return -1; } } public interface LoadSoFileListener { void onSuccess(); void onError(); /** * 验证so * * @param loadSofile 需要验证的so */ boolean compareSo(File... loadSofile); } }