Android Settings,SourceSet,自定义Plugin

简介: Android Settings,SourceSet,自定义Plugin

Settings 类


决定一个工程中有哪些模块是需要被处理的。


public interface Settings extends PluginAware, ExtensionAware {
  //默认的文件名称
    String DEFAULT_SETTINGS_FILE = "settings.gradle";
    //将指定的 project 加载到的构建中
    void include(String... projectPaths);
}


Settings 类如何被 gradle 初始化完全取决于 settings.gradle 文件的配置。setting.gradle 中就需要指定有哪些模块需要被处理。


include  ':app', ':core', ':detegateManager', ':tabHome', ':tabShop', ':tabDiscover', ':tabMall', ':tabMine', ':ui'


如上就是有多个模块被加载到构建中,Settings 会在 gradle 生命周期的初始化阶段执行,确定要构建的模块,并创建 project 对象


SourceSet 类


gradle 是如何从从 src/main/java/package/ 下面去读取我们的源码,然后生成字节码文件呢?其实就是通过 SourceSet 类的配置中拿到的。


SourceSet 类决定了我们所有的代码,资源,第三方库等存放的位置。


gradle 中约定大于配置,只要没有配置,那就是按约定的来。gradle 默认从 java 文件下获取源码,从 res 文件下获取资源 进行编译。这些约定可以进行修改。


通过 SourceSet 类我们可以修改默认的存放路径,如 so 的路径,res 的路径,java 文件的路径等。如下所示:


android {
    sourceSets {
            main {
                //修改 so 文件存放的位置
                jniLibs.srcDirs = ['libs']
            }
        }
}


使用上面的配置后,gradle 在加载 so 文件时就会从 libs 下进行加载。


修改资源路径:如果一个项目太过庞大,其代码还可以通过创建 package 来整理一下,看起来会更加简洁,容易寻找。但是资源文件却不行,默认只有一个 res 目录,所有的自愈都需要放在 res 中。但是通过 SourceSet 类可以指定多个 res 文件夹,这些文件夹里面就可以存放不同模块下的资源文件了。如下:


在 main 文件下新建文件夹 res-ad 用来存放广告资源,res-play 存放游戏资源。创建完成后在 build.gradle 中的 android 下添加如下代码:


sourceSets {
        main {
            res.srcDirs = ['src/main/res',
                           'src/main/res-ad',
                           'src/main/res-play']
        }
}


接着同步一下,就会发现这两个文件夹上面的图标和 res 的图标是一样的了。


0a2653c851af460fa595bd959398a8f1.png


Plugin 详解及自定义 Plugin


Gradle 插件使用 Groovy 开发的,而 Groovy 完全兼容 Java ,使用 AS 完全可以开发 Gradle 插件。


处理插件:Gradle 会自动找到插件的所在位置,如 buildSrc 名字会被 Gradle 识别为 插件工程


应用环境:一旦插件被应用到构建的脚本中,那么插件对应的 apply 方法就会被调用


插件项目的创建:在 as 中新建一个 library。删除一些内容。使其和图片中的一样:


0a2653c851af460fa595bd959398a8f1.png


  groovy 下新建一个包名。


META-INF/gradle-plugins/下新建一个 .properties 文件,这里的为文件名字最终会出现在:


apply plugin: 'com.car.srcplugin'


注意 :build.gradle 中所有的内容都需要删掉


下面开始一个小 Demo:还是保存每次发布的版本信息。只不过有了很大的改进。


1,配置一些 build.gradle


apply plugin: 'groovy'
sourceSets {
    main {
        groovy {
            srcDir 'src/main/groovy'
        }
        resources {
            srcDir 'src/main/resources'
        }
    }
}
dependencies {
    //gradle sdk
    implementation gradleApi()
    //groovy sdk
    implementation localGroovy()
}


2,自定义 Taks


