1. 程式人生 > >java解析apk報錯 Expected chunk of type 0x80003, read 0x80001.

java解析apk報錯 Expected chunk of type 0x80003, read 0x80001.

業務需求: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();
            }
        }
    }
}