插件加载带有动态库so的apk处理

     插件加载带有动态库的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文件,这个是后面需要改进的方向。



你可能感兴趣的:(插件加载带有动态库so的apk处理)