class UpDataInfoTask extends DefaultTask {
    private VersionInfo versionInfo
    ReleaseInfoTask() {
        //设置组名和描述信息
        group = '345'
        description = 'update the release info'
    }
    /**
     * 使用 TaskAction 注解,这个方法会执行在执行阶段
     * doFirst 就是给这个方法的最前面添加代码
     * doLast 就是给这个方法的最后面添加代码
     */
    @TaskAction
    void doAction() {
        upDataInfo()
    }
    /**
     * 将 Extension 类中的信息写入到指定的文件中
     */
    void upDataInfo() {
        project.logger.error "------------------- 开始插入信息 -------------------"
        String versionNameMsg = project.extensions
                .upDataInfo.versionName
        String versionCodeMsg = project.extensions
                .upDataInfo.versionCode
        String versionInfoMsg = project.extensions
                .upDataInfo.versionInfo
        String buildType = project.extensions.
                upDataInfo.buildType
        if (buildType == null || buildType.isEmpty()) {
            buildType = "Release"
        }
        File file = project.file(buildType + ".json")
        if (file != null && !file.exists()) {
            file.createNewFile()
        }
        if (file.text != null && file.text.size() >= 0) {
            String text = file.text
            if (text != null && !text.isEmpty()) {
                versionInfo = new JsonSlurper().parseText(text)
            } else {
                versionInfo = new VersionInfo()
                versionInfo.setUpDataInfo = []
            }
            if (versionInfo.setUpDataInfo.size() > 0) {
                //如果版本号一样,使用新的
                int pos = versionInfo.setUpDataInfo.size() - 1;
                if (versionNameMsg == versionInfo.setUpDataInfo.get(pos).versionName) {
                    project.logger.error "------------------- 版本号相同,已替换 -------------------"
                    versionInfo.setUpDataInfo.remove(pos)
                }
            }
            VersionInfo.UpDataInfoBean bean = new VersionInfo.UpDataInfoBean();
            bean.versionCode = versionCodeMsg
            bean.versionName = versionNameMsg
            bean.versionInfo = versionInfoMsg
            bean.versionTime = stampToDate(System.currentTimeMillis())
            versionInfo.setUpDataInfo.add(bean)
            String json = JsonOutput.toJson(versionInfo)
            file.withWriter {
                write ->
                    write.write(JsonOutput.prettyPrint(json))
            }
            project.logger.error "------------------- 更新信息已生成 -------------------"
        }
    }
    private static String stampToDate(long time) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date(time)
        simpleDateFormat.format(date)
    }
}


3,VersionInfo


class VersionInfo {
    private List<UpDataInfoBean> updataInfo;
    public List<UpDataInfoBean> getSetUpDataInfo() {
        return updataInfo;
    }
    public void setSetUpDataInfo(List<UpDataInfoBean> relaseInfo) {
        this.updataInfo = relaseInfo;
    }
    public static class UpDataInfoBean {
        /**
         * versionName :
         * versionCode :
         * versionInfo :
         * versionTime :
         */
        private String versionName;
        private String versionCode;
        private String versionInfo;
        private String versionTime;
        public String getVersionName() {
            return versionName;
        }
        public void setVersionName(String versionName) {
            this.versionName = versionName;
        }
        public String getVersionCode() {
            return versionCode;
        }
        public void setVersionCode(String versionCode) {
            this.versionCode = versionCode;
        }
        public String getVersionInfo() {
            return versionInfo;
        }
        public void setVersionInfo(String versionInfo) {
            this.versionInfo = versionInfo;
        }
        public String getVersionTime() {
            return versionTime;
        }
        public void setVersionTime(String versionTime) {
            this.versionTime = versionTime;
        }
    }
}


4,UpDataInfoExtension


闭包中要用到的属性


class UpDataInfoExtension {
    /**
     * code
     */
    String versionCode
    /**
     * name
     */
    String versionName
    /**
     * 发布信息
     */
    String versionInfo
    /**
     * 打包类型。默认为 Release ,也可以是 Debug。注意 首字母大写。
     */
    String buildType
}


5,自定义 plugin


/**
 * 自定义插件
 */
class GradleStudyPlugin implements Plugin<Project> {
    Project mProject = null;
    /**
     * 插件被引入时要执行的方法
     * @param project 引入当前插件的 project
     */
    @Override
    void apply(Project project) {
        mProject = project
        def android = mProject.extensions.android
        //通过在外边定义 upDataInfo 闭包,完成对 UpDataInfoExtension 的初始化
        project.extensions.create('upDataInfo', UpDataInfoExtension)
        //创建 Task
        UpDataInfoTask task = project.tasks.create('upDataInfoTask', UpDataInfoTask)
        //配置阶段完成后执行
        mProject.afterEvaluate {
            String buildType = mProject.extensions.upDataInfo.buildType
            //默认 Release
            if (buildType == null || buildType.isEmpty()) {
                buildType = "Release"
            }
            mProject.logger.error("------------------- ${buildType} -------------------")
            def buildTask = mProject.tasks.getByName("assemble${buildType}")
            if (buildTask == null) {
                throw GradleException('the build task is not fond')
            }
            buildTask.doLast {
                task.upDataInfo()
            }
        }
    }
}


6,META-INF/gradle-plugins/


META-INF/gradle-plugins/下新建一个 .properties 文件。文件名字一般和包名一样


implementation-class=com.car.srcplugin.GradleStudyPlugin


这里指向自定义的 Plugin


