最近刚到公司,发现公司没有一套完整的插件化的工具,于是准备研究一下。(毕竟能称得上大公司(阿里,360,滴滴等)的都在积极开源自己的插件化工具)。
本篇主要介绍我遇到的第一个坑:provided不支持android library。
在本篇之前建议先看下这篇
如果不了解gradle的插件怎么开发,还是先百度学习一下,再继续;
这里只介绍实现思路:
provoided:
provided并不是android build tool新添加的一个配置,这是在java的插件上就有的。它提供给我们一种依赖场景,可以使配置的依赖只编译不打包到最终程序中。android build tool沿用了这个配置,但是它对android library类型的依赖做了限制。每次用provided去配置一个android library的依赖的时候,都会报
Project %s: provided dependencies can only be jars. %s is an Android Library的错误。
仔细看下报错的代码,最后发现,报错是故意加进去的。我们把报错的代码去掉就可以了。同时把改lib配成optional为true。 然后,就没有然后了。对这么修改之后 ,provided就可以支持android library了。
修改是简单,但是不能直接改源代码把!能!但是这做不符合我们要开发一个插件的思路。所以我们不直接修改,我们利用反射机制,把需要修改的文件类给替换掉。下面我们开始具体操作:
下载com.android.tools.build:gradle:2.1.0的源码,找到报错对应的文件:
DependencyManager.java。
修改报错文件:
复制DependencyManager.java到自己的gradle插件中(建议:包名保持一致),重命名:
修改文件中报错的地方:
图片中灰色部分是原来的代码,红框内是修改后的内容。第一行打印可以随意,第二个lib.setIsOptional(true)是必须的,这么设置之后的lib都不会被打入最终的apk了。
替换报错文件对应的对象:
public void replaceTaskManager(){
AppPlugin appPlugin = project.getPlugins().findPlugin(AppPlugin.class);
if(null == appPlugin) return;
TaskManager taskManager = (TaskManager) ReflectUtils.getField(BasePlugin.class,appPlugin,"taskManager");
DependencyManager dependencyManager = (DependencyManager) ReflectUtils.getField(TaskManager.class,taskManager,"dependencyManager");
WhrDependencyManager newDependencyManager = new WhrDependencyManager(project,
(ExtraModelInfo) ReflectUtil.getField(dependencyManager,"extraModelInfo"));
ReflectUtils.updateField(TaskManager.class,taskManager,"dependencyManager",newDependencyManager);
}
其中ReflectUtils的代码:
public static Object getField(Class parentClazz,Object obj,String fieldName){
try {
Field t = parentClazz.getDeclaredField(fieldName);
t.setAccessible(true);
return t.get(obj);
} catch (NoSuchFieldException e) {
e.printStackTrace();
return null;
} catch (IllegalAccessException e) {
e.printStackTrace();
return null;
}
}
public static void updateField(Class parentClazz,Object obj,String fieldName,Object value){
try {
Field t = parentClazz.getDeclaredField(fieldName);
t.setAccessible(true);
t.set(obj,value);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
最后在工程项目的build.gradle加入自己的plugin,并在最外层的build.gradle加入自己插件的引用:
完了!!哈哈!,如果没有明白可以看源码