1 package com.apkutils;
2
3 import java.io.BufferedReader;
4 import java.io.Closeable;
5 import java.io.File;
6 import java.io.FileInputStream;
7 import java.io.IOException;
8 import java.io.InputStream;
9 import java.io.InputStreamReader;
10 import java.util.HashMap;
11 import java.util.Map;
12 import java.util.Properties; 16
13
14 /**
15 * apk工具类。封装了获取Apk信息的方法。
16 *
17 * @author @author tony
18 *
19 *
20 * version description
21 * V0.2.1 修改程序名字为从路径中获得。
22 *
23 */
24 public class ApkUtil {
25 public static final String VERSION_CODE = "versionCode";
26 public static final String VERSION_NAME = "versionName";
27 public static final String SDK_VERSION = "sdkVersion";
28 public static final String TARGET_SDK_VERSION = "targetSdkVersion";
29 public static final String USES_PERMISSION = "uses-permission";
30 public static final String APPLICATION_LABEL = "application-label";
31 public static final String APPLICATION_ICON = "application-icon";
32 public static final String USES_FEATURE = "uses-feature";
33 public static final String USES_IMPLIED_FEATURE = "uses-implied-feature";
34 public static final String SUPPORTS_SCREENS = "supports-screens";
35 public static final String SUPPORTS_ANY_DENSITY = "supports-any-density";
36 public static final String DENSITIES = "densities";
37 public static final String PACKAGE = "package";
38 public static final String APPLICATION = "application:";
39 public static final String LAUNCHABLE_ACTIVITY = "launchable-activity";
40
41 // api ---- os
42 static Map OSVersion = new HashMap();
43
44 static {
45 OSVersion.put("3", "1.5");
46 OSVersion.put("4", "1.6");
47 OSVersion.put("5", "2.0");
48 OSVersion.put("6", "2.0.1");
49 OSVersion.put("7", "2.1");
50 OSVersion.put("8", "2.2");
51 OSVersion.put("9", "2.3");
52 OSVersion.put("10", "2.3.3");
53 OSVersion.put("11", "3.0");
54 OSVersion.put("12", "3.1");
55 OSVersion.put("13", "3.2");
56 OSVersion.put("14", "4.0");
57 OSVersion.put("15", "4.0.3");
58 OSVersion.put("16", "4.1.1");
59 OSVersion.put("17", "4.2");
60 OSVersion.put("18", "4.3");
61 OSVersion.put("19", "4.4");
62 }
63
64 private static final String SPLIT_REGEX = "(: )|(=')|(' )|'";
65 private static final String FEATURE_SPLIT_REGEX = "(:')|(',')|'";
66 /**
67 * aapt所在的目录。
68 */
69 private String mAaptPath = "D:\\App\\";//winOS
70 //private String mAaptPath = ApkUtil.class.getClassLoader().getResource("").getPath();//linux
71
72 static String[] shellCommand;
73 static String softName = "";
74 static {
75 shellCommand = new String[2];
76 final String anOSName = System.getProperty("os.name");
77 if (anOSName.toLowerCase().startsWith("windows")) {
78 // Windows XP, Vista ...
79 shellCommand[0] = "cmd";
80 shellCommand[1] = "/C";
81 softName = "aapt.exe";
82 } else {
83 // Unix, Linux ...
84 shellCommand[0] = "/bin/sh";
85 shellCommand[1] = "-c";
86 softName = "aapt";
87 }
88 }
89
90 /***
91 * apkPath
92 */
93 static String apkPath = "C:/Users/win7/Desktop/Android/baiduyinyue_49.apk";
94
95 /**
96 * 返回一个apk程序的信息。
97 *
98 * @param apkPath
99 * apk的路径。
100 * @return apkInfo 一个Apk的信息。
101 */
102 public ApkInfo getApkInfo(String apkPath) throws Exception {
103 String command = mAaptPath + softName + "d badging \"" + apkPath
104 + "\"";
105 Process process;
106 try {
107 process = Runtime.getRuntime().exec(
108 new String[] {shellCommand[0], shellCommand[1], command});
109 } catch (IOException e) {
110 process = null;
111 throw e;
112 }
113
114 ApkInfo apkInfo = null;
115 if(process != null){
116 InputStream is = process.getInputStream();
117 BufferedReader br = new BufferedReader(
118 new InputStreamReader(is, "utf8"));
119 String tmp = br.readLine();
120 try {
121 if (tmp == null || !tmp.startsWith("package")) {
122 throw new Exception("参数不正确,无法正常解析APK包。输出结果为:\n" + tmp + "...");
123 }
124 apkInfo = new ApkInfo();
125 do {
126 setApkInfoProperty(apkInfo, tmp);
127 } while ((tmp = br.readLine()) != null);
128 } catch (Exception e) {
129 throw e;
130 } finally {
131 process.destroy();
132 closeIO(is);
133 closeIO(br);
134 }
135 }
136 return apkInfo;
137 }
138
139 /**
140 * 设置APK的属性信息。
141 *
142 * @param apkInfo
143 * @param source
144 */
145 private void setApkInfoProperty(ApkInfo apkInfo, String source) {
146 if (source.startsWith(PACKAGE)) {
147 splitPackageInfo(apkInfo, source);
148 } else if (source.startsWith(LAUNCHABLE_ACTIVITY)) {
149 apkInfo.setLaunchableActivity(getPropertyInQuote(source));
150 } else if (source.startsWith(SDK_VERSION)) {
151 apkInfo.setSdkVersion(getPropertyInQuote(source));
152 apkInfo.setMinOSVersion(OSVersion.get(getPropertyInQuote(source)));
153 } else if (source.startsWith(TARGET_SDK_VERSION)) {
154 apkInfo.setTargetSdkVersion(getPropertyInQuote(source));
155 } else if (source.startsWith(USES_PERMISSION)) {
156 apkInfo.addToUsesPermissions(getPropertyInQuote(source));
157 } else if (source.startsWith(APPLICATION_LABEL)) {
158 apkInfo.setApplicationLable(getPropertyInQuote(source));
159 } else if (source.startsWith(APPLICATION_ICON)) {
160 apkInfo.addToApplicationIcons(getKeyBeforeColon(source),
161 getPropertyInQuote(source));
162 } else if (source.startsWith(APPLICATION)) {
163 String[] rs = source.split("( icon=')|'");
164 apkInfo.setApplicationIcon(rs[rs.length - 1]);
165 } else if (source.startsWith(USES_FEATURE)) {
166 apkInfo.addToFeatures(getPropertyInQuote(source));
167 } else if (source.startsWith(USES_IMPLIED_FEATURE)) {
168 apkInfo.addToImpliedFeatures(getFeature(source));
169 } else {
170
171 }
172 try {
173 apkInfo.setApkFileSize(getFileSizes(new File(apkPath)));
174 } catch (Exception e) {
175 e.printStackTrace();
176 }
177 }
178
179 private ImpliedFeature getFeature(String source) {
180 String[] result = source.split(FEATURE_SPLIT_REGEX);
181 ImpliedFeature impliedFeature = new ImpliedFeature(result[1], result[2]);
182 return impliedFeature;
183 }
184
185 /**
186 * 返回出格式为name: 'value'中的value内容。
187 *
188 * @param source
189 * @return
190 */
191 private String getPropertyInQuote(String source) {
192 int index = source.indexOf("'") + 1;
193 return source.substring(index, source.indexOf('\'', index));
194 }
195
196 /**
197 * 返回冒号前的属性名称
198 *
199 * @param source
200 * @return
201 */
202 private String getKeyBeforeColon(String source) {
203 return source.substring(0, source.indexOf(':'));
204 }
205
206 /**
207 * 分离出包名、版本等信息。
208 *
209 * @param apkInfo
210 * @param packageSource
211 */
212 private void splitPackageInfo(ApkInfo apkInfo, String packageSource) {
213 String[] packageInfo = packageSource.split(SPLIT_REGEX);
214 apkInfo.setPackageName(packageInfo[2]);
215 apkInfo.setVersionCode(packageInfo[4]);
216 apkInfo.setVersionName(packageInfo[6]);
217 }
218
219 /**
220 * 释放资源。
221 *
222 * @param c
223 * 将关闭的资源
224 */
225 private final void closeIO(Closeable c) {
226 if (c != null) {
227 try {
228 c.close();
229 } catch (IOException e) {
230 e.printStackTrace();
231 }
232 }
233 }
234
235 public static void main(String[] args) {
236 try {
237 ApkInfo apkInfo = new ApkUtil().getApkInfo(apkPath);
238 System.out.println(apkInfo);
239 IconUtil.extractFileFromApk(apkPath, apkInfo.getApplicationIcon(),
240 "D:\\icon.png");
241 } catch (Exception e) {
242 e.printStackTrace();
243 }
244 }
245
246 public String getmAaptPath() {
247 return mAaptPath;
248 }
249
250 public void setmAaptPath(String mAaptPath) {
251 this.mAaptPath = mAaptPath;
252 }
253
254 // 取得文件大小
255 public static long getFileSizes(File f) throws Exception {
256 long s = 0;
257 if (f.exists()) {
258 FileInputStream fis = null;
259 fis = new FileInputStream(f);
260 s = fis.available();
261 } else {
262 System.out.println("文件不存在");
263 }
264 return s;
265 }
266 }