Android 探索之 Task 分析(五)

本文将会分析如下几个task

createReleaseCompatibleScreenManifests
processReleaseManifest
splitsDiscoveryTaskRelease
processReleaseResources
generateReleaseSources
javaPreCompileRelease

13.createReleaseCompatibleScreenManifests

我们有一步生成了apk_list.json,此处生成对应apk的manifest,并输出output.json

源码分析

//com.android.build.gradle.tasks.CompatibleScreensManifest
@TaskAction
public void generateAll() throws IOException {
    // 1、遍历所有的density,通过generate方法产生相应的manifest文件
    // process all outputs.
    new BuildElements(
                    outputScope
                            .getApkDatas()
                            .stream()
                            .map(
                                    apkInfo -> {
                                        // 遍历 density 生成对应的manifest文件
                                        File generatedManifest = generate(apkInfo);
                                        
                                        return generatedManifest != null
                                                ? new BuildOutput(
                                                        VariantScope.TaskOutputType
                                                                .COMPATIBLE_SCREEN_MANIFEST,
                                                        apkInfo,
                                                        generatedManifest)
                                                : null;
                                    })
                            .filter(Objects::nonNull)
                            .collect(Collectors.toList()))
                            // 将结果输出为output.json并保存
            .save(outputFolder);
}
@Nullable
public File generate(ApkData apkData) {
    FilterData densityFilter =
            apkData.getFilter(com.android.build.OutputFile.FilterType.DENSITY);
    if (densityFilter == null) {
        return null;
    }

    StringBuilder content = new StringBuilder();
    content.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n")
            .append("<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n")
            .append("    package=\"${packageName}\">\n")
            .append("\n");
    if (minSdkVersion.get() != null) {
        content.append("    <uses-sdk android:minSdkVersion=\"")
                .append(minSdkVersion.get())
                .append("\"/>\n");
    }
    content.append("    <compatible-screens>\n");

    // convert unsupported values to numbers.
    String density = convert(densityFilter.getIdentifier(), Density.XXHIGH, Density.XXXHIGH);

    for (String size : getScreenSizes()) {
        content.append(
                "        <screen android:screenSize=\"").append(size).append("\" "
                + "android:screenDensity=\"").append(density).append("\" />\n");
    }

    content.append(
            "    </compatible-screens>\n" +
            "</manifest>");


    File splitFolder = new File(outputFolder, apkData.getDirName());
    FileUtils.mkdirs(splitFolder);
    File manifestFile = new File(splitFolder, SdkConstants.ANDROID_MANIFEST_XML);

    try {
        Files.write(content.toString(), manifestFile, Charsets.UTF_8);
    } catch (IOException e) {
        throw new BuildException(e.getMessage(), e);
    }
    return manifestFile;
}

输入输出

-----task begin-------->
project:     project ':app_driver' 
name:        createReleaseCompatibleScreenManifests 
group:       null 
description: null
conv:        [:]
inputs:
outputs:
 /Users/dongkai/Code/XiWeiLogistics/app_driver/build/intermediates/manifests/density/release
<------task end -------

示例

参考文档:
Apk 拆分机制
Split_Config_google
build.gradle配置如下内容

splits {
        // Screen density split settings
        density {

            // Enable or disable the density split mechanism
            enable true

            // Exclude these densities from splits
            exclude "ldpi", "tvdpi", "xxhdpi", "xxxhdpi"
            compatibleScreens 'small', 'normal', 'large', 'xlarge'

        }
    }

会生成如下的内容:

其中关于生成的manifest也可以手动配置,主要是为了google play 使用
具体详细分析可以参考https://blog.csdn.net/think_soft/article/details/7559563
生成的output.json文件类似如下:

[
    {
        "outputType": {
            "type": "COMPATIBLE_SCREEN_MANIFEST"
        },
        "apkInfo": {
            "type": "FULL_SPLIT",
            "splits": [
                {
                    "filterType": "DENSITY",
                    "value": "mdpi"
                }
            ],
            "versionCode": 1,
            "versionName": "1.0",
            "enabled": true,
            "filterName": "mdpi",
            "outputFile": "app-mdpi-release-unsigned.apk",
            "fullName": "mdpiRelease",
            "baseName": "mdpi-release"
        },
        "path": "mdpi/AndroidManifest.xml",
        "properties": {}
    },
    {
        "outputType": {
            "type": "COMPATIBLE_SCREEN_MANIFEST"
        },
        "apkInfo": {
            "type": "FULL_SPLIT",
            "splits": [
                {
                    "filterType": "DENSITY",
                    "value": "hdpi"
                }
            ],
            "versionCode": 1,
            "versionName": "1.0",
            "enabled": true,
            "filterName": "hdpi",
            "outputFile": "app-hdpi-release-unsigned.apk",
            "fullName": "hdpiRelease",
            "baseName": "hdpi-release"
        },
        "path": "hdpi/AndroidManifest.xml",
        "properties": {}
    },
    {
        "outputType": {
            "type": "COMPATIBLE_SCREEN_MANIFEST"
        },
        "apkInfo": {
            "type": "FULL_SPLIT",
            "splits": [
                {
                    "filterType": "DENSITY",
                    "value": "xhdpi"
                }
            ],
            "versionCode": 1,
            "versionName": "1.0",
            "enabled": true,
            "filterName": "xhdpi",
            "outputFile": "app-xhdpi-release-unsigned.apk",
            "fullName": "xhdpiRelease",
            "baseName": "xhdpi-release"
        },
        "path": "xhdpi/AndroidManifest.xml",
        "properties": {}
    }
]

14.processReleaseManifest

processReleaseManifest任务实际上做的是manifest文件的merge操作,将三种输入类型的manifest合成一个manifest文件,并生成相应操作日志文件。

源码分析

//com.android.build.gradle.tasks.MergeManifests
// 主要逻辑
//MergeManifest.java中的doFullTaskAction()方法。
@Override
    protected void doFullTaskAction() throws IOException {
        // 1.获取compatibleScreenManifests生成的manifest集合
        // read the output of the compatible screen manifest.
        BuildElements compatibleScreenManifests =
                ExistingBuildElements.from(
                        VariantScope.TaskOutputType.COMPATIBLE_SCREEN_MANIFEST,
                        compatibleScreensManifest);
        //2、重新设置packageName
        String packageOverride;
        if (packageManifest != null && !packageManifest.isEmpty()) {
            packageOverride =
                    ApplicationId.load(packageManifest.getSingleFile()).getApplicationId();
        } else {
            packageOverride = getPackageOverride();
        }

        @Nullable BuildOutput compatibleScreenManifestForSplit;

        ImmutableList.Builder<BuildOutput> mergedManifestOutputs = ImmutableList.builder();
        ImmutableList.Builder<BuildOutput> irMergedManifestOutputs = ImmutableList.builder();

        // FIX ME : multi threading.
        // TODO : LOAD the APK_LIST FILE .....
        //3.遍历apkDatas->上一步的split过程生成的apkdata
        for (ApkData apkData : outputScope.getApkDatas()) {
            //4.指定分辨率的buildOutput对象
            compatibleScreenManifestForSplit = compatibleScreenManifests.element(apkData);
            //5、正常模式内容的输出 full/release目录下
            File manifestOutputFile =
                    FileUtils.join(
                            getManifestOutputDirectory(),
                            apkData.getDirName(),
                            SdkConstants.ANDROID_MANIFEST_XML);
            //6、 instantRun模式的输出
            File instantRunManifestOutputFile =
                    FileUtils.join(
                            getInstantRunManifestOutputDirectory(),
                            apkData.getDirName(),
                            SdkConstants.ANDROID_MANIFEST_XML);
            //7、 生成mergingreport对象
            MergingReport mergingReport =
                    getBuilder()
                            .mergeManifestsForApplication(
                                    getMainManifest(),
                                    getManifestOverlays(),
                                    computeFullProviderList(compatibleScreenManifestForSplit),
                                    getNavigationFiles(),
                                    getFeatureName(),
                                    packageOverride,
                                    apkData.getVersionCode(),
                                    apkData.getVersionName(),
                                    getMinSdkVersion(),
                                    getTargetSdkVersion(),
                                    getMaxSdkVersion(),
                                    manifestOutputFile.getAbsolutePath(),
                                    // no aapt friendly merged manifest file necessary for applications.
                                    null /* aaptFriendlyManifestOutputFile */,
                                    instantRunManifestOutputFile.getAbsolutePath(),
                                    ManifestMerger2.MergeType.APPLICATION,
                                    variantConfiguration.getManifestPlaceholders(),
                                    getOptionalFeatures(),
                                    getReportFile());

            XmlDocument mergedXmlDocument =
                    mergingReport.getMergedXmlDocument(MergingReport.MergedManifestKind.MERGED);

            ImmutableMap<String, String> properties =
                    mergedXmlDocument != null
                            ? ImmutableMap.of(
                                    "packageId",
                                    mergedXmlDocument.getPackageName(),
                                    "split",
                                    mergedXmlDocument.getSplitName(),
                                    SdkConstants.ATTR_MIN_SDK_VERSION,
                                    mergedXmlDocument.getMinSdkVersion())
                            : ImmutableMap.of();
            
            mergedManifestOutputs.add(
                    new BuildOutput(
                            VariantScope.TaskOutputType.MERGED_MANIFESTS,
                            apkData,
                            manifestOutputFile,
                            properties));
            
            irMergedManifestOutputs.add(
                    new BuildOutput(
                            VariantScope.TaskOutputType.INSTANT_RUN_MERGED_MANIFESTS,
                            apkData,
                            instantRunManifestOutputFile,
                            properties));
        }
        // 8、存储full模式下的output.json
        new BuildElements(mergedManifestOutputs.build()).save(getManifestOutputDirectory());
        // 9、存储instantRun模式下的output.json文件
        new BuildElements(irMergedManifestOutputs.build())
                .save(getInstantRunManifestOutputDirectory());
    }

