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 ...
随机推荐
- opencms忘记Admin用户登录密码解决方案
不知道现在还有多少人在用opencms: 我今天就是遇到一个问题,很久之前部署的一台opencms服务器,突然忘记密码了,记录下处理方法: 希望对你有帮助: opencms忘记Admin用户登录密码了 ...
- 日常工作生活中的做人做事道理[持续更新ing]
1.凡是预则立,不预则废 2.不能用特殊案例说明事情本身的发展规律 3.任务不能拖,需主动出击,想方设法完成 4.工作要有细致化的沟通和安排 5.解决问题和安排任务可以逆向思维的去想 6.问题要举一反 ...
- 使用ExposedObject对Asp.net MVC中匿名类型的JsonResult做单元测试
返回JsonResult是MVC中的常见返回值类型,而且简单方便的方式是结合匿名类型一起使用. 比如: public ActionResult PreviewEmail() { …… return J ...
- JavaScript Patterns 3.8 Error Objects
The error objects created by constructors(Error(), SyntaxError(), TypeError(), and others) have the ...
- solr 导入数据
从sqlserver导入数据到solr, solr 采用的版本6.0.1,并且本机解压到:F:\Tool\solr-6.0.1: 1. 命令启动solr,创建core 启动,进入solr文件目录下,执 ...
- hibernate一对一关系实现
按照主键映射,按照外键映射 Address.hbm.xml: <?xml version="1.0"?><!DOCTYPE hibernate-mapping P ...
- python datetime模块用strftime 格式化时间
1 2 3 #!usr/bin/python import datetime datetime.datetime.now() 这个会返回 microsecond.因此这个是我们不需要的.所以得做一下修 ...
- ubuntu + hadoop2.5.2分布式环境配置
ubuntu + hadoop2.5.2分布式环境配置 我之前有详细写过hadoop-0.20.203.0rc1版本的环境搭建 hadoop学习笔记——环境搭建 http://www.cnblogs. ...
- history介绍及bash命令快速调用
在日常工作中,能够快速并准确的使用命令是必不可少的,下面为大家介绍一下其中的小技巧. 一.查找命令历史——history 使用history能够快速的找到之前输入过的命令. # history 大家可 ...
- cmd获取系统时间
查看时间格式: echo %date% echo %time% 通过%date:~5,2%来组合得出当前日期,组合的效果为yyyymmdd,date命令得到的日期格式默认为yyyy-mm-dd,通过% ...