插件加载带有动态库的apk时,会报UnsatisfiedLinkError找不到动态库的错误。
解决方法是在DexClassLoader中
dalvik.system.DexClassLoader.DexClassLoader(String dexPath, String optimizedDirectory, String libraryPath, ClassLoader parent)
第三个参数是指定动态库的路径,因此我们需要把动态库给解压出来放到data/data/xx(package),arm手机的t卡是加载不了
因此我需要找到对应的手机cpu类型,并解压对应的动态库,对应的代码如下:
private static boolean IsDirEquals(String srcfile,String objDir)
{
try{
int index = srcfile.lastIndexOf("/");
String dir = null;
String firstDirName = null;
if(index != -1)
dir = srcfile.substring(0,index );
index = srcfile.indexOf("/");
if(index != -1)
firstDirName = srcfile.substring(0, index);
if(null != dir && dir.equalsIgnoreCase(objDir))
{
return true;
}
else if(null != firstDirName && firstDirName.equalsIgnoreCase(objDir))
{
return true;
}
}catch(Exception e){
e.printStackTrace();
}
return false;
}
public static void UnzipSpecificFile(String zipFile, String targetDir,ArrayList<String> objDirList) {
int BUFFER = 4096; // 这里缓冲区我们使用4KB,
String strEntry; // 保存每个zip的条目名称
ZipInputStream zis = null;
try {
BufferedOutputStream dest = null; // 缓冲输出流
FileInputStream fis = new FileInputStream(zipFile);
zis = new ZipInputStream(new BufferedInputStream(fis));
ZipEntry entry; // 每个zip条目的实例
while ((entry = zis.getNextEntry()) != null) {
try {
// Log.i("Unzip: ","="+ entry);
int count;
byte data[] = new byte[BUFFER];
strEntry = entry.getName();
boolean find = false;
for(String dir:objDirList)
{
if(IsDirEquals(strEntry.toString(),dir))
{
find = true;
break;
}
}
if(false == find)
continue;
File entryFile = new File(targetDir + strEntry);
File entryDir = new File(entryFile.getParent());
if (!entryDir.exists()) {
entryDir.mkdirs();
}
FileOutputStream fos = new FileOutputStream(entryFile);
dest = new BufferedOutputStream(fos, BUFFER);
while ((count = zis.read(data, 0, BUFFER)) != -1) {
dest.write(data, 0, count);
}
dest.flush();
} catch (Exception ex) {
ex.printStackTrace();
} finally {
if (null != dest)
dest.close();
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != zis)
zis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
// 获取手机CPU类型信息
final static public String getCpuInfo() {
String str1 = "/proc/cpuinfo";
String str2 = "";
String[] cpuInfo = { "", "" }; // 1-cpu型号 //2-cpu频率
String[] arrayOfString;
FileReader fr = null;
BufferedReader localBufferedReader = null;
try {
fr = new FileReader(str1);
localBufferedReader = new BufferedReader(fr, 8192);
str2 = localBufferedReader.readLine();
arrayOfString = str2.split("\\s+");
for (int i = 2; i < arrayOfString.length; i++) {
cpuInfo[0] = cpuInfo[0] + arrayOfString[i] + " ";
}
str2 = localBufferedReader.readLine();
arrayOfString = str2.split("\\s+");
cpuInfo[1] += arrayOfString[2]; // cpu频率。
localBufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fr != null)
fr.close();
if (localBufferedReader != null)
localBufferedReader.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// Log.i(TAG, "cpuinfo:" + cpuInfo[0] + " " + cpuInfo[1]);
if ((cpuInfo[0].toLowerCase().contains("armv7"))) {
return "armeabi-v7a";
} else if ((cpuInfo[0].toLowerCase().contains("arm"))) {
return "armeabi";
} else if ((cpuInfo[0].toLowerCase().contains("mips"))) {
return "mips";
} else {
return "x86";
}
}
解压完lib/xxx(armeabi/armeabi-v7a等)放到对应的目录,并使用
System.loadLibrary
来加载动态库就ok了,其中这个方法会根据之前的classLoader传入的路径去查找文件。
后面找lib库貌似有点多余,应该只需要找到apk的lib文件夹就可以避免枚举整个apk文件,这个是后面需要改进的方向。