Android构建流程——篇四

Task9 generateDebugResValues

1. input/ouput

taskName:generateDebugResValues
=========================================================
output:/Users/dingbaosheng/work/mockuai/project/AndroidGradleTaskDemo/app/build/generated/res/resValues/debug

简单的说该任务就是生成一个generated.xml文件,里面包含了在build.gradle文件中自定义的资源属性

  1. 配置自定义资源属性
    在这里插入图片描述
  2. 输出xml文件结构
    在这里插入图片描述

2. 核心类(GenerateResValues)

public class GenerateResValues extends AndroidBuilderTask {
   
	@TaskAction
    void generate() throws IOException, ParserConfigurationException {
   
        File folder = getResOutputDir();
		
		//1. 读取build.gradle中自定义的资源配置数据项
        List<Object> resolvedItems = getItems();
		
		//2. 如果未自定义,清空旧数据
        if (resolvedItems.isEmpty()) {
   
            FileUtils.cleanOutputDir(folder);
        } else {
   
        	//如果自定义了,将自定义资源数据项交给资源值生成器对象
            ResValueGenerator generator = new ResValueGenerator(folder);
            generator.addItems(getItems());
			
			//3. 生成generated.xml
            generator.generate();
        }
    }
}

代码看流程清晰明了,关键代码就是将自定义属性(支持12种类型属性哦)写入到xml文件中,其实现细节集中在类ResValueGenerator.generater中;内部主要使用DOM API来实现,具体不再详细说明,贴下实现代码

public class ResValueGenerator {
   

    public static final String RES_VALUE_FILENAME_XML = "generated.xml";

    private static final List<ResourceType> RESOURCES_WITH_TAGS = ImmutableList.of(
            ResourceType.ARRAY,
            ResourceType.ATTR,
            ResourceType.BOOL,
            ResourceType.COLOR,
            ResourceType.DECLARE_STYLEABLE,
            ResourceType.DIMEN,
            ResourceType.FRACTION,
            ResourceType.INTEGER,
            ResourceType.PLURALS,
            ResourceType.STRING,
            ResourceType.STYLE);
	/**
     * Generates the resource files
     */
    public void generate() throws IOException, ParserConfigurationException {
   
        File pkgFolder = getFolderPath();
        if (!pkgFolder.isDirectory()) {
   
            if (!pkgFolder.mkdirs()) {
   
                throw new RuntimeException("Failed to create " + pkgFolder.getAbsolutePath());
            }
        }

        File resFile = new File(pkgFolder, RES_VALUE_FILENAME_XML);

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true);
        factory.setValidating(false);
        factory.setIgnoringComments(true);
        DocumentBuilder builder;

        builder = factory.newDocumentBuilder();
        Document document = builder.newDocument();
		
		//创建根节点resources
        Node rootNode = document.createElement(TAG_RESOURCES);
        document.appendChild(rootNode);
		
		//添加子节点,此处就是添加些注释说明
        rootNode.appendChild(document.createTextNode("\n"));
        rootNode.appendChild(document.createComment("Automatically generated file. DO NOT MODIFY"));
        rootNode.appendChild(document.createTextNode("\n\n"));
		
		//遍历自定义资源属性
        for (Object item : mItems) {
   
            if (item instanceof ClassField) {
   
                ClassField field = (ClassField)item;

                ResourceType type = ResourceType.getEnum(field.getType());
				
				//判断是否是通用的11种类型中一种
                boolean hasResourceTag = (type != null && RESOURCES_WITH_TAGS.contains(type));
				
				//如果不是通用的资源类型,则生成<item>标签节点
                Node itemNode = document.createElement(hasResourceTag ? field.getType() : TAG_ITEM);
                Attr nameAttr = document.createAttribute(ATTR_NAME);

                nameAttr.setValue(field.getName());
                itemNode.getAttributes().setNamedItem(nameAttr);
				
				
                if (!hasResourceTag) {
   
                	//如果是item标签,需要设置其type、name属性值
                	//eg:<item type="id" name="button_ok" />
                    Attr typeAttr = document.createAttribute(ATTR_TYPE);
                    typeAttr.setValue(field.getType());
                    itemNode.getAttributes().setNamedItem(typeAttr);
                }

                if (type == ResourceType.STRING) {
   
                	//如果是string资源,添加traslatable属性,使其设备统一使用该字段,和系统语言等无关
                    Attr translatable = document.createAttribute(ATTR_TRANSLATABLE);
                    translatable.setValue(VALUE_FALSE);
                    itemNode.getAttributes().setNamedItem(translatable);
                }

                if (!field.getValue().isEmpty()) {
   
                    itemNode.appendChild(document.createTextNode(field.getValue()));
                }

                rootNode.appendChild(itemNode);
            } else if (item instanceof String) {
   
                rootNode.appendChild(document.createTextNode("\n"));
                rootNode.appendChild(document.createComment((String) item));
                rootNode.appendChild(document.createTextNode("\n"));
            }
        }

