Android构建流程——篇五
文章目錄
- Task13: processDebugManifest
- 1. input/ouput
- 2. 整體流程
- 3. 調(diào)用鏈路
- 4. 核心類(MergeManifests)
- 5. AndroidBuilder.mergeManifestsForApplication
- 6. ManifestMerge2.merge
- Task14: splitsDiscoveryTaskDebug
- 1. input/ouput
- 2. 核心類(SplitsDiscovery)
- Task15: processDebugResources
- 1. input/output
- 2. 整體流程
- 3. 核心類(LinkApplicationAndroidResourcesTask)
- 4. invokeAaptForSplit
- 5. **package-aware-r.txt**內(nèi)容格式如下
- 6. AndroidBuilder.processResources
- Task16: generateDebugSources
Task13: processDebugManifest
1. input/ouput
taskName:processDebugManifest input:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/intermediates/apk_list/debug/mainApkListPersistenceDebug/apk-list.gson input:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/intermediates/compatible_screen_manifest/debug/createDebugCompatibleScreenManifests/out input:/Users/apple/work/project/AndroidGradleTaskDemo/app/src/main/AndroidManifest.xml input:/Users/apple/.gradle/caches/transforms-1/files-1.1/appcompat-v7-26.1.0.aar/2774ea4f1cf1e83a6ad8e8d3c8b463b6/AndroidManifest.xml input:/Users/apple/.gradle/caches/transforms-1/files-1.1/constraint-layout-1.1.3.aar/f43c0ba95b6494825ed940fc4f04662b/AndroidManifest.xml input:/Users/apple/.gradle/caches/transforms-1/files-1.1/animated-vector-drawable-26.1.0.aar/559112320064089dfaf6780e71d5b44f/AndroidManifest.xml input:/Users/apple/.gradle/caches/transforms-1/files-1.1/support-vector-drawable-26.1.0.aar/c2c3ad4abfd49316f6769b8238b0f010/AndroidManifest.xml input:/Users/apple/.gradle/caches/transforms-1/files-1.1/support-v4-26.1.0.aar/9ac5f97e8ccb24c52b7cbb6202c12ad0/AndroidManifest.xml input:/Users/apple/.gradle/caches/transforms-1/files-1.1/support-media-compat-26.1.0.aar/53ab5ad72634f3497309a8788f3ca200/AndroidManifest.xml input:/Users/apple/.gradle/caches/transforms-1/files-1.1/support-fragment-26.1.0.aar/7e6a4ce6591d722d47aafc36d980f8b4/AndroidManifest.xml input:/Users/apple/.gradle/caches/transforms-1/files-1.1/support-core-utils-26.1.0.aar/4c474caa9ac1f01c4936bd96905ecacd/AndroidManifest.xml input:/Users/apple/.gradle/caches/transforms-1/files-1.1/support-core-ui-26.1.0.aar/868eaa7e0c620cd85d72ad4f340e8bb1/AndroidManifest.xml input:/Users/apple/.gradle/caches/transforms-1/files-1.1/support-compat-26.1.0.aar/4ec3c1c46e5bad9ac3b91f45a2afec3e/AndroidManifest.xml input:/Users/apple/.gradle/caches/transforms-1/files-1.1/runtime-1.0.0.aar/5b2333922ba05b1f174de51739b24d14/AndroidManifest.xml ========================================================= output:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/intermediates/instant_run_merged_manifests/debug/processDebugManifest/instant-run output:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/intermediates/merged_manifests/debug/processDebugManifest/merged output:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/outputs/logs/manifest-merger-debug-report.txt該任務(wù)是用來合并所有Manifests清單文件
2. 整體流程
3. 調(diào)用鏈路
#mermaid-svg-jefhpveyWB8IjK34 .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-jefhpveyWB8IjK34 .label text{fill:#333}#mermaid-svg-jefhpveyWB8IjK34 .node rect,#mermaid-svg-jefhpveyWB8IjK34 .node circle,#mermaid-svg-jefhpveyWB8IjK34 .node ellipse,#mermaid-svg-jefhpveyWB8IjK34 .node polygon,#mermaid-svg-jefhpveyWB8IjK34 .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-jefhpveyWB8IjK34 .node .label{text-align:center;fill:#333}#mermaid-svg-jefhpveyWB8IjK34 .node.clickable{cursor:pointer}#mermaid-svg-jefhpveyWB8IjK34 .arrowheadPath{fill:#333}#mermaid-svg-jefhpveyWB8IjK34 .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-jefhpveyWB8IjK34 .flowchart-link{stroke:#333;fill:none}#mermaid-svg-jefhpveyWB8IjK34 .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-jefhpveyWB8IjK34 .edgeLabel rect{opacity:0.9}#mermaid-svg-jefhpveyWB8IjK34 .edgeLabel span{color:#333}#mermaid-svg-jefhpveyWB8IjK34 .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-jefhpveyWB8IjK34 .cluster text{fill:#333}#mermaid-svg-jefhpveyWB8IjK34 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-jefhpveyWB8IjK34 .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-jefhpveyWB8IjK34 text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-jefhpveyWB8IjK34 .actor-line{stroke:grey}#mermaid-svg-jefhpveyWB8IjK34 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-jefhpveyWB8IjK34 .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-jefhpveyWB8IjK34 #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-jefhpveyWB8IjK34 .sequenceNumber{fill:#fff}#mermaid-svg-jefhpveyWB8IjK34 #sequencenumber{fill:#333}#mermaid-svg-jefhpveyWB8IjK34 #crosshead path{fill:#333;stroke:#333}#mermaid-svg-jefhpveyWB8IjK34 .messageText{fill:#333;stroke:#333}#mermaid-svg-jefhpveyWB8IjK34 .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-jefhpveyWB8IjK34 .labelText,#mermaid-svg-jefhpveyWB8IjK34 .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-jefhpveyWB8IjK34 .loopText,#mermaid-svg-jefhpveyWB8IjK34 .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-jefhpveyWB8IjK34 .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-jefhpveyWB8IjK34 .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-jefhpveyWB8IjK34 .noteText,#mermaid-svg-jefhpveyWB8IjK34 .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-jefhpveyWB8IjK34 .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-jefhpveyWB8IjK34 .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-jefhpveyWB8IjK34 .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-jefhpveyWB8IjK34 .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-jefhpveyWB8IjK34 .section{stroke:none;opacity:0.2}#mermaid-svg-jefhpveyWB8IjK34 .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-jefhpveyWB8IjK34 .section2{fill:#fff400}#mermaid-svg-jefhpveyWB8IjK34 .section1,#mermaid-svg-jefhpveyWB8IjK34 .section3{fill:#fff;opacity:0.2}#mermaid-svg-jefhpveyWB8IjK34 .sectionTitle0{fill:#333}#mermaid-svg-jefhpveyWB8IjK34 .sectionTitle1{fill:#333}#mermaid-svg-jefhpveyWB8IjK34 .sectionTitle2{fill:#333}#mermaid-svg-jefhpveyWB8IjK34 .sectionTitle3{fill:#333}#mermaid-svg-jefhpveyWB8IjK34 .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-jefhpveyWB8IjK34 .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-jefhpveyWB8IjK34 .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-jefhpveyWB8IjK34 .grid path{stroke-width:0}#mermaid-svg-jefhpveyWB8IjK34 .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-jefhpveyWB8IjK34 .task{stroke-width:2}#mermaid-svg-jefhpveyWB8IjK34 .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-jefhpveyWB8IjK34 .taskText:not([font-size]){font-size:11px}#mermaid-svg-jefhpveyWB8IjK34 .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-jefhpveyWB8IjK34 .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-jefhpveyWB8IjK34 .task.clickable{cursor:pointer}#mermaid-svg-jefhpveyWB8IjK34 .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-jefhpveyWB8IjK34 .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-jefhpveyWB8IjK34 .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-jefhpveyWB8IjK34 .taskText0,#mermaid-svg-jefhpveyWB8IjK34 .taskText1,#mermaid-svg-jefhpveyWB8IjK34 .taskText2,#mermaid-svg-jefhpveyWB8IjK34 .taskText3{fill:#fff}#mermaid-svg-jefhpveyWB8IjK34 .task0,#mermaid-svg-jefhpveyWB8IjK34 .task1,#mermaid-svg-jefhpveyWB8IjK34 .task2,#mermaid-svg-jefhpveyWB8IjK34 .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-jefhpveyWB8IjK34 .taskTextOutside0,#mermaid-svg-jefhpveyWB8IjK34 .taskTextOutside2{fill:#000}#mermaid-svg-jefhpveyWB8IjK34 .taskTextOutside1,#mermaid-svg-jefhpveyWB8IjK34 .taskTextOutside3{fill:#000}#mermaid-svg-jefhpveyWB8IjK34 .active0,#mermaid-svg-jefhpveyWB8IjK34 .active1,#mermaid-svg-jefhpveyWB8IjK34 .active2,#mermaid-svg-jefhpveyWB8IjK34 .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-jefhpveyWB8IjK34 .activeText0,#mermaid-svg-jefhpveyWB8IjK34 .activeText1,#mermaid-svg-jefhpveyWB8IjK34 .activeText2,#mermaid-svg-jefhpveyWB8IjK34 .activeText3{fill:#000 !important}#mermaid-svg-jefhpveyWB8IjK34 .done0,#mermaid-svg-jefhpveyWB8IjK34 .done1,#mermaid-svg-jefhpveyWB8IjK34 .done2,#mermaid-svg-jefhpveyWB8IjK34 .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-jefhpveyWB8IjK34 .doneText0,#mermaid-svg-jefhpveyWB8IjK34 .doneText1,#mermaid-svg-jefhpveyWB8IjK34 .doneText2,#mermaid-svg-jefhpveyWB8IjK34 .doneText3{fill:#000 !important}#mermaid-svg-jefhpveyWB8IjK34 .crit0,#mermaid-svg-jefhpveyWB8IjK34 .crit1,#mermaid-svg-jefhpveyWB8IjK34 .crit2,#mermaid-svg-jefhpveyWB8IjK34 .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-jefhpveyWB8IjK34 .activeCrit0,#mermaid-svg-jefhpveyWB8IjK34 .activeCrit1,#mermaid-svg-jefhpveyWB8IjK34 .activeCrit2,#mermaid-svg-jefhpveyWB8IjK34 .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-jefhpveyWB8IjK34 .doneCrit0,#mermaid-svg-jefhpveyWB8IjK34 .doneCrit1,#mermaid-svg-jefhpveyWB8IjK34 .doneCrit2,#mermaid-svg-jefhpveyWB8IjK34 .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-jefhpveyWB8IjK34 .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-jefhpveyWB8IjK34 .milestoneText{font-style:italic}#mermaid-svg-jefhpveyWB8IjK34 .doneCritText0,#mermaid-svg-jefhpveyWB8IjK34 .doneCritText1,#mermaid-svg-jefhpveyWB8IjK34 .doneCritText2,#mermaid-svg-jefhpveyWB8IjK34 .doneCritText3{fill:#000 !important}#mermaid-svg-jefhpveyWB8IjK34 .activeCritText0,#mermaid-svg-jefhpveyWB8IjK34 .activeCritText1,#mermaid-svg-jefhpveyWB8IjK34 .activeCritText2,#mermaid-svg-jefhpveyWB8IjK34 .activeCritText3{fill:#000 !important}#mermaid-svg-jefhpveyWB8IjK34 .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-jefhpveyWB8IjK34 g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-jefhpveyWB8IjK34 g.classGroup text .title{font-weight:bolder}#mermaid-svg-jefhpveyWB8IjK34 g.clickable{cursor:pointer}#mermaid-svg-jefhpveyWB8IjK34 g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-jefhpveyWB8IjK34 g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-jefhpveyWB8IjK34 .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-jefhpveyWB8IjK34 .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-jefhpveyWB8IjK34 .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-jefhpveyWB8IjK34 .dashed-line{stroke-dasharray:3}#mermaid-svg-jefhpveyWB8IjK34 #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-jefhpveyWB8IjK34 #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-jefhpveyWB8IjK34 #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-jefhpveyWB8IjK34 #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-jefhpveyWB8IjK34 #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-jefhpveyWB8IjK34 #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-jefhpveyWB8IjK34 #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-jefhpveyWB8IjK34 #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-jefhpveyWB8IjK34 .commit-id,#mermaid-svg-jefhpveyWB8IjK34 .commit-msg,#mermaid-svg-jefhpveyWB8IjK34 .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-jefhpveyWB8IjK34 .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-jefhpveyWB8IjK34 .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-jefhpveyWB8IjK34 g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-jefhpveyWB8IjK34 g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-jefhpveyWB8IjK34 g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-jefhpveyWB8IjK34 g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-jefhpveyWB8IjK34 g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-jefhpveyWB8IjK34 g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-jefhpveyWB8IjK34 .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-jefhpveyWB8IjK34 .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-jefhpveyWB8IjK34 .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-jefhpveyWB8IjK34 .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-jefhpveyWB8IjK34 .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-jefhpveyWB8IjK34 .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-jefhpveyWB8IjK34 .edgeLabel text{fill:#333}#mermaid-svg-jefhpveyWB8IjK34 .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-jefhpveyWB8IjK34 .node circle.state-start{fill:black;stroke:black}#mermaid-svg-jefhpveyWB8IjK34 .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-jefhpveyWB8IjK34 #statediagram-barbEnd{fill:#9370db}#mermaid-svg-jefhpveyWB8IjK34 .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-jefhpveyWB8IjK34 .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-jefhpveyWB8IjK34 .statediagram-state .divider{stroke:#9370db}#mermaid-svg-jefhpveyWB8IjK34 .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-jefhpveyWB8IjK34 .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-jefhpveyWB8IjK34 .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-jefhpveyWB8IjK34 .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-jefhpveyWB8IjK34 .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-jefhpveyWB8IjK34 .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-jefhpveyWB8IjK34 .note-edge{stroke-dasharray:5}#mermaid-svg-jefhpveyWB8IjK34 .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-jefhpveyWB8IjK34 .error-icon{fill:#522}#mermaid-svg-jefhpveyWB8IjK34 .error-text{fill:#522;stroke:#522}#mermaid-svg-jefhpveyWB8IjK34 .edge-thickness-normal{stroke-width:2px}#mermaid-svg-jefhpveyWB8IjK34 .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-jefhpveyWB8IjK34 .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-jefhpveyWB8IjK34 .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-jefhpveyWB8IjK34 .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-jefhpveyWB8IjK34 .marker{fill:#333}#mermaid-svg-jefhpveyWB8IjK34 .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}#mermaid-svg-jefhpveyWB8IjK34 {color: rgba(0, 0, 0, 0.75);font: ;}MergeManifests.ConfigAction.executeMergeManifests.doFullTaskActionAndroidBuilder.mergeManifestsForApplicationManifestMerger2.Invoker.mergeManifestMerger2.mergeManifestMerger2.writeReport整個(gè)merge重點(diǎn)集中在ManifestMerge2.merge方法中
4. 核心類(MergeManifests)
public class MergeManifests extends ManifestProcessorTask {...@Overrideprotected void doFullTaskAction() throws IOException {// read the output of the compatible screen manifest.BuildElements compatibleScreenManifests =ExistingBuildElements.from(InternalArtifactType.COMPATIBLE_SCREEN_MANIFEST, compatibleScreensManifest);ModuleMetadata moduleMetadata = null;if (packageManifest != null && !packageManifest.isEmpty()) {moduleMetadata = ModuleMetadata.load(packageManifest.getSingleFile());boolean isDebuggable = optionalFeatures.get().contains(Feature.DEBUGGABLE);if (moduleMetadata.getDebuggable() != isDebuggable) {...}}@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 .....for (ApkData apkData : outputScope.getApkDatas()) {compatibleScreenManifestForSplit = compatibleScreenManifests.element(apkData);// 1. 構(gòu)建一個(gè)合并的清單文件;// path:build/intermediates/merged_manifests/${buildType}/process${BuildType}Manifest/merged/AndroidManifest.xmlFile manifestOutputFile =FileUtils.join(getManifestOutputDirectory(),apkData.getDirName(),SdkConstants.ANDROID_MANIFEST_XML);File instantRunManifestOutputFile =FileUtils.join(getInstantRunManifestOutputDirectory(),apkData.getDirName(),SdkConstants.ANDROID_MANIFEST_XML);// 2. merge AndroidManifest.xmlMergingReport mergingReport =getBuilder().mergeManifestsForApplication(getMainManifest(),getManifestOverlays(),computeFullProviderList(compatibleScreenManifestForSplit),getNavigationFiles(),getFeatureName(),moduleMetadata == null? getPackageOverride(): moduleMetadata.getApplicationId(),moduleMetadata == null? apkData.getVersionCode(): Integer.parseInt(moduleMetadata.getVersionCode()),moduleMetadata == null? apkData.getVersionName(): moduleMetadata.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(InternalArtifactType.MERGED_MANIFESTS,apkData,manifestOutputFile,properties));irMergedManifestOutputs.add(new BuildOutput(InternalArtifactType.INSTANT_RUN_MERGED_MANIFESTS,apkData,instantRunManifestOutputFile,properties));}// 3. save merged AndroidManifest.xml and output.json filenew BuildElements(mergedManifestOutputs.build()).save(getManifestOutputDirectory());new BuildElements(irMergedManifestOutputs.build()).save(getInstantRunManifestOutputDirectory());} }從上述代碼可以看到merge AndroidMainfest動(dòng)作集中在AndroidBuilder.mergeManifestsForApplication中
5. AndroidBuilder.mergeManifestsForApplication
/** Invoke the Manifest Merger version 2. */ public MergingReport mergeManifestsForApplication(@NonNull File mainManifest,@NonNull List<File> manifestOverlays,@NonNull List<? extends ManifestProvider> dependencies,@NonNull List<File> navigationFiles,@Nullable String featureName,String packageOverride,int versionCode,String versionName,@Nullable String minSdkVersion,@Nullable String targetSdkVersion,@Nullable Integer maxSdkVersion,@NonNull String outManifestLocation,@Nullable String outAaptSafeManifestLocation,@Nullable String outInstantRunManifestLocation,ManifestMerger2.MergeType mergeType,Map<String, Object> placeHolders,@NonNull Collection<Invoker.Feature> optionalFeatures,@Nullable File reportFile) {try {// 1. 構(gòu)建合并工具對(duì)象用于合并操作Invoker manifestMergerInvoker =ManifestMerger2.newMerger(mainManifest, mLogger, mergeType).setPlaceHolderValues(placeHolders).addFlavorAndBuildTypeManifests(manifestOverlays.toArray(new File[manifestOverlays.size()])).addManifestProviders(dependencies).addNavigationFiles(navigationFiles).withFeatures(optionalFeatures.toArray(new Invoker.Feature[optionalFeatures.size()])).setMergeReportFile(reportFile).setFeatureName(featureName);if (mergeType == ManifestMerger2.MergeType.APPLICATION) {manifestMergerInvoker.withFeatures(Invoker.Feature.REMOVE_TOOLS_DECLARATIONS);}//noinspection VariableNotUsedInsideIfif (outAaptSafeManifestLocation != null) {manifestMergerInvoker.withFeatures(Invoker.Feature.MAKE_AAPT_SAFE);}// 2. 注入幾個(gè)清單系統(tǒng)屬性值到清單文件中setInjectableValues(manifestMergerInvoker,packageOverride, versionCode, versionName,minSdkVersion, targetSdkVersion, maxSdkVersion);// 3. 執(zhí)行合并操作,如何合并操作OK,執(zhí)行寫操作,否則提示相關(guān)報(bào)錯(cuò)信息MergingReport mergingReport = manifestMergerInvoker.merge();mLogger.verbose("Merging result: %1$s", mergingReport.getResult());switch (mergingReport.getResult()) {case WARNING:mergingReport.log(mLogger);// fall through since these are just warnings.case SUCCESS:String xmlDocument = mergingReport.getMergedDocument(MergingReport.MergedManifestKind.MERGED);String annotatedDocument = mergingReport.getMergedDocument(MergingReport.MergedManifestKind.BLAME);if (annotatedDocument != null) {mLogger.verbose(annotatedDocument);}save(xmlDocument, new File(outManifestLocation));mLogger.verbose("Merged manifest saved to " + outManifestLocation);if (outAaptSafeManifestLocation != null) {save(mergingReport.getMergedDocument(MergingReport.MergedManifestKind.AAPT_SAFE),new File(outAaptSafeManifestLocation));}if (outInstantRunManifestLocation != null) {String instantRunMergedManifest = mergingReport.getMergedDocument(MergingReport.MergedManifestKind.INSTANT_RUN);if (instantRunMergedManifest != null) {save(instantRunMergedManifest, new File(outInstantRunManifestLocation));}}break;case ERROR:mergingReport.log(mLogger);throw new RuntimeException(mergingReport.getReportString());default:throw new RuntimeException("Unhandled result type : "+ mergingReport.getResult());}return mergingReport;} catch (ManifestMerger2.MergeFailureException e) {// TODO: unacceptable.throw new RuntimeException(e);} } /*** Sets the {@link ManifestSystemProperty} that can be injected* in the manifest file.*/ private static void setInjectableValues(ManifestMerger2.Invoker<?> invoker,String packageOverride,int versionCode,String versionName,@Nullable String minSdkVersion,@Nullable String targetSdkVersion,@Nullable Integer maxSdkVersion) {if (!Strings.isNullOrEmpty(packageOverride)) {invoker.setOverride(ManifestSystemProperty.PACKAGE, packageOverride);}if (versionCode > 0) {invoker.setOverride(ManifestSystemProperty.VERSION_CODE,String.valueOf(versionCode));}if (!Strings.isNullOrEmpty(versionName)) {invoker.setOverride(ManifestSystemProperty.VERSION_NAME, versionName);}if (!Strings.isNullOrEmpty(minSdkVersion)) {invoker.setOverride(ManifestSystemProperty.MIN_SDK_VERSION, minSdkVersion);}if (!Strings.isNullOrEmpty(targetSdkVersion)) {invoker.setOverride(ManifestSystemProperty.TARGET_SDK_VERSION, targetSdkVersion);}if (maxSdkVersion != null) {invoker.setOverride(ManifestSystemProperty.MAX_SDK_VERSION, maxSdkVersion.toString());} }mergeManifestsForApplication主要有三個(gè)操作
這里的幾個(gè)屬性值其實(shí)就是大家熟知的applicationId、versionCode、versionName、minSdkVersion、targetSdkVersion等;為后面注入做準(zhǔn)備
步驟二操作最終還是轉(zhuǎn)給了ManifestMerge2.merge
6. ManifestMerge2.merge
merge主要概括為幾個(gè)步驟
校驗(yàn)主清單文件合法性(manifest:package屬性是否聲明)
// first do we have a package declaration in the main manifest ? Optional<XmlAttribute> mainPackageAttribute =loadedMainManifestInfo.getXmlDocument().getPackage(); if (mDocumentType != XmlDocument.Type.OVERLAY && !mainPackageAttribute.isPresent()) {mergingReportBuilder.addMessage(loadedMainManifestInfo.getXmlDocument().getSourceFile(),MergingReport.Record.Severity.ERROR,String.format("Main AndroidManifest.xml at %1$s manifest:package attribute "+ "is not declared",loadedMainManifestInfo.getXmlDocument().getSourceFile().print(true)));return mergingReportBuilder.build(); }加載所有l(wèi)ibrary的清單文件
// load all the libraries xml files early to have a list of all possible node:selector // values. List<LoadedManifestInfo> loadedLibraryDocuments =loadLibraries(selectors,mergingReportBuilder,mainPackageAttribute.isPresent()? mainPackageAttribute.get().getValue(): null);將系統(tǒng)屬性值注入到主清單文件中
// perform system property injection performSystemPropertiesInjection(mergingReportBuilder, loadedMainManifestInfo.getXmlDocument())重新解析主清單文件(因?yàn)橄到y(tǒng)屬性值可能被3操作修改)
// force the re-parsing of the xml as elements may have been added through system // property injection. loadedMainManifestInfo = new LoadedManifestInfo(loadedMainManifestInfo,loadedMainManifestInfo.getOriginalPackageName(),loadedMainManifestInfo.getXmlDocument().reparse());對(duì)flavors和buildType特定的清單文件進(jìn)行校驗(yàn)/合并(包含元素重復(fù)校驗(yàn)等操作)操作
// invariant : xmlDocumentOptional holds the higher priority document and we try to// merge in lower priority documents.Optional<XmlDocument> xmlDocumentOptional = Optional.absent();for (File inputFile : mFlavorsAndBuildTypeFiles) {mLogger.verbose("Merging flavors and build manifest %s \n", inputFile.getPath());LoadedManifestInfo overlayDocument = load(new ManifestInfo(null, inputFile, XmlDocument.Type.OVERLAY,Optional.of(mainPackageAttribute.get().getValue())),selectors,mergingReportBuilder);// check package declaration.Optional<XmlAttribute> packageAttribute =overlayDocument.getXmlDocument().getPackage();// if both files declare a package name, it should be the same.if (loadedMainManifestInfo.getOriginalPackageName().isPresent() &&packageAttribute.isPresent()&& !loadedMainManifestInfo.getOriginalPackageName().get().equals(packageAttribute.get().getValue())) {// no suggestion for library since this is actually forbidden to change the// the package name per flavor.// 1. 清單文件中包名校驗(yàn)操作String message = mMergeType == MergeType.APPLICATION? String.format("Overlay manifest:package attribute declared at %1$s value=(%2$s)\n"+ "\thas a different value=(%3$s) "+ "declared in main manifest at %4$s\n"+ "\tSuggestion: remove the overlay declaration at %5$s "+ "\tand place it in the build.gradle:\n"+ "\t\tflavorName {\n"+ "\t\t\tapplicationId = \"%2$s\"\n"+ "\t\t}",packageAttribute.get().printPosition(),packageAttribute.get().getValue(),mainPackageAttribute.get().getValue(),mainPackageAttribute.get().printPosition(),packageAttribute.get().getSourceFile().print(true)): String.format("Overlay manifest:package attribute declared at %1$s value=(%2$s)\n"+ "\thas a different value=(%3$s) "+ "declared in main manifest at %4$s",packageAttribute.get().printPosition(),packageAttribute.get().getValue(),mainPackageAttribute.get().getValue(),mainPackageAttribute.get().printPosition());mergingReportBuilder.addMessage(overlayDocument.getXmlDocument().getSourceFile(),MergingReport.Record.Severity.ERROR,message);return mergingReportBuilder.build();}overlayDocument.getXmlDocument().getRootNode().getXml().setAttribute("package",mainPackageAttribute.get().getValue());// 2.合并操作;將overlayDocument(低優(yōu)先級(jí))合并到xmlDocumentOptional中xmlDocumentOptional = merge(xmlDocumentOptional, overlayDocument, mergingReportBuilder);if (!xmlDocumentOptional.isPresent()) {return mergingReportBuilder.build();}}如果 build.gradle中的applicationId和flavor/buildType中的清單文件包名如果存在不一致則構(gòu)建會(huì)失敗,錯(cuò)誤類似如下
將主清單文件合并到xmlDocumentOptioal中
mLogger.verbose("Merging main manifest %s\n", mManifestFile.getPath()); xmlDocumentOptional =merge(xmlDocumentOptional, loadedMainManifestInfo, mergingReportBuilder);if (!xmlDocumentOptional.isPresent()) {return mergingReportBuilder.build(); }這操作也解釋了為什么flavor/buildType中的清單文件優(yōu)先級(jí)會(huì)比主清單文件高
合并庫清單文件
// force main manifest package into resulting merged file when creating a library manifest. if (mMergeType == MergeType.LIBRARY) {// extract the package name...String mainManifestPackageName = loadedMainManifestInfo.getXmlDocument().getRootNode().getXml().getAttribute("package");// save it in the selector instance.if (!Strings.isNullOrEmpty(mainManifestPackageName)) {xmlDocumentOptional.get().getRootNode().getXml().setAttribute("package", mainManifestPackageName);}}for (LoadedManifestInfo libraryDocument : loadedLibraryDocuments) {mLogger.verbose("Merging library manifest " + libraryDocument.getLocation());xmlDocumentOptional = merge(xmlDocumentOptional, libraryDocument, mergingReportBuilder);if (!xmlDocumentOptional.isPresent()) {return mergingReportBuilder.build();}}不難推測(cè)出AndroidManifest.xml的優(yōu)先級(jí)是flavor/buildType > Main > Library
導(dǎo)航組件合并
// done with proper merging phase, now we need to expand <nav-graph> elements, trim unwanted // elements, perform placeholder substitution and system properties injection. Map<String, NavigationXmlDocument> loadedNavigationMap = new HashMap<>(); for (File navigationFile : mNavigationFiles) {String navigationId = navigationFile.getName().replaceAll("\\.xml$", "");if (loadedNavigationMap.get(navigationId) != null) {continue;}try (InputStream inputStream = mFileStreamProvider.getInputStream(navigationFile)) {loadedNavigationMap.put(navigationId,NavigationXmlLoader.INSTANCE.load(navigationId, navigationFile, inputStream));} catch (Exception e) {throw new MergeFailureException(e);} } xmlDocumentOptional =Optional.of(NavGraphExpander.INSTANCE.expandNavGraphs(xmlDocumentOptional.get(),loadedNavigationMap,mergingReportBuilder)); if (mergingReportBuilder.hasErrors()) {return mergingReportBuilder.build(); }ElementsTrimmer.trim(xmlDocumentOptional.get(), mergingReportBuilder); if (mergingReportBuilder.hasErrors()) {return mergingReportBuilder.build(); }構(gòu)建變量注入清單
if (!mOptionalFeatures.contains(Invoker.Feature.NO_PLACEHOLDER_REPLACEMENT)) {// do one last placeholder substitution, this is useful as we don't stop the build// when a library failed a placeholder substitution, but the element might have// been overridden so the problem was transient. However, with the final document// ready, all placeholders values must have been provided.MergingReport.Record.Severity severity =mMergeType == MergeType.LIBRARY? MergingReport.Record.Severity.INFO: MergingReport.Record.Severity.ERROR;performPlaceHolderSubstitution(loadedMainManifestInfo,xmlDocumentOptional.get(),mergingReportBuilder,severity);if (mergingReportBuilder.hasErrors()) {return mergingReportBuilder.build();} }系統(tǒng)屬性注入
// perform system property injection. performSystemPropertiesInjection(mergingReportBuilder, xmlDocumentOptional.get())記錄操作并保存到日志
mergingReportBuilder.setFinalPackageName(finalMergedDocument.getPackageName()); mergingReportBuilder.setMergedXmlDocument(MergingReport.MergedManifestKind.MERGED, finalMergedDocument);MergingReport mergingReport = mergingReportBuilder.build();if (mReportFile.isPresent()) {writeReport(mergingReport);}return mergingReport;日志文件中記錄了整個(gè)合并清單文件中的各個(gè)動(dòng)作,其位置和內(nèi)容如下
Task14: splitsDiscoveryTaskDebug
為驗(yàn)證splits相關(guān)輸出產(chǎn)物,需要在build.gradle中添加如下代碼
splits {density {enable trueexclude "ldpi", "xhdpi", "xxxhdpi","mdpi"}abi {enable trueinclude "x86"exclude "x86_64","arm64-v8a"}}1. input/ouput
taskName:splitsDiscoveryTaskDebug ========================================================= output:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/intermediates/split_list/debug/splitsDiscoveryTaskDebug/split-list.gson該任務(wù)輸出split-list.json文件用來記錄splits配置的filters相關(guān)信息
[{"splitType": "DENSITY","filters": [{"value": "xxhdpi"},{"value": "hdpi"}]},{"splitType": "LANGUAGE","filters": []},{"splitType": "ABI","filters": [{"value": "x86"},{"value": "armeabi-v7a"}]},{"splitType": "ResConfigs","filters": []} ]2. 核心類(SplitsDiscovery)
@TaskAction void taskAction() throws IOException {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()));}//SplitList.java public static synchronized void save(@NonNull File outputFile,@NonNull Collection<Filter> densityFilters,@NonNull Collection<Filter> languageFilters,@NonNull Collection<Filter> abiFilters,@NonNull Collection<Filter> resourceConfigs)throws IOException {ImmutableList<Record> records =ImmutableList.of(new Record(OutputFile.FilterType.DENSITY.name(), densityFilters),new Record(OutputFile.FilterType.LANGUAGE.name(), languageFilters),new Record(OutputFile.FilterType.ABI.name(), abiFilters),new Record(RESOURCE_CONFIGS, resourceConfigs));Gson gson = new Gson();String listOfFilters = gson.toJson(records);FileUtils.write(outputFile, listOfFilters);}這個(gè)任務(wù)很簡(jiǎn)單,大家自己看看源碼,此處不再贅述
Task15: processDebugResources
1. input/output
taskName:processDebugResources 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/intermediates/apk_list/debug/mainApkListPersistenceDebug/apk-list.gson input:/Users/apple/.gradle/caches/transforms-1/files-1.1/2774ea4f1cf1e83a6ad8e8d3c8b463b6/fb74d3934b89348681de5912dd579470/package-aware-r.txt input:/Users/apple/.gradle/caches/transforms-1/files-1.1/f43c0ba95b6494825ed940fc4f04662b/a4dc303cf15df05fd52e4aa68bb3e24b/package-aware-r.txt input:/Users/apple/.gradle/caches/transforms-1/files-1.1/559112320064089dfaf6780e71d5b44f/528c8bc27f87079d1a5feb19167d8529/package-aware-r.txt input:/Users/apple/.gradle/caches/transforms-1/files-1.1/c2c3ad4abfd49316f6769b8238b0f010/44eff7e3109a2a25c778ec9eea73330f/package-aware-r.txt input:/Users/apple/.gradle/caches/transforms-1/files-1.1/9ac5f97e8ccb24c52b7cbb6202c12ad0/03664ae6771a578888f58946abef2c97/package-aware-r.txt input:/Users/apple/.gradle/caches/transforms-1/files-1.1/53ab5ad72634f3497309a8788f3ca200/e8f8785dfba7408948b434106eedffb0/package-aware-r.txt input:/Users/apple/.gradle/caches/transforms-1/files-1.1/7e6a4ce6591d722d47aafc36d980f8b4/5eadbed13a71b081489e135cd7029e3c/package-aware-r.txt input:/Users/apple/.gradle/caches/transforms-1/files-1.1/4c474caa9ac1f01c4936bd96905ecacd/758757c855a983785c9f95f25701bf31/package-aware-r.txt input:/Users/apple/.gradle/caches/transforms-1/files-1.1/868eaa7e0c620cd85d72ad4f340e8bb1/d70d6bf0b6654f3820b804ca284240c5/package-aware-r.txt input:/Users/apple/.gradle/caches/transforms-1/files-1.1/4ec3c1c46e5bad9ac3b91f45a2afec3e/d22ce50748e9f79823928b22234498f1/package-aware-r.txt input:/Users/apple/.gradle/caches/transforms-1/files-1.1/5b2333922ba05b1f174de51739b24d14/38a5e94d88e675da0d746fcc4cc77239/package-aware-r.txt input:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/intermediates/res/merged/debug input:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/intermediates/split_list/debug/splitsDiscoveryTaskDebug/split-list.gson input:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/intermediates/merged_manifests/debug/processDebugManifest/merged ========================================================= output:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/intermediates/incremental/processDebugResources output:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/intermediates/processed_res/debug/processDebugResources/out output:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/generated/not_namespaced_r_class_sources/debug/processDebugResources/r output:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/intermediates/res/symbol-table-with-package/debug/package-aware-r.txt output:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/intermediates/symbols/debug/R.txt該任務(wù)主要是將aapt編譯后的flat產(chǎn)物和對(duì)合并后的清單文件進(jìn)行鏈接處理生成.ap_文件,ap_文件解壓后其實(shí)包含三類文件,資源文件、清單文件、資源關(guān)系映射表文件(resources.arsc)
除了.ap_文件外還會(huì)生成我們熟悉的R.java文件
symbols/debug/R.txt保存了資源類型,資源名稱,以及地址的映射關(guān)系
2. 整體流程
#mermaid-svg-yUtvayuHWOA9r6F5 .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-yUtvayuHWOA9r6F5 .label text{fill:#333}#mermaid-svg-yUtvayuHWOA9r6F5 .node rect,#mermaid-svg-yUtvayuHWOA9r6F5 .node circle,#mermaid-svg-yUtvayuHWOA9r6F5 .node ellipse,#mermaid-svg-yUtvayuHWOA9r6F5 .node polygon,#mermaid-svg-yUtvayuHWOA9r6F5 .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-yUtvayuHWOA9r6F5 .node .label{text-align:center;fill:#333}#mermaid-svg-yUtvayuHWOA9r6F5 .node.clickable{cursor:pointer}#mermaid-svg-yUtvayuHWOA9r6F5 .arrowheadPath{fill:#333}#mermaid-svg-yUtvayuHWOA9r6F5 .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-yUtvayuHWOA9r6F5 .flowchart-link{stroke:#333;fill:none}#mermaid-svg-yUtvayuHWOA9r6F5 .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-yUtvayuHWOA9r6F5 .edgeLabel rect{opacity:0.9}#mermaid-svg-yUtvayuHWOA9r6F5 .edgeLabel span{color:#333}#mermaid-svg-yUtvayuHWOA9r6F5 .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-yUtvayuHWOA9r6F5 .cluster text{fill:#333}#mermaid-svg-yUtvayuHWOA9r6F5 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-yUtvayuHWOA9r6F5 .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-yUtvayuHWOA9r6F5 text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-yUtvayuHWOA9r6F5 .actor-line{stroke:grey}#mermaid-svg-yUtvayuHWOA9r6F5 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-yUtvayuHWOA9r6F5 .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-yUtvayuHWOA9r6F5 #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-yUtvayuHWOA9r6F5 .sequenceNumber{fill:#fff}#mermaid-svg-yUtvayuHWOA9r6F5 #sequencenumber{fill:#333}#mermaid-svg-yUtvayuHWOA9r6F5 #crosshead path{fill:#333;stroke:#333}#mermaid-svg-yUtvayuHWOA9r6F5 .messageText{fill:#333;stroke:#333}#mermaid-svg-yUtvayuHWOA9r6F5 .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-yUtvayuHWOA9r6F5 .labelText,#mermaid-svg-yUtvayuHWOA9r6F5 .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-yUtvayuHWOA9r6F5 .loopText,#mermaid-svg-yUtvayuHWOA9r6F5 .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-yUtvayuHWOA9r6F5 .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-yUtvayuHWOA9r6F5 .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-yUtvayuHWOA9r6F5 .noteText,#mermaid-svg-yUtvayuHWOA9r6F5 .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-yUtvayuHWOA9r6F5 .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-yUtvayuHWOA9r6F5 .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-yUtvayuHWOA9r6F5 .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-yUtvayuHWOA9r6F5 .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-yUtvayuHWOA9r6F5 .section{stroke:none;opacity:0.2}#mermaid-svg-yUtvayuHWOA9r6F5 .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-yUtvayuHWOA9r6F5 .section2{fill:#fff400}#mermaid-svg-yUtvayuHWOA9r6F5 .section1,#mermaid-svg-yUtvayuHWOA9r6F5 .section3{fill:#fff;opacity:0.2}#mermaid-svg-yUtvayuHWOA9r6F5 .sectionTitle0{fill:#333}#mermaid-svg-yUtvayuHWOA9r6F5 .sectionTitle1{fill:#333}#mermaid-svg-yUtvayuHWOA9r6F5 .sectionTitle2{fill:#333}#mermaid-svg-yUtvayuHWOA9r6F5 .sectionTitle3{fill:#333}#mermaid-svg-yUtvayuHWOA9r6F5 .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-yUtvayuHWOA9r6F5 .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-yUtvayuHWOA9r6F5 .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-yUtvayuHWOA9r6F5 .grid path{stroke-width:0}#mermaid-svg-yUtvayuHWOA9r6F5 .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-yUtvayuHWOA9r6F5 .task{stroke-width:2}#mermaid-svg-yUtvayuHWOA9r6F5 .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-yUtvayuHWOA9r6F5 .taskText:not([font-size]){font-size:11px}#mermaid-svg-yUtvayuHWOA9r6F5 .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-yUtvayuHWOA9r6F5 .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-yUtvayuHWOA9r6F5 .task.clickable{cursor:pointer}#mermaid-svg-yUtvayuHWOA9r6F5 .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-yUtvayuHWOA9r6F5 .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-yUtvayuHWOA9r6F5 .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-yUtvayuHWOA9r6F5 .taskText0,#mermaid-svg-yUtvayuHWOA9r6F5 .taskText1,#mermaid-svg-yUtvayuHWOA9r6F5 .taskText2,#mermaid-svg-yUtvayuHWOA9r6F5 .taskText3{fill:#fff}#mermaid-svg-yUtvayuHWOA9r6F5 .task0,#mermaid-svg-yUtvayuHWOA9r6F5 .task1,#mermaid-svg-yUtvayuHWOA9r6F5 .task2,#mermaid-svg-yUtvayuHWOA9r6F5 .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-yUtvayuHWOA9r6F5 .taskTextOutside0,#mermaid-svg-yUtvayuHWOA9r6F5 .taskTextOutside2{fill:#000}#mermaid-svg-yUtvayuHWOA9r6F5 .taskTextOutside1,#mermaid-svg-yUtvayuHWOA9r6F5 .taskTextOutside3{fill:#000}#mermaid-svg-yUtvayuHWOA9r6F5 .active0,#mermaid-svg-yUtvayuHWOA9r6F5 .active1,#mermaid-svg-yUtvayuHWOA9r6F5 .active2,#mermaid-svg-yUtvayuHWOA9r6F5 .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-yUtvayuHWOA9r6F5 .activeText0,#mermaid-svg-yUtvayuHWOA9r6F5 .activeText1,#mermaid-svg-yUtvayuHWOA9r6F5 .activeText2,#mermaid-svg-yUtvayuHWOA9r6F5 .activeText3{fill:#000 !important}#mermaid-svg-yUtvayuHWOA9r6F5 .done0,#mermaid-svg-yUtvayuHWOA9r6F5 .done1,#mermaid-svg-yUtvayuHWOA9r6F5 .done2,#mermaid-svg-yUtvayuHWOA9r6F5 .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-yUtvayuHWOA9r6F5 .doneText0,#mermaid-svg-yUtvayuHWOA9r6F5 .doneText1,#mermaid-svg-yUtvayuHWOA9r6F5 .doneText2,#mermaid-svg-yUtvayuHWOA9r6F5 .doneText3{fill:#000 !important}#mermaid-svg-yUtvayuHWOA9r6F5 .crit0,#mermaid-svg-yUtvayuHWOA9r6F5 .crit1,#mermaid-svg-yUtvayuHWOA9r6F5 .crit2,#mermaid-svg-yUtvayuHWOA9r6F5 .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-yUtvayuHWOA9r6F5 .activeCrit0,#mermaid-svg-yUtvayuHWOA9r6F5 .activeCrit1,#mermaid-svg-yUtvayuHWOA9r6F5 .activeCrit2,#mermaid-svg-yUtvayuHWOA9r6F5 .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-yUtvayuHWOA9r6F5 .doneCrit0,#mermaid-svg-yUtvayuHWOA9r6F5 .doneCrit1,#mermaid-svg-yUtvayuHWOA9r6F5 .doneCrit2,#mermaid-svg-yUtvayuHWOA9r6F5 .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-yUtvayuHWOA9r6F5 .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-yUtvayuHWOA9r6F5 .milestoneText{font-style:italic}#mermaid-svg-yUtvayuHWOA9r6F5 .doneCritText0,#mermaid-svg-yUtvayuHWOA9r6F5 .doneCritText1,#mermaid-svg-yUtvayuHWOA9r6F5 .doneCritText2,#mermaid-svg-yUtvayuHWOA9r6F5 .doneCritText3{fill:#000 !important}#mermaid-svg-yUtvayuHWOA9r6F5 .activeCritText0,#mermaid-svg-yUtvayuHWOA9r6F5 .activeCritText1,#mermaid-svg-yUtvayuHWOA9r6F5 .activeCritText2,#mermaid-svg-yUtvayuHWOA9r6F5 .activeCritText3{fill:#000 !important}#mermaid-svg-yUtvayuHWOA9r6F5 .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-yUtvayuHWOA9r6F5 g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-yUtvayuHWOA9r6F5 g.classGroup text .title{font-weight:bolder}#mermaid-svg-yUtvayuHWOA9r6F5 g.clickable{cursor:pointer}#mermaid-svg-yUtvayuHWOA9r6F5 g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-yUtvayuHWOA9r6F5 g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-yUtvayuHWOA9r6F5 .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-yUtvayuHWOA9r6F5 .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-yUtvayuHWOA9r6F5 .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-yUtvayuHWOA9r6F5 .dashed-line{stroke-dasharray:3}#mermaid-svg-yUtvayuHWOA9r6F5 #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-yUtvayuHWOA9r6F5 #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-yUtvayuHWOA9r6F5 #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-yUtvayuHWOA9r6F5 #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-yUtvayuHWOA9r6F5 #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-yUtvayuHWOA9r6F5 #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-yUtvayuHWOA9r6F5 #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-yUtvayuHWOA9r6F5 #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-yUtvayuHWOA9r6F5 .commit-id,#mermaid-svg-yUtvayuHWOA9r6F5 .commit-msg,#mermaid-svg-yUtvayuHWOA9r6F5 .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-yUtvayuHWOA9r6F5 .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-yUtvayuHWOA9r6F5 .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-yUtvayuHWOA9r6F5 g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-yUtvayuHWOA9r6F5 g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-yUtvayuHWOA9r6F5 g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-yUtvayuHWOA9r6F5 g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-yUtvayuHWOA9r6F5 g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-yUtvayuHWOA9r6F5 g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-yUtvayuHWOA9r6F5 .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-yUtvayuHWOA9r6F5 .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-yUtvayuHWOA9r6F5 .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-yUtvayuHWOA9r6F5 .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-yUtvayuHWOA9r6F5 .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-yUtvayuHWOA9r6F5 .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-yUtvayuHWOA9r6F5 .edgeLabel text{fill:#333}#mermaid-svg-yUtvayuHWOA9r6F5 .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-yUtvayuHWOA9r6F5 .node circle.state-start{fill:black;stroke:black}#mermaid-svg-yUtvayuHWOA9r6F5 .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-yUtvayuHWOA9r6F5 #statediagram-barbEnd{fill:#9370db}#mermaid-svg-yUtvayuHWOA9r6F5 .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-yUtvayuHWOA9r6F5 .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-yUtvayuHWOA9r6F5 .statediagram-state .divider{stroke:#9370db}#mermaid-svg-yUtvayuHWOA9r6F5 .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-yUtvayuHWOA9r6F5 .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-yUtvayuHWOA9r6F5 .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-yUtvayuHWOA9r6F5 .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-yUtvayuHWOA9r6F5 .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-yUtvayuHWOA9r6F5 .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-yUtvayuHWOA9r6F5 .note-edge{stroke-dasharray:5}#mermaid-svg-yUtvayuHWOA9r6F5 .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-yUtvayuHWOA9r6F5 .error-icon{fill:#522}#mermaid-svg-yUtvayuHWOA9r6F5 .error-text{fill:#522;stroke:#522}#mermaid-svg-yUtvayuHWOA9r6F5 .edge-thickness-normal{stroke-width:2px}#mermaid-svg-yUtvayuHWOA9r6F5 .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-yUtvayuHWOA9r6F5 .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-yUtvayuHWOA9r6F5 .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-yUtvayuHWOA9r6F5 .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-yUtvayuHWOA9r6F5 .marker{fill:#333}#mermaid-svg-yUtvayuHWOA9r6F5 .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}#mermaid-svg-yUtvayuHWOA9r6F5 {color: rgba(0, 0, 0, 0.75);font: ;}LinkApplicationAndroidResourcesTask.doFullTaskActioninvokeAaptForSplitAndroidBuilder.processResourcesAapt2DaemonManager.LeasedAaptDaemon.linkAapt2DaemoImpl.linkAapt2DaemonUtil.requestLink3. 核心類(LinkApplicationAndroidResourcesTask)
@Override protected void doFullTaskAction() throws IOException {...// 1. 讀取build/inermediates/merged_manifest/debug/processDebugManifest/merged/output.json文件;該文件記錄了打包出apkinfo(如果配置splits則可能是多個(gè)apkinfo)BuildElements manifestBuildElements =ExistingBuildElements.from(taskInputType, manifestFiles);...// 2. 構(gòu)建一個(gè)aapt對(duì)象(QueueableAapt2)try (@Nullable Aapt aapt = makeAapt()) {Aapt2ServiceKey aapt2ServiceKey;if (aaptGeneration == AaptGeneration.AAPT_V2_DAEMON_SHARED_POOL) {aapt2ServiceKey =Aapt2DaemonManagerService.registerAaptService(aapt2FromMaven, getBuildTools(), getILogger());} else {aapt2ServiceKey = null;}// 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());for (BuildOutput manifestBuildOutput : manifestBuildElements) {ApkInfo apkInfo = manifestBuildOutput.getApkInfo();boolean codeGen =(apkInfo.getType() == OutputFile.OutputType.MAIN|| apkInfo.getFilter(OutputFile.FilterType.DENSITY) == null);if (codeGen) {unprocessedManifest.remove(manifestBuildOutput);buildOutputs.add(invokeAaptForSplit(manifestBuildOutput,dependencies,imports,splitList,featureResourcePackages,apkInfo,true,aapt,aapt2ServiceKey));break;}}// now all remaining splits will be generated asynchronously.if (variantScope.getType().getCanHaveSplits()) {for (BuildOutput manifestBuildOutput : unprocessedManifest) {ApkInfo apkInfo = manifestBuildOutput.getApkInfo();if (apkInfo.requiresAapt()) {executor.execute(() ->invokeAaptForSplit(manifestBuildOutput,dependencies,imports,splitList,featureResourcePackages,apkInfo,false,aapt,aapt2ServiceKey));}}}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);}... }4. invokeAaptForSplit
BuildOutput invokeAaptForSplit(BuildOutput manifestOutput,@NonNull Set<File> dependencies,Set<File> imports,@NonNull SplitList splitList,@NonNull Set<File> featureResourcePackages,ApkInfo apkData,boolean generateCode,@Nullable Aapt aapt,@Nullable Aapt2ServiceKey aapt2ServiceKey)throws IOException {ImmutableList.Builder<File> featurePackagesBuilder = ImmutableList.builder();for (File featurePackage : featureResourcePackages) {BuildElements buildElements =ExistingBuildElements.from(InternalArtifactType.PROCESSED_RES, featurePackage);if (!buildElements.isEmpty()) {BuildOutput mainBuildOutput =buildElements.elementByType(VariantOutput.OutputType.MAIN);if (mainBuildOutput != null) {featurePackagesBuilder.add(mainBuildOutput.getOutputFile());} else {throw new IOException("Cannot find PROCESSED_RES output for "+ variantScope.getOutputScope().getMainSplit());}}}// 1. 指定了aapt鏈接輸出的文件名,格式為:resources-${apk.getFullName}.ap_// 路徑在build/intermediates/processed_res/debug/processDebugResources/outFile resOutBaseNameFile =new File(resPackageOutputFolder,FN_RES_BASE+ RES_QUALIFIER_SEP+ apkData.getFullName()+ SdkConstants.DOT_RES);File manifestFile = manifestOutput.getOutputFile();String packageForR = null;File srcOut = null;File symbolOutputDir = null;File proguardOutputFile = null;File mainDexListProguardOutputFile = null;if (generateCode) {// workaround for b/74068247. Until that's fixed, if it's a namespaced feature,// an extra empty dummy R.java file will be generated as wellif (isNamespaced&& variantScope.getVariantData().getType() == VariantTypeImpl.FEATURE) {packageForR = "dummy";} else {packageForR = originalApplicationId.get();}// we have to clean the source folder output in case the package name changed.srcOut = getSourceOutputDir();if (srcOut != null) {FileUtils.cleanOutputDir(srcOut);}// 指定主R.txt文件輸出目錄symbolOutputDir = textSymbolOutputDir.get();proguardOutputFile = getProguardOutputFile();mainDexListProguardOutputFile = getMainDexListProguardOutputFile();}FilterData densityFilterData = apkData.getFilter(OutputFile.FilterType.DENSITY);String preferredDensity =densityFilterData != null? densityFilterData.getIdentifier()// if resConfigs is set, we should not use our preferredDensity.: splitList.getFilters(SplitList.RESOURCE_CONFIGS).isEmpty()? buildTargetDensity: null;try {...// If the new resources flag is enabled and if we are dealing with a library process// resources through the new parsers{AaptPackageConfig.Builder configBuilder =new AaptPackageConfig.Builder().setManifestFile(manifestFile).setOptions(DslAdaptersKt.convert(aaptOptions)).setCustomPackageForR(packageForR).setSymbolOutputDir(symbolOutputDir).setSourceOutputDir(srcOut).setResourceOutputApk(resOutBaseNameFile).setProguardOutputFile(proguardOutputFile).setMainDexListProguardOutputFile(mainDexListProguardOutputFile).setVariantType(getType()).setDebuggable(getDebuggable()).setPseudoLocalize(getPseudoLocalesEnabled()).setResourceConfigs(splitList.getFilters(SplitList.RESOURCE_CONFIGS)).setSplits(getSplits(splitList)).setPreferredDensity(preferredDensity).setPackageId(getResOffset()).setAllowReservedPackageId(minSdkVersion < AndroidVersion.VersionCodes.O).setDependentFeatures(featurePackagesBuilder.build()).setImports(imports).setIntermediateDir(getIncrementalFolder()).setAndroidTarget(getBuilder().getTarget());if (isNamespaced) {configBuilder.setStaticLibraryDependencies(ImmutableList.copyOf(dependencies));} else {if (generateCode) {configBuilder.setLibrarySymbolTableFiles(dependencies);}configBuilder.setResourceDir(BuildableArtifactUtil.singleFile(checkNotNull(getInputResourcesDir())));}AaptPackageConfig config = configBuilder.build();if (aaptGeneration == AaptGeneration.AAPT_V2_DAEMON_SHARED_POOL) {Preconditions.checkNotNull(aapt2ServiceKey, "AAPT2 daemon manager service not initialized");try (Aapt2DaemonManager.LeasedAaptDaemon aaptDaemon =Aapt2DaemonManagerService.getAaptDaemon(aapt2ServiceKey)) {// 2. 處理資源文件AndroidBuilder.processResources(aaptDaemon, config, getILogger());} catch (Aapt2Exception e) {throw Aapt2ErrorUtils.rewriteLinkException(e, new MergingLog(getMergeBlameLogFolder()));}} else {Preconditions.checkNotNull(aapt,"AAPT needs be instantiated for linking if bypassing AAPT is disabled");AndroidBuilder.processResources(aapt, config, getILogger());}if (LOG.isInfoEnabled()) {LOG.info("Aapt output file {}", resOutBaseNameFile.getAbsolutePath());}}if (generateCode&& (isLibrary || !dependencies.isEmpty())&& symbolsWithPackageNameOutputFile != null) {// 3. 寫符號(hào)表文件package-aware-r.txt;// symbolsWithPackageNameOutputFile的賦值可以參見TaskManger.createNonNamespacedResourceTasks方法體,見下圖SymbolIo.writeSymbolListWithPackageName(Preconditions.checkNotNull(getTextSymbolOutputFile()).toPath(),manifestFile.toPath(),symbolsWithPackageNameOutputFile.toPath());}return new BuildOutput(InternalArtifactType.PROCESSED_RES,apkData,resOutBaseNameFile,manifestOutput.getProperties());} catch (ProcessException e) {throw new BuildException("Failed to process resources, see aapt output above for details.", e);}}總結(jié)下,主流程如下
每個(gè)module其實(shí)都會(huì)生成一個(gè)這樣的文件,首行為其packageName
5. package-aware-r.txt內(nèi)容格式如下
com.gradle.task.demo.debug anim abc_fade_in anim abc_fade_out anim abc_grow_fade_in_from_bottom attr borderlessButtonStyle attr buttonBarButtonStyle attr buttonBarNegativeButtonStyle ... bool abc_action_bar_embed_tabs bool abc_allow_stacked_button_bar bool abc_config_actionMenuItemAllCaps bool abc_config_closeDialogWhenTouchOutside bool abc_config_showMenuShortcutsWhenKeyboardPresent bool bool_is_boy color abc_background_cache_hint_selector_material_dark color abc_background_cache_hint_selector_material_light .. dimen abc_action_bar_content_inset_material dimen abc_action_bar_content_inset_with_nav dimen abc_action_bar_default_height_material dimen abc_action_bar_default_padding_end_material ... drawable abc_ab_share_pack_mtrl_alpha drawable abc_action_bar_item_background_material drawable abc_btn_borderless_material drawable abc_btn_check_material ... id action0 id action_bar ... integer abc_config_activityDefaultDur integer abc_config_activityShortDur integer cancel_button_image_alpha integer config_tooltipAnimTime integer integer_age integer status_bar_notification_info_maxnum layout abc_action_bar_title_item layout abc_action_bar_up_container layout abc_action_bar_view_list_nav_layout layout activity_main layout notification_action ... mipmap ic_launcher mipmap ic_launcher_round string abc_action_bar_home_description string string_key ... style AlertDialog_AppCompat style AlertDialog_AppCompat_Light style Widget_Compat_NotificationActionContainer style Widget_Compat_NotificationActionText styleable ActionBar background backgroundSplit backgroundStacked contentInsetEnd contentInsetEndWithActions contentInsetLeft contentInsetRight contentInsetStart contentInsetStartWithNavigation customNavigationLayout displayOptions divider elevation height hideOnContentScroll homeAsUpIndicator homeLayout icon indeterminateProgressStyle itemPadding logo navigationMode popupTheme progressBarPadding progressBarStyle subtitle subtitleTextStyle title titleTextStyle styleable ActionBarLayout android_layout_gravity styleable ActionMenuItemView android_minWidth styleable ActionMenuView styleable ActionMode background backgroundSplit closeItemLayout height subtitleTextStyle titleTextStyle ...接下來主要看步驟二processResoureces操作
6. AndroidBuilder.processResources
public static void processResources(@NonNull BlockingResourceLinker aapt,@NonNull AaptPackageConfig aaptConfig,@NonNull ILogger logger)throws IOException, ProcessException {try {// 1. 執(zhí)行AAPT鏈接操作處理aapt.link(aaptConfig, logger);} catch (Aapt2Exception | Aapt2InternalException e) {throw e;} catch (Exception e) {throw new ProcessException("Failed to execute aapt", e);}// aapt輸出R.java文件目錄 // AndroidGradleTaskDemo/app/build/generated/not_namespaced_r_class_sources/debug/processDebugResources/rFile sourceOut = aaptConfig.getSourceOutputDir();if (sourceOut != null) {// Figure out what the main symbol file's package is.String mainPackageName = aaptConfig.getCustomPackageForR();if (mainPackageName == null) {mainPackageName =SymbolUtils.getPackageNameFromManifest(aaptConfig.getManifestFile());}// Load the main symbol file.// 2. 加載aapt產(chǎn)物主R.txt文件File mainRTxt = new File(aaptConfig.getSymbolOutputDir(), "R.txt");// 從aapt生成的R.txt文件解析成主符號(hào)表對(duì)象SymbolTable mainSymbols =mainRTxt.isFile()? SymbolIo.readFromAapt(mainRTxt, mainPackageName): SymbolTable.builder().tablePackage(mainPackageName).build();// For each dependency, load its symbol file.// 3. 同理加載main app所有依賴庫的符號(hào)表// aaptConfig.getLibrarySymbolTableFiles() 為依賴庫的的文件集合// eg: /Users/apple/.gradle/caches/transforms-1/files-1.1/2774ea4f1cf1e83a6ad8e8d3c8b463b6/fb74d3934b89348681de5912dd579470/package-aware-r.txtSet<SymbolTable> depSymbolTables =SymbolUtils.loadDependenciesSymbolTables(aaptConfig.getLibrarySymbolTableFiles());boolean finalIds = true;// 4. 如果是aar則資源id不可以設(shè)置為final,否則打包會(huì)引起同名資源(不同模塊)找不到問題// 也解釋了為什么module中R文件不是final修飾的,只有主module文件為final修飾的if (aaptConfig.getVariantType().isAar()) {finalIds = false;}// 5. 生成多個(gè)R.java文件RGeneration.generateRForLibraries(mainSymbols, depSymbolTables, sourceOut, finalIds);}}可以看到此步驟
關(guān)于R.txt解析細(xì)節(jié)以及R.java文件如何生成,有興趣可以自行研究;其實(shí)可以再拓展下,R文件資源如何優(yōu)化,此處不再詳細(xì)深入分析
Task16: generateDebugSources
空task,無輸入輸出結(jié)果
👇
Android構(gòu)建流程——上篇
Android構(gòu)建流程——下篇
參考
https://developer.android.com/studio/command-line/aapt2#link
總結(jié)
以上是生活随笔為你收集整理的Android构建流程——篇五的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android-gradle插件调试
- 下一篇: Android构建流程——篇六