|
2 | 2 |
|
3 | 3 | 此插件用于做马甲包时,减小马甲包与主包的代码相似度,避免被某些应用市场识别为马甲包。 |
4 | 4 |
|
5 | | -### 使用方法 |
| 5 | +使用方法见[wiki](https://github.com/qq549631030/AndroidJunkCode/wiki) |
6 | 6 |
|
7 | | -根目录的build.gradle中: |
| 7 | +使用插件[methodCount](https://github.com/KeepSafe/dexcount-gradle-plugin)对比 |
8 | 8 |
|
9 | | -``` |
10 | | -buildscript { |
11 | | - repositories { |
12 | | - mavenCentral() |
13 | | - } |
14 | | - dependencies { |
15 | | - classpath "com.github.qq549631030:android-junk-code:x.x.x" //x.x.x换成最新的插件版本号 |
16 | | - } |
17 | | -} |
18 | | -``` |
19 | | - |
20 | | -app目录的build.gradle模块中: |
21 | | - |
22 | | -```groovy |
23 | | -apply plugin: 'com.android.application' |
24 | | -apply plugin: 'android-junk-code' |
25 | | -
|
26 | | -androidJunkCode { |
27 | | - variantConfig { |
28 | | - release { |
29 | | -//注意:这里的release是变体名称,如果没有设置productFlavors就是buildType名称,如果有设置productFlavors就是flavor+buildType,例如(freeRelease、proRelease) |
30 | | - packageBase = "cn.hx.plugin.ui" //生成java类根包名 |
31 | | - packageCount = 30 //生成包数量 |
32 | | - activityCountPerPackage = 3 //每个包下生成Activity类数量 |
33 | | - excludeActivityJavaFile = false |
34 | | - //是否排除生成Activity的Java文件,默认false(layout和写入AndroidManifest.xml还会执行),主要用于处理类似神策全埋点编译过慢问题 |
35 | | - otherCountPerPackage = 50 //每个包下生成其它类的数量 |
36 | | - methodCountPerClass = 20 //每个类下生成方法数量 |
37 | | - resPrefix = "junk_" //生成的layout、drawable、string等资源名前缀 |
38 | | - drawableCount = 300 //生成drawable资源数量 |
39 | | - stringCount = 300 //生成string数量 |
40 | | - } |
41 | | - } |
42 | | -} |
43 | | -``` |
44 | | - |
45 | | -**注:从1.3.1开始本库已经上传到Gradle Plugin Portal 可直接这样使用** |
46 | | - |
47 | | -```groovy |
48 | | -plugins { |
49 | | - //插件id和前面mavenCentral的不一样 |
50 | | - //开头是io.github不是com.github |
51 | | - id "io.github.qq549631030.android-junk-code" version "x.x.x" |
52 | | -} |
53 | | -
|
54 | | -androidJunkCode { |
55 | | - variantConfig { |
56 | | - release { |
57 | | - //... |
58 | | - } |
59 | | - } |
60 | | -} |
61 | | -``` |
62 | | - |
63 | | -如果有多个变体共用一个配置可以这样做 |
64 | | - |
65 | | -```groovy |
66 | | -androidJunkCode { |
67 | | - def config = { |
68 | | - packageBase = "cn.hx.plugin.ui" |
69 | | - packageCount = 30 |
70 | | - activityCountPerPackage = 3 |
71 | | - excludeActivityJavaFile = false |
72 | | - otherCountPerPackage = 50 |
73 | | - methodCountPerClass = 20 |
74 | | - resPrefix = "junk_" |
75 | | - drawableCount = 300 |
76 | | - stringCount = 300 |
77 | | - } |
78 | | - variantConfig { |
79 | | - //注意:这里的debug,release为变体名称,如果没有设置productFlavors就是buildType名称,如果有设置productFlavors就是flavor+buildType,例如(freeRelease、proRelease) |
80 | | - debug config |
81 | | - release config |
82 | | - } |
83 | | -} |
84 | | -``` |
85 | | - |
86 | | -如果APP开启了混淆,需要在混淆文件里配置 (1.3.1之后不需求配置) |
87 | | - |
88 | | -``` |
89 | | -#cn.hx.plugin.ui为前面配置的packageBase |
90 | | --keep class cn.hx.plugin.ui.** {*;} |
91 | | -``` |
92 | | - |
93 | | -**如果不想用插件默认生成的代码,可通过下面实现自定义。注意,修改生成方式后必须先clean再build才生效** |
94 | | - |
95 | | -```groovy |
96 | | -androidJunkCode { |
97 | | - variantConfig { |
98 | | - release { |
99 | | - packageBase = "cn.hx.plugin.ui" |
100 | | - packageCount = 30 |
101 | | - activityCountPerPackage = 30 |
102 | | - excludeActivityJavaFile = false |
103 | | - otherCountPerPackage = 50 |
104 | | - methodCountPerClass = 20 |
105 | | - resPrefix = "junk_" |
106 | | - drawableCount = 300 |
107 | | - stringCount = 300 |
108 | | -
|
109 | | - //自定义生成包名(设置此项后packageBase将无效) |
110 | | - //注意,要把生成的包名加入混淆文件 |
111 | | - packageCreator = { tuple2 -> |
112 | | - //int:下标 [0,packageCount) |
113 | | - def index = tuple2.first |
114 | | - //StringBuilder: 生成包名格式xx.xx.xx |
115 | | - def packageNameBuilder = tuple2.second |
116 | | - packageNameBuilder.append("cn.hx.package" + index) |
117 | | - } |
118 | | -
|
119 | | - /** |
120 | | - * 自定义生成Activity |
121 | | - */ |
122 | | - activityCreator = { tuple4 -> |
123 | | - //int:下标 [0,activityCountPerPackage) |
124 | | - def index = tuple4.first |
125 | | - //StringBuilder: 生成Activity文件名 |
126 | | - def activityNameBuilder = tuple4.second |
127 | | - //StringBuilder: 生成layout文件名 |
128 | | - def layoutNameBuilder = tuple4.third |
129 | | - //StringBuilder: 生成layout内容 |
130 | | - def layoutContentBuilder = tuple4.fourth |
131 | | -
|
132 | | - //例 |
133 | | - activityNameBuilder.append("Activity${index}") |
134 | | - layoutNameBuilder.append("activity_${index}") |
135 | | - layoutContentBuilder.append('''<?xml version="1.0" encoding="utf-8"?> |
136 | | -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
137 | | - android:layout_width="match_parent" |
138 | | - android:layout_height="match_parent" |
139 | | - android:orientation="vertical"> |
140 | | -
|
141 | | - <TextView |
142 | | - android:layout_width="wrap_content" |
143 | | - android:layout_height="wrap_content" |
144 | | - android:layout_gravity="center" /> |
145 | | -</LinearLayout>''') |
146 | | - } |
147 | | -
|
148 | | - //自定义生成类名(Activity除外) |
149 | | - classNameCreator = { tuple2 -> |
150 | | - //int:下标 [0,otherCountPerPackage) |
151 | | - def index = tuple2.first |
152 | | - //StringBuilder: 生成Java文件名 |
153 | | - def classNameBuilder = tuple2.second |
154 | | -
|
155 | | - //例 |
156 | | - classNameBuilder.append("Class${index}") |
157 | | - } |
158 | | -
|
159 | | - //自定义生成方法名 |
160 | | - methodNameCreator = { tuple2 -> |
161 | | - //int:下标 [0,methodCountPerClass) |
162 | | - def index = tuple2.first |
163 | | - //StringBuilder: 生成的方法名 |
164 | | - def classNameBuilder = tuple2.second |
165 | | -
|
166 | | - //例 |
167 | | - classNameBuilder.append("method${index}") |
168 | | - } |
169 | | -
|
170 | | - //自定义生成drawable(只支持xml) |
171 | | - drawableCreator = { tuple3 -> |
172 | | - //int:下标 [0,drawableCount) |
173 | | - def index = tuple3.first |
174 | | - //StringBuilder: 生成drawable文件名 |
175 | | - def fileNameBuilder = tuple3.second |
176 | | - //StringBuilder: 生成drawable文件内容 |
177 | | - def contentBuilder = tuple3.third |
178 | | -
|
179 | | - //例 |
180 | | - fileNameBuilder.append("drawable${index}") |
181 | | - contentBuilder.append('''<?xml version="1.0" encoding="utf-8"?> |
182 | | -<shape xmlns:android="http://schemas.android.com/apk/res/android"> |
183 | | - <corners android:radius="4dp" /> |
184 | | - <stroke |
185 | | - android:width="1dp" |
186 | | - android:color="#333333" /> |
187 | | -</shape> |
188 | | -''') |
189 | | - } |
190 | | -
|
191 | | - //自定义生成 string |
192 | | - stringCreator = { tuple3 -> |
193 | | - //int:下标 [0,drawableCount) |
194 | | - def index = tuple3.first |
195 | | - //StringBuilder: 生成string名 |
196 | | - def keyBuilder = tuple3.second |
197 | | - //StringBuilder: 生成string值 |
198 | | - def valueBuilder = tuple3.third |
199 | | -
|
200 | | - //例 |
201 | | - keyBuilder.append("string${index}") |
202 | | - valueBuilder.append("value${index}") |
203 | | - } |
204 | | -
|
205 | | - //自定义生成keep.xm |
206 | | - keepCreator = { tuple2 -> |
207 | | - //StringBuilder:生成文件名 |
208 | | - def fileNameBuilder = tuple2.first |
209 | | - //StringBuilder: 生成的文件内容 |
210 | | - def contentBuilder = tuple2.second |
211 | | -
|
212 | | - //例 |
213 | | - fileNameBuilder.append("android_junk_code_keep") |
214 | | - contentBuilder.append( "<resources xmlns:tools=\"http://schemas.android.com/tools\"\n" + |
215 | | - " tools:keep=\"@layout/junk_*, @drawable/junk_*\" />\n") |
216 | | - } |
217 | | -
|
218 | | - //自定义类实现(类名已经实现随机,Activity类已经实现了onCreate,其它自己实现随机) |
219 | | - //注意设置了此实现将忽略 methodGenerator,methodCountPerClass |
220 | | - //TypeSpec.Builder用法请参考(https://github.com/square/javapoet) |
221 | | -// typeGenerator = { typeBuilder -> |
222 | | -// //例 |
223 | | -// for (i in 0..<10) { |
224 | | -// typeBuilder.addMethod(MethodSpec.methodBuilder("method" + i) |
225 | | -// .addCode("" + "int total = 0;\n" + "for (int i = 0; i < 10; i++) {\n" + " total += i;\n" + "}\n") |
226 | | -// .build()) |
227 | | -// } |
228 | | -// } |
229 | | -
|
230 | | - //自定义方法实现(方法名已经实现随机,其它自己实现随机) |
231 | | - //MethodSpec.Builder用法请参考(https://github.com/square/javapoet) |
232 | | -// methodGenerator = { methodBuilder -> |
233 | | -// //例 |
234 | | -// methodBuilder.addCode("" + "int total = 0;\n" + "for (int i = 0; i < 10; i++) {\n" + " total += i;\n" + "}\n") |
235 | | -// } |
236 | | - } |
237 | | - } |
238 | | -} |
239 | | -``` |
240 | | - |
241 | | -如果所有代码生成都不想用插件来完成,可用如下实现。插件只负责把你生成的文件打进包里 |
242 | | - |
243 | | -```groovy |
244 | | -androidJunkCode { |
245 | | - variantConfig { |
246 | | - release { |
247 | | - javaGenerator = { javaDir -> |
248 | | - //File:java目录 |
249 | | - //把你生成的所有java文件放到这个目录下 |
250 | | - } |
251 | | - resGenerator = { resDir -> |
252 | | - //File:res目录 |
253 | | - //把你生成的所有资源文件放到这个目录下 |
254 | | - } |
255 | | -
|
256 | | - manifestGenerator = { manifestFile -> |
257 | | - //File:AndroidManifest.xml文件 |
258 | | - //把你生成的AndroidManifest.xml内容写入到这个文件 |
259 | | - } |
260 | | - } |
261 | | - } |
262 | | -} |
263 | | -``` |
264 | | - |
265 | | -### 打包 |
266 | | - |
267 | | -执行配置变体的打包命令:assembleXXX(XXX是你配置的变体,如:assembleRelease、assembleFreeRelease) |
268 | | - |
269 | | -### 生成文件所在目录 |
270 | | - |
271 | | -*AGP 7.4.0以前* |
272 | | -build/generated/source/junk |
273 | | - |
274 | | -*AGP 7.4.0以后 (XXX是你配置的变体首字母大写,如:Release、FreeRelease)* |
275 | | -build/generated/java/generateXXXJunkCode |
276 | | -build/generated/res/generateXXXJunkCode |
277 | | -build/generated/source/junk/XXX/AndroidManifest.xml |
278 | | - |
279 | | -### 使用插件[methodCount](https://github.com/KeepSafe/dexcount-gradle-plugin)对比 |
280 | | - |
281 | | -#### 未加垃圾代码 |
282 | | - |
283 | | -**项目代码占比 0.13%** |
284 | | - |
285 | | - |
286 | | - |
287 | | -#### 加了垃圾代码 |
288 | | - |
289 | | -**项目代码占比 52.93%** |
290 | | - |
291 | | - |
| 9 | +| | 方法总数 | 项目方法数 | |
| 10 | +| ----------------------------- |:--------------------------------:|:-----------------------------------:| |
| 11 | +| 未加垃圾代码<br/><br/>项目代码占比 0.13% |  |  | |
| 12 | +| 加了垃圾代码<br/><br/>项目代码占比 52.93% |  |  | |
292 | 13 |
|
293 | 14 | 安利我的两个新库: |
294 | 15 | [PriorityDialog](https://github.com/qq549631030/PriorityDialog)(带优先级对话框实现) |
|
0 commit comments