Gradle脚本小总结

Posted 莫川

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gradle脚本小总结相关的知识,希望对你有一定的参考价值。

1.禁用task

    gradle.taskGraph.whenReady 
        tasks.each  task ->
            if (task.name.equalsIgnoreCase("transformClassesWithDelegateProguardTransformForRelease")
            || task.name.equalsIgnoreCase("transformClassesWithApplicationInjectForRelease"))
            
                task.enabled = false
                println '####disable task.. '+task.name
            
        
    

2.插入task或者脚本

  • task的doFirstdoLast
project.afterEvaluate 

    File buildGradleFile = project.getBuildFile()
    println "kblog:buildDir = " + project.getBuildDir().getAbsolutePath()
    println "kblog:rootDir 2 " + buildGradleFile.getText()

    Task buildRelease = project.tasks.findByName("buildRelease")
    if (buildRelease) 
        buildRelease.doLast 
            File mappingFile = new File(project.getBuildDir().getAbsolutePath() + "/intermediates/bundle/mapping.txt")
            if (mappingFile.exists()) 
                mappingFile.renameTo(project.getBuildDir().getAbsolutePath() + "/intermediates/bundle/mapping.mochuan.4mtl.xml")
            
        
    

    Task assembleRelease = project.tasks.findByName("assembleRelease")
    if (assembleRelease) 
        assembleRelease.doLast 
            File mappingFile = new File(project.getBuildDir().getAbsolutePath() + "/intermediates/bundle/mapping.txt")
            if (mappingFile.exists()) 
                mappingFile.renameTo(project.getBuildDir().getAbsolutePath() + "/intermediates/bundle/mapping.mochuan.4mtl.xml")
            
        
    


  • dependOn
mOrganizeImportsTask.dependsOn project.tasks.findByName(REPLACE_TASK_NAME)

3.使用transform复制so

  • 将部分aar中的armeabi-v7a中的文件,复制到armeabi
import com.android.annotations.NonNull
import com.android.build.api.transform.Format
import com.android.build.api.transform.QualifiedContent
import com.android.build.api.transform.Transform
import com.android.build.api.transform.TransformException
import com.android.build.api.transform.TransformInvocation

import com.android.build.gradle.internal.pipeline.ExtendedContentType

//@version mochuan.zhb on 2019/6/15.
//@Author Zheng Haibo
//@Blog github.com/nuptboyzhb
//@Company Alibaba Group
//@Description 将部分aar中的armeabi-v7a中的文件,复制到armeabi;
public class NativeTransform extends Transform 

    public def projectContext;

    public static final String ABI_ARMEABI = "armeabi";
    public static final String ABI_ARMEABI_V7A = "armeabi-v7a";


    @Override
    public String getName() 
        return "copyNativeLibraries"
    

    @Override
    public Set<QualifiedContent.ContentType> getInputTypes() 
        Set<QualifiedContent.ContentType> set = EnumSet.of(ExtendedContentType.NATIVE_LIBS);
        return set;
    

    @Override
    public Set<QualifiedContent.Scope> getScopes() 
        Set<QualifiedContent.Scope> set = EnumSet.of(
                QualifiedContent.Scope.EXTERNAL_LIBRARIES,
                QualifiedContent.Scope.PROJECT,
                QualifiedContent.Scope.SUB_PROJECTS
        )
        return set;
    

    @Override
    public boolean isIncremental() 
        return false;
    

    @Override
    public void transform(@NonNull TransformInvocation transformInvocation)
            throws TransformException, InterruptedException, IOException 

        def outputProvider = transformInvocation.outputProvider
        if (!transformInvocation.isIncremental()) 
            outputProvider.deleteAll()
        

        transformInvocation.inputs.forEach  transformInput ->

            transformInput.directoryInputs.forEach  directoryInput ->
                def dir = directoryInput.file.toPath()
                def output = outputProvider.getContentLocation(
                        directoryInput.name, inputTypes, directoryInput.scopes, Format.DIRECTORY)

                projectContext.fileTree(dir).forEach  input ->
                    def path = dir.relativize(input.toPath())
                    def destDir = output.toPath().resolve(path).toFile().parentFile

                    def abiName = input.parentFile.name

                    println 'kblog:path = ' + path + ",abiName = " + abiName

                    if (ABI_ARMEABI_V7A == abiName) 
                        def v5Dir = new File(destDir.parentFile, ABI_ARMEABI)

                        projectContext.copy  spec ->
                            spec.from(input)
                            spec.into(v5Dir)
                        
                        println 'kblog:copy ' + path + " into " + v5Dir.getAbsolutePath()
                        projectContext.copy  spec ->
                            spec.from(input)
                            spec.into(destDir)
                        
                     else if (ABI_ARMEABI == abiName) 
                        def v7Dir = new File(destDir.parentFile, ABI_ARMEABI_V7A)
                        if (!(new File(v7Dir, input.name)).isFile()) 
                            // copy if not present
                            projectContext.copy  spec ->
                                spec.from(input)
                                spec.into(v7Dir)
                            
                        
                        projectContext.copy  spec ->
                            spec.from(input)
                            spec.into(destDir)
                        
                     else 
                        // just copy
                        projectContext.copy  spec ->
                            spec.from(input)
                            spec.into(destDir)
                        
                    
                
            
        

    