        String content;
        try {
   
            content = XmlPrettyPrinter.prettyPrint(document, true);
        } catch (Throwable t) {
   
            content = XmlUtils.toXml(document);
        }
		
		//写文件
        Files.write(content, resFile, Charsets.UTF_8);
    }
}    

支持的自定义资源属性类型

序号 类型
1 array
2 attr
3 bool
4 color
5 declare-styleable
6 dimen
7 fraction
8 integer
9 plurals
10 string
11 style
12 item

Task10 generateDebugResources

属于空task直接忽略

Task11 mergeDebugResources

合并资源任务

1. input/ouput

taskName:mergeDebugResources
input:/Users/apple/.gradle/caches/transforms-1/files-1.1/aapt2-3.2.0-4818971-osx.jar/c5355294e416159d9559f45d46460f7d/aapt2-3.2.0-4818971-osx
input:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/generated/res/resValues/debug
input:/Users/apple/.gradle/caches/transforms-1/files-1.1/appcompat-v7-26.1.0.aar/2774ea4f1cf1e83a6ad8e8d3c8b463b6/res
input:/Users/apple/.gradle/caches/transforms-1/files-1.1/constraint-layout-1.1.3.aar/f43c0ba95b6494825ed940fc4f04662b/res
input:/Users/apple/.gradle/caches/transforms-1/files-1.1/support-media-compat-26.1.0.aar/53ab5ad72634f3497309a8788f3ca200/res
input:/Users/apple/.gradle/caches/transforms-1/files-1.1/support-compat-26.1.0.aar/4ec3c1c46e5bad9ac3b91f45a2afec3e/res
input:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/generated/res/rs/debug
input:/Users/apple/work/project/AndroidGradleTaskDemo/app/src/main/res
input:/Users/apple/work/project/AndroidGradleTaskDemo/app/src/debug/res
=========================================================
output:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/intermediates/blame/res/debug
output:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/generated/res/pngs/debug
output:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/intermediates/incremental/mergeDebugResources
output:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/intermediates/res/merged/debug

先来一张总流程图吧,先把握主线;文字描述的不一定有图清楚
在这里插入图片描述

xml -> drawable 、string 、color、anim、layout、value
layout、generated
png
先看输入好了,可以很清楚看到输入都是项目依赖的库的res文件以及本身结构的res文件

输出路径 产物 备注 所在类
app/build/intermediates/blame/res/debug 1. 日志文件 2. 资源文件和编译后产物的映射表文件
app/build/generated/res/pngs/debug 资源文件vector、png xxx
app/build/intermediates/incremental/mergeDebugResources 1、merged.dir 存放合并资源文件的地方2、stripped.dir 3、compile-file-map.properties 资源和编译产物映射表 4、merger.xml 合并文件 MergedResourceWriter
app/build/intermediates/res/merged/debug flat文件 AAPT2编译的产物,也就是本上图的重点产物 MergedResourceWriter

app/build/intermediates/incremental/mergeDebugResources

  1. merged.dir
  2. stripped.dir
  3. compile-file-map.properties
  4. merger.xml

2. 核心类(MergeResources)

