Android Gradle 插件 DiscardFilePlugin(清空类和方法) An android gradle plugin for discard class or method in compile time.
用于在编译构建时期忽略清空类和方法的一个Android Gradle插件。
Github: https://github.com/wangjiegulu/DiscardFilePlugin
1.1 使用场景 在实际的生产中,我们总是会在我们的app中增加一些调试的工具,比如在debug
模式下加入DebugPanelActivity
(调试面板工具页面,提供比如“切换服务器”等操作)。我们需要在正式上线的release版本中清空相关类和方法,或者修改boolean isProductionEnvironment()
方法,让它永远返回true
,以此来避免上线之后调试相关代码通过反编译等手段暴露出来。
1.2 @Discard
注解 1.2.1 Target
1.2.2 参数 1.2.2.1 apply
apply
参数规范:key==exceptValue
表示当key==exceptValue
时,Discard才会生效,才会真正在编译时去对方法或者类进行清空。因此可以在每个方法或者类中去进行不同的配置,在不同状态下通过如下方式对不同方法进行Discard:
1 2 3 4 5 6 7 8 9 @Discard (apply = "test1==true" )public void testMethod_1 () { System.out.println("testMethod_1..." ); } @Discard (apply = "test2==true" )public void testMethod_2 () { System.out.println("testMethod_2..." ); }
使用gradle assembleDebug -Ptest1=true -Ptest2=false
来构建时,testMethod_1()
方法会被discard,而testMethod_2()
不会被discard。构建完毕反编译class结果如下:
1 2 3 4 5 6 7 8 @Discard (apply = "test1==true" )public void testMethod_1 () {} @Discard (apply = "test2==true" )public void testMethod_2 () { System.out.println("testMethod_2..." ); }
1.2.2.2 srcCode
替换方法的方法体,如果不设置,默认discard方法实现:
返回类型为void
: discard后方法体为{}
返回类型为原始数据类型:discard后方法返回默认值,比如{ return 0; }
返回类型为类对象时: discard后方法返回为{ return null; }
可以如下填写具体的方法体代码块:
1 2 3 4 5 6 7 8 @Discard (srcCode = "{super.onCreate($1); System.out.println(\"this: \" + $0);}" ) protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); usernameEt = (EditText) findViewById(R.id.activity_main_username_et); passwordEt = (EditText) findViewById(R.id.activity_main_password_et); setTestAccount(); }
discard之后的class反编译代码如下:
1 2 3 4 5 6 7 @Discard ( srcCode = "{super.onCreate($1); System.out.println(\"this: \" + $0);}" ) protected void onCreate (Bundle var1) { super .onCreate(var1); System.out.println("this: " + this ); }
方法的$0
表示当前对象this
,方法参数依次为$1, $2, $3...
,详细文档参考这里
1.2.2.3 makeClassNames
可以在这里指定具体的类名,在discard时对未在classPath的类进行make。不常用,可以省略。
1.2.2.4 enable
表示该方法或者类的discard是否开启,默认为true
,比较典型的场景为,在类上面增加@Discard
对该类所有方法进行discard,但是需要某个方法不discard,这时可以使用@Discard(enable = false)
来对方法进行排除在discard
范围外。
1.3 使用方式 build.gradle
in Project:
1 2 3 4 5 6 7 8 9 10 11 buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:2.2.2' classpath 'com.github.wangjiegulu:discardfile:x.x.x' } }
build.gradle
in app
or library
:
1 2 3 4 5 apply plugin: 'com.github.wangjiegulu.plg.discardfile' dependencies { compile 'com.github.wangjiegulu:discardfile-api:x.x.x' }
1.3.1. build.gradle
1 2 3 4 5 6 7 8 apply plugin: 'com.github.wangjiegulu.plg.discardfile' discard { includePackagePath 'com.wangjie.plg.discardfile.sample.ui' , 'com.wangjie.plg.discardfile.sample.include' excludePackagePath 'com.wangjie.plg.discardfile.sample.exclude' }
1.3.2. 使用@Discard
注解 创建自定义apply配置(publish
和disable
两种apply配置):
1 2 3 4 5 6 7 8 9 10 public class ApplyConstants { public static class Publish { private static final String PUBLISH = "publish" ; public static final String _TRUE = PUBLISH + "==true" ; } public static class DISABLE { private static final String DISABLE = "disable" ; public static final String _TRUE = DISABLE + "==true" ; } }
在需要清空的类上添加@Discard
注解,apply = ApplyConstants.Publish._TRUE
表示只有在publish=true
的情况下,才会执行Discard。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 @Discard (apply = ApplyConstants.Publish._TRUE)public class IncludeClassC { public void onIncludeMethodC () { System.out.println("onIncludeMethodC..." ); } @Discard (apply = ApplyConstants.Publish._TRUE, srcCode = "{System.out.println(\"onIncludeMethodC_2... injected!\");}" ) public void onIncludeMethodC_2 () { System.out.println("onIncludeMethodC_2..." ); } @Discard (apply = ApplyConstants.Publish._TRUE, srcCode = "{return true;}" ) public boolean onIncludeMethodC_3 () { System.out.println("onIncludeMethodC_3..." ); return false ; } public int onIncludeMethodC_4 () { System.out.println("onIncludeMethodC_4..." ); return 100 ; } @Discard (apply = ApplyConstants.Publish._TRUE, enable = false ) public String onIncludeMethodC_5 () { System.out.println("onIncludeMethodC_5..." ); return "hello world" ; } @Discard (apply = ApplyConstants.Publish._TRUE, srcCode = "{return \"hello world injected!\";}" ) public String onIncludeMethodC_6 () { System.out.println("onIncludeMethodC_6..." ); return "hello world" ; } }
1.3.3. build运行 通过以下命令进行构建:
1 gradle clean assembleFullDebug -Ppublish=true -Pdisable=true
命令编译完成之后,该类的class
文件将会根据配置的@Discard
注解被自动修改成如下:
1 build/intermediates/transforms/discardFile/.../IncludeClassC.class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 @Discard ( apply = "publish==true" ) public class IncludeClassC { public IncludeClassC () { } public void onIncludeMethodC () { Object var10000 = null ; } @Discard ( apply = "publish==true" , srcCode = "{System.out.println(\"onIncludeMethodC_2... injected!\");}" ) public void onIncludeMethodC_2 () { System.out.println("onIncludeMethodC_2... injected!" ); } @Discard ( apply = "publish==true" , srcCode = "{return true;}" ) public boolean onIncludeMethodC_3 () { return true ; } public int onIncludeMethodC_4 () { return 0 ; } @Discard ( apply = "publish==true" , enable = false ) public String onIncludeMethodC_5 () { System.out.println("onIncludeMethodC_5..." ); return "hello world" ; } @Discard ( apply = "publish==true" , srcCode = "{return \"hello world injected!\";}" ) public String onIncludeMethodC_6 () { return "hello world injected!" ; } }