业务需求:web页面上传一个apk,java后端读取apk信息展现。
传统的读取apk方式:用zip解压读取AndroidManifest.xml中的配置信息。
上述读取方式不能适用于所有市面上的apk,遇到某些金融类等等apk需要用aapt工具才能读取。
linux下无法使用aapt.exe读取方式,估附带Linux安装aapt教程。
linux下载安装aapt工具
java整合aapt读取apk信息(直接贴代码了,只贴了业务需要的读取的apk信息,并非全部)
import com.skr.mdm.util.ReadApk;
import net.sf.json.JSONObject;
import java.io.*;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
public class AaptUtil {
private ProcessBuilder mBuilder;
private static final String SPLIT_REGEX = "(: )|(=')|(' )|'";
/**
* aapt所在的目录。
*/
private String mAaptPath = "src/main/java/com/xxx/xxx/utils/apk/aapt/aapt.exe";
public AaptUtil() {
if (System.getProperty("os.name").equals("Linux")) mAaptPath = "/usr/local/apktool/aapt" ;
mBuilder = new ProcessBuilder();
mBuilder.redirectErrorStream(true);
}
public static void main(String[] args) throws Exception {
System.out.println(JSONObject.fromObject(new AaptUtil().readApk("C:\\Users\\hx\\Desktop\\xxx.apk")).toString());
}
public Map<String, Object> readApk(String apkPath) throws Exception {
Map<String, Object> apkInfoMap = new HashMap<String, Object>();
return getApkInfo(apkInfoMap, apkPath);
}
/**
* 返回一个apk程序的信息。
*
* @param apkPath apk的路径。
* @return apkInfoMap 一个Apk的信息。
*/
public Map<String, Object> getApkInfo(Map<String, Object> apkInfoMap, String apkPath) throws Exception {
//通过命令调用aapt工具解析apk文件
Process process = mBuilder.command(mAaptPath, "d", "badging", apkPath).start();
InputStream is = null;
is = process.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is, "utf8"));
String tmp = br.readLine();
try {
if (tmp == null || !tmp.startsWith("package"))
throw new Exception("参数不正确,无法正常解析APK包。输出结果为:\n" + tmp + "...");
do {
setApkInfoProperty(apkInfoMap, tmp);
} while ((tmp = br.readLine()) != null);
return apkInfoMap;
} catch (Exception e) {
throw e;
} finally {
process.destroy();
closeIO(is);
closeIO(br);
}
}
/**
* 设置APK的属性信息。
*
* @param apkInfoMap
* @param source
*/
private void setApkInfoProperty(Map<String, Object> apkInfoMap, String source) {
if (source.startsWith("package")) splitPackageInfo(apkInfoMap, source);
}
/**
* 分离出包名、版本等信息。
*
* @param apkInfoMap
* @param packageSource
*/
private void splitPackageInfo(Map<String, Object> apkInfoMap, String packageSource) {
String[] packageInfo = packageSource.split(SPLIT_REGEX);
apkInfoMap.put("apkPackageName", packageInfo[2]) ;
apkInfoMap.put("versionCode", packageInfo[4]) ;
apkInfoMap.put("apkVersion", packageInfo[6]) ;
}
/**
* 释放资源。
*
* @param c 将关闭的资源
*/
private final void closeIO(Closeable c) {
if (c != null) {
try {
c.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}