@CacheableTask
public class MergeResources extends IncrementalTask {
   
	
	@Override
    protected void doFullTaskAction() throws IOException, JAXBException {
   
        ResourcePreprocessor preprocessor = getPreprocessor();

        // this is full run, clean the previous outputs
        File destinationDir = getOutputDir();
        FileUtils.cleanOutputDir(destinationDir);
        if (dataBindingLayoutInfoOutFolder != null) {
   
            FileUtils.deleteDirectoryContents(dataBindingLayoutInfoOutFolder);
        }

        List<ResourceSet> resourceSets = getConfiguredResourceSets(preprocessor);

        // create a new merger and populate it with the sets.
        ResourceMerger merger = new ResourceMerger(minSdk.get());
        MergingLog mergingLog = null;
        if (blameLogFolder != null) {
   
            FileUtils.cleanOutputDir(blameLogFolder);
            mergingLog = new MergingLog(blameLogFolder);
        }

        try (ResourceCompilationService resourceCompiler =
                getResourceProcessor(
                        aaptGeneration,
                        getBuilder(),
                        aapt2FromMaven,
                        workerExecutorFacade,
                        crunchPng,
                        variantScope,
                        mergingLog,
                        flags,
                        processResources)) {
   

            for (ResourceSet resourceSet : resourceSets) {
   
                resourceSet.loadFromFiles(getILogger());
				//1. 添加资源
                merger.addDataSet(resourceSet);
            }

            MergedResourceWriter writer =
                    new MergedResourceWriter(
                            workerExecutorFacade,
                            destinationDir,
                            getPublicFile(),
                            mergingLog,
                            preprocessor,
                            resourceCompiler,
                            getIncrementalFolder(),
                            dataBindingLayoutProcessor,
                            mergedNotCompiledResourcesOutputDirectory,
                            pseudoLocalesEnabled,
                            getCrunchPng());
			//2. 执行资源合并操作
            merger.mergeData
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
android技术内幕:系统卷》 前言 第1章 准备工作 /1 1.1 深入认识android /2 1.1.1 android的系统构架 /2 1.1.2 android的初始化流程 /5 1.1.3 各个层次之间的相互关系 /8 1.1.4 android系统开发(移植)和应用开发 /11 1.2 获取和编译android的源码 /13 1.2.1 环境配置 /13 1.2.2 获取android源码 /14 1.2.3 编译android的源码及其工具包 /16 1.2.4 运行android系统 /21 1.3 开发环境搭建 /23 1.3.1 应用开发环境搭建 /23 1.3.2 源码开发环境搭建 /26 1.4 android源码结构 /32 1.5 小结 /33 第2章 android的内核机制和结构剖析 /34 2.1 linux与android的关系 /35 .2.1.1 为什么会选择linux /35 2.1.2 android不是linux /35 2.2 android对linux内核的改动 /37 2.2.1 goldfish /37 2.2.2 yaffs2 /38 2.2.3 蓝牙 /39 2.2.4 调度器(scheduler)/39 2.2.5 android新增的驱动 /40 2.2.6 电源管理 /41 2.2.7 杂项 /41 2.3 android对linux内核的增强 /42 2.3.1 alarm(硬件时钟)/43 2.3.2 ashmem(匿名内存共享)/46 2.3.3 low memory killer(低内存管理)/52 2.3.4 logger(日志设备)/56 2.3.5 android pmem /65 2.3.6 switch /79 2.3.7 timed gpio /88 2.3.8 android ram console /94 2.4 小结 /99 第3章 android的ipc机制--binder /100 3.1 binder概述 /101 3.1.1 为什么选择binder /101 3.1.2 初识binder /102 3.2 binder驱动的原理和实现 /102 3.2.1 binder驱动的原理 /102 3.2.2 binder驱动的实现 /103 3.3 binder的构架与实现 /132 3.3.1 binder的系统构架 /132 3.3.2 binder的机制和原理 /133 3.4 小结 /150 第4章 电源管理 /151 4.1 电源管理概述 /152 4.2 电源管理结构 /152 4.3 android的电源管理机制 /153 4.4 android电源管理机制的实现 /154 4.5 小结 /187 第5章 驱动的工作原理及实现机制 /188 5.1 显示驱动(framebuffer)/189 5.1.1 framebuffer的工作原理 /189 5.1.2 framebuffer的构架 /190 5.1.3 framebuffer驱动的实现机制 /190 5.2 视频驱动(v4l和v4l2)/201 5.2.1 v4l2介绍 /201 5.2.2 v4l2的原理和构架 /201 5.2.3 v4l2的实现 /202 5.3 音频驱动(oss和alsa)/208 5.3.1 oss与alsa介绍 /208 5.3.2 oss的构架与实现 /209 5.3.3 alsa的构架与实现 /213 5.4 mtd驱动 /214 5.4.1 mtd驱动的功能 /214 5.4.2 mtd驱动的构架 /215 5.4.3 mtd驱动的原理及实现 /215 5.5 event输入设备驱动 /223 5.5.1 input的系统构架 /223 5.5.2 event输入驱动的构架 /224 5.5.3 event输入驱动的原理 /224 5.5.4 event输入驱动的实现 /225 5.6 蓝牙驱动(bluetooth)/235 5.6.1 bluetooth驱动的构架 /235 5.6.2 bluez的原理及实现 /237 5.7 wlan驱动(wi-fi)/244 5.7.1 wlan构架 /244 5.7.2 wi-fi驱动的实现原理 /245 5.8 小结 /245 第6章 原生库的原理及实现 /246 6.1 系统c库(bionic libc)/247 6.1.1 bionic libc功能概述 /247 6.1.2 bionic libc实现原理 /248 6.2 功能库 /258 6.2.1 webkit构架与实现 /258 6.2.2 多媒体框架与实现 /275 6.2.3 android sqlite框架及原理

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值