您现在的位置是:首页 > 正文

java读取apk、ipa包名、版本名、版本号等信息

2024-02-01 02:19:48阅读 4

下载相关jar

首先我们需要下载两个jar,分别为:AXmlResourceParser.jar、dd-plist-1.0.jar
下载地址:https://download.csdn.net/download/qq_35309973/11905588

工具类

新建一个工具类,代码如下:

import java.io.*;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;

import com.dd.plist.NSArray;
import org.apkinfo.api.util.AXmlResourceParser;
import org.apkinfo.api.util.TypedValue;
import org.apkinfo.api.util.XmlPullParser;

import com.dd.plist.NSDictionary;
import com.dd.plist.NSString;
import com.dd.plist.PropertyListParser;

/**
 * 【描 述】:读取apk、ipa信息工具类
 * 【环 境】:J2SE 1.8
 * 【详 细】:
 *
 * @author 
 * @version v1.0 2019年10月17日 新建
 * @since 2019年10月17日
 */
public class ReadApkUtil {
    /**
     * 读取apk
     *
     * @param apkUrl
     * @return
     */
    public static Map<String, Object> readAPK(String apkUrl) {
        ZipFile zipFile;
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            zipFile = new ZipFile(apkUrl);
            Enumeration<?> enumeration = zipFile.entries();
            ZipEntry zipEntry = null;
            while (enumeration.hasMoreElements()) {
                zipEntry = (ZipEntry) enumeration.nextElement();
                if (zipEntry.isDirectory()) {

                } else {
                    if ("androidmanifest.xml".equals(zipEntry.getName().toLowerCase())) {
                        AXmlResourceParser parser = new AXmlResourceParser();
                        parser.open(zipFile.getInputStream(zipEntry));
                        while (true) {
                            int type = parser.next();
                            if (type == XmlPullParser.END_DOCUMENT) {
                                break;
                            }
                            String name = parser.getName();
                            if (null != name && name.toLowerCase().equals("manifest")) {
                                for (int i = 0; i != parser.getAttributeCount(); i++) {
                                    if ("versionName".equals(parser.getAttributeName(i))) {
                                        String versionName = getAttributeValue(parser, i);
                                        if (null == versionName) {
                                            versionName = "";
                                        }
                                        map.put("versionName", versionName);
                                    } else if ("package".equals(parser.getAttributeName(i))) {
                                        String packageName = getAttributeValue(parser, i);
                                        if (null == packageName) {
                                            packageName = "";
                                        }
                                        map.put("package", packageName);
                                    } else if ("versionCode".equals(parser.getAttributeName(i))) {
                                        String versionCode = getAttributeValue(parser, i);
                                        if (null == versionCode) {
                                            versionCode = "";
                                        }
                                        map.put("versionCode", versionCode);
                                    }
                                }
                                break;
                            }
                        }
                    }

                }
            }
            zipFile.close();
        } catch (Exception e) {
            map.put("code", "fail");
            map.put("error", "读取apk失败");
        }
        return map;
    }

    private static String getAttributeValue(AXmlResourceParser parser, int index) {
        int type = parser.getAttributeValueType(index);
        int data = parser.getAttributeValueData(index);
        if (type == TypedValue.TYPE_STRING) {
            return parser.getAttributeValue(index);
        }
        if (type == TypedValue.TYPE_ATTRIBUTE) {
            return String.format("?%s%08X", getPackage(data), data);
        }
        if (type == TypedValue.TYPE_REFERENCE) {
            return String.format("@%s%08X", getPackage(data), data);
        }
        if (type == TypedValue.TYPE_FLOAT) {
            return String.valueOf(Float.intBitsToFloat(data));
        }
        if (type == TypedValue.TYPE_INT_HEX) {
            return String.format("0x%08X", data);
        }
        if (type == TypedValue.TYPE_INT_BOOLEAN) {
            return data != 0 ? "true" : "false";
        }
        if (type == TypedValue.TYPE_DIMENSION) {
            return Float.toString(complexToFloat(data)) + DIMENSION_UNITS[data & TypedValue.COMPLEX_UNIT_MASK];
        }
        if (type == TypedValue.TYPE_FRACTION) {
            return Float.toString(complexToFloat(data)) + FRACTION_UNITS[data & TypedValue.COMPLEX_UNIT_MASK];
        }
        if (type >= TypedValue.TYPE_FIRST_COLOR_INT && type <= TypedValue.TYPE_LAST_COLOR_INT) {
            return String.format("#%08X", data);
        }
        if (type >= TypedValue.TYPE_FIRST_INT && type <= TypedValue.TYPE_LAST_INT) {
            return String.valueOf(data);
        }
        return String.format("<0x%X, type 0x%02X>", data, type);
    }

    private static String getPackage(int id) {
        if (id >>> 24 == 1) {
            return "android:";
        }
        return "";
    }

    // / ILLEGAL STUFF, DONT LOOK :)
    public static float complexToFloat(int complex) {
        return (float) (complex & 0xFFFFFF00) * RADIX_MULTS[(complex >> 4) & 3];
    }

    private static final float RADIX_MULTS[] =
            {
                    0.00390625F, 3.051758E-005F,
                    1.192093E-007F, 4.656613E-010F
            };
    private static final String DIMENSION_UNITS[] = {"px", "dip", "sp", "pt", "in", "mm", "", ""};
    private static final String FRACTION_UNITS[] = {"%", "%p", "", "", "", "", "", ""};

    /**
     * 读取ipa
     */
    public static Map<String, Object> readIPA(String ipaURL) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            File file = new File(ipaURL);
            InputStream is = new FileInputStream(file);
            InputStream is2 = new FileInputStream(file);
            ZipInputStream zipIns = new ZipInputStream(is);
            ZipInputStream zipIns2 = new ZipInputStream(is2);
            ZipEntry ze;
            ZipEntry ze2;
            InputStream infoIs = null;
            NSDictionary rootDict = null;
            String icon = null;
            while ((ze = zipIns.getNextEntry()) != null) {
                if (!ze.isDirectory()) {
                    String name = ze.getName();
                    if (null != name &&
                            name.toLowerCase().contains(".app/info.plist")) {
                        ByteArrayOutputStream _copy = new
                                ByteArrayOutputStream();
                        int chunk = 0;
                        byte[] data = new byte[1024];
                        while (-1 != (chunk = zipIns.read(data))) {
                            _copy.write(data, 0, chunk);
                        }
                        infoIs = new ByteArrayInputStream(_copy.toByteArray());
                        rootDict = (NSDictionary) PropertyListParser.parse(infoIs);

                        //我们可以根据info.plist结构获取任意我们需要的东西
                        //比如下面我获取图标名称,图标的目录结构请下面图片
                        //获取图标名称
                        NSDictionary iconDict = (NSDictionary) rootDict.get("CFBundleIcons");

                        while (null != iconDict) {
                            if (iconDict.containsKey("CFBundlePrimaryIcon")) {
                                NSDictionary CFBundlePrimaryIcon = (NSDictionary) iconDict.get("CFBundlePrimaryIcon");
                                if (CFBundlePrimaryIcon.containsKey("CFBundleIconFiles")) {
                                    NSArray CFBundleIconFiles = (NSArray) CFBundlePrimaryIcon.get("CFBundleIconFiles");
                                    icon = CFBundleIconFiles.getArray()[0].toString();
                                    if (icon.contains(".png")) {
                                        icon = icon.replace(".png", "");
                                    }
                                    System.out.println("获取icon名称:" + icon);
                                    break;
                                }
                            }
                        }
                        break;
                    }
                }
            }

            //根据图标名称下载图标文件到指定位置
            while ((ze2 = zipIns2.getNextEntry()) != null) {
                if (!ze2.isDirectory()) {
                    String name = ze2.getName();
                    System.out.println(name);
                    if (name.contains(icon.trim())) {
                        System.out.println(11111);
                        FileOutputStream fos = new FileOutputStream(new File("E:\\python\\img\\icon.png"));
                        int chunk = 0;
                        byte[] data = new byte[1024];
                        while (-1 != (chunk = zipIns2.read(data))) {
                            fos.write(data, 0, chunk);
                        }
                        fos.close();
                        break;
                    }
                }
            }

            
            //如果想要查看有哪些key ,可以把下面注释放开
//            for (String keyName : rootDict.allKeys()) {
//				System.out.println(keyName + ":" + rootDict.get(keyName).toString());
//			  }


            // 应用包名
            NSString parameters = (NSString) rootDict.get("CFBundleIdentifier");
            map.put("package", parameters.toString());
            // 应用版本名
            parameters = (NSString) rootDict.objectForKey("CFBundleShortVersionString");
            map.put("versionName", parameters.toString());
            //应用版本号
            parameters = (NSString) rootDict.get("CFBundleVersion");
            map.put("versionCode", parameters.toString());

            /
            infoIs.close();
            is.close();
            zipIns.close();

        } catch (Exception e) {
            map.put("code", "fail");
            map.put("error", "读取ipa文件失败");
        }
        return map;
    }


    /**
     * 获取文件md5值
     *
     * @param path
     * @return
     */
    public static String getMD5Three(String path) {
        BigInteger bi = null;
        try {
            byte[] buffer = new byte[8192];
            int len = 0;
            MessageDigest md = MessageDigest.getInstance("MD5");
            File f = new File(path);
            FileInputStream fis = new FileInputStream(f);
            while ((len = fis.read(buffer)) != -1) {
                md.update(buffer, 0, len);
            }
            fis.close();
            byte[] b = md.digest();
            bi = new BigInteger(1, b);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bi.toString(16);
    }


    /**
     * 获得指定文件的byte数组
     */
    public static byte[] getBytes(String filePath) {
        byte[] buffer = null;
        try {
            File file = new File(filePath);
            FileInputStream fis = new FileInputStream(file);
            ByteArrayOutputStream bos = new ByteArrayOutputStream(1000);
            byte[] b = new byte[1000];
            int n;
            while ((n = fis.read(b)) != -1) {
                bos.write(b, 0, n);
            }
            fis.close();
            bos.close();
            buffer = bos.toByteArray();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return buffer;
    }

    /**
     * 根据byte数组,生成文件
     */
    public static void getFile(byte[] bfile, String filePath, String fileName) {
        BufferedOutputStream bos = null;
        FileOutputStream fos = null;
        File file = null;
        try {
            File dir = new File(filePath);
            //判断文件目录是否存在
            if (!dir.exists() && dir.isDirectory()) {
                dir.mkdirs();
            }
            file = new File(filePath + "\\" + fileName);
            fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
            bos.write(bfile);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }


    public static void main(String[] args) {
        System.out.println("======apk=========");
        String apkUrl = "F:\\NetDisk.apk";
        Map<String, Object> mapApk = ReadApkUtil.readAPK(apkUrl);
        for (String key : mapApk.keySet()) {
            System.out.println(key + ":" + mapApk.get(key));
        }

        String md5 = ReadApkUtil.getMD5Three(apkUrl);
        System.out.println("md5:" + md5);

        byte[] apkByte = ReadApkUtil.getBytes(apkUrl);

        System.out.println("======ipa==========");
        /*String ipaUrl = "src/IM.ipa";
        Map<String, Object> mapIpa = ReadApkUtil.readIPA(ipaUrl);
        for (String key : mapIpa.keySet()) {
            System.out.println(key + ":" + mapIpa.get(key));
        }*/
    }

网站文章

  • Nginx Rewrite规则

    #Nginx Rewrite规则#1.URL访问跳转,支持开发设计(页面跳转,兼容性开发,展示效果)#2.SEO优化#3.维护(后台维护,流量转发等)#4.安全#配置Syntax: rewrite regex replacement [flag];Default : ——Context:server,location,if#例:rewrite ^(.*)$/pages/mai...

    2024-02-01 02:19:20
  • 今天面了个腾讯拿98K出来的大佬,让我见识到什么是基础的天花板

    今天面了个腾讯拿98K出来的大佬,让我见识到什么是基础的天花板

    今天面了个腾讯拿98K出来的大佬,让我见识到什么是基础的天花板

    2024-02-01 02:19:12
  • linux中查看文件大小,以G为单位

    linux中查看文件大小,以G为单位

    linux中查看文件大小,以G为单位 ls -lh 查看某个单独文件的大小:du -sh hteafile.tar

    2024-02-01 02:19:05
  • module ‘cv2.cv2‘ has no attribute ‘xfeatures2d‘ 错误

    报错原因:该算法已经申请专利,开源OpenCV没有版权,新的OpenCV去掉了这个算法。解决方法:卸掉目前的包,安装3.4.2.16版本pip uninstall opencv-pythonpip i...

    2024-02-01 02:18:59
  • python多线程—终止子线程

    python多线程—终止子线程

    python如何终止子进程

    2024-02-01 02:18:30
  • 中间件---rabbitMQ学习笔记

    中间件---rabbitMQ学习笔记

    1、中间件是什么?中间件是介于应用系统和系统软件之间的一类软件,它使用系统软件所提供的基础服务(功能),衔接网络上应用系统的各个部分或不同的应用,能够达到资源共享、功能共享的目的 。比如微服务,分布式...

    2024-02-01 02:18:23
  • python之__doc__

    十一 __doc__ 类的描述信息 class Foo: &#39;我是描述信息&#39; pass f = Foo() print(f.__doc__) # 打印描述信息, &#39;&#39;&#...

    2024-02-01 02:18:16
  • CentOS 8 更换yum国内源

    CentOS 8 更换yum国内源

    2024-02-01 02:17:47
  • javascript 数组的解构赋值

    右边不是数组(或者不是可遍历的解构,不具有lterator接口)Generator 函数(原生具有lterator接口)默认值可以使用解构赋值的其他变量,但该变量必须已经声明。),判断一个位置是否有值,只有当一个数组成员严格等于。之前,为变量赋值,只能直接指定值。解构赋值不成功,则变量的值等于。ES6内部使用严格相等(ES6 允许如下写法。

    2024-02-01 02:17:39
  • IoC 及 AOP 使用扩展

    IoC 及 AOP 使用扩展

    JOP与AOP 扩展以及JOP与AOP注解的使用。

    2024-02-01 02:17:33