第一步:从`createReleaseCompatibleScreenManifests'任务的输出读取,生成compatibleScreenManifests集合。所以这里的值有三个(hdpi、mdpi、xhdpi)BuildOutput对象;

第二步:重新设置packageName。如果我们同时在Manifest.xml和gradle里面同时设置packageId,且id值不同,则会在此用gradle里面的package覆盖Manifest.xml里面的id值。

第三步:遍历apkDatas->上一步的split过程生成的apkdata

第四步:进入不同的split遍历,得到指定分辨率的BuildOutput对象;
第五步:正常的manifest输出文件。(/app/build/intermediates/manifests/full/release/universal/AndroidManifest.xml)
第六步:instantRun模式下的Manifest输出。

第七步:生成mergingReport对象,调用的是AndroidBuilder中的mergeManifestsForApplication()方法,该方法会生成/output/logs/manifest-merger-release-report.txt

第八步:存储full模式下的output.json文件;

第九步:存储instantRun模式下的output.json文件

输入输出

-----task begin-------->
project:     project ':app_driver' 
name:        processReleaseManifest 
group:       null 
description: null
conv:        [:]
inputs:
 /Users/dongkai/Code/XiWeiLogistics/app_driver/build/intermediates/splits-support/release/apk-list/apk-list.gson
 /Users/dongkai/Code/XiWeiLogistics/app_driver/build/intermediates/manifests/density/release
 /Users/dongkai/Code/XiWeiLogistics/app_driver/src/main/AndroidManifest.xml
 /Users/dongkai/Code/XiWeiLogistics/ymm_app_driver_main_module/build/intermediates/manifests/full/release/AndroidManifest.xml
  ...
  ...
  ...
 /Users/dongkai/.gradle/caches/transforms-1/files-1.1/vivo-1.0.4.aar/8865158a811f23e9d9b6545f5ff48d01/AndroidManifest.xml
 /Users/dongkai/.gradle/caches/transforms-1/files-1.1/mmkv-static-1.0.17.aar/0c39c42d42d3b884ed1b1cdbff217b58/AndroidManifest.xml
outputs:
 /Users/dongkai/Code/XiWeiLogistics/app_driver/build/intermediates/manifests/instant-run/release
 /Users/dongkai/Code/XiWeiLogistics/app_driver/build/intermediates/manifests/full/release
 /Users/dongkai/Code/XiWeiLogistics/app_driver/build/outputs/logs/manifest-merger-release-report.txt
<------task end -------

根据input file路径,可知输入分为三种类型:

  • createReleaseCompatibleScreenManifests 任务生成的density规则(intermediates/manifests/density/release);
  • 项目的manifest文件(/app/src/main/AndroidManifest.xml);
  • 依赖的aar包的manifest和运行环境的manifest文件(appcompat-v7-26.1.0.aar/.../AndroidManifest.xml,runtime-1.0.0.aar/.../AndroidManifest.xml)。

根据output file路径,可知输出文件也为三种:

  • instant-run模式下的输出(manifests/instant-run/release);
  • 正常模式下的输出(manifests/full/release);
  • merge manifest 的log记录(outputs/logs/manifest-merger-release-report.txt);

15.splitsDiscoveryTaskRelease

源码分析

//com.android.build.gradle.tasks.SplitsDiscovery
        Set<File> mergedResourcesFolderFiles =
                mergedResourcesFolders != null ? mergedResourcesFolders.getFiles() : null;
        Collection<String> resConfigs = resourceConfigs;
        if (resConfigAuto) {
            resConfigs = discoverListOfResourceConfigsNotDensities();
        }
        SplitList.save(
                getPersistedList(),
                getFilters(mergedResourcesFolderFiles, DiscoverableFilterType.DENSITY),
                getFilters(mergedResourcesFolderFiles, DiscoverableFilterType.LANGUAGE),
                // no need to pass the source folders, we don't support Auto for ABI splits so far.
                getFilters(ImmutableList.of(), DiscoverableFilterType.ABI),
                resConfigs.stream().map(SplitList.Filter::new).collect(Collectors.toList()));

输入输出

-----task begin-------->
project:     project ':app_driver' 
name:        splitsDiscoveryTaskRelease 
group:       null 
description: null
conv:        [:]
inputs:
outputs:
 /Users/dongkai/Code/XiWeiLogistics/app_driver/build/intermediates/splits-support/release/split-list/split-list.gson
<------task end -------
输出文件类似如下结构

通过输出json文件,基本可以才到splitsDiscoveryTaskRelease任务就是实现对DENSITY、LANGUAGE、ABI和resConfig配置的存储,即生成split-list.json.

[
    {
        "splitType": "DENSITY",
        "filters": [
            {
                "value": "mdpi"
            },
            {
                "value": "hdpi"
            },
            {
                "value": "xhdpi"
            }
        ]
    },
    {
        "splitType": "LANGUAGE",
        "filters": []
    },
    {
        "splitType": "ABI",
        "filters": []
    },
    {
        "splitType": "ResConfigs",
        "filters": []
    }
]

16.processReleaseResources

源码分析

// com.android.build.gradle.internal.res.LinkApplicationAndroidResourcesTask
@Override
    protected void doFullTaskAction() throws IOException {

        WaitableExecutor executor = WaitableExecutor.useGlobalSharedThreadPool();

        BuildElements manifestBuildElements =
                ExistingBuildElements.from(taskInputType, manifestFiles);

        final Set<File> packageIdFileSet =
                packageIdsFiles != null
                        ? packageIdsFiles.getArtifactFiles().getAsFileTree().getFiles()
                        : null;

        final Set<File> featureResourcePackages = this.featureResourcePackages.getFiles();

        SplitList splitList =
                splitListInput == null ? SplitList.EMPTY : SplitList.load(splitListInput);

        Set<File> dependencies =
                dependenciesFileCollection != null
                        ? dependenciesFileCollection.getFiles()
                        : Collections.emptySet();
        Set<File> imports =
                sharedLibraryDependencies != null
                        ? sharedLibraryDependencies.getFiles()
                        : Collections.emptySet();

        ImmutableList.Builder<BuildOutput> buildOutputs = ImmutableList.builder();

        try (Aapt aapt = makeAapt()) {

            // do a first pass at the list so we generate the code synchronously since it's required
            // by the full splits asynchronous processing below.
            List<BuildOutput> unprocessedManifest =
                    manifestBuildElements.stream().collect(Collectors.toList());
            // 遍历所有的 split 
            for (BuildOutput manifestBuildOutput : manifestBuildElements) {
                ApkInfo apkInfo = manifestBuildOutput.getApkInfo();

                boolean codeGen =
                        (apkInfo.getType() == OutputFile.OutputType.MAIN
                                || apkInfo.getFilter(OutputFile.FilterType.DENSITY) == null);
                if (codeGen) {
                    // 这里只处理 main 和不依赖 density 的资源,此task 可以生成R.java文件
                    unprocessedManifest.remove(manifestBuildOutput);
                    buildOutputs.add(
                            invokeAaptForSplit(
                                    manifestBuildOutput,
                                    dependencies,
                                    imports,
                                    packageIdFileSet,
                                    splitList,
                                    featureResourcePackages,
                                    apkInfo,
                                    true, // 是否生成R文件
                                    aapt));
                    break;
                }
            }
            // 异步处理剩下的其他split,无需生成R.java文件
            // now all remaining splits will be generated asynchronously.
            for (BuildOutput manifestBuildOutput : unprocessedManifest) {
                ApkInfo apkInfo = manifestBuildOutput.getApkInfo();
                if (apkInfo.requiresAapt()) {
                    executor.execute(
                            () ->
                                    invokeAaptForSplit(
                                            manifestBuildOutput,
                                            dependencies,
                                            imports,
                                            packageIdFileSet,
                                            splitList,
                                            featureResourcePackages,
                                            apkInfo,
                                            false,
                                            aapt));
                }
            }
            // 等待所有task完成
            List<WaitableExecutor.TaskResult<BuildOutput>> taskResults = executor.waitForAllTasks();
            taskResults.forEach(
                    taskResult -> {
                        if (taskResult.getException() != null) {
                            throw new BuildException(
                                    taskResult.getException().getMessage(),
                                    taskResult.getException());
                        } else {
                            buildOutputs.add(taskResult.getValue());
                        }
                    });

        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException(e);
        }

        if (multiOutputPolicy == MultiOutputPolicy.SPLITS) {
            //...... 这一大串 普通app用不到,一般我们用的是Full模式,而不是split模式
        }
        // and save the metadata file.
        new BuildElements(buildOutputs.build()).save(resPackageOutputFolder);
    }

核心代码如下:

void invokeAaptForSplit(
            Collection<BuildOutput> manifestsOutputs,
            @NonNull Set<File> dependencySymbolTableFiles,
            @Nullable Set<File> packageIdFileSet,
            @NonNull SplitList splitList,
            @NonNull Set<File> featureResourcePackages,
            ApkData apkData,
            boolean generateCode,
            @Nullable Aapt aapt)
            throws IOException {
        // *.ap_ 文件
        File resOutBaseNameFile =
                new File(
                        resPackageOutputFolder,
                        FN_RES_BASE
                                + RES_QUALIFIER_SEP
                                + apkData.getFullName()
                                + SdkConstants.DOT_RES);
        ...
        // manifest file
        File manifestFile = manifestOutput.getOutputFile();

        ...
        // 生产相应的文件
        getBuilder().processResources(aapt, config);

    }

根据输入文件,生成resoure(*.ap_)文件和相应的R文件。

输入输出

-----task begin-------->
project:     project ':app_driver' 
name:        processReleaseResources 
group:       null 
description: null
conv:        [:]
inputs:
 /Users/dongkai/Code/XiWeiLogistics/app_driver/build/intermediates/splits-support/release/apk-list/apk-list.gson
 /Users/dongkai/Code/XiWeiLogistics/ymm_app_driver_main_module/build/intermediates/res/symbol-table-with-package/release/package-aware-r.txt
  ...
  ...
  ...
 /Users/dongkai/.gradle/caches/transforms-1/files-1.1/0c39c42d42d3b884ed1b1cdbff217b58/8696c64a66460929c73f0f3bd4321f4e/package-aware-r.txt
 /Users/dongkai/Code/XiWeiLogistics/app_driver/build/intermediates/res/merged/release
 /Users/dongkai/Code/XiWeiLogistics/app_driver/build/intermediates/manifests/full/release
 /Users/dongkai/Code/XiWeiLogistics/app_driver/build/intermediates/splits-support/release/split-list/split-list.gson
outputs:
 /Users/dongkai/Code/XiWeiLogistics/app_driver/build/intermediates/incremental/processReleaseResources
 /Users/dongkai/Code/XiWeiLogistics/app_driver/build/intermediates/multi-dex/release/manifest_keep.txt
 /Users/dongkai/Code/XiWeiLogistics/app_driver/build/intermediates/proguard-rules/release/aapt_rules.txt
 /Users/dongkai/Code/XiWeiLogistics/app_driver/build/intermediates/res/release
 /Users/dongkai/Code/XiWeiLogistics/app_driver/build/generated/source/r/release
 /Users/dongkai/Code/XiWeiLogistics/app_driver/build/intermediates/res/symbol-table-with-package/release/package-aware-r.txt
 /Users/dongkai/Code/XiWeiLogistics/app_driver/build/intermediates/symbols/release/R.txt
<------task end -------

首先看下输入目录类型:

  • mergeReleaseResources 任务的输出目录,intermediates/res/merged/release该文件夹下是经过aapt处理过的flat文件;
  • processReleaseManifest 任务的输出目录,intermediates/manifests/full/release该文件夹下是生成的manifest.xml文件;
  • splitsDiscoveryTaskRelease任务输出的目录;
  • 各个依赖包的cache目录中的package-aware-r.txt文件,该文件里面的内容是相应包的资源的映射,类似如下:
android.support.v7.appcompat
int anim abc_fade_in 0x7f010001
int anim abc_fade_out 0x7f010002
int anim abc_grow_fade_in_from_bottom 0x7f010003
int anim abc_popup_enter 0x7f010004

第一行是包名,后面是资源的映射关系。
再来看下输出目录:

  • /intermediates/incremental/processReleaseResources
  • /build/intermediates/multi-dex/release/manifest_keep.txt 后续混淆的时候会用到
  • /build/intermediates/proguard-rules/release/aapt_rules.txt aapt 混淆规则
  • /intermediates/res/release该目录下主要是resources.ap_文件,该文件实际就是资源通过aapt后生成的资源压缩文件(解压后会发现里面就是:AndroidManifest.xml、res文件,以及resoures.arsc);
  • /generated/source/r/release该目录也就是R.java文件。
  • symbol-table-with-package/release/package-aware-r.txt生成项目的R文件的映射关系;
  • intermediates/symbols/release/R.txt生成R文件的txt文件。

17.generateReleaseSources

空实现 锚task,无输入输出

源码分析

输入输出

-----task begin-------->
project:     project ':app_driver' 
name:        generateReleaseSources 
group:       null 
description: null
conv:        [:]
inputs:
outputs:
<------task end -------

18.javaPreCompileRelease

源码分析

//com.android.build.gradle.tasks.JavaPreCompileTask
@TaskAction
    public void preCompile() throws IOException {
        boolean grandfathered = annotationProcessorOptions.getIncludeCompileClasspath() != null;
        Collection<ResolvedArtifactResult> compileProcessors = null;
        if (!grandfathered) {
            compileProcessors = collectAnnotationProcessors(compileClasspaths);
            FileCollection annotationProcessors =
                    annotationProcessorConfiguration.getArtifactFiles();
            compileProcessors =
                    compileProcessors
                            .stream()
                            .filter(artifact -> !annotationProcessors.contains(artifact.getFile()))
                            .collect(Collectors.toList());
            if (!compileProcessors.isEmpty()) {
                String message =
                        "Annotation processors must be explicitly declared now.  The following "
                                + "dependencies on the compile classpath are found to contain "
                                + "annotation processor.  Please add them to the "
                                + annotationProcessorConfigurationName
                                + " configuration.\n  - "
                                + Joiner.on("\n  - ")
                                        .join(convertArtifactsToNames(compileProcessors))
                                + "\nAlternatively, set "
                                + "android.defaultConfig.javaCompileOptions.annotationProcessorOptions.includeCompileClasspath = true "
                                + "to continue with previous behavior.  Note that this option "
                                + "is deprecated and will be removed in the future.\n"
                                + "See "
                                + "https://developer.android.com/r/tools/annotation-processor-error-message.html "
                                + "for more details.";
                if (isForTesting) {
                    getLogger().warn(message);
                } else {
                    throw new RuntimeException(message);
                }
            }
        }

        // Get all the annotation processors for metrics collection.
        Set<String> classNames = Sets.newHashSet();

        // Add the annotation processors on classpath only when includeCompileClasspath is true.
        if (Boolean.TRUE.equals(annotationProcessorOptions.getIncludeCompileClasspath())) {
            if (compileProcessors == null) {
                compileProcessors = collectAnnotationProcessors(compileClasspaths);
            }
            classNames.addAll(convertArtifactsToNames(compileProcessors));
        }

        // Add all annotation processors on the annotation processor configuration.
        classNames.addAll(
                convertArtifactsToNames(
                        collectAnnotationProcessors(annotationProcessorConfiguration)));

        // Add the explicitly declared processors.
        // For metrics purposes, we don't care how they include the processor in their build.
        classNames.addAll(annotationProcessorOptions.getClassNames());

        // Add a generic reference to data binding, if present.
        if (dataBindingEnabled) {
            classNames.add(DATA_BINDING_SPEC);
        }

        FileUtils.deleteIfExists(processorListFile);
        Gson gson = new GsonBuilder().create();
        try (FileWriter writer = new FileWriter(processorListFile)) {
            gson.toJson(classNames, writer);
        }
    }

输入输出

-----task begin-------->
project:     project ':app_driver' 
name:        javaPreCompileRelease 
group:       null 
description: null
conv:        [:]
inputs:
 /Users/dongkai/Code/XiWeiLogistics/ymm_app_driver_main_module/build/intermediates/intermediate-jars/release/classes.jar
 /Users/dongkai/Code/XiWeiLogistics/ymm_app_driver_main_module/libs/yunceng.jar
 /Users/dongkai/.gradle/caches/transforms-1/files-1.1/activity_result_util-1.0.1.aar/4b6d13d6fe7210d069c29939ba8fea95/jars/classes.jar
  ...
  ...
  ...
 /Users/dongkai/.gradle/caches/modules-2/files-2.1/org.jetbrains/annotations/13.0/919f0dfe192fb4e063e7dacadee7f8bb9a2672a9/annotations-13.0.jar
 /Users/dongkai/.gradle/caches/transforms-1/files-1.1/mmkv-static-1.0.17.aar/0c39c42d42d3b884ed1b1cdbff217b58/jars/classes.jar
outputs:
 /Users/dongkai/Code/XiWeiLogistics/app_driver/build/intermediates/javaPrecompile/release/annotationProcessors.json
<------task end -------

所有的输入均为项目直接或者间接引用到的库的jar包,
输出是一个annotationProcessors.json文件。文件类似如下:
["butterknife-compiler.jar (com.jakewharton:butterknife-compiler:9.0.0-rc2)"]
如果root 的build.gradle 使用了annotationProcessor则会产生一个映射

这年头生活不易,人生不息,折腾不止!!!!

发表评论