def transform = new NativeTransform()
transform.projectContext = project
project.android.registerTransform(transform)

4.使用Transform检查类

  • 用于检查依赖的类是否有重复,如果重复,则随机删除一个
import org.apache.commons.io.FileUtils;
import com.android.annotations.NonNull
import com.android.build.api.transform.Format
import com.android.build.api.transform.QualifiedContent
import com.android.build.api.transform.Transform
import com.android.build.api.transform.TransformInput
import com.android.build.api.transform.DirectoryInput
import com.android.build.api.transform.JarInput
import com.android.build.api.transform.TransformOutputProvider
import com.android.build.api.transform.TransformException
import com.android.build.api.transform.TransformInvocation
import com.android.build.gradle.internal.pipeline.TransformManager

import java.util.jar.JarFile
import java.util.zip.ZipEntry;


//@version mochuan.zhb on 2021/6/23.
//@Author Zheng Haibo
//@Blog github.com/nuptboyzhb
//@Company Alibaba Group
//@Description
public class FilterJarTransform extends Transform 

    public def projectContext;


    @Override
    public String getName() 
        return "filterJar"
    

    @Override
    public Set<QualifiedContent.ContentType> getInputTypes() 
        return TransformManager.CONTENT_JARS;
    

    @Override
    public Set<? super QualifiedContent.Scope> getScopes() 
        return TransformManager.SCOPE_FULL_PROJECT;
    

    @Override
    public boolean isIncremental() 
        return false;
    

    private Map<String, String> clazzJarMap = new HashMap<>();

    public static class FileModel
        public FileModel(File file1,JarInput jarInput1)
            this.jarInput = jarInput1;
            this.file = file1;
        
        public File file;
        public JarInput jarInput;
    

    @Override
    public void transform(@NonNull TransformInvocation transformInvocation)
            throws TransformException, InterruptedException, IOException 

        List<FileModel> inputFiles = new ArrayList<>();
        for (TransformInput input : transformInvocation.getInputs()) 
            for (DirectoryInput directoryInput : input.getDirectoryInputs()) 
                if (directoryInput.getFile().isDirectory()) 
                    inputFiles.add(new FileModel(directoryInput.getFile(),null));
                
            
            for (JarInput jarInput : input.getJarInputs()) 
                if (jarInput.getFile().isFile()) 
                    inputFiles.add(new FileModel(jarInput.getFile(),jarInput));
                
            
        
        Map<String, String> multiJarPath = new HashMap<>();
        inputFiles.each  fileModel ->
            println('process file = ' + fileModel.file.getAbsolutePath())
            TransformOutputProvider outputProvider = transformInvocation.getOutputProvider();
            if (fileModel.file.isFile() && fileModel.file.getName().endsWith(".jar")) 
                JarFile jarFile = new JarFile(fileModel.file);
                Enumeration<? extends ZipEntry> entries = jarFile.entries();
                boolean isMultiJar = false;
                while (entries.hasMoreElements()) 
                    ZipEntry element = entries.nextElement();
                    //element.setExtra();
                    String currentClass = element.getName();
                    String path = clazzJarMap.get(currentClass);
                    if (path != null && path.length() > 0) 
                        println('find multi-class: ' + currentClass)
                        isMultiJar = true;
                        multiJarPath.put(path, fileModel.file.getAbsolutePath());
                     else 
                        clazzJarMap.put(currentClass, fileModel.file.getAbsolutePath());
                    
                
                if (!isMultiJar) 
                    if(fileModel.jarInput != null)
                        File dest = outputProvider.getContentLocation(
                                fileModel.jarInput.getFile().getAbsolutePath(),
                                fileModel.jarInput.getContentTypes(),
                                fileModel.jarInput.getScopes(),
                                Format.JAR);
                        FileUtils.copyFile(fileModel.file, dest);
                    else
                        //
                        println("TODO:///"+fileModel.file.getAbsolutePath())
                    
                
            
        

        for (Map.Entry<String, String> entry : multiJarPath) 
            println('### multi-jar: ' + entry.getKey() + "," + entry.getValue())
        

    



