Java环境解析apk文件信息
概述:Java解析apk文件,获取apk文件里的包名,版本号,图标文件等;
功能:可以提供给windows和linux平台使用;
原理:利用aapt.exe或者aapt这些anroid平台解析apk文件的工具,借用终端shell调用命令解析输出信息;
代码:
这里贴出一些关键代码,并给出代码注释,如下
- package com.apkutils;
- import java.io.BufferedReader;
- import java.io.Closeable;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.Properties;
- /**
- * apk工具类。封装了获取Apk信息的方法。
- *
- * @author @author tony
- *
- * <p>
- * <b>version description</b><br />
- * V0.2.1 修改程序名字为从路径中获得。
- * </p>
- */
- public class ApkUtil {
- public static final String VERSION_CODE = "versionCode";
- public static final String VERSION_NAME = "versionName";
- public static final String SDK_VERSION = "sdkVersion";
- public static final String TARGET_SDK_VERSION = "targetSdkVersion";
- public static final String USES_PERMISSION = "uses-permission";
- public static final String APPLICATION_LABEL = "application-label";
- public static final String APPLICATION_ICON = "application-icon";
- public static final String USES_FEATURE = "uses-feature";
- public static final String USES_IMPLIED_FEATURE = "uses-implied-feature";
- public static final String SUPPORTS_SCREENS = "supports-screens";
- public static final String SUPPORTS_ANY_DENSITY = "supports-any-density";
- public static final String DENSITIES = "densities";
- public static final String PACKAGE = "package";
- public static final String APPLICATION = "application:";
- public static final String LAUNCHABLE_ACTIVITY = "launchable-activity";
- // api ---- os
- static Map<String, String> OSVersion = new HashMap<String, String>();
- static {
- OSVersion.put("3", "1.5");
- OSVersion.put("4", "1.6");
- OSVersion.put("5", "2.0");
- OSVersion.put("6", "2.0.1");
- OSVersion.put("7", "2.1");
- OSVersion.put("8", "2.2");
- OSVersion.put("9", "2.3");
- OSVersion.put("10", "2.3.3");
- OSVersion.put("11", "3.0");
- OSVersion.put("12", "3.1");
- OSVersion.put("13", "3.2");
- OSVersion.put("14", "4.0");
- OSVersion.put("15", "4.0.3");
- OSVersion.put("16", "4.1.1");
- OSVersion.put("17", "4.2");
- OSVersion.put("18", "4.3");
- OSVersion.put("19", "4.4");
- }
- private static final String SPLIT_REGEX = "(: )|(=')|(' )|'";
- private static final String FEATURE_SPLIT_REGEX = "(:')|(',')|'";
- /**
- * aapt所在的目录。
- */
- private String mAaptPath = "D:\\App\\";//winOS
- //private String mAaptPath = ApkUtil.class.getClassLoader().getResource("").getPath();//linux
- static String[] shellCommand;
- static String softName = "";
- static {
- shellCommand = new String[2];
- final String anOSName = System.getProperty("os.name");
- if (anOSName.toLowerCase().startsWith("windows")) {
- // Windows XP, Vista ...
- shellCommand[0] = "cmd";
- shellCommand[1] = "/C";
- softName = "aapt.exe";
- } else {
- // Unix, Linux ...
- shellCommand[0] = "/bin/sh";
- shellCommand[1] = "-c";
- softName = "aapt";
- }
- }
- /***
- * apkPath
- */
- static String apkPath = "C:/Users/win7/Desktop/Android/baiduyinyue_49.apk";
- /**
- * 返回一个apk程序的信息。
- *
- * @param apkPath
- * apk的路径。
- * @return apkInfo 一个Apk的信息。
- */
- public ApkInfo getApkInfo(String apkPath) throws Exception {
- String command = mAaptPath + softName + " d badging \"" + apkPath
- + "\"";
- Process process;
- try {
- process = Runtime.getRuntime().exec(
- new String[] {shellCommand[0], shellCommand[1], command});
- } catch (IOException e) {
- process = null;
- throw e;
- }
- ApkInfo apkInfo = null;
- if(process != null){
- InputStream 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 + "...");
- }
- apkInfo = new ApkInfo();
- do {
- setApkInfoProperty(apkInfo, tmp);
- } while ((tmp = br.readLine()) != null);
- } catch (Exception e) {
- throw e;
- } finally {
- process.destroy();
- closeIO(is);
- closeIO(br);
- }
- }
- return apkInfo;
- }
- /**
- * 设置APK的属性信息。
- *
- * @param apkInfo
- * @param source
- */
- private void setApkInfoProperty(ApkInfo apkInfo, String source) {
- if (source.startsWith(PACKAGE)) {
- splitPackageInfo(apkInfo, source);
- } else if (source.startsWith(LAUNCHABLE_ACTIVITY)) {
- apkInfo.setLaunchableActivity(getPropertyInQuote(source));
- } else if (source.startsWith(SDK_VERSION)) {
- apkInfo.setSdkVersion(getPropertyInQuote(source));
- apkInfo.setMinOSVersion(OSVersion.get(getPropertyInQuote(source)));
- } else if (source.startsWith(TARGET_SDK_VERSION)) {
- apkInfo.setTargetSdkVersion(getPropertyInQuote(source));
- } else if (source.startsWith(USES_PERMISSION)) {
- apkInfo.addToUsesPermissions(getPropertyInQuote(source));
- } else if (source.startsWith(APPLICATION_LABEL)) {
- apkInfo.setApplicationLable(getPropertyInQuote(source));
- } else if (source.startsWith(APPLICATION_ICON)) {
- apkInfo.addToApplicationIcons(getKeyBeforeColon(source),
- getPropertyInQuote(source));
- } else if (source.startsWith(APPLICATION)) {
- String[] rs = source.split("( icon=')|'");
- apkInfo.setApplicationIcon(rs[rs.length - 1]);
- } else if (source.startsWith(USES_FEATURE)) {
- apkInfo.addToFeatures(getPropertyInQuote(source));
- } else if (source.startsWith(USES_IMPLIED_FEATURE)) {
- apkInfo.addToImpliedFeatures(getFeature(source));
- } else {
- }
- try {
- apkInfo.setApkFileSize(getFileSizes(new File(apkPath)));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- private ImpliedFeature getFeature(String source) {
- String[] result = source.split(FEATURE_SPLIT_REGEX);
- ImpliedFeature impliedFeature = new ImpliedFeature(result[1], result[2]);
- return impliedFeature;
- }
- /**
- * 返回出格式为name: 'value'中的value内容。
- *
- * @param source
- * @return
- */
- private String getPropertyInQuote(String source) {
- int index = source.indexOf("'") + 1;
- return source.substring(index, source.indexOf('\'', index));
- }
- /**
- * 返回冒号前的属性名称
- *
- * @param source
- * @return
- */
- private String getKeyBeforeColon(String source) {
- return source.substring(0, source.indexOf(':'));
- }
- /**
- * 分离出包名、版本等信息。
- *
- * @param apkInfo
- * @param packageSource
- */
- private void splitPackageInfo(ApkInfo apkInfo, String packageSource) {
- String[] packageInfo = packageSource.split(SPLIT_REGEX);
- apkInfo.setPackageName(packageInfo[2]);
- apkInfo.setVersionCode(packageInfo[4]);
- apkInfo.setVersionName(packageInfo[6]);
- }
- /**
- * 释放资源。
- *
- * @param c
- * 将关闭的资源
- */
- private final void closeIO(Closeable c) {
- if (c != null) {
- try {
- c.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- public static void main(String[] args) {
- try {
- ApkInfo apkInfo = new ApkUtil().getApkInfo(apkPath);
- System.out.println(apkInfo);
- IconUtil.extractFileFromApk(apkPath, apkInfo.getApplicationIcon(),
- "D:\\icon.png");
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- public String getmAaptPath() {
- return mAaptPath;
- }
- public void setmAaptPath(String mAaptPath) {
- this.mAaptPath = mAaptPath;
- }
- // 取得文件大小
- public static long getFileSizes(File f) throws Exception {
- long s = 0;
- if (f.exists()) {
- FileInputStream fis = null;
- fis = new FileInputStream(f);
- s = fis.available();
- } else {
- System.out.println("文件不存在");
- }
- return s;
- }
- }
上面加上阴影的部分代码,我想基本都是很好理解的,获取当前运行的操作系统类型,适配上相应的指令和软件,这样可以跨平台操作,而不需要修改代码;
获取到相应软件后,对apk文件一行一行的进行解析,将相应的属性存到javaBean中,并将apk文件图片通过流的方式写出到文件系统中,
- package com.apkutils;
- import java.io.BufferedInputStream;
- import java.io.BufferedOutputStream;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.util.zip.ZipEntry;
- import java.util.zip.ZipFile;
- /**
- * 通过ApkInfo 里的applicationIcon从APK里解压出icon图片并存放到磁盘上
- * @author @author tony
- */
- public class IconUtil {
- /**
- * 从指定的apk文件里获取指定file的流
- * @param apkpath
- * @param fileName
- * @return
- */
- public static InputStream extractFileFromApk(String apkpath, String fileName) {
- try {
- ZipFile zFile = new ZipFile(apkpath);
- ZipEntry entry = zFile.getEntry(fileName);
- entry.getComment();
- entry.getCompressedSize();
- entry.getCrc();
- entry.isDirectory();
- entry.getSize();
- entry.getMethod();
- InputStream stream = zFile.getInputStream(entry);
- return stream;
- } catch (IOException e) {
- e.printStackTrace();
- }
- return null;
- }
- public static void extractFileFromApk(String apkpath, String fileName, String outputPath) throws Exception {
- InputStream is = extractFileFromApk(apkpath, fileName);
- File file = new File(outputPath);
- BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file), 1024);
- byte[] b = new byte[1024];
- BufferedInputStream bis = new BufferedInputStream(is, 1024);
- while(bis.read(b) != -1){
- bos.write(b);
- }
- bos.flush();
- is.close();
- bis.close();
- bos.close();
- }
- }
这里没什么好说的,就是用JavaIO中zip的方式解析文件,并拿出图标写出到指定文件目录
参考文献 :
纯java从apk文件里获取包名、版本号、icon
Java环境解析apk文件信息的更多相关文章
- c# 借助cmd命令解析apk文件信息
借助aapt.exe文件 aapt.exe 解析apk包信息cmd命令: aapt dump badging *.apkaapt d badging *.apk >1.txt(保存成1.txt文 ...
- JAVA简便解析json文件
JAVA简便解析json文件 首先放上我要解析的json文件: { "resultcode":"200", "reason":"S ...
- Java jdom解析xml文件带冒号的属性
Java jdom解析xml文件带冒号的属性 转载请标明出处: https://dujinyang.blog.csdn.net/article/details/99644824 本文出自:[奥特曼超人 ...
- c#调用aapt查看apk文件信息功能实现
第一篇随笔就此开始. 1. 起源 思路源自于项目开发过程中.需要确认apk文件版本以验证其功能差异以便于定位问题,于是度娘,得到APK信息查看器(APK-info)这个工具,其版本号为0.2.它能显示 ...
- 【Android】获取手机中已安装apk文件信息(PackageInfo、ResolveInfo)(应用图片、应用名、包名等)
众所周知,通过PackageManager可以获取手机端已安装的apk文件的信息,具体代码如下 PackageManager packageManager = this.getPackageManag ...
- java opencsv解析csv文件
记一次使用opencsv解析csv文件时碰到的坑 最近在开发过程中需要解析csv文件,公司用的解析工具是opencsv,在根据opencsv的官方文档去解析时发现csv文件中含有繁体字,使用其自带的C ...
- Java(Android)解析KML文件
參考自:http://blog.csdn.net/yyywyr/article/details/38359049 http://blog.csdn.net/warrenwyf/article/deta ...
- 获取手机中已安装apk文件信息(PackageInfo、ResolveInfo)(应用图片、应用名、包名等)
众所周知,通过PackageManager可以获取手机端已安装的apk文件的信息,具体代码如下: PackageManager packageManager = this.getPackageMana ...
- python解析json文件信息到csv中
json格式多种多样,本代码着重看函数部分 import json, csv, os import pandas as pd josns_root = 'jsons' csvs_root = 'csv ...
随机推荐
- 通过设置虚拟机(ubantu15.10)的分辨率达到全屏效果
最近搭建了一个ubantu 15.10虚拟机,怎么折腾都不能全屏显示.虽然我已经点了, 还是无法达到真正的全屏. 查了一下,http://jingyan.baidu.com/article/0964 ...
- centos性能监控系列一:常用监控命令
Linux系统出现问题时,我们不仅需要查看系统日志信息,而且还要使用大量的性能监测工具来判断究竟是哪一部分(内存.CPU.硬盘--)出了问题 下面就让我们了解一下这些常用的性能监控工具. 1.upti ...
- MySQL之ALTER
1:删除列 ALTER TABLE [表名字] DROP [列名称] 2:增加列 ALTER TABLE [表名字] ADD [列名称] INT NOT NULL COMMENT '注释说明' 3:修 ...
- cd dirname $0
这个命令的功能是返回脚本正在执行的目录. 可以根据这个目录来定位运行的程序的相对位置. 这样,对shell脚本里面的相对目录的路径代码就比较安全了.在任何一台服务器上面都可以安全执行.
- ThinkPHP 获取get post参数与I方法
传统方式获取变量 $id = $_GET['id']; // 获取get变量 $name = $_POST['name']; // 获取post变量 $value = $_SESSION['var'] ...
- 烂泥:LVM学习之KVM利用LVM快照备份与恢复虚拟机
本文由秀依林枫提供友情赞助,首发于烂泥行天下. 最近一段时间一直在学习有关LVM逻辑卷方面的知识,前几篇文章介绍了有关LVM的逻辑卷的基本相关知识,包括逻辑卷及卷组的扩容与缩小.今天我们再来介绍LVM ...
- 关于google电子地图跟卫星地图位置不重合
再做项目时,用到了google地图的显示位置,就是在网页上插入事物在地图上的位置,点击卫星地图跟电子地图时发现不是重合,网上GOOGLE了下,说是加密的问题给偏移了500米左右,用google测量工具 ...
- leetcode抽风的解决办法
添加hosts: 173.230.148.103 oj.leetcode.com173.230.148.103 leetcode.com
- 广搜+输出路径 POJ 3414 Pots
POJ 3414 Pots Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 13547 Accepted: 5718 ...
- 内网穿透利器 Ngrok 使用教程
ngrok 服务可以分配给你一个域名让你本地的web项目提供给外网访问,特别适合向别人展示你本机的web demo 以及调试一些远程的API (比如微信公众号,企业号的开发) 下面开始教程 Step ...