7,使用方式


每次打Release 或者 Debug 包的时候这个会自动执行。或者是使用命令行直接启动也可以。


在 app/build.gradle 中引入


apply plugin: 'com.car.srcplugin'


创建闭包,注意和 android 闭包平级


upDataInfo {
    versionCode String.valueOf(version_code)
    versionName version_name
    versionInfo version_info
    //默认 Release,还可以是Debug ,注意首字母大写
    buildType "Debug"
}


8,使用结果


0a2653c851af460fa595bd959398a8f1.png2d65d23f6d4748949b924e4057485923.png


9,总结


这个插件也写了好久,因为也是刚开始学,到现在有些问题还没有解决。以后再慢慢解决吧。


android 插件对 gradle 扩展


在 build.gradle 中,有一个 android 的闭包,在这个闭包中可以的定义非常多的内容。BaseExtension 类就是 闭包中能够调用的所有方法如下:


public abstract class BaseExtension implements AndroidConfig {
    /** Secondary dependencies for the custom transform. */
    private final List<List<Object>> transformDependencies = Lists.newArrayList();
    protected final GlobalScope globalScope;
    private final DefaultConfig defaultConfig;
    private final AaptOptions aaptOptions;
    private final LintOptions lintOptions;
    private final ExternalNativeBuild externalNativeBuild;
    private final DexOptions dexOptions;
    private final TestOptions testOptions;
    private final CompileOptions compileOptions;
    private final PackagingOptions packagingOptions;
    private final JacocoOptions jacoco;
    private final Splits splits;
    ......
}


上面列举了部分的属性。android 闭包中所有的属性方法都是调用这个类里面的。


相关文章
|
21天前
|
Java API 调度
Android系统 自定义开机广播,禁止后台服务,运行手动安装应用接收开机广播
Android系统 自定义开机广播,禁止后台服务,运行手动安装应用接收开机广播
42 0
|
21天前
|
存储 Java Linux
Android Mstar增加IR 自定义遥控头码完整调试过程
Android Mstar增加IR 自定义遥控头码完整调试过程
29 1
|
1月前
|
缓存 测试技术 Android开发
深入探究Android中的自定义View绘制优化策略
【4月更文挑战第8天】 在Android开发实践中,自定义View的绘制性能至关重要,尤其是当涉及到复杂图形和动画时。本文将探讨几种提高自定义View绘制效率的策略,包括合理使用硬件加速、减少不必要的绘制区域以及利用缓存机制等。这些方法不仅能改善用户体验,还能提升应用的整体性能表现。通过实例分析和性能测试结果,我们将展示如何有效地实现这些优化措施,并为开发者提供实用的技术指南。
|
1月前
|
前端开发 Android开发 开发者
深入探究Android中的自定义View组件开发
【4月更文挑战第3天】 在现代Android应用程序的开发过程中,创建具有独特功能和高度定制化的用户界面是一个常见需求。为此,理解并掌握自定义View组件的开发成为了开发者必备的技能之一。本文将深入探讨如何在Android中创建自定义View,从基础的绘制原理到事件处理机制,再到性能优化技巧,旨在为读者提供一个全面的技术视角,并通过实例代码演示如何实现一个功能丰富、响应迅速的自定义View组件。
|
1月前
|
XML Java Android开发
Android实现自定义进度条(源码+解析)
Android实现自定义进度条(源码+解析)
59 1
|
21天前
|
Java Android开发
Android系统 修改无源码普通应用为默认Launcher和隐藏Settings中应用信息图标
Android系统 修改无源码普通应用为默认Launcher和隐藏Settings中应用信息图标
52 0
|
2天前
|
存储 消息中间件 缓存
Android应用开发:实现自定义View的高效绘制
【5月更文挑战第12天】 在Android开发中,创建高性能的自定义视图是一项挑战,它要求开发者深入理解Android的绘图机制以及UI渲染过程。本文将探讨如何优化自定义View的绘制流程,减少不必要的重绘和布局计算,以提升应用的响应速度和流畅度。我们将介绍几种关键策略,包括利用硬件加速、缓存绘制内容和使用高效的数据结构来存储视图状态。通过实例分析和性能对比,读者将学会如何在自己的应用中运用这些技巧,从而打造出更加流畅和响应迅速的用户界面。
|
4天前
|
XML Android开发 数据格式
Android下自定义Button样式
Android下自定义Button样式
10 3
|
4天前
|
XML Java Android开发
如何美化android程序:自定义ListView背景
如何美化android程序:自定义ListView背景
|
4天前
|
搜索推荐 Android开发
自定义Android标题栏TitleBar布局
自定义Android标题栏TitleBar布局