def transform = new FilterJarTransform()
transform.projectContext = project
project.android.registerTransform(transform)

5.Hook所有task的输入输出

/**
 * @version mochuan.zhb on 2019/7/3.
 * @Author Zheng Haibo
 * @Blog github.com/nuptboyzhb
 * @Company Alibaba Group
 * @Description task执行的顺序以及所有的input/output
 */
public class TaskIOPlugin implements Plugin<Project> 

    private Map<String, TaskNode> taskExecuteMap = new LinkedHashMap<>();

    private File buildDir;

    private static long gradleStartTime = 0L;

    @Override
    public void apply(Project project) 

        buildDir = project.getBuildDir();
        project.getGradle().addBuildListener(new BuildListener() 
            @Override
            public void buildStarted(Gradle gradle) 
                myLog("buildStarted")
            

            @Override
            public void settingsEvaluated(Settings settings) 
                myLog("settingsEvaluated")
            

            @Override
            public void projectsLoaded(Gradle gradle) 
                myLog("projectsLoaded")
            

            @Override
            public void projectsEvaluated(Gradle gradle) 
                gradleStartTime = System.currentTimeMillis();
                myLog("projectsEvaluated")
            

            @Override
            public void buildFinished(BuildResult buildResult) 
                myLog("buildFinished")
                printTaskMap();
            
        );
        taskExecuteMap.clear()
        project.getGradle().getTaskGraph().addTaskExecutionListener(new TaskExecutionListener() 
            @Override
            public void beforeExecute(Task task) 
                TaskNode taskNode = taskExecuteMap.get(getTaskName(task))
                if (taskNode != null) 
                    println("== taskNode added ...")
                    return;
                
                List<String> inputFileList = new ArrayList<>();
                task.getInputs().files.each  item ->
                    inputFileList.add(item.getAbsolutePath())
                
                taskNode = new TaskNode();
                taskNode.startTime = System.currentTimeMillis()
                taskNode.name = getTaskName(task);
                taskNode.clazz = task.getClass().getName()
                taskNode.input = inputFileList
                taskExecuteMap.put(getTaskName(task), taskNode)
            

            @Override
            public void afterExecute(Task task, TaskState taskState) 
                List<String> outputList = new ArrayList<>();
                task.getOutputs().files.each  item ->
                    outputList.add(item.getAbsolutePath())
                
                TaskNode taskNode = taskExecuteMap.get(getTaskName(task))
                if (taskNode == null) 
                    taskNode = new TaskNode();
                    taskNode.name = getTaskName(task);
                    taskNode.clazz = task.getClass().getName()
                
                taskNode.endTime = System.currentTimeMillis()
                taskNode.output = outputList
                taskExecuteMap.put(getTaskName(task), taskNode)
            
        );

        project.getGradle().getTaskGraph().addTaskExecutionGraphListener(new TaskExecutionGraphListener() 
            @Override
            public void graphpopulated(TaskExecutionGraph taskExecutionGraph) 
                myLog("---graphPopulated---")
            
        );

    

    private static String getTaskName(Task task) 
        String taskName = String.format("%s:%s", task.getProject().getName(), task.getName());
        println("== afterExecute > " + taskName)
        return taskName;
    

    private static void myLog(String content) 
        myLog(content, false)
    

    private static void myLog(String content, boolean node) 
        if (node) 
            println("       [node]:" + content)
         else 
            println("[====task-io===]:" + content)
        
    

    private void printTaskMap() 
        println("start task io file.")
        StringBuilder stringBuilder = new StringBuilder()
        StringBuilder taskList = new StringBuilder();
        boolean lastItem = false
        int taskCount = 0;
        List<TimeData> timeDataList = new ArrayList<>();
        taskExecuteMap.each  item ->
            taskCount++
            TaskNode taskNode = item.value
            long time = taskNode.endTime - taskNode.startTime
            if (time > 0) 
                TimeData timeData = new TimeData();
                timeData.taskName = taskNode.name;
                timeData.time = time;
                timeData.startTime4Charts = taskNode.startTime - gradleStartTime
                timeDataList.add(timeData);
            
            taskList.append(taskCount).append(" ").append(taskNode.name).append("(" + time + " ms)").append("   ::<" + taskNode.clazz + ">").append("\\n")
            taskList.append("           ↓").append("\\n")
            stringBuilder.append(":").append(taskNode.name).append("\\n")
            stringBuilder.append('   input→').append("\\n")
            int count = 0
            taskNode.input.each  i ->
                count++
                if (count == taskNode.input.size()) 
                    stringBuilder.append("       └──" + i).append("\\n")
                    lastItem = true
                 else 
                    stringBuilder.append("       ├──" + i).append("\\n")
                    lastItem = false
                
                if (new File(i).isDirectory()) 
                    printChildFiles(new File(i), stringBuilder, lastItem);
                
            
            stringBuilder.append('   output→').append("\\n")
            count = 0
            taskNode.output.each  o ->
                count++
                if (count == taskNode.output.size()) 
                    stringBuilder.append("       └──" + o).append("\\n")
                    lastItem = true
                 else 
                    stringBuilder.append("       ├──" + o).append("\\n")
                    lastItem = false
                
                if (new File(o).isDirectory()) 
                    printChildFiles(new File(o), stringBuilder, lastItem);
                
            
        

        stringBuilder.append("\\n\\n\\n")
        stringBuilder.append(taskList.toString())

        printData4Charts(timeDataList, stringBuilder);

        printData4Markdown(timeDataList, stringBuilder)

        printTimeline4Text(new ArrayList<TimeData>(timeDataList), stringBuilder)

        File outPutDir = new File(buildDir, "/outputs/");
        if (!outPutDir.exists()) 
            outPutDir.mkdirs()
        
        long currentTime = System.currentTimeMillis();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
        Date date = new Date(currentTime);
        String fileName = formatter.format(date) + "_taskio.txt";
        File resultFile = new File(outPutDir, fileName);
        boolean success = FileUtils.toFile(resultFile, stringBuilder)
        if (success) 
            println("task io file finished. file path = " + resultFile.getAbsolutePath())
         else 
            println("task io file failed.")
        
    

    /**
     * 递归打印
     * @param dir
     * @param stringBuilder
     * @param lastItem
     */
    private void printChildFiles(File dir, StringBuilder stringBuilder, boolean lastItem) 
        int childCount = 0;
        boolean nextLastItem = false;
        dir.listFiles().each  child ->
            childCount++
            if (lastItem) 
                if (childCount == dir.listFiles().size()) 
                    stringBuilder.append("            └──" + child.getAbsolutePath()).append("\\n")
                    nextLastItem = true
                 else 
                    stringBuilder.append("            ├──" + child.getAbsolutePath()).append("\\n")
                    nextLastItem = false
                
             else 
                if (childCount == dir.listFiles().size()) 
                    stringBuilder.append("       |    └──" + child.getAbsolutePath()).append("\\n")
                 else 
                    stringBuilder.append("       |    ├──" + child.getAbsolutePath()).append("\\n")
                
            
            if (child.isDirectory()) 
                printChildFiles(child, stringBuilder, nextLastItem);
            
        
    

    /**
     *  data: [
     *value: 1048, name: '搜索引擎',
     *value: 735, name: '直接访问',
     *value: 580, name: '邮件营销',
     *value: 484, name: '联盟广告',
     *value: 300, name: '视频广告'*             ],
     * @param timeDataList
     * @param stringBuilder
     */
    private void printData4Charts(List<TimeData> timeDataList, StringBuilder stringBuilder) 
        stringBuilder.append("\\n\\n\\n")
        stringBuilder.append("option = \\n" +
                "    title: \\n" +
                "        text: 'Task耗时分布',\\n" +
                "        subtext: '耗时详情',\\n" +
                "        left: 'center'\\n" +
                "    ,\\n" +
                "    tooltip: \\n" +
                "        trigger: 'item'\\n" +
                "    ,\\n" +
                "    series: [\\n" +
                "        \\n" +
                "            name: '耗时详情',\\n" +
                "            type: 'pie',\\n" +
                "            radius: '50%',\\n" +
                "            data: [").append("\\n");
        for (TimeData timeData : timeDataList) 
            stringBuilder.append("value:")
                    .append(timeData.time)
                    .append(",name:'")
                    .append(timeData.taskName)
                    .append("',").append("\\n")
        
        stringBuilder.append("],\\n" +
                "            emphasis: \\n" +
                "                itemStyle: \\n" +
                "                    shadowBlur: 10,\\n" +
                "                    shadowOffsetX: 0,\\n" +
                "                    shadowColor: 'rgba(0, 0, 0, 0.5)'\\n" +
                "                \\n" +
                "            \\n" +
                "        \\n" +
                "    ]\\n" +
                ";");
    


    /**
     * 打印markdown
     * @param timeDataList
     * @param stringBuilder
     */
    private void printData4Markdown(List<TimeData> timeDataList, StringBuilder stringBuilder) 
        timeDataList.sort(new Comparator<TimeData>() 
            @Override
            int compare(TimeData timeData, TimeData t1) 
                return (int) (t1.time - timeData.time);
            
        );
        stringBuilder.append("\\n\\n\\n")
        stringBuilder.append("|task名称|耗时(ms)|备注|").append("\\n")
        stringBuilder.append("|:---|:---|:---|").append("\\n")
        for (TimeData timeData : timeDataList) 
            stringBuilder.append(String.format("|%s|%s||", timeData.taskName, timeData.time)).append("\\n")
        
        stringBuilder.append("\\n\\n\\n")
    


    /**
     * 打印任务执行的时间线
     * @param timeDataList
     * @param stringBuilder
     */
    private void printTimeline4Text(List<TimeData> timeDataList, StringBuilder stringBuilder) 
        timeDataList.sort(new Comparator<TimeData>() 
            @Override
            int compare(TimeData timeData, TimeData t1) 
                return (int) (timeData.startTime4Charts - t1.startTime4Charts);
            
        );
        stringBuilder.append("\\n\\n\\n")
        stringBuilder.append("task执行的timeline").append("\\n")
        TimeData lastItem = timeDataList.get(timeDataList.size() - 1);
        int step = (int) (lastItem.startTime4Charts + lastItem.time) / 120 + 1;
        println('[taskio]:step = '+step)
        char eChar = ' ';
        char sChar = '▇';
        for (TimeData timeData : timeDataList) 
            int eCount = (int) (timeData.startTime4Charts / step) + 1;
            int sCount = (int) (timeData.time / step) + 1;
            for (int i = 0; i < eCount; i++) 
                stringBuilder.append(eChar);
            
            for (int i = 0; i < sCount; i++) 
                stringBuilder.append(sChar);
            
            stringBuilder.append("(").append(timeData.time).append("ms)").append(timeData.taskName).append("\\n");
        
        stringBuilder.append("\\n\\n\\n")
    


6.对Jar文件进行处理

    /**
     * 从inputJarPath删除特定的class,将剩余的class,写入到outPutJarPath
     * @param inputJarPath
     * @param outPutJarPath
     * @param clazzNameSet
     */
    private void removeClassInJar(String inputJarPath, String outPutJarPath, HashSet<String> clazzNameSet) 
        try 
            JarFile inputJarFile = new JarFile(inputJarPath);
            Enumeration<JarEntry> inputJarEntries = inputJarFile.entries();
            //将oldJarEntries中的oldJar替换掉,并将对应的新Jar生成
            File outFile = new File(outPutJarPath);
            if (outFile.exists()) 
                outFile.delete();
            
            outFile.createNewFile();
            FileOutputStream fileOutputStream = new FileOutputStream(outFile);
            CheckedOutputStream checksum = new CheckedOutputStream(fileOutputStream, new Adler32());
            ZipOutputStream out = new ZipOutputStream(checksum);
            while (inputJarEntries.hasMoreElements()) 
                ZipEntry element = inputJarEntries.nextElement();
                String currentClassName = element.getName();
                if (!clazzNameSet.contains(currentClassName)) 
                    try 
                        out.putNextEntry(element);
                        InputStream entryIn = inputJarFile.getInputStream(element);
                        int read;
                        byte[] buf = new byte[4096];
                        while ((read = entryIn.read(buf, 0, buf.length)) != -1) 
                            out.write(buf, 0, read);
                        
                        out.flush();
                        out.closeEntry();
                        entryIn.close();
                     catch (Exception e) 
                        throw e;
                    
                
            
            out.finish();
            out.close();
            fileOutputStream.close();
            inputJarFile.close();
         catch (IOException e) 
            e.printStackTrace();
        

    

7.修改AndroidManifest

//@version mochuan.zhb on 2019/4/15.
//@Author Zheng Haibo
//@Blog github.com/nuptboyzhb
//@Company Alibaba Group
//@Description 适配mateX + targetSdkVersion升级适配:透明背景的Activity,删除其screenOrientation属性


import javax.xml.parsers.DocumentBuilderFactory
import javax.xml.transform.dom.DOMSource
import javax.xml.transform.stream.StreamResult
import javax.xml.transform.TransformerFactory

project.afterEvaluate 
    def LOG_TAG = 'ManifestFlodHandler: '
    Task taskProcessReleaseManifest = project.tasks.findByName('splitsDiscoveryTaskRelease')
    if (taskProcessReleaseManifest) 
        taskProcessReleaseManifest.doFirst 
            println(LOG_TAG + 'splitsDiscoveryTaskRelease doFirst files: ' + it.outputs.files.files)
            def manifestFileName = './launcher/build/intermediates/manifests/full/release/AndroidManifest.xml'
            def document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(manifestFileName)
            def activities = document.getElementsByTagName('activity')
            println(LOG_TAG + 'Activites size: ' + activities.getLength())

            def buffReader = new BufferedReader(new FileReader('./launcher/recreate_activites'))
            def recreateActivities = []
            def line = null
            while (null != (line = buffReader.readLine())) 
                if (line.startsWith('com.')) 
                    recreateActivities.add(line)
                
            
            buffReader.close()
            def attNameName = 'android:name'
            def attConfigChangesName = 'android:configChanges'
            def attResizeableActivityName = 'android:resizeableActivity'
            //android:screenOrientation="portrait"
            def attScreenOrientationName = 'android:screenOrientation'
            def attThemeName = 'android:theme'
            for (int i = 0; i < activities.getLength(); i++) 
                def attributes = activities.item(i).getAttributes()

                def attName = attributes.getNamedItem(attNameName)
                def attConfigChanges = attributes.getNamedItem(attConfigChangesName)
                def attResizeableActivity = attributes.getNamedItem(attResizeableActivityName)
                def attScreenOrientation = attributes.getNamedItem(attScreenOrientationName)
                def attTheme = attributes.getNamedItem(attThemeName)

                // add multi-window support
                if (attResizeableActivity == null) 
                    def attResizeNew = document.createAttribute(attResizeableActivityName)
                    attResizeNew.setNodeValue('true')
                    attributes.setNamedItem(attResizeNew)
                 else if (attResizeableActivity.getNodeValue() == 'false') 
                    println(LOG_TAG + "不支持多窗口 ==> " + attName.getNodeValue())
                

                if (attName.getNodeValue() in recreateActivities) 
                    println(LOG_TAG + ' ' + attName.getNodeValue() + ' In WhiteList, Use Recreate Plan.')
                    continue
                

                // add config change support
                if (attConfigChanges != null) 
                    //screenSize|smallestScreenSize|screenLayout
                    def value = attConfigChanges.getNodeValue()
                    if (!value.contains('screenSize')) 
                        value += '|screenSize'
                    
                    if (!value.contains('smallestScreenSize')) 
                        value += '|smallestScreenSize'
                    
                    if (!value.contains('screenLayout')) 
                        value += '|screenLayout'
                    
                    attConfigChanges.setNodeValue(value)
                 else 
                    def attConfigNew = document.createAttribute(attConfigChangesName)
                    attConfigNew.setNodeValue('screenSize|smallestScreenSize|screenLayout')
                    attributes.setNamedItem(attConfigNew)
                

                if (attTheme != null && attScreenOrientation != null) 
                    if (attTheme.getNodeValue() != null && (attTheme.getNodeValue().toLowerCase().contains("translucent")
                            || attTheme.getNodeValue().toLowerCase().contains("transparent")
                            || attTheme.getNodeValue().toLowerCase().contains("vrtheme")
                            || attTheme.getNodeValue().toLowerCase().contains("alipaylogintheme")
                            || attTheme.getNodeValue().toLowerCase().contains("mspapppaytheme")
                            || attTheme.getNodeValue().toLowerCase().contains("mspapptheme"))) 
                        attributes.removeNamedItem(attScreenOrientationName)
                        println 'remove screenOrientation:' + attName
                    
                

            

            //save change to AndroidManifest.xml
            def transformer = TransformerFactory.newInstance().newTransformer()
            transformer.transform(new DOMSource(document), new StreamResult(manifestFileName))

        
    
    Task taskProcessDebugManifest = project.tasks.findByName('splitsDiscoveryTaskDebug')
    if (taskProcessDebugManifest) 
        taskProcessDebugManifest.doFirst 
            println(LOG_TAG + 'splitsDiscoveryTaskDebug doFirst files: ' + it.outputs.files.files)
            def manifestFileName = './launcher/build/intermediates/manifests/full/debug/AndroidManifest.xml'
            def document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(manifestFileName)
            def activities = document.getElementsByTagName('activity')
            println(LOG_TAG + 'Activites size: ' + activities.getLength())

            def buffReader = new BufferedReader(new FileReader('./launcher/recreate_activites'))
            def recreateActivities = []
            def line = null
            while (null != (line = buffReader.readLine())) 
                if (line.startsWith('com.')) 
                    recreateActivities.add(line)
                
            
            buffReader.close()
            def attNameName = 'android:name'
            def attConfigChangesName = 'android:configChanges'
            def attResizeableActivityName = 'android:resizeableActivity'
            //android:screenOrientation="portrait"
            def attScreenOrientationName = 'android:screenOrientation'
            def attThemeName = 'android:theme'
            for (int i = 0; i < activities.getLength(); i++) 
                def attributes = activities.item(i).getAttributes()

                def attName = attributes.getNamedItem(attNameName)
                def attConfigChanges = attributes.getNamedItem(attConfigChangesName)
                def attResizeableActivity = attributes.getNamedItem(attResizeableActivityName)
                def attScreenOrientation = attributes.getNamedItem(attScreenOrientationName)
                def attTheme = attributes.getNamedItem(attThemeName)

                // add multi-window support
                if (attResizeableActivity == null) 
                    def attResizeNew = document.createAttribute(attResizeableActivityName)
                    attResizeNew.setNodeValue('true')
                    attributes.setNamedItem(attResizeNew)
                 else if (attResizeableActivity.getNodeValue() == 'false') 
                    println(LOG_TAG + "不支持多窗口 ==> " + attName.getNodeValue())
                

                if (attName.getNodeValue() in recreateActivities) 
                    println(LOG_TAG + ' ' + attName.getNodeValue() + ' In WhiteList, Use Recreate Plan.')
                    continue
                

                // add config change support
                if (attConfigChanges != null) 
                    //screenSize|smallestScreenSize|screenLayout
                    def value = attConfigChanges.getNodeValue()
                    if (!value.contains('screenSize')) 
                        value += '|screenSize'
                    
                    if (!value.contains('smallestScreenSize')) 
                        value += '|smallestScreenSize'
                    
                    if (!value.contains('screenLayout')) 
                        value += '|screenLayout'
                    
                    attConfigChanges.setNodeValue(value)
                 else 
                    def attConfigNew = document.createAttribute(attConfigChangesName)
                    attConfigNew.setNodeValue('screenSize|smallestScreenSize|screenLayout')
                    attributes.setNamedItem(attConfigNew)
                

                if (attTheme != null && attScreenOrientation != null) 
                    if (attTheme.getNodeValue() != null && (attTheme.getNodeValue().toLowerCase().contains("translucent")
                            || attTheme.getNodeValue().toLowerCase().contains("transparent")
                            || attTheme.getNodeValue().toLowerCase().contains("vrtheme")
                            || attTheme.getNodeValue().toLowerCase().contains("alipaylogintheme")
                            || attTheme.getNodeValue().toLowerCase().contains("mspapppaytheme")
                            || attTheme.getNodeValue().toLowerCase().contains("mspapptheme"))) 
                        attributes.removeNamedItem(attScreenOrientationName)
                        println 'remove screenOrientation:' + attName
                    
                

            

            //save change to AndroidManifest.xml
            def transformer = TransformerFactory.newInstance().newTransformer()
            transformer.transform(new DOMSource(document), new StreamResult(manifestFileName))

        
    


排查编译问题的思路

  • 分析每个Task的构建产物
  • 反编译jar
  • 反编译apk

以上是关于Gradle脚本小总结的主要内容,如果未能解决你的问题,请参考以下文章

Gradle脚本小总结

gradle学习总结

gradle学习总结

Gradle构建简介

Gradle日常开发技巧总结

Gradle使用总结