纯java环境解析apk文件

纯java环境解析apk文件

前话

公司需要解析apk文件来获取部分信息,上网找了许久,不是不全,就是要加载applet.exe 或者需要积分下载,太难了,充钱太贵了。找了最后发现一篇不错,可以实际应用,分享给大家。

Maven依赖

<dependency>
			<groupId>net.dongliu</groupId>
			<artifactId>apk-parser</artifactId>
			<version>2.5.3</version>
		</dependency>

实战代码

import net.dongliu.apk.parser.ApkFile;
import net.dongliu.apk.parser.bean.ApkMeta;

import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;

/**
 * 	获取apk的包名、版本名、版本号、图标等信息
 */
public class ApkUtil {

    //  文件名称
    private static String name = "";
    //  apk的绝对地址
    private static String apk = "E:\\com.tencent.android.qqdownloader.apk";
    //  拷贝图标的存放位置
    private static String fileName = "E:\\" + name + ".png";


    public static void main(String[] args) {

        try {
            File file = new File(apk);

            if (file.exists() && file.isFile()) {
                ApkFile apkFile = new ApkFile(file);
                ApkMeta apkMeta = apkFile.getApkMeta();

                //  拷贝出的icon文件名 根据需要可以随便改
                name = apkMeta.getLabel();

                System.out.println("应用名称   :" + apkMeta.getLabel());
                System.out.println("包名       :" + apkMeta.getPackageName());
                System.out.println("版本号     :" + apkMeta.getVersionName());
                System.out.println("图标       :" + apkMeta.getIcon());
                System.out.println("大小       :" + (double) (file.length() * 100 / 1024 / 1024) / 100 + " MB");
                //  System.out.println("全部       :===============================");
                //  System.out.println(apkMeta.toString());

                //  拷贝图标
                saveBit(apkMeta.getIcon());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

	//  拷贝图标
    public static void saveBit(String Icon) throws IOException {
        ZipInputStream zin = null;

        try {
            //  访问apk 里面的文件
            ZipFile zf = new ZipFile(apk);
            InputStream in = new BufferedInputStream(new FileInputStream(apk));
            zin = new ZipInputStream(in);
            ZipEntry ze;
            while ((ze = zin.getNextEntry()) != null) {
                if (ze.getName().equals(Icon)) {
                    //  拷贝出图标
                    System.out.println("拷贝开始");
                    InputStream inStream = zf.getInputStream(ze);

                    ByteArrayOutputStream outStream = new ByteArrayOutputStream();
                    //创建一个Buffer字符串
                    byte[] buffer = new byte[1024];
                    //每次读取的字符串长度,如果为-1,代表全部读取完毕
                    int len = 0;
                    //使用一个输入流从buffer里把数据读取出来
                    while ((len = inStream.read(buffer)) != -1) {
                        //用输出流往buffer里写入数据,中间参数代表从哪个位置开始读,len代表读取的长度
                        outStream.write(buffer, 0, len);
                    }
                    //关闭输入流
                    inStream.close();
                    //把outStream里的数据写入内存

                    //得到图片的二进制数据,以二进制封装得到数据,具有通用性
                    byte[] data = outStream.toByteArray();
                    //new一个文件对象用来保存图片,默认保存当前工程根目录
                    File imageFile = new File(fileName);
                    //创建输出流
                    FileOutputStream fileOutStream = new FileOutputStream(imageFile);
                    //写入数据
                    fileOutStream.write(data);
                    System.out.println("拷贝结束");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            zin.closeEntry();
        }
    }
}

结果

在这里插入图片描述

原文引用:链接: https://blog.csdn.net/weixin_44653409/article/details/104376528

踩坑经历

按照上面的思路可以进行应用了,但是在获取信息后删除文件这一步出现了问题,通过不断的查找和网上查询终于找出了问题。
删除文件时,首先要确保流关闭了,并且文件存在,否者不能成功也不会报错。
我这里遇到是的Apkfile也是一个流需要关闭,还有字符流也需要关闭,上面的文档案例中都没有体现。

修改之后的
这里也将其变为了两个方法

public static ApkMeta findapkMeta(String url) {

        try {
            File file = new File(url);

            if (file.exists() && file.isFile()) {
                ApkFile apkFile = new ApkFile(file);
                ApkMeta apkMeta = apkFile.getApkMeta();
//                System.out.println("应用名称   :" + apkMeta.getLabel());
//                System.out.println("包名       :" + apkMeta.getPackageName());
//                System.out.println("版本号     :" + apkMeta.getVersionName());
//                System.out.println("图标       :" + apkMeta.getIcon());
//                System.out.println("大小       :" + (double) (file.length() * 100 / 1024 / 1024) / 100 + " MB");
//                  System.out.println("全部       :===============================");
//                 System.out.println(apkMeta.toString());
                //  拷贝图标
               // saveBit(apkMeta.getIcon());
                apkFile.close();
                return apkMeta;
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    //  拷贝图标
    public static Boolean saveBit(String Icon, String apk, String iconpath)  {
        ZipInputStream zin = null;
        boolean flag = true;
        try {
            //  访问apk 里面的文件
            ZipFile zf = new ZipFile(apk);
            InputStream in = new BufferedInputStream(new FileInputStream(apk));
            zin = new ZipInputStream(in);
            ZipEntry ze;
            while ((ze = zin.getNextEntry()) != null) {
                if (ze.getName().equals(Icon)) {
                    //  拷贝出图标
                   // System.out.println("拷贝开始");
                    InputStream inStream = zf.getInputStream(ze);

                    ByteArrayOutputStream outStream = new ByteArrayOutputStream();
                    //创建一个Buffer字符串
                    byte[] buffer = new byte[1024];
                    //每次读取的字符串长度,如果为-1,代表全部读取完毕
                    int len = 0;
                    //使用一个输入流从buffer里把数据读取出来
                    while ((len = inStream.read(buffer)) != -1) {
                        //用输出流往buffer里写入数据,中间参数代表从哪个位置开始读,len代表读取的长度
                        outStream.write(buffer, 0, len);
                    }
                    //关闭输入流
                    inStream.close();
                    //把outStream里的数据写入内存

                    //得到图片的二进制数据,以二进制封装得到数据,具有通用性
                    byte[] data = outStream.toByteArray();
                    //new一个文件对象用来保存图片,默认保存当前工程根目录
                    File imageFile = new File(iconpath);
                    //创建输出流
                    FileOutputStream fileOutStream = new FileOutputStream(imageFile);
                    //写入数据
                    fileOutStream.write(data);
                    // System.out.println("拷贝结束");
                    fileOutStream.close();
                    outStream.close();
                   flag =  FileRepository.upload("jmct_files/app/apk/", imageFile);
                }
            }
            in.close();
            zf.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                zin.close();
                flag  =  FileUtil.deleteFile(iconpath);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return  flag;
    }

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值