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的
doFirst
或doLast
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脚本小总结的主要内容,如果未能解决你的问题,请参考以下文章