Skip to content

Commit 39a71a3

Browse files
authored
Add files via upload
1 parent 0fbc2e0 commit 39a71a3

File tree

3 files changed

+741
-0
lines changed

3 files changed

+741
-0
lines changed
Lines changed: 359 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,359 @@
1+
# coding = utf-8
2+
3+
"""
4+
https://github.com/Tencent/matrix/wiki/Matrix-ApkChecker#matrix-apkchecker-的使用
5+
6+
7+
APK Checker Usage
8+
9+
APK Checker can run independently in Jar (matrix-apk-canary-0.4.10.jar) mode, usage:
10+
11+
java -jar matrix-apk-canary-0.4.10.jar
12+
Usages:
13+
--config CONFIG-FILE-PATH
14+
or
15+
[--input INPUT-DIR-PATH] [--apk APK-FILE-PATH] [--unzip APK-UNZIP-PATH] [--mappingTxt MAPPING-FILE-PATH] [--resMappingTxt RESGUARD-MAPPING-FILE-PATH] [--output OUTPUT-PATH] [--format OUTPUT-FORMAT] [--formatJar OUTPUT-FORMAT-JAR] [--formatConfig OUTPUT-FORMAT-CONFIG (json-array format)] [Options]
16+
17+
Options:
18+
-manifest
19+
Read package info from the AndroidManifest.xml.
20+
-fileSize [--min DOWN-LIMIT-SIZE (KB)] [--order ORDER-BY ('asc'|'desc')] [--suffix FILTER-SUFFIX-LIST (split by ',')]
21+
Show files whose size exceed limit size in order.
22+
-countMethod [--group GROUP-BY ('class'|'package')]
23+
Count methods in dex file, output results group by class name or package name.
24+
-checkResProguard
25+
Check if the resguard was applied.
26+
-findNonAlphaPng [--min DOWN-LIMIT-SIZE (KB)]
27+
Find out the non-alpha png-format files whose size exceed limit size in desc order.
28+
-checkMultiLibrary
29+
Check if there are more than one library dir in the 'lib'.
30+
-uncompressedFile [--suffix FILTER-SUFFIX-LIST (split by ',')]
31+
Show uncompressed file types.
32+
-countR
33+
Count the R class.
34+
-duplicatedFile
35+
Find out the duplicated resource files in desc order.
36+
-checkMultiSTL --toolnm TOOL-NM-PATH
37+
Check if there are more than one shared library statically linked the STL.
38+
-unusedResources --rTxt R-TXT-FILE-PATH [--ignoreResources IGNORE-RESOURCES-LIST (split by ',')]
39+
Find out the unused resources.
40+
-unusedAssets [--ignoreAssets IGNORE-ASSETS-LIST (split by ',')]
41+
Find out the unused assets file.
42+
-unstrippedSo --toolnm TOOL-NM-PATH
43+
Find out the unstripped shared library file.
44+
45+
"""
46+
import os
47+
import json
48+
from time import sleep
49+
import matplotlib.pyplot as plt
50+
51+
"""
52+
53+
load_dict[0]: Unzip the apk file to current project path.
54+
load_dict[1]: Read package info from the AndroidManifest.xml.
55+
load_dict[2]: Check if the apk handled by resguard.
56+
load_dict[3]: Find out the non-alpha png-format files whose size exceed limit size in desc order.
57+
load_dict[4]: Show uncompressed file types.
58+
load_dict[5]: Find out the duplicated files.
59+
load_dict[6]: Find out the unused assets.
60+
load_dict[7]: Show files whose size exceed limit size in order.
61+
load_dict[8]: Count methods in dex file, output results group by class name or package name.
62+
load_dict[9]: Check if there are more than one library dir in the 'lib'.
63+
load_dict[10]: Count the R class.
64+
65+
66+
每项 Task 都是 load_dict{} 中的一个元素
67+
68+
task{"":1, "":2, ........"entries":[{}, {}, {}, .....]}
69+
70+
解析每一项 Task
71+
72+
"""
73+
74+
os.popen("/Users/william/PycharmProjects/System/Mobile/Android/Android_Package_Check/android_check.sh")
75+
76+
sleep(10)
77+
78+
79+
json_path = "/Users/william/PycharmProjects/System/Mobile/Android/Android_Package_Check/result/result.json"
80+
with open(json_path, 'r') \
81+
as load_f:
82+
83+
load_dict = json.load(load_f)
84+
85+
86+
# 读取manifest的信息:从AndroidManifest.xml文件中读取apk的全局信息,如packageName、versionCode等。
87+
def read_info():
88+
89+
return \
90+
load_dict[1]["taskDescription"], \
91+
load_dict[1]["start-time"], \
92+
load_dict[1]["end-time"], \
93+
load_dict[1]["manifest"]["package"], \
94+
load_dict[1]["manifest"]["android:minSdkVersion"], \
95+
load_dict[1]["manifest"]["android:targetSdkVersion"], \
96+
load_dict[1]["manifest"]["android:versionCode"], \
97+
load_dict[1]["manifest"]["android:versionName"]
98+
99+
100+
# 按文件大小排序列出apk中包含的文件:列出超过一定大小的文件,可按文件后缀过滤,并且按文件大小排序。
101+
def check_unzip():
102+
103+
unzip_package = []
104+
type_number = len(load_dict[0]["entries"])
105+
106+
for i in range(type_number):
107+
108+
# round(x/y, 2), 除法保留两位小数
109+
unzip_package.append("\n" + load_dict[0]["entries"][i]["suffix"]
110+
+ " == " +
111+
str(round(load_dict[0]["entries"][i]["total-size"]/1024, 3)) + "KB")
112+
113+
# print(unzip_package[i])
114+
115+
type_sum = "".join(unzip_package[0:])
116+
117+
# 画图
118+
file_name = []
119+
file_size = []
120+
121+
for i in range(type_number):
122+
123+
file_name.append(load_dict[0]["entries"][i]["suffix"])
124+
125+
for i in range(type_number):
126+
file_size.append(load_dict[0]["entries"][i]["total-size"])
127+
128+
new_file_name = [x + "\n" for x in file_name]
129+
130+
plt.figure(figsize=(14, 9))
131+
# explode = [0, 0.1, 0, 0] # 0.1 凸出这部分,
132+
plt.axes(aspect=1) # set this , Figure is round, otherwise it is an ellipse
133+
patches, l_text, p_text = plt.pie(
134+
x=file_size, labels=new_file_name, autopct='%3.1f %%',
135+
shadow=False, labeldistance=1.1, startangle=90, pctdistance=0.6)
136+
'''
137+
labeldistance,文本的位置离远点有多远,1.1指1.1倍半径的位置
138+
autopct,圆里面的文本格式,%3.1f%%表示小数有三位,整数有一位的浮点数
139+
shadow,饼是否有阴影
140+
startangle,起始角度,0,表示从0开始逆时针转,为第一块。一般选择从90度开始比较好看
141+
pctdistance,百分比的text离圆心的距离
142+
patches, l_texts, p_texts,为了得到饼图的返回值,p_texts饼图内部文本的,l_texts饼图外label的文本
143+
'''
144+
# 改变文本的大小,方法是把每一个text遍历。调用set_size方法设置它的属性
145+
for t in l_text:
146+
t.set_size = 70
147+
for t in p_text:
148+
t.set_size = 70
149+
# 设置x,y轴刻度一致,这样饼图才能是圆的
150+
plt.axis('equal')
151+
plt.legend()
152+
plt.savefig("/Users/william/PycharmProjects/System/Mobile/Android/Android_Package_Check/o.png")
153+
154+
return \
155+
load_dict[0]["taskDescription"], \
156+
load_dict[0]["start-time"], \
157+
load_dict[0]["end-time"], \
158+
str(round(load_dict[0]["total-size"]/1024/1024, 2)) + " " + "MB", \
159+
type_sum
160+
161+
162+
# 搜索不含alpha通道的png文件:对于不含alpha通道的png文件,可以转成jpg格式来减少文件的大小
163+
def find_non_alpha():
164+
165+
non_alpha = []
166+
files_number = len(load_dict[3]["files"])
167+
168+
for i in range(files_number):
169+
170+
non_alpha.append("\n\n" + load_dict[3]["files"][i]["entry-name"]
171+
+ " == " +
172+
str(round(load_dict[3]["files"][i]["entry-size"]/1024, 3)) + "KB")
173+
print(non_alpha[i])
174+
175+
files_sum = "".join(non_alpha[0:])
176+
177+
return \
178+
load_dict[3]["taskDescription"], \
179+
load_dict[3]["start-time"], \
180+
load_dict[3]["end-time"], \
181+
files_sum
182+
183+
184+
# 搜索未经压缩的文件类型:某个文件类型的所有文件都没有经过压缩,可以考虑是否需要压缩
185+
def show_uncompressed():
186+
187+
uncompressed = []
188+
files_number = len(load_dict[4]["files"])
189+
190+
for i in range(files_number):
191+
192+
uncompressed.append("\n\n" + load_dict[4]["files"][i]["suffix"]
193+
+ " == " +
194+
str(round(load_dict[4]["files"][i]["total-size"]/1024/1024, 3)) + "MB")
195+
print(uncompressed[i])
196+
197+
uncompressed_sum = "".join(uncompressed[0:])
198+
199+
return \
200+
load_dict[4]["taskDescription"], \
201+
load_dict[4]["start-time"], \
202+
load_dict[4]["end-time"], \
203+
uncompressed_sum
204+
205+
206+
# 搜索冗余的文件:对于两个内容完全相同的文件,应该去冗余
207+
def find_duplicated():
208+
209+
duplicated = []
210+
duplicated_sum_size = []
211+
duplicated_number = len(load_dict[5]["files"])
212+
size = 0
213+
214+
for i in range(duplicated_number):
215+
216+
duplicated.append("\n\n" + "MD5: " + load_dict[5]["files"][i]["md5"]
217+
+ "\nFile_Size: " +
218+
str(round(load_dict[5]["files"][i]["size"]/1024, 3))
219+
+ "KB" + "\n")
220+
duplicated_sum_size.append(load_dict[5]["files"][i]["size"])
221+
222+
size = size + duplicated_sum_size[i]
223+
224+
size = str(round(size/1024, 3)) + "KB"
225+
226+
files = []
227+
# 单独处理重复的文件路径
228+
for i in range(duplicated_number):
229+
230+
unit_path_sun = " ======>>> ".join(load_dict[5]["files"][i]["files"])
231+
232+
files.append(unit_path_sun)
233+
234+
duplicated_sum = []
235+
236+
for i in range(len(duplicated)):
237+
238+
duplicated_sum.append(duplicated[i] + files[i])
239+
240+
duplicated_sum_1 = "".join(duplicated_sum[0:])
241+
242+
return \
243+
load_dict[5]["taskDescription"], \
244+
load_dict[5]["start-time"], \
245+
load_dict[5]["end-time"], \
246+
duplicated_sum_1, \
247+
size
248+
249+
250+
# 按顺序显示大小超过限制大小的文件。
251+
def limit_file():
252+
253+
limit_ = []
254+
limit_number = len(load_dict[7]["files"])
255+
256+
for i in range(limit_number):
257+
258+
limit_.append("\n" + "Entry-name: " + load_dict[7]["files"][i]["entry-name"]
259+
+ "\nEntry_Size: " +
260+
str(round(load_dict[7]["files"][i]["entry-size"]/1024, 3))
261+
+ "KB" + "\n")
262+
263+
limit_sum = "".join(limit_[0:])
264+
265+
# print(limit_sum)
266+
267+
return \
268+
load_dict[7]["taskDescription"], \
269+
load_dict[7]["start-time"], \
270+
load_dict[7]["end-time"], \
271+
limit_sum
272+
273+
274+
# 统计方法数:统计dex包含的方法数,并支持将输出结果按照类名(class)或者包名(package)来分组.
275+
def method_count():
276+
277+
method = []
278+
method_number = len(load_dict[8]["groups"])
279+
280+
for i in range(method_number):
281+
method.append("\n" + "Name: " + load_dict[8]["groups"][i]["name"]
282+
+ "\nMethod-count: " +
283+
str(load_dict[8]["groups"][i]["method-count"]) + "\n")
284+
285+
method_sum = "".join(method[0:])
286+
# print(method_sum)
287+
288+
return \
289+
load_dict[8]["taskDescription"], \
290+
load_dict[8]["start-time"], \
291+
load_dict[8]["end-time"], \
292+
load_dict[8]["total-methods"], \
293+
method_sum
294+
295+
296+
# 检查是否包含多个ABI版本的动态库.
297+
def check_multilibrary():
298+
299+
multilibrary = []
300+
multilibrary_number = len(load_dict[9]["lib-dirs"])
301+
302+
for i in range(multilibrary_number):
303+
multilibrary.append("\n" + "lib-dirs: " + load_dict[9]["lib-dirs"][i] + "\n")
304+
305+
multilibrary_sum = "".join(multilibrary[0:])
306+
307+
print(multilibrary_sum)
308+
309+
return \
310+
load_dict[9]["taskDescription"], \
311+
load_dict[9]["start-time"], \
312+
load_dict[9]["end-time"], \
313+
load_dict[9]["multi-lib"], \
314+
multilibrary_sum
315+
316+
317+
# 统计apk中包含的R类以及R类中的field count:
318+
# 编译之后,代码中对资源的引用都会优化成int常量,除了R.styleable之外,其他的R类其实都可以删除
319+
def r_count():
320+
321+
r = []
322+
r_number = len(load_dict[10]["R-classes"])
323+
324+
for i in range(r_number):
325+
r.append("\n" + "Name: " + load_dict[10]["R-classes"][i]["name"]
326+
+ "\nR-classes: " +
327+
str(load_dict[10]["R-classes"][i]["field-count"]) + "\n")
328+
329+
r_sum = "".join(r[0:])
330+
331+
# print(r_sum)
332+
return \
333+
load_dict[10]["taskDescription"], \
334+
load_dict[10]["start-time"], \
335+
load_dict[10]["end-time"], \
336+
load_dict[10]["R-count"], \
337+
load_dict[10]["Field-counts"], \
338+
r_sum
339+
340+
341+
if __name__ == '__main__':
342+
343+
# check_unzip()
344+
345+
# read_info()
346+
347+
# find_non_alpha()
348+
349+
# show_uncompressed()
350+
351+
find_duplicated()
352+
353+
# limit_file()
354+
355+
# method_count()
356+
357+
# check_multilibrary()
358+
359+
# r_count()

0 commit comments

Comments
 (0)