Android:provided支持android library

最近刚到公司,发现公司没有一套完整的插件化的工具,于是准备研究一下。(毕竟能称得上大公司(阿里,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加入自己插件的引用:
这里写图片描述


完了!!哈哈!,如果没有明白可以看源码

猜你喜欢

转载自blog.csdn.net/weixin_38801333/article/details/76152910