From 2b74ab4c096cea3c330d718fa8f0f232c30f32ed Mon Sep 17 00:00:00 2001 From: typ0520 Date: Thu, 2 Nov 2017 16:01:38 +0800 Subject: [PATCH] support android gradle plugin 3.0.0 --- CHANGELOG.md | 10 + README.md | 4 +- build.gradle | 2 + .../groovy/fastdex/build/FastdexPlugin.groovy | 260 +- .../build/extension/FastdexExtension.groovy | 2 +- .../build/task/FastdexCleanTask.groovy | 4 +- .../FastdexCreateMaindexlistFileTask.groovy | 4 +- .../build/task/FastdexCustomJavacTask.groovy | 8 +- .../task/FastdexDataBindingPrepareTask.groovy | 23 - .../task/FastdexInstantRunMarkTask.groovy | 9 +- .../build/task/FastdexInstantRunTask.groovy | 4 +- .../build/task/FastdexManifestTask.groovy | 4 +- .../build/task/FastdexPatchTask.groovy | 13 +- .../build/task/FastdexPrepareTask.groovy | 4 +- .../build/task/FastdexResourceIdTask.groovy | 12 +- .../task/FastdexScanAptOutputTask.groovy | 14 +- .../FastdexDexBuilderTransform.groovy | 39 + .../FastdexDexMergerTransform.groovy | 71 + .../transform/FastdexDexTransform.groovy | 181 + .../FastdexJarMergingTransform.groovy | 35 +- .../transform/FastdexPreDexTransform.groovy | 60 + .../build/transform/FastdexTransform.groovy | 376 -- .../build/transform/TransformProxy.groovy | 22 +- .../fastdex/build/util/ClassInject.groovy | 94 +- .../fastdex/build/util/Constants.groovy | 7 +- .../fastdex/build/util/DexOperation.groovy | 36 +- .../build/util/FastdexBuildListener.groovy | 56 +- .../build/util/FastdexInstantRun.groovy | 71 +- .../build/util/FastdexRuntimeException.groovy | 2 +- .../fastdex/build/util/FastdexUtils.groovy | 180 +- .../build/util/FindDexFileVisitor.groovy | 26 +- .../fastdex/build/util/GradleUtils.groovy | 147 +- .../fastdex/build/util/JarOperation.groovy | 29 +- .../fastdex/build/util/JumpException.groovy | 11 +- .../fastdex/build/util/LibDependency.groovy | 100 +- .../groovy/fastdex/build/util/MetaInfo.groovy | 23 +- .../build/util/ProjectSnapshoot.groovy | 54 +- .../build/variant/FastdexBuilder.groovy | 272 ++ .../build/variant/FastdexVariant.groovy | 68 +- gradle.properties | 2 +- sample/app/build.gradle | 65 +- .../java/fastdex/sample/MainActivity.java | 2 +- .../app/src/main/res/layout/activity_main.xml | 3 + sample/build-log.txt | 3102 ----------------- sample/build.gradle | 8 +- sample/common-group/common2/build.gradle | 2 +- sample/common/build.gradle | 2 +- sample/gradle.properties | 4 +- .../gradle/wrapper/gradle-wrapper.properties | 4 +- sample/javalib/build.gradle | 6 +- settings.gradle | 2 +- 51 files changed, 1471 insertions(+), 4068 deletions(-) delete mode 100644 fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexDataBindingPrepareTask.groovy create mode 100644 fastdex-gradle/src/main/groovy/fastdex/build/transform/FastdexDexBuilderTransform.groovy create mode 100644 fastdex-gradle/src/main/groovy/fastdex/build/transform/FastdexDexMergerTransform.groovy create mode 100644 fastdex-gradle/src/main/groovy/fastdex/build/transform/FastdexDexTransform.groovy create mode 100644 fastdex-gradle/src/main/groovy/fastdex/build/transform/FastdexPreDexTransform.groovy delete mode 100644 fastdex-gradle/src/main/groovy/fastdex/build/transform/FastdexTransform.groovy create mode 100644 fastdex-gradle/src/main/groovy/fastdex/build/variant/FastdexBuilder.groovy delete mode 100644 sample/build-log.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 82d661bc..6df23a03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## 0.8.0 (2017-11-2) + +Features: + + - 支持android gradle plugin 3.0 + +Bugfixes: + + - 修复assets目录为空时生成资源补丁出错的问题 + ## 0.7.4 (2017-10-20) Bugfixes: diff --git a/README.md b/README.md index 3d93ee2b..38830e3f 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ Android API 9(2.3)+ ; android-gradle-build 2.0.0+ } dependencies { - classpath 'com.github.typ0520:fastdex-gradle:0.7.4' + classpath 'com.github.typ0520:fastdex-gradle:0.8.0' } } ```` @@ -95,7 +95,7 @@ Android API 9(2.3)+ ; android-gradle-build 2.0.0+ classes.dex => classes2.dex classes2.dex => classes3.dex 然后运行期在入口Application(fastdex.runtime.FastdexApplication)使用MultiDex把所有的dex加载进来 - - @see [fastdex.build.transform.FastdexTransform](https://github.com/typ0520/fastdex/blob/master/fastdex-gradle/src/main/groovy/fastdex/build/transform/FastdexTransform.groovy) + - @see [fastdex.build.transform.FastdexDexTransform](https://github.com/typ0520/fastdex/blob/master/fastdex-gradle/src/main/groovy/fastdex/build/transform/FastdexTransform.groovy) - 7、保存资源映射表,为了保持id的值一致,详情看 - @see [fastdex.build.task.FastdexResourceIdTask](https://github.com/typ0520/fastdex/blob/master/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexResourceIdTask.groovy) diff --git a/build.gradle b/build.gradle index c140062e..1ecdb751 100644 --- a/build.gradle +++ b/build.gradle @@ -3,6 +3,7 @@ buildscript { repositories { jcenter() + maven { url 'https://maven.google.com' } maven { url 'http://dl.bintray.com/jetbrains/intellij-plugin-service' } } @@ -17,6 +18,7 @@ buildscript { allprojects { repositories { jcenter() + maven { url 'https://maven.google.com' } } } diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/FastdexPlugin.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/FastdexPlugin.groovy index 163b653d..01cabc36 100644 --- a/fastdex-gradle/src/main/groovy/fastdex/build/FastdexPlugin.groovy +++ b/fastdex-gradle/src/main/groovy/fastdex/build/FastdexPlugin.groovy @@ -5,34 +5,20 @@ import com.android.build.gradle.api.ApplicationVariant import com.android.build.gradle.internal.pipeline.TransformTask import com.android.build.gradle.internal.transforms.DexTransform import com.android.build.gradle.internal.transforms.JarMergingTransform -import fastdex.build.task.FastdexCleanTask -import fastdex.build.task.FastdexCreateMaindexlistFileTask -import fastdex.build.task.FastdexInstantRunMarkTask -import fastdex.build.task.FastdexInstantRunTask -import fastdex.build.task.FastdexManifestTask -import fastdex.build.task.FastdexPatchTask -import fastdex.build.task.FastdexResourceIdTask -import fastdex.build.task.FastdexScanAptOutputTask +import fastdex.build.extension.FastdexExtension +import fastdex.build.task.* +import fastdex.build.transform.FastdexDexBuilderTransform +import fastdex.build.transform.FastdexDexMergerTransform +import fastdex.build.transform.FastdexDexTransform import fastdex.build.transform.FastdexJarMergingTransform -import fastdex.build.util.Constants -import fastdex.build.util.FastdexBuildListener -import fastdex.build.util.FastdexInstantRun -import fastdex.build.util.FastdexUtils -import fastdex.build.util.GradleUtils +import fastdex.build.transform.FastdexPreDexTransform +import fastdex.build.util.* import fastdex.build.variant.FastdexVariant -import org.gradle.api.GradleException -import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.api.Task -import org.gradle.api.UnknownTaskException +import fastdex.common.utils.FileUtils +import org.gradle.api.* import org.gradle.api.execution.TaskExecutionGraph import org.gradle.api.execution.TaskExecutionGraphListener import java.lang.reflect.Field -import fastdex.build.transform.FastdexTransform -import fastdex.build.extension.FastdexExtension -import fastdex.build.task.FastdexPrepareTask -import fastdex.build.task.FastdexCustomJavacTask -import fastdex.common.utils.FileUtils /** * 注册相应节点的任务 @@ -40,12 +26,24 @@ import fastdex.common.utils.FileUtils */ class FastdexPlugin implements Plugin { @Override - public void apply(Project project) { + void apply(Project project) { + if (!project.plugins.hasPlugin('com.android.application')) { + throw new GradleException('Android Application plugin required') + } + project.extensions.create('fastdex', FastdexExtension) FastdexBuildListener.addByProject(project) + GradleUtils.addDynamicProperty(project,"android.enableAapt2","false") - if (!project.plugins.hasPlugin('com.android.application')) { - throw new GradleException('Android Application plugin required') + def android = project.extensions.android + try { + //open jumboMode + android.dexOptions.jumboMode = true + } catch (Throwable e) { + } + try { + reflectAapt2Flag() + } catch (Throwable e) { } project.afterEvaluate { @@ -79,10 +77,6 @@ class FastdexPlugin implements Plugin { throw new GradleException("Android gradle version too old 'com.android.tools.build:gradle:${GradleUtils.getAndroidGradlePluginVersion()}', minimum support version ${minSupportVersion}") } - def android = project.extensions.android - //open jumboMode - android.dexOptions.jumboMode = true - project.tasks.create("fastdexCleanAll", FastdexCleanTask) def aptConfiguration = project.configurations.findByName("apt") @@ -106,7 +100,7 @@ class FastdexPlugin implements Plugin { // Not in instant run mode, continue. } - boolean proguardEnable = variant.getVariantData().getVariantConfiguration().isMinifyEnabled() + boolean proguardEnable = variant.getVariantData().getVariantConfiguration().getBuildType().isMinifyEnabled() //TODO 暂时忽略开启混淆的buildType(目前的快照对比方案 无法映射java文件的类名和混淆后的class的类名) if (proguardEnable) { String buildTypeName = variant.getBuildType().buildType.getName() @@ -121,8 +115,15 @@ class FastdexPlugin implements Plugin { FastdexVariant fastdexVariant = new FastdexVariant(project,variant) fastdexVariant.fastdexInstantRun = new FastdexInstantRun(fastdexVariant) FastdexInstantRun fastdexInstantRun = fastdexVariant.fastdexInstantRun - fastdexInstantRun.resourceApFile = variantOutput.processResources.packageOutputFile - fastdexInstantRun.resDir = variantOutput.processResources.resDir + if (GradleUtils.getAndroidGradlePluginVersion().compareTo("3.0") < 0) { + fastdexInstantRun.resourceApFile = variantOutput.processResources.packageOutputFile + fastdexVariant.textSymbolOutputFile = new File(variant.getVariantData().getScope().getSymbolLocation(),"R.txt") + } + else { + def config = variant.getVariantData().getVariantConfiguration() + fastdexInstantRun.resourceApFile = new File(variantOutput.processResources.getResPackageOutputFolder(),"resources-" + config.getFullName() + ".ap_") + fastdexVariant.textSymbolOutputFile = variantOutput.processResources.getTextSymbolOutputFile() + } javaCompile.doLast { fastdexVariant.compiledByOriginJavac = true @@ -160,19 +161,23 @@ class FastdexPlugin implements Plugin { manifestTask.mustRunAfter tinkerPatchManifestTask } - //保持补丁打包时R文件中相同的节点和第一次打包时的值保持一致 -// FastdexResourceIdTask applyResourceTask = project.tasks.create("fastdexProcess${variantName}ResourceId", FastdexResourceIdTask) -// applyResourceTask.fastdexVariant = fastdexVariant -// applyResourceTask.resDir = variantOutput.processResources.resDir -// applyResourceTask.mustRunAfter manifestTask -// variantOutput.processResources.dependsOn applyResourceTask +// 保持补丁打包时R文件中相同的节点和第一次打包时的值保持一致 +// FastdexResourceIdTask applyResourceTask = project.tasks.create("fastdexProcess${variantName}ResourceId", FastdexResourceIdTask) +// applyResourceTask.fastdexVariant = fastdexVariant +// applyResourceTask.resDir = variantOutput.processResources.resDir +// applyResourceTask.mustRunAfter manifestTask +// variantOutput.processResources.dependsOn applyResourceTask //这样做是为了解决第一次补丁打包时虽然资源没有发生变化但是也会执行processResources任务的问题(因为在processResources任务执行之前往输入目录里添加了public.xml) variantOutput.processResources.doFirst { FastdexResourceIdTask applyResourceTask = new FastdexResourceIdTask() applyResourceTask.project = project applyResourceTask.fastdexVariant = fastdexVariant - applyResourceTask.resDir = variantOutput.processResources.resDir + if (variantOutput.processResources.properties['resDir'] != null) { + applyResourceTask.resDir = variantOutput.processResources.resDir + } else if (variantOutput.processResources.properties['inputResourcesDir'] != null) { + applyResourceTask.resDir = variantOutput.processResources.inputResourcesDir.getFiles().first() + } applyResourceTask.applyResourceId() } @@ -189,9 +194,13 @@ class FastdexPlugin implements Plugin { prepareTask.mustRunAfter generateSourcesTask } - Task transformClassesWithDex = getTransformClassesWithDex(project,variantName) - File classesDir = variant.getVariantData().getScope().getJavaOutputDir() + Task transformClassesWithJarMergingTask = getTransformClassesWithJarMergingTask(project,variantName) + Task transformClassesWithDexTask = getTransformClassesWithDexTask(project,variantName) + Task transformDexWithDexForTask = getTransformDexWithDexForTask(project,variantName) + Task transformDexArchiveWithDexMergerTask = getTransformDexArchiveWithDexMergerTask(project,variantName) + Task transformClassesWithPreDexTask = getTransformClassesWithPreDexTask(project,variantName) + File classesDir = variant.getVariantData().getScope().getJavaOutputDir() boolean hasDexCache = FastdexUtils.hasDexCache(project,variantName) FastdexScanAptOutputTask scanAptOutputTask = project.tasks.create("fastdexScanAptOutputFor${variantName}", FastdexScanAptOutputTask) @@ -219,7 +228,23 @@ class FastdexPlugin implements Plugin { } scanAptOutputTask.mustRunAfter javaCompile - transformClassesWithDex.dependsOn scanAptOutputTask + + //有可能成为入口的transform任务如果在scanAptOutputTask执行之后在执行 + if (transformClassesWithJarMergingTask != null) { + transformClassesWithJarMergingTask.dependsOn scanAptOutputTask + } + if (transformClassesWithDexTask != null) { + transformClassesWithDexTask.dependsOn scanAptOutputTask + } + if (transformDexArchiveWithDexMergerTask != null) { + transformDexArchiveWithDexMergerTask.dependsOn scanAptOutputTask + } + if (transformDexWithDexForTask != null) { + transformDexWithDexForTask.dependsOn scanAptOutputTask + } + if (transformClassesWithPreDexTask != null) { + transformClassesWithPreDexTask.dependsOn scanAptOutputTask + } Task multidexlistTask = getTransformClassesWithMultidexlistTask(project,variantName) if (multidexlistTask != null) { @@ -249,7 +274,18 @@ class FastdexPlugin implements Plugin { fastdexPatchTask.fastdexVariant = fastdexVariant Task packageTask = getPackageTask(project, variantName) - fastdexPatchTask.mustRunAfter transformClassesWithDex + if (transformClassesWithDexTask != null) { + fastdexPatchTask.mustRunAfter transformClassesWithDexTask + } + if (transformDexWithDexForTask != null) { + fastdexPatchTask.mustRunAfter transformDexWithDexForTask + } + if (transformDexArchiveWithDexMergerTask != null) { + fastdexPatchTask.mustRunAfter transformDexArchiveWithDexMergerTask + } + if (transformClassesWithPreDexTask != null) { + fastdexPatchTask.mustRunAfter transformClassesWithPreDexTask + } fastdexPatchTask.mustRunAfter mergeAssetsTask packageTask.dependsOn fastdexPatchTask @@ -274,43 +310,94 @@ class FastdexPlugin implements Plugin { project.getGradle().getTaskGraph().addTaskExecutionGraphListener(new TaskExecutionGraphListener() { @Override - public void graphPopulated(TaskExecutionGraph taskGraph) { + void graphPopulated(TaskExecutionGraph taskGraph) { + //2.0.0 2.1.0 2.2.0 2.3.0 3.3.0 + //3.0.0适配功能 +// assembleDebug_multidex_false_15_output.txt ok +// assembleDebug_multidex_false_21_output.txt ok +// assembleDebug_multidex_true_15_output.txt ok +// assembleDebug_multidex_true_21_output.txt ok + +// assembleRelease_multidex_false_15_output.txt ok +// assembleRelease_multidex_false_15_predex_false_output.txt ok +// assembleRelease_multidex_false_21_output.txt ok +// assembleRelease_multidex_false_21_output_predex_false.txt ok +// assembleRelease_multidex_true_15_output.txt ok +// assembleRelease_multidex_true_15_output_predex_false.txt ok +// assembleRelease_multidex_true_21_output.txt +// assembleRelease_multidex_true_21_output_predex_false.txt + + for (Task task : taskGraph.getAllTasks()) { if (task.getProject().equals(project) && task instanceof TransformTask - //fix # + && task.name.startsWith("transform") && task.name.endsWith("For" + variantName)) { Transform transform = ((TransformTask) task).getTransform() - //如果开启了multiDexEnabled true,存在transformClassesWithJarMergingFor${variantName}任务 - if ((((transform instanceof JarMergingTransform)) && !(transform instanceof FastdexJarMergingTransform))) { + + println "task: " + task.name + "transform: " + transform.getClass() + + //如果开启了multiDex并且minSdkVersion < 21,存在transformClassesWithJarMergingFor${variantName}任务 + if (((transform instanceof JarMergingTransform)) && !(transform instanceof FastdexJarMergingTransform)) { if (fastdexVariant.configuration.debug) { project.logger.error("==fastdex find jarmerging transform. transform class: " + task.transform.getClass() + " . task name: " + task.name) } fastdexVariant.hasJarMergingTask = true - FastdexJarMergingTransform jarMergingTransform = new FastdexJarMergingTransform(transform,fastdexVariant) + FastdexJarMergingTransform jarMergingTransform = new FastdexJarMergingTransform(transform,task.getStreamOutputFolder(),fastdexVariant) Field field = getFieldByName(task.getClass(),'transform') field.setAccessible(true) field.set(task,jarMergingTransform) } - if ((((transform instanceof DexTransform)) && !(transform instanceof FastdexTransform))) { + //3.0.0以下任务名叫transformClassesWithDexFor${variantName} ; 3.0.0以上任务名叫transformDexWithDexFor${variantName} + if (((transform instanceof DexTransform)) && !(transform instanceof FastdexDexTransform)) { if (fastdexVariant.configuration.debug) { project.logger.error("==fastdex find dex transform. transform class: " + task.transform.getClass() + " . task name: " + task.name) } //代理DexTransform,实现自定义的转换 - FastdexTransform fastdexTransform = new FastdexTransform(transform,fastdexVariant) - fastdexVariant.fastdexTransform = fastdexTransform + FastdexDexTransform dexTransform = new FastdexDexTransform(transform,task.getStreamOutputFolder(),fastdexVariant) + fastdexVariant.fastdexTransform = dexTransform + Field field = getFieldByName(task.getClass(),'transform') + field.setAccessible(true) + field.set(task,dexTransform) + } + + //transformClassesWithDexBuilderFor${variantName},3.0.0以后才有这个任务 + if ((transform.getClass().getName().equals("com.android.build.gradle.internal.transforms.DexArchiveBuilderTransform") && !(transform instanceof FastdexDexBuilderTransform))) { + FastdexDexBuilderTransform dexBuilderTransform = new FastdexDexBuilderTransform(transform,task.getStreamOutputFolder(),fastdexVariant) + fastdexVariant.dexBuilderOutputFolder = task.getStreamOutputFolder() + + Field field = getFieldByName(task.getClass(),'transform') + field.setAccessible(true) + field.set(task,dexBuilderTransform) + } + + //transformDexArchiveWithDexMergerFor${variantName},3.0.0以后才有这个任务 + if ((transform.getClass().getName().equals("com.android.build.gradle.internal.transforms.DexMergerTransform") && !(transform instanceof FastdexDexBuilderTransform))) { + FastdexDexMergerTransform dexMergerTransform = new FastdexDexMergerTransform(transform,task.getStreamOutputFolder(),fastdexVariant) + fastdexVariant.dexMergerOutputFolder = task.getStreamOutputFolder() + + Field field = getFieldByName(task.getClass(),'transform') + field.setAccessible(true) + field.set(task,dexMergerTransform) + } + + //transformClassesWithPreDexFor{variantName},3.0.0以后才有这个任务 + if ((transform.getClass().getName().equals("com.android.build.gradle.internal.transforms.PreDexTransform") && !(transform instanceof FastdexPreDexTransform))) { + FastdexPreDexTransform preDexTransform = new FastdexPreDexTransform(transform,task.getStreamOutputFolder(),fastdexVariant) + fastdexVariant.preDexOutputFolder = task.getStreamOutputFolder() + fastdexVariant.hasPreDexTask = true + Field field = getFieldByName(task.getClass(),'transform') field.setAccessible(true) - field.set(task,fastdexTransform) + field.set(task,preDexTransform) } } } } - }); - + }) } } } @@ -329,7 +416,7 @@ class FastdexPlugin implements Plugin { def aptOutput = new File(aptOutputDir, variant.dirName) if (variant.variantData.extraGeneratedSourceFolders == null || !variant.variantData.extraGeneratedSourceFolders.contains(aptOutput)) { - variant.addJavaSourceFoldersToModel(aptOutput); + variant.addJavaSourceFoldersToModel(aptOutput) } javaCompile.doFirst { @@ -369,6 +456,21 @@ class FastdexPlugin implements Plugin { javaCompile.options.compilerArgs.addAll(compilerArgs) } + //禁掉aapt2 + def reflectAapt2Flag() { + try { + def booleanOptClazz = Class.forName('com.android.build.gradle.options.BooleanOption') + def enableAAPT2Field = booleanOptClazz.getDeclaredField('ENABLE_AAPT2') + enableAAPT2Field.setAccessible(true) + def enableAAPT2EnumObj = enableAAPT2Field.get(null) + def defValField = enableAAPT2EnumObj.getClass().getDeclaredField('defaultValue') + defValField.setAccessible(true) + defValField.set(enableAAPT2EnumObj, false) + } catch (Throwable thr) { + project.logger.error("relectAapt2Flag error: ${thr.getMessage()}.") + } + } + Task getPackageTask(Project project, String variantName) { String taskName = "package${variantName}" try { @@ -424,7 +526,7 @@ class FastdexPlugin implements Plugin { } } - Task getTransformClassesWithDex(Project project, String variantName) { + Task getTransformClassesWithDexTask(Project project, String variantName) { String taskName = "transformClassesWithDexFor${variantName}" try { return project.tasks.findByName(taskName) @@ -433,6 +535,42 @@ class FastdexPlugin implements Plugin { } } + Task getTransformClassesWithPreDexTask(Project project, String variantName) { + String taskName = "transformClassesWithPreDexFor${variantName}" + try { + return project.tasks.findByName(taskName) + } catch (Throwable e) { + return null + } + } + + Task getTransformClassesWithJarMergingTask(Project project, String variantName) { + String taskName = "transformClassesWithJarMergingFor${variantName}" + try { + return project.tasks.findByName(taskName) + } catch (Throwable e) { + return null + } + } + + Task getTransformDexWithDexForTask(Project project, String variantName) { + String taskName = "transformDexWithDexFor${variantName}" + try { + return project.tasks.findByName(taskName) + } catch (Throwable e) { + return null + } + } + + Task getTransformDexArchiveWithDexMergerTask(Project project, String variantName) { + String taskName = "transformDexArchiveWithDexMergerFor${variantName}" + try { + return project.tasks.findByName(taskName) + } catch (Throwable e) { + return null + } + } + Task getCollectMultiDexComponentsTask(Project project, String variantName) { String taskName = "collect${variantName}MultiDexComponents" try { @@ -443,15 +581,15 @@ class FastdexPlugin implements Plugin { } Field getFieldByName(Class aClass, String name) { - Class currentClass = aClass; + Class currentClass = aClass while (currentClass != null) { try { - return currentClass.getDeclaredField(name); + return currentClass.getDeclaredField(name) } catch (NoSuchFieldException e) { // ignored. } - currentClass = currentClass.getSuperclass(); + currentClass = currentClass.getSuperclass() } - return null; + return null } } \ No newline at end of file diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/extension/FastdexExtension.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/extension/FastdexExtension.groovy index f7b8b3c4..d848596f 100644 --- a/fastdex-gradle/src/main/groovy/fastdex/build/extension/FastdexExtension.groovy +++ b/fastdex-gradle/src/main/groovy/fastdex/build/extension/FastdexExtension.groovy @@ -3,7 +3,7 @@ package fastdex.build.extension /** * Created by tong on 17/10/3. */ -public class FastdexExtension { +class FastdexExtension { /** * 是否可用 */ diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexCleanTask.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexCleanTask.groovy index f4cd55e8..a20b701f 100644 --- a/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexCleanTask.groovy +++ b/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexCleanTask.groovy @@ -9,7 +9,7 @@ import org.gradle.api.tasks.TaskAction * 清空指定variantName的缓存,如果variantName == null清空所有缓存 * Created by tong on 17/3/12. */ -public class FastdexCleanTask extends DefaultTask { +class FastdexCleanTask extends DefaultTask { FastdexVariant fastdexVariant FastdexCleanTask() { @@ -17,7 +17,7 @@ public class FastdexCleanTask extends DefaultTask { } @TaskAction - void clean() { + def clean() { if (fastdexVariant == null) { FastdexUtils.cleanAllCache(project) } diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexCreateMaindexlistFileTask.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexCreateMaindexlistFileTask.groovy index dee1e668..32d7b76f 100644 --- a/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexCreateMaindexlistFileTask.groovy +++ b/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexCreateMaindexlistFileTask.groovy @@ -10,7 +10,7 @@ import org.gradle.api.tasks.TaskAction * 所以这个任务就没有存在的意义了,禁止掉这个任务以提高打包速度,但是transformClassesWithDexFor${variantName}会使用这个任务输出的txt文件,所以需要生成一个空文件防止报错 * Created by tong on 17/3/12. */ -public class FastdexCreateMaindexlistFileTask extends DefaultTask { +class FastdexCreateMaindexlistFileTask extends DefaultTask { FastdexVariant fastdexVariant FastdexCreateMaindexlistFileTask() { @@ -18,7 +18,7 @@ public class FastdexCreateMaindexlistFileTask extends DefaultTask { } @TaskAction - void createFile() { + def createFile() { if (fastdexVariant.androidVariant != null) { File maindexlistFile = fastdexVariant.androidVariant.getVariantData().getScope().getMainDexListFile() File parentFile = maindexlistFile.getParentFile() diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexCustomJavacTask.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexCustomJavacTask.groovy index 9043a91e..7fafc17a 100755 --- a/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexCustomJavacTask.groovy +++ b/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexCustomJavacTask.groovy @@ -30,7 +30,7 @@ import java.nio.file.attribute.BasicFileAttributes * * Created by tong on 17/3/12. */ -public class FastdexCustomJavacTask extends DefaultTask { +class FastdexCustomJavacTask extends DefaultTask { FastdexVariant fastdexVariant Task javaCompile Task javacIncrementalSafeguard @@ -60,7 +60,7 @@ public class FastdexCustomJavacTask extends DefaultTask { } @TaskAction - void compile() { + def compile() { if (!fastdexVariant.hasDexCache) { project.logger.error("==fastdex miss dex cache, just ignore") return @@ -248,8 +248,8 @@ public class FastdexCustomJavacTask extends DefaultTask { project.logger.error("==fastdex apply class to ${destFile}") String classRelativePath = relativePath.toString() - classRelativePath = classRelativePath.substring(0, classRelativePath.length() - ShareConstants.CLASS_SUFFIX.length()); - classRelativePath = classRelativePath.replaceAll(Os.isFamily(Os.FAMILY_WINDOWS) ? "\\\\" : File.separator,"\\."); + classRelativePath = classRelativePath.substring(0, classRelativePath.length() - ShareConstants.CLASS_SUFFIX.length()) + classRelativePath = classRelativePath.replaceAll(Os.isFamily(Os.FAMILY_WINDOWS) ? "\\\\" : File.separator,"\\.") int index = classRelativePath.indexOf("\$") if (index != -1) { diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexDataBindingPrepareTask.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexDataBindingPrepareTask.groovy deleted file mode 100644 index 4b40b350..00000000 --- a/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexDataBindingPrepareTask.groovy +++ /dev/null @@ -1,23 +0,0 @@ -package fastdex.build.task - -import fastdex.build.variant.FastdexVariant -import org.gradle.api.DefaultTask -import org.gradle.api.tasks.TaskAction - -/** - * 开启DataBinding准备上下文环境 - * Created by tong on 17/9/14. - */ -public class FastdexDataBindingPrepareTask extends DefaultTask { - FastdexVariant fastdexVariant - - FastdexDataBindingPrepareTask() { - group = 'fastdex' - } - - @TaskAction - void prepareContext() { - fastdexVariant.projectSnapshoot.prepareEnv() - fastdexVariant.fastdexInstantRun.onFastdexPrepare() - } -} diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexInstantRunMarkTask.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexInstantRunMarkTask.groovy index ce161fea..cb3baf6d 100644 --- a/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexInstantRunMarkTask.groovy +++ b/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexInstantRunMarkTask.groovy @@ -7,7 +7,7 @@ import org.gradle.api.tasks.TaskAction /** * Created by tong on 17/3/12. */ -public class FastdexInstantRunMarkTask extends DefaultTask { +class FastdexInstantRunMarkTask extends DefaultTask { FastdexVariant fastdexVariant FastdexInstantRunMarkTask() { @@ -15,7 +15,7 @@ public class FastdexInstantRunMarkTask extends DefaultTask { } @TaskAction - void mark() { + def mark() { fastdexVariant.fastdexInstantRun.fromFastdexInstantRun = true project.logger.error("==fastdex fromFastdexInstantRun: true") @@ -27,11 +27,6 @@ public class FastdexInstantRunMarkTask extends DefaultTask { } catch (Throwable e) { } -// try { -// fastdexVariant.fastdexInstantRun.startTransparentActivity(true) -// } catch (Throwable e) { -// -// } } }).start() } diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexInstantRunTask.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexInstantRunTask.groovy index 93bb028e..280e993f 100644 --- a/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexInstantRunTask.groovy +++ b/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexInstantRunTask.groovy @@ -9,7 +9,7 @@ import org.gradle.api.tasks.TaskAction /** * Created by tong on 17/3/12. */ -public class FastdexInstantRunTask extends DefaultTask { +class FastdexInstantRunTask extends DefaultTask { FastdexVariant fastdexVariant FastdexInstantRunTask() { @@ -17,7 +17,7 @@ public class FastdexInstantRunTask extends DefaultTask { } @TaskAction - void instantRun() { + def instantRun() { FastdexInstantRun fastdexInstantRun = fastdexVariant.fastdexInstantRun if (!fastdexInstantRun.isInstallApk()) { diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexManifestTask.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexManifestTask.groovy index ebfeb0cb..4aede99a 100644 --- a/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexManifestTask.groovy +++ b/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexManifestTask.groovy @@ -14,7 +14,7 @@ import org.gradle.api.tasks.TaskAction * * Created by tong on 17/3/11. */ -public class FastdexManifestTask extends DefaultTask { +class FastdexManifestTask extends DefaultTask { static final String FASTDEX_ORIGIN_APPLICATION_CLASSNAME = "FASTDEX_ORIGIN_APPLICATION_CLASSNAME" static final String FASTDEX_BOOT_ACTIVITY_CLASSNAME = "FASTDEX_BOOT_ACTIVITY_CLASSNAME" static final String MIDDLEWARE_ACTIVITY = "fastdex.runtime.MiddlewareActivity" @@ -34,7 +34,7 @@ public class FastdexManifestTask extends DefaultTask { def application = xml.application[0] if (application) { - QName nameAttr = new QName("http://schemas.android.com/apk/res/android", 'name', 'android'); + QName nameAttr = new QName("http://schemas.android.com/apk/res/android", 'name', 'android') def applicationName = application.attribute(nameAttr) if (applicationName == null || applicationName.isEmpty()) { applicationName = "android.app.Application" diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexPatchTask.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexPatchTask.groovy index cde00371..efff341d 100644 --- a/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexPatchTask.groovy +++ b/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexPatchTask.groovy @@ -16,7 +16,7 @@ import org.gradle.api.tasks.TaskAction /** * Created by tong on 17/3/12. */ -public class FastdexPatchTask extends DefaultTask { +class FastdexPatchTask extends DefaultTask { FastdexVariant fastdexVariant FastdexPatchTask() { @@ -59,7 +59,7 @@ public class FastdexPatchTask extends DefaultTask { try { runtimeMetaInfo = serviceCommunicator.talkToService(fastdexInstantRun.device, new Communicator() { @Override - public MetaInfo communicate(DataInputStream input, DataOutputStream output) throws IOException { + MetaInfo communicate(DataInputStream input, DataOutputStream output) throws IOException { output.writeInt(ProtocolConstants.MESSAGE_PING_AND_SHOW_TOAST) MetaInfo info = new MetaInfo() @@ -106,7 +106,6 @@ public class FastdexPatchTask extends DefaultTask { } catch (Throwable e) { if (!(e instanceof FastdexRuntimeException)) { - e.printStackTrace() fastdexVariant.project.logger.error("==fastdex ping installed app fail: " + e.message) } return @@ -140,7 +139,7 @@ public class FastdexPatchTask extends DefaultTask { try { boolean result = serviceCommunicator.talkToService(fastdexInstantRun.device, new Communicator() { @Override - public Boolean communicate(DataInputStream input, DataOutputStream output) throws IOException { + Boolean communicate(DataInputStream input, DataOutputStream output) throws IOException { output.writeInt(ProtocolConstants.MESSAGE_PATCHES) output.writeLong(ShareConstants.MESSAGE_TOKEN) output.writeInt(changeCount) @@ -184,7 +183,7 @@ public class FastdexPatchTask extends DefaultTask { } } }) - long end = System.currentTimeMillis(); + long end = System.currentTimeMillis() project.logger.error("==fastdex send patch data success. use: ${end - start}ms") //app不在后台、补丁发送失败、补丁中包含dex并且有设置使用命令强制重启 @@ -195,7 +194,9 @@ public class FastdexPatchTask extends DefaultTask { } fastdexInstantRun.setInstallApk(false) } catch (Throwable e) { - e.printStackTrace() + if (!(e instanceof FastdexRuntimeException)) { + fastdexVariant.project.logger.error("==fastdex send patch fail: " + e.message) + } } } diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexPrepareTask.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexPrepareTask.groovy index 18452cbb..3b2b57c1 100644 --- a/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexPrepareTask.groovy +++ b/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexPrepareTask.groovy @@ -8,7 +8,7 @@ import org.gradle.api.tasks.TaskAction * 准备上下文环境 * Created by tong on 17/4/18. */ -public class FastdexPrepareTask extends DefaultTask { +class FastdexPrepareTask extends DefaultTask { FastdexVariant fastdexVariant FastdexPrepareTask() { @@ -16,7 +16,7 @@ public class FastdexPrepareTask extends DefaultTask { } @TaskAction - void prepareContext() { + def prepareContext() { fastdexVariant.prepareEnv() } } diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexResourceIdTask.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexResourceIdTask.groovy index 8a03cbb5..aa70c8e1 100644 --- a/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexResourceIdTask.groovy +++ b/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexResourceIdTask.groovy @@ -22,7 +22,7 @@ import fastdex.build.util.FastdexUtils * * Created by tong on 17/3/11. */ -public class FastdexResourceIdTask { +class FastdexResourceIdTask { Project project FastdexVariant fastdexVariant String resDir @@ -43,8 +43,8 @@ public class FastdexResourceIdTask { File idsXmlFile = FastdexUtils.getIdxXmlFile(project,fastdexVariant.variantName) File publicXmlFile = FastdexUtils.getPublicXmlFile(project,fastdexVariant.variantName) - String idsXml = resDir + "/values/ids.xml"; - String publicXml = resDir + "/values/public.xml"; + String idsXml = resDir + "/values/ids.xml" + String publicXml = resDir + "/values/public.xml" File resDirIdsXmlFile = new File(idsXml) File resDirPublicXmlFile = new File(publicXml) @@ -61,8 +61,9 @@ public class FastdexResourceIdTask { return } - FileUtils.deleteFile(idsXml); - FileUtils.deleteFile(publicXml); + FileUtils.deleteFile(idsXml) + FileUtils.deleteFile(publicXml) + List resourceDirectoryList = new ArrayList() resourceDirectoryList.add(resDir) @@ -72,7 +73,6 @@ public class FastdexResourceIdTask { AaptResourceCollector aaptResourceCollector = AaptUtil.collectResource(resourceDirectoryList, rTypeResourceMap) PatchUtil.generatePublicResourceXml(aaptResourceCollector, idsXml, publicXml) File publicFile = new File(publicXml) - if (publicFile.exists()) { FileUtils.copyFileUsingStream(publicFile, publicXmlFile) project.logger.error("==fastdex gen resource public.xml in ${Constants.RESOURCE_PUBLIC_XML}") diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexScanAptOutputTask.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexScanAptOutputTask.groovy index 27411c10..1e10e607 100644 --- a/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexScanAptOutputTask.groovy +++ b/fastdex-gradle/src/main/groovy/fastdex/build/task/FastdexScanAptOutputTask.groovy @@ -16,7 +16,7 @@ import org.gradle.api.tasks.TaskAction * 恢复对apt目录的扫描 * Created by tong on 17/10/13. */ -public class FastdexScanAptOutputTask extends DefaultTask { +class FastdexScanAptOutputTask extends DefaultTask { FastdexVariant fastdexVariant FastdexScanAptOutputTask() { @@ -24,7 +24,7 @@ public class FastdexScanAptOutputTask extends DefaultTask { } @TaskAction - void scan() { + def scan() { //如果没有使用自定义的编译任务需要拿老的apt快照与当前的对比 boolean needDiff = fastdexVariant.hasDexCache && !fastdexVariant.compiledByCustomJavac //开启自定义的javac任务正常是不需要在扫描apt目录的,但是如果执行了dex merge会在保存一次当前快照,所以这种情况下要重新加回去 @@ -60,16 +60,16 @@ public class FastdexScanAptOutputTask extends DefaultTask { project.logger.error("==fastdex not find old apt snapshoot") //add - JavaDirectoryDiffResultSet resultSet = aptDirectorySnapshoot.createEmptyResultSet(); + JavaDirectoryDiffResultSet resultSet = aptDirectorySnapshoot.createEmptyResultSet() for (FileNode node : aptDirectorySnapshoot.nodes) { - resultSet.add(new JavaFileDiffInfo(Status.ADDED,node,null)); + resultSet.add(new JavaFileDiffInfo(Status.ADDED,node,null)) project.logger.error("==fastdex find new apt file: " + node.uniqueKey) } - diffResultSet.mergeJavaDirectoryResultSet(sourceSetSnapshoot.path,resultSet); + diffResultSet.mergeJavaDirectoryResultSet(sourceSetSnapshoot.path,resultSet) } else { //diff - JavaDirectoryDiffResultSet resultSet = (JavaDirectoryDiffResultSet) aptDirectorySnapshoot.diff(oldAptJavaDirectorySnapshoot); + JavaDirectoryDiffResultSet resultSet = (JavaDirectoryDiffResultSet) aptDirectorySnapshoot.diff(oldAptJavaDirectorySnapshoot) for (JavaFileDiffInfo diffInfo : resultSet.changedDiffInfos) { if (diffInfo.status == Status.ADDED) { project.logger.error("==fastdex find new apt file: " + diffInfo.uniqueKey) @@ -78,7 +78,7 @@ public class FastdexScanAptOutputTask extends DefaultTask { project.logger.error("==fastdex find changed apt file: " + diffInfo.uniqueKey) } } - diffResultSet.mergeJavaDirectoryResultSet(sourceSetSnapshoot.path,resultSet); + diffResultSet.mergeJavaDirectoryResultSet(sourceSetSnapshoot.path,resultSet) } } } diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/transform/FastdexDexBuilderTransform.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/transform/FastdexDexBuilderTransform.groovy new file mode 100644 index 00000000..ef8329d0 --- /dev/null +++ b/fastdex-gradle/src/main/groovy/fastdex/build/transform/FastdexDexBuilderTransform.groovy @@ -0,0 +1,39 @@ +package fastdex.build.transform + +import com.android.build.api.transform.Transform +import com.android.build.api.transform.TransformException +import com.android.build.api.transform.TransformInvocation +import fastdex.build.util.Constants +import fastdex.build.util.JarOperation +import fastdex.build.variant.FastdexVariant +import fastdex.common.utils.FileUtils + +/** + * Created by tong on 17/10/31. + */ +class FastdexDexBuilderTransform extends TransformProxy { + + FastdexDexBuilderTransform(Transform base,File streamOutputFolder, FastdexVariant fastdexVariant) { + super(base,streamOutputFolder,fastdexVariant) + } + + @Override + void transform(TransformInvocation transformInvocation) throws TransformException, IOException, InterruptedException { + if (fastdexVariant.hasDexCache) { + project.logger.error("\n==fastdex patch transform start,we will generate dex file") + if (fastdexVariant.projectSnapshoot.diffResultSet.isJavaFileChanged()) { + FileUtils.deleteDir(streamOutputFolder) + File patchJar = new File(streamOutputFolder,Constants.PATCH_JAR) + //生成补丁jar + JarOperation.generatePatchJar(fastdexVariant,transformInvocation,patchJar) + } + else { + project.logger.error("==fastdex no java files have changed, just ignore") + } + } + else { + fastdexBuilder.injectInputAndSaveClassPath(transformInvocation) + base.transform(transformInvocation) + } + } +} diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/transform/FastdexDexMergerTransform.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/transform/FastdexDexMergerTransform.groovy new file mode 100644 index 00000000..1149a243 --- /dev/null +++ b/fastdex-gradle/src/main/groovy/fastdex/build/transform/FastdexDexMergerTransform.groovy @@ -0,0 +1,71 @@ +package fastdex.build.transform + +import com.android.build.api.transform.* +import fastdex.build.util.Constants +import fastdex.build.variant.FastdexVariant +import org.gradle.api.file.FileCollection +import java.lang.reflect.Constructor + +/** + * Created by tong on 17/10/31. + */ +class FastdexDexMergerTransform extends TransformProxy { + + FastdexDexMergerTransform(Transform base,File streamOutputFolder, FastdexVariant fastdexVariant) { + super(replaceBaseTransform(base,fastdexVariant),streamOutputFolder,fastdexVariant) + } + + @Override + void transform(TransformInvocation transformInvocation) throws TransformException, IOException, InterruptedException { + if (fastdexVariant.hasDexCache) { + if (fastdexVariant.projectSnapshoot.diffResultSet.isJavaFileChanged()) { + File patchJar = new File(fastdexVariant.dexBuilderOutputFolder,Constants.PATCH_JAR) + fastdexBuilder.patchBuild(base,patchJar,streamOutputFolder) + } + else { + project.logger.error("==fastdex no java files have changed, just ignore") + } + } + else { + project.logger.error("\n==fastdex normal transform start") + fastdexBuilder.invokeNormalBuildTransform(base,transformInvocation) + project.logger.error("==fastdex normal transform end\n") + } + } + + static Transform replaceBaseTransform(Transform base, FastdexVariant fastdexVariant) { + //multiDexEnabled true, minSdkVersion 15 +// base.dexingType: LEGACY_MULTIDEX +// base.mainDexListFile: file collection +// base.errorReporter: com.android.build.gradle.internal.ExtraModelInfo@5b238f1d +// base.dexMerger: DX +// base.minSdkVersion: 15 +// base.isDebuggable: true +// + + //multiDexEnabled true, minSdkVersion 21 +// base.dexingType: NATIVE_MULTIDEX +// base.mainDexListFile: null +// base.errorReporter: com.android.build.gradle.internal.ExtraModelInfo@3c9d924 +// base.dexMerger: DX +// base.minSdkVersion: 21 +// base.isDebuggable: true + + //com.android.build.gradle.internal.transforms.DexMergerTransform + + Class dexingTypeClass = Class.forName("com.android.builder.dexing.DexingType") + Object[] values = dexingTypeClass.getMethod("values").invoke(null,null) + + Constructor[] constructors = base.getClass().getConstructors() + Constructor targetConstructor = constructors[0] + + Transform result = + targetConstructor.newInstance(values.find { it.isMultiDex() && it.isPreDex() } + ,(FileCollection)null + , base.errorReporter + ,base.dexMerger + ,21 + ,true) + return result + } +} \ No newline at end of file diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/transform/FastdexDexTransform.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/transform/FastdexDexTransform.groovy new file mode 100644 index 00000000..967905eb --- /dev/null +++ b/fastdex-gradle/src/main/groovy/fastdex/build/transform/FastdexDexTransform.groovy @@ -0,0 +1,181 @@ +package fastdex.build.transform + +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.TransformInvocationBuilder +import com.android.build.gradle.internal.transforms.DexTransform +import fastdex.build.util.Constants +import fastdex.build.util.FastdexUtils +import fastdex.build.util.GradleUtils +import fastdex.build.variant.FastdexVariant +import com.google.common.collect.Lists +import com.android.build.api.transform.JarInput +import com.android.build.api.transform.TransformInput +import fastdex.build.util.JarOperation + +/** + * 用于dex生成 + * 全量打包时的流程: + * 1、合并所有的class文件生成一个jar包 + * 2、扫描所有的项目代码并且在构造方法里添加对com.dx168.fastdex.runtime.antilazyload.AntilazyLoad类的依赖 + * 这样做的目的是为了解决class verify的问题, + * 详情请看https://mp.weixin.qq.com/s?__biz=MzI1MTA1MzM2Nw==&mid=400118620&idx=1&sn=b4fdd5055731290eef12ad0d17f39d4a + * 3、对项目代码做快照,为了以后补丁打包时对比那些java文件发生了变化 + * 4、对当前项目的所以依赖做快照,为了以后补丁打包时对比依赖是否发生了变化,如果变化需要清除缓存 + * 5、调用真正的transform生成dex + * 6、缓存生成的dex,并且把fastdex-runtime.dex插入到dex列表中,假如生成了两个dex,classes.dex classes2.dex 需要做一下操作 + * fastdex-runtime.dex => classes.dex + * classes.dex => classes2.dex + * classes2.dex => classes3.dex + * 然后运行期在入口Application(com.dx168.fastdex.runtime.FastdexApplication)使用MultiDex把所有的dex加载进来 + * 7、保存资源映射映射表,为了保持id的值一致,详情看 + * @see fastdex.build.task.FastdexResourceIdTask + * + * 补丁打包时的流程 + * 1、检查缓存的有效性 + * @see fastdex.build.task.FastdexCustomJavacTask 的prepareEnv方法说明 + * 2、扫描所有变化的java文件并编译成class + * @see fastdex.build.task.FastdexCustomJavacTask + * 3、合并所有变化的class并生成jar包 + * 4、生成补丁dex + * 5、把所有的dex按照一定规律放在transformClassesWithMultidexlistFor${variantName}任务的输出目录 + * fastdex-runtime.dex => classes.dex + * patch.dex => classes2.dex + * dex_cache.classes.dex => classes3.dex + * dex_cache.classes2.dex => classes4.dex + * dex_cache.classesN.dex => classes(N + 2).dex + * + * Created by tong on 17/10/3. + */ +class FastdexDexTransform extends TransformProxy { + + FastdexDexTransform(Transform base,File streamOutputFolder, FastdexVariant fastdexVariant) { + super(replaceBaseTransform(base, fastdexVariant),streamOutputFolder,fastdexVariant) + } + + @Override + void transform(TransformInvocation transformInvocation) throws TransformException, IOException, InterruptedException { + if (fastdexVariant.hasDexCache) { + project.logger.error("\n==fastdex patch transform start,we will generate dex file") + if (fastdexVariant.projectSnapshoot.diffResultSet.isJavaFileChanged()) { + //生成补丁jar包 + File patchJar = generatePatchJar(transformInvocation) + //获取dex输出路径 + File dexOutputDir = GradleUtils.getDexOutputDir(transformInvocation) + fastdexBuilder.patchBuild(base,patchJar,dexOutputDir) + } + else { + project.logger.error("==fastdex no java files have changed, just ignore") + } + } + else { + project.logger.error("==fastdex normal transform start") + + if (!fastdexVariant.hasJarMergingTask) { + fastdexBuilder.injectInputAndSaveClassPath(transformInvocation) + } + + if (fastdexVariant.hasJarMergingTask && GradleUtils.getAndroidGradlePluginVersion().compareTo(Constants.MIN_BUILD_CACHE_ENABLED_VERSION) >= 0) { + TransformInvocationBuilder builder = new TransformInvocationBuilder(transformInvocation.context) + builder.addInputs(fastdexVariant.transformInvocation.inputs) + builder.addReferencedInputs(fastdexVariant.transformInvocation.referencedInputs) + builder.addSecondaryInputs(fastdexVariant.transformInvocation.secondaryInputs) + builder.setIncrementalMode(transformInvocation.incremental) + builder.addOutputProvider(transformInvocation.outputProvider) + + transformInvocation = builder.build() + } + + fastdexBuilder.invokeNormalBuildTransform(base,transformInvocation) + project.logger.error("==fastdex normal transform end\n") + } + } + + + + /** + * 获取输出jar路径 + * @param invocation + * @return + */ + def getCombinedJarFile(TransformInvocation invocation) { + List jarInputs = Lists.newArrayList() + for (TransformInput input : invocation.getInputs()) { + jarInputs.addAll(input.getJarInputs()) + } + if (jarInputs.size() != 1) { + throw new RuntimeException("==fastdex jar input size is ${jarInputs.size()}, expected is 1") + } + File combinedJar = jarInputs.get(0).getFile() + return combinedJar + } + + /** + * 生成补丁jar包 + * @param transformInvocation + * @return + */ + def generatePatchJar(TransformInvocation transformInvocation) { + if (fastdexVariant.hasJarMergingTask) { + //如果开启了multidex,FastdexJarMergingTransform完成了jar merge的操作 + File patchJar = getCombinedJarFile(transformInvocation) + project.logger.error("==fastdex multiDex enabled use patch.jar: ${patchJar}") + return patchJar + } + else if (fastdexVariant.hasPreDexTask) { + File patchJar = new File(fastdexVariant.preDexOutputFolder,Constants.PATCH_JAR) + return patchJar + } + else { + //补丁jar + File patchJar = new File(FastdexUtils.getBuildDir(project,variantName),Constants.PATCH_JAR) + //生成补丁jar + JarOperation.generatePatchJar(fastdexVariant,transformInvocation,patchJar) + return patchJar + } + } + + static Transform replaceBaseTransform(Transform base, FastdexVariant fastdexVariant) { +// if (GradleUtils.getAndroidGradlePluginVersion().compareTo("3.0") >= 0) { +// Class dexingTypeClass = Class.forName("com.android.builder.dexing.DexingType") +// Object[] values = dexingTypeClass.getMethod("values").invoke(null,null) +// +// //com.android.build.gradle.internal.transforms.DexTransform +// Constructor[] constructors = base.getClass().getConstructors() +// Constructor targetConstructor = constructors[0] +// +// Transform result = +// targetConstructor.newInstance( base.dexOptions +// ,values.find { it.isMultiDex() && it.isPreDex() } +// ,base.preDexEnabled +// ,(FileCollection)null +// ,base.targetInfo +// ,base.dexByteCodeConverter +// , base.errorReporter +// ,21) +// +// return result +// } +// else + if (GradleUtils.getAndroidGradlePluginVersion().compareTo(Constants.MIN_BUILD_CACHE_ENABLED_VERSION) >= 0 && GradleUtils.getAndroidGradlePluginVersion().compareTo("3.0") < 0) { + //在所有的build-type上触发2.2以后的build-cache + //boolean needMerge = !multiDex || mainDexListFile != null;// || !debugMode; + + fastdexVariant.project.logger.error("==fastdex android gradle >= ${Constants.MIN_BUILD_CACHE_ENABLED_VERSION} ,replace dex transform") + return new DexTransform( + base.dexOptions, + base.debugMode, + base.multiDex, + null, + base.intermediateFolder, + base.androidBuilder, + base.logger.logger, + base.instantRunBuildContext, + base.buildCache) + } + else { + return base + } + } +} \ No newline at end of file diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/transform/FastdexJarMergingTransform.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/transform/FastdexJarMergingTransform.groovy index 833e28e8..ebf9afd3 100644 --- a/fastdex-gradle/src/main/groovy/fastdex/build/transform/FastdexJarMergingTransform.groovy +++ b/fastdex-gradle/src/main/groovy/fastdex/build/transform/FastdexJarMergingTransform.groovy @@ -1,30 +1,23 @@ package fastdex.build.transform -import com.android.build.api.transform.JarInput import com.android.build.api.transform.Transform import com.android.build.api.transform.TransformException -import com.android.build.api.transform.TransformInput import com.android.build.api.transform.TransformInvocation -import fastdex.build.util.ClassInject import fastdex.build.util.Constants -import fastdex.build.util.FastdexUtils import fastdex.build.util.GradleUtils import fastdex.build.util.JarOperation import fastdex.build.variant.FastdexVariant import com.android.build.api.transform.Format import fastdex.common.utils.FileUtils -import fastdex.common.utils.SerializeUtils /** * 拦截transformClassesWithJarMergingFor${variantName}任务, * Created by tong on 17/27/3. */ class FastdexJarMergingTransform extends TransformProxy { - FastdexVariant fastdexVariant - FastdexJarMergingTransform(Transform base, FastdexVariant fastdexVariant) { - super(base) - this.fastdexVariant = fastdexVariant + FastdexJarMergingTransform(Transform base,File streamOutputFolder, FastdexVariant fastdexVariant) { + super(base,streamOutputFolder,fastdexVariant) } @Override @@ -41,21 +34,7 @@ class FastdexJarMergingTransform extends TransformProxy { } } else { - //所有输入的jar - Set jarInputFiles = new HashSet<>(); - for (TransformInput input : transformInvocation.getInputs()) { - Collection jarInputs = input.getJarInputs() - if (jarInputs != null) { - for (JarInput jarInput : jarInputs) { - jarInputFiles.add(jarInput.getFile().absolutePath) - } - } - } - File classpathFile = new File(FastdexUtils.getBuildDir(fastdexVariant.project,fastdexVariant.variantName),Constants.CLASSPATH_FILENAME) - SerializeUtils.serializeTo(classpathFile,jarInputFiles) - - //inject dir input - ClassInject.injectTransformInvocation(fastdexVariant,transformInvocation) + fastdexBuilder.injectInputAndSaveClassPath(transformInvocation) if (GradleUtils.getAndroidGradlePluginVersion().compareTo(Constants.MIN_BUILD_CACHE_ENABLED_VERSION) >= 0) { //不做合并时为了使用build-cache @@ -72,13 +51,13 @@ class FastdexJarMergingTransform extends TransformProxy { * @param invocation * @return */ - public File getCombinedJarFile(TransformInvocation invocation) { - def outputProvider = invocation.getOutputProvider(); + def getCombinedJarFile(TransformInvocation invocation) { + def outputProvider = invocation.getOutputProvider() // all the output will be the same since the transform type is COMBINED. // and format is SINGLE_JAR so output is a jar - File jarFile = outputProvider.getContentLocation("combined", base.getOutputTypes(), base.getScopes(), Format.JAR); - FileUtils.ensumeDir(jarFile.getParentFile()); + File jarFile = outputProvider.getContentLocation("combined", base.getOutputTypes(), base.getScopes(), Format.JAR) + FileUtils.ensumeDir(jarFile.getParentFile()) return jarFile } } \ No newline at end of file diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/transform/FastdexPreDexTransform.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/transform/FastdexPreDexTransform.groovy new file mode 100644 index 00000000..87393769 --- /dev/null +++ b/fastdex-gradle/src/main/groovy/fastdex/build/transform/FastdexPreDexTransform.groovy @@ -0,0 +1,60 @@ +package fastdex.build.transform + +import com.android.build.api.transform.Transform +import com.android.build.api.transform.TransformException +import com.android.build.api.transform.TransformInvocation +import fastdex.build.util.Constants +import fastdex.build.util.FastdexUtils +import fastdex.build.util.JarOperation +import fastdex.build.variant.FastdexVariant +import fastdex.common.utils.FileUtils + +/** + * Created by tong on 17/11/2. + */ +class FastdexPreDexTransform extends TransformProxy { + + FastdexPreDexTransform(Transform base,File streamOutputFolder, FastdexVariant fastdexVariant) { + super(base,streamOutputFolder,fastdexVariant) + } + + @Override + void transform(TransformInvocation transformInvocation) throws TransformException, IOException, InterruptedException { + if (fastdexVariant.hasDexCache) { + project.logger.error("\n==fastdex patch transform start,we will generate dex file") + + if (base.dexingType.isMultiDex() && base.dexingType.isPreDex()) { + if (fastdexVariant.projectSnapshoot.diffResultSet.isJavaFileChanged()) { + //生成补丁jar包 + File patchJar = new File(FastdexUtils.getBuildDir(project,variantName),Constants.PATCH_JAR) + JarOperation.generatePatchJar(fastdexVariant,transformInvocation,patchJar) + fastdexBuilder.patchBuild(base,patchJar,streamOutputFolder) + } + else { + project.logger.error("==fastdex no java files have changed, just ignore") + } + } + else { + if (fastdexVariant.projectSnapshoot.diffResultSet.isJavaFileChanged()) { + FileUtils.deleteDir(streamOutputFolder) + File patchJar = new File(streamOutputFolder,Constants.PATCH_JAR) + //生成补丁jar + JarOperation.generatePatchJar(fastdexVariant,transformInvocation,patchJar) + } + else { + project.logger.error("==fastdex no java files have changed, just ignore") + } + } + } + else { + if (base.dexingType.isMultiDex() && base.dexingType.isPreDex()) { + fastdexBuilder.injectInputAndSaveClassPath(transformInvocation) + fastdexBuilder.invokeNormalBuildTransform(base,transformInvocation) + } + else { + fastdexBuilder.injectInputAndSaveClassPath(transformInvocation) + base.transform(transformInvocation) + } + } + } +} diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/transform/FastdexTransform.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/transform/FastdexTransform.groovy deleted file mode 100644 index a1c40809..00000000 --- a/fastdex-gradle/src/main/groovy/fastdex/build/transform/FastdexTransform.groovy +++ /dev/null @@ -1,376 +0,0 @@ -package fastdex.build.transform - -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.TransformInvocationBuilder -import com.android.build.gradle.internal.transforms.DexTransform -import fastdex.build.util.ClassInject -import fastdex.build.util.Constants -import fastdex.build.util.DexOperation -import fastdex.build.util.FastdexUtils -import fastdex.build.util.GradleUtils -import fastdex.build.variant.FastdexVariant -import com.google.common.collect.Lists -import fastdex.common.utils.SerializeUtils -import org.gradle.api.Project -import fastdex.common.utils.FileUtils -import com.android.build.api.transform.JarInput -import com.android.build.api.transform.TransformInput -import fastdex.build.util.JarOperation - -/** - * 用于dex生成 - * 全量打包时的流程: - * 1、合并所有的class文件生成一个jar包 - * 2、扫描所有的项目代码并且在构造方法里添加对com.dx168.fastdex.runtime.antilazyload.AntilazyLoad类的依赖 - * 这样做的目的是为了解决class verify的问题, - * 详情请看https://mp.weixin.qq.com/s?__biz=MzI1MTA1MzM2Nw==&mid=400118620&idx=1&sn=b4fdd5055731290eef12ad0d17f39d4a - * 3、对项目代码做快照,为了以后补丁打包时对比那些java文件发生了变化 - * 4、对当前项目的所以依赖做快照,为了以后补丁打包时对比依赖是否发生了变化,如果变化需要清除缓存 - * 5、调用真正的transform生成dex - * 6、缓存生成的dex,并且把fastdex-runtime.dex插入到dex列表中,假如生成了两个dex,classes.dex classes2.dex 需要做一下操作 - * fastdex-runtime.dex => classes.dex - * classes.dex => classes2.dex - * classes2.dex => classes3.dex - * 然后运行期在入口Application(com.dx168.fastdex.runtime.FastdexApplication)使用MultiDex把所有的dex加载进来 - * 7、保存资源映射映射表,为了保持id的值一致,详情看 - * @see fastdex.build.task.FastdexResourceIdTask - * - * 补丁打包时的流程 - * 1、检查缓存的有效性 - * @see fastdex.build.task.FastdexCustomJavacTask 的prepareEnv方法说明 - * 2、扫描所有变化的java文件并编译成class - * @see fastdex.build.task.FastdexCustomJavacTask - * 3、合并所有变化的class并生成jar包 - * 4、生成补丁dex - * 5、把所有的dex按照一定规律放在transformClassesWithMultidexlistFor${variantName}任务的输出目录 - * fastdex-runtime.dex => classes.dex - * patch.dex => classes2.dex - * dex_cache.classes.dex => classes3.dex - * dex_cache.classes2.dex => classes4.dex - * dex_cache.classesN.dex => classes(N + 2).dex - * - * Created by tong on 17/10/3. - */ -class FastdexTransform extends TransformProxy { - FastdexVariant fastdexVariant - - Project project - String variantName - - FastdexTransform(Transform base, FastdexVariant fastdexVariant) { - super(base) - if (GradleUtils.getAndroidGradlePluginVersion().compareTo(Constants.MIN_BUILD_CACHE_ENABLED_VERSION) >= 0) { - //在所有的build-type上触发2.2以后的build-cache - //boolean needMerge = !multiDex || mainDexListFile != null;// || !debugMode; - - fastdexVariant.project.logger.error("==fastdex android gradle >= ${Constants.MIN_BUILD_CACHE_ENABLED_VERSION} ,replace dex transform") - this.base = new DexTransform( - base.dexOptions, - base.debugMode, - base.multiDex, - null, - base.intermediateFolder, - base.androidBuilder, - base.logger.logger, - base.instantRunBuildContext, - base.buildCache); - } - - this.fastdexVariant = fastdexVariant - this.project = fastdexVariant.project - this.variantName = fastdexVariant.variantName - } - - @Override - void transform(TransformInvocation transformInvocation) throws TransformException, IOException, InterruptedException { - if (fastdexVariant.hasDexCache) { - project.logger.error("\n==fastdex patch transform start,we will generate dex file") - if (fastdexVariant.projectSnapshoot.diffResultSet.isJavaFileChanged()) { - //生成补丁jar包 - File patchJar = generatePatchJar(transformInvocation) - File patchDex = FastdexUtils.getPatchDexFile(fastdexVariant.project,fastdexVariant.variantName) - DexOperation.generatePatchDex(fastdexVariant,base,patchJar,patchDex) - fastdexVariant.metaInfo.patchDexVersion += 1 - - //获取dex输出路径 - File dexOutputDir = GradleUtils.getDexOutputDir(transformInvocation) - - //merged dex - File mergedPatchDexDir = FastdexUtils.getMergedPatchDexDir(fastdexVariant.project,fastdexVariant.variantName) - - boolean willExecDexMerge = fastdexVariant.willExecDexMerge() - boolean firstMergeDex = fastdexVariant.metaInfo.mergedDexVersion == 0 - - if (willExecDexMerge) { - //merge dex - if (firstMergeDex) { - //第一次执行dex merge,直接保存patchDex - //copy 一份相同的,做冗余操作,如果直接移动文件,会丢失patch.dex造成免安装模块特别难处理 - FileUtils.copyFileUsingStream(patchDex,new File(mergedPatchDexDir,Constants.CLASSES_DEX)) - } - else { - //已经执行过一次dex merge - File mergedPatchDex = new File(mergedPatchDexDir,Constants.CLASSES_DEX) - //更新patch.dex - DexOperation.mergeDex(fastdexVariant,mergedPatchDex,patchDex,mergedPatchDex) - } - fastdexVariant.metaInfo.mergedDexVersion += 1 - } - fastdexVariant.metaInfo.save(fastdexVariant) - //复制补丁打包的dex到输出路径,为了触发package任务 - hookPatchBuildDex(dexOutputDir,willExecDexMerge) - fastdexVariant.onDexGenerateSuccess(false,willExecDexMerge) - } - else { - project.logger.error("==fastdex no java files have changed, just ignore") - } - } - else { - project.logger.error("==fastdex normal transform start") - - if (!fastdexVariant.hasJarMergingTask) { - //所有输入的jar - Set jarInputFiles = new HashSet<>(); - for (TransformInput input : transformInvocation.getInputs()) { - Collection jarInputs = input.getJarInputs() - if (jarInputs != null) { - for (JarInput jarInput : jarInputs) { - jarInputFiles.add(jarInput.getFile().absolutePath) - } - } - } - File classpathFile = new File(FastdexUtils.getBuildDir(project,variantName),Constants.CLASSPATH_FILENAME) - SerializeUtils.serializeTo(classpathFile,jarInputFiles) - - ClassInject.injectTransformInvocation(fastdexVariant,transformInvocation) - - } - - if (fastdexVariant.hasJarMergingTask && GradleUtils.getAndroidGradlePluginVersion().compareTo(Constants.MIN_BUILD_CACHE_ENABLED_VERSION) >= 0) { - TransformInvocationBuilder builder = new TransformInvocationBuilder(transformInvocation.context) - builder.addInputs(fastdexVariant.transformInvocation.inputs) - builder.addReferencedInputs(fastdexVariant.transformInvocation.referencedInputs) - builder.addSecondaryInputs(fastdexVariant.transformInvocation.secondaryInputs) - builder.setIncrementalMode(transformInvocation.incremental) - builder.addOutputProvider(transformInvocation.outputProvider) - - transformInvocation = builder.build() - } - - //调用默认转换方法 - base.transform(transformInvocation) - //获取dex输出路径 - File dexOutputDir = GradleUtils.getDexOutputDir(transformInvocation) - - project.logger.error("==fastdex dexOutputDir: ${dexOutputDir}") - - //缓存dex - int dexCount = cacheNormalBuildDex(dexOutputDir) - - //复制全量打包的dex到输出路径 - hookNormalBuildDex(dexOutputDir) - - fastdexVariant.metaInfo.dexCount = dexCount - fastdexVariant.metaInfo.buildMillis = System.currentTimeMillis() - - fastdexVariant.onDexGenerateSuccess(true,false) - project.logger.error("==fastdex normal transform end\n") - } - } - - public void copyFastdexRuntimeDex(File dist) { - File buildDir = FastdexUtils.getBuildDir(project) - - File fastdexRuntimeDex = new File(buildDir, Constants.RUNTIME_DEX_FILENAME) - if (!FileUtils.isLegalFile(fastdexRuntimeDex)) { - FileUtils.copyResourceUsingStream(Constants.RUNTIME_DEX_FILENAME, fastdexRuntimeDex) - } - FileUtils.copyFileUsingStream(fastdexRuntimeDex, dist) - - project.logger.error("==fastdex fastdex-runtime.dex => " + dist) - } - - /** - * 获取输出jar路径 - * @param invocation - * @return - */ - public File getCombinedJarFile(TransformInvocation invocation) { - List jarInputs = Lists.newArrayList(); - for (TransformInput input : invocation.getInputs()) { - jarInputs.addAll(input.getJarInputs()); - } - if (jarInputs.size() != 1) { - throw new RuntimeException("==fastdex jar input size is ${jarInputs.size()}, expected is 1") - } - File combinedJar = jarInputs.get(0).getFile() - return combinedJar - } - - /** - * 生成补丁jar包 - * @param transformInvocation - * @return - */ - File generatePatchJar(TransformInvocation transformInvocation) { - if (fastdexVariant.hasJarMergingTask) { - //如果开启了multidex,FastdexJarMergingTransform完成了jar merge的操作 - File patchJar = getCombinedJarFile(transformInvocation) - project.logger.error("==fastdex multiDex enabled use patch.jar: ${patchJar}") - return patchJar - } - else { - //补丁jar - File patchJar = new File(FastdexUtils.getBuildDir(project,variantName),"patch-combined.jar") - //生成补丁jar - JarOperation.generatePatchJar(fastdexVariant,transformInvocation,patchJar) - return patchJar - } - } - - /** - * 缓存全量打包时生成的dex - * @param dexOutputDir dex输出路径 - */ - int cacheNormalBuildDex(File dexOutputDir) { - File cacheDexDir = FastdexUtils.getDexCacheDir(project,variantName) - return FileUtils.copyDir(dexOutputDir,cacheDexDir,Constants.DEX_SUFFIX) - } - - /** - * 全量打包时复制dex到指定位置 - * @param dexOutputDir dex输出路径 - */ - def hookNormalBuildDex(File dexOutputDir) { - //dexelements [fastdex-runtime.dex ${dex_cache}.listFiles] - //runtime.dex => classes.dex - //dex_cache.classes.dex => classes2.dex - //dex_cache.classes2.dex => classes3.dex - //dex_cache.classesN.dex => classes(N + 1).dex - - dexOutputDir = FastdexUtils.mergeDexOutputDir(dexOutputDir) - - project.logger.error(" ") - printLogWhenDexGenerateComplete(dexOutputDir,true) - - //fastdex-runtime.dex = > classes.dex - copyFastdexRuntimeDex(new File(dexOutputDir,Constants.CLASSES_DEX)) - printLogWhenDexGenerateComplete(dexOutputDir,true) - project.logger.error(" ") - - //清除除了classesN.dex以外的文件 - FastdexUtils.clearDexOutputDir(dexOutputDir) - return dexOutputDir - } - - /** - * 补丁打包时复制dex到指定位置 - * @param dexOutputDir dex输出路径 - */ - def hookPatchBuildDex(File dexOutputDir,boolean willExecDexMerge) { - //dexelements [fastdex-runtime.dex patch.dex ${dex_cache}.listFiles] - //runtime.dex => classes.dex - //patch.dex => classes2.dex - //dex_cache.classes.dex => classes3.dex - //dex_cache.classes2.dex => classes4.dex - //dex_cache.classesN.dex => classes(N + 2).dex - - project.logger.error(" ") - project.logger.error("==fastdex patch transform hook patch dex start") - - File cacheDexDir = FastdexUtils.getDexCacheDir(project,variantName) - - File patchDex = FastdexUtils.getPatchDexFile(fastdexVariant.project,fastdexVariant.variantName) - File mergedPatchDex = FastdexUtils.getMergedPatchDexFile(fastdexVariant.project,fastdexVariant.variantName) - - FileUtils.cleanDir(dexOutputDir) - FileUtils.copyDir(cacheDexDir,dexOutputDir,Constants.DEX_SUFFIX) - - int dsize = 1 - //如果本次打包触发了dexmerge就不需要patch.dex了 - boolean copyPatchDex = !willExecDexMerge && FileUtils.isLegalFile(patchDex) - if (copyPatchDex) { - dsize += 1 - } - boolean copyMergedPatchDex = FileUtils.isLegalFile(mergedPatchDex) - if (copyMergedPatchDex) { - dsize += 1 - } - - dexOutputDir = FastdexUtils.mergeDexOutputDir(dexOutputDir,dsize) - - printLogWhenDexGenerateComplete(dexOutputDir,false) - //copy fastdex-runtime.dex - copyFastdexRuntimeDex(new File(dexOutputDir,Constants.CLASSES_DEX)) - - int point = 2 - if (copyPatchDex) { - //copy patch.dex - FileUtils.copyFileUsingStream(patchDex,new File(dexOutputDir,"classes${point}.dex")) - project.logger.error("==fastdex patch.dex => " + new File(dexOutputDir,"classes${point}.dex")) - - point += 1 - } - if (copyMergedPatchDex) { - //copy merged-patch.dex - FileUtils.copyFileUsingStream(mergedPatchDex,new File(dexOutputDir,"classes${point}.dex")) - project.logger.error("==fastdex merged-patch.dex => " + new File(dexOutputDir,"classes${point}.dex")) - } - printLogWhenDexGenerateComplete(dexOutputDir,false) - - //清除除了classesN.dex以外的文件 - FastdexUtils.clearDexOutputDir(dexOutputDir) - project.logger.error(" ") - - return dexOutputDir - } - - /** - * 当dex生成完成后打印日志 - * @param normalBuild - */ - void printLogWhenDexGenerateComplete(File dexOutputDir,boolean normalBuild) { - //log - StringBuilder sb = new StringBuilder() - File[] dexFiles = dexOutputDir.listFiles() - - if (dexFiles != null) { - if (dexFiles.length < 7) { - sb.append("dex-dir[") - int idx = 0 - for (File file : dexFiles) { - if (file.getName().endsWith(Constants.DEX_SUFFIX)) { - sb.append(file.getName()) - if (idx < (dexFiles.length - 1)) { - sb.append(",") - } - } - idx ++ - } - sb.append("]") - } - else { - int[] range = FastdexUtils.getClassesDexBoundary(dexOutputDir) - sb.append("dex-dir[") - if (range[0] == 1) { - sb.append("classes.dex") - } - else { - sb.append("classes${range[0]}.dex") - } - sb.append(" - ") - sb.append("classes${range[1]}.dex") - sb.append("]") - } - } - - if (normalBuild) { - project.logger.error("==fastdex first build ${sb}") - } - else { - project.logger.error("==fastdex patch build ${sb}") - } - } -} \ No newline at end of file diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/transform/TransformProxy.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/transform/TransformProxy.groovy index e199a3d2..ea4d07a2 100644 --- a/fastdex-gradle/src/main/groovy/fastdex/build/transform/TransformProxy.groovy +++ b/fastdex-gradle/src/main/groovy/fastdex/build/transform/TransformProxy.groovy @@ -2,15 +2,31 @@ package fastdex.build.transform import com.android.build.api.transform.QualifiedContent import com.android.build.api.transform.Transform +import com.android.build.gradle.api.ApplicationVariant +import fastdex.build.variant.FastdexBuilder +import fastdex.build.variant.FastdexVariant +import org.gradle.api.Project /** * Created by tong on 17/10/3. */ -public class TransformProxy extends Transform { - Transform base +class TransformProxy extends Transform { + final Transform base + final File streamOutputFolder + final FastdexVariant fastdexVariant + final FastdexBuilder fastdexBuilder + final Project project + final String variantName + final ApplicationVariant androidVariant - TransformProxy(Transform base) { + TransformProxy(Transform base,File streamOutputFolder,FastdexVariant fastdexVariant) { this.base = base + this.streamOutputFolder = streamOutputFolder + this.fastdexVariant = fastdexVariant + this.fastdexBuilder = fastdexVariant.fastdexBuilder + this.project = fastdexVariant.project + this.variantName = fastdexVariant.variantName + this.androidVariant = fastdexVariant.androidVariant } @Override diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/util/ClassInject.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/util/ClassInject.groovy index 43f8ae07..ebbc3cfa 100644 --- a/fastdex-gradle/src/main/groovy/fastdex/build/util/ClassInject.groovy +++ b/fastdex-gradle/src/main/groovy/fastdex/build/util/ClassInject.groovy @@ -34,17 +34,19 @@ import java.nio.file.attribute.BasicFileAttributes * 代码注入,往所有的构造方法中添加对fastdex.runtime.antilazyload.AntilazyLoad的依赖 * Created by tong on 17/10/3. */ -public class ClassInject implements Opcodes { +class ClassInject implements Opcodes { + private static final boolean DEBUG_INJECT = false + /** * 注入class目录和jar文件 * @param fastdexVariant * @param transformInvocation */ - public static void injectTransformInvocation(FastdexVariant fastdexVariant, TransformInvocation transformInvocation) { + static void injectTransformInvocation(FastdexVariant fastdexVariant, TransformInvocation transformInvocation) { //所有的class目录 - HashSet directoryInputFiles = new HashSet<>(); + HashSet directoryInputFiles = new HashSet<>() //所有输入的jar - HashSet jarInputFiles = new HashSet<>(); + HashSet jarInputFiles = new HashSet<>() for (TransformInput input : transformInvocation.getInputs()) { Collection directoryInputs = input.getDirectoryInputs() if (directoryInputs != null) { @@ -68,7 +70,7 @@ public class ClassInject implements Opcodes { * 往所有项目代码里注入解决pre-verify问题的code * @param directoryInputFiles */ - public static void injectDirectoryInputFiles(FastdexVariant fastdexVariant, HashSet directoryInputFiles) { + static void injectDirectoryInputFiles(FastdexVariant fastdexVariant, HashSet directoryInputFiles) { def project = fastdexVariant.project long start = System.currentTimeMillis() for (File classpathFile : directoryInputFiles) { @@ -85,11 +87,19 @@ public class ClassInject implements Opcodes { * @param fastdexVariant * @param directoryInputFiles */ - public static void injectJarInputFiles(FastdexVariant fastdexVariant, HashSet jarInputFiles) { + static void injectJarInputFiles(FastdexVariant fastdexVariant, HashSet jarInputFiles) { + if (jarInputFiles == null || jarInputFiles.isEmpty()) { + return + } def project = fastdexVariant.project long start = System.currentTimeMillis() - Set libraryDependencies = fastdexVariant.libraryDependencies + Set libraryDependencies = fastdexVariant.getLibraryDependencies() + + if (DEBUG_INJECT) { + project.logger.error("==jarInputFiles: " + jarInputFiles) + project.logger.error("==libraryDependencies: " + libraryDependencies) + } List projectJarFiles = new ArrayList<>() //获取所有依赖工程的输出jar (compile project(':xxx')) for (LibDependency dependency : libraryDependencies) { @@ -116,7 +126,7 @@ public class ClassInject implements Opcodes { * @param outputJar * @return */ - public static injectJar(FastdexVariant fastdexVariant, File inputJar,File outputJar) { + static injectJar(FastdexVariant fastdexVariant, File inputJar,File outputJar) { File tempDir = new File(fastdexVariant.buildDir,"temp") FileUtils.deleteDir(tempDir) FileUtils.ensumeDir(tempDir) @@ -135,7 +145,7 @@ public class ClassInject implements Opcodes { * 注入指定目录下的所有class * @param classpath */ - public static void injectDirectory(FastdexVariant fastdexVariant,File classesDir,boolean applicationProjectSrc) { + static void injectDirectory(FastdexVariant fastdexVariant,File classesDir,boolean applicationProjectSrc) { if (!FileUtils.dirExists(classesDir.absolutePath)) { return } @@ -147,17 +157,18 @@ public class ClassInject implements Opcodes { File classFile = file.toFile() String fileName = classFile.getName() if (!fileName.endsWith(Constants.CLASS_SUFFIX)) { - return FileVisitResult.CONTINUE; + return FileVisitResult.CONTINUE } boolean needInject = true - if (applicationProjectSrc && (fileName.endsWith("R.class") || fileName.matches("R\\\$\\S{1,}.class"))) { - String packageName = fastdexVariant.getOriginPackageName() - String packageNamePath = packageName.split("\\.").join(File.separator) - if (!classFile.absolutePath.endsWith("${packageNamePath}${File.separator}${fileName}")) { - needInject = false - } - } + // +// if (applicationProjectSrc && (fileName.endsWith("R.class") || fileName.matches("R\\\$\\S{1,}.class"))) { +// String packageName = fastdexVariant.getOriginPackageName() +// String packageNamePath = packageName.split("\\.").join(File.separator) +// if (!classFile.absolutePath.endsWith("${packageNamePath}${File.separator}${fileName}")) { +// needInject = false +// } +// } if (needInject) { fastdexVariant.project.logger.error("==fastdex inject: ${classFile.getAbsolutePath()}") byte[] classBytes = FileUtils.readContents(classFile) @@ -174,56 +185,55 @@ public class ClassInject implements Opcodes { * @param classBytes * @return */ - public static final byte[] inject(byte[] classBytes) { - ClassReader classReader = new ClassReader(classBytes); - ClassWriter classWriter = new ClassWriter(classReader, ClassWriter.COMPUTE_MAXS); - ClassVisitor classVisitor = new MyClassVisitor(classWriter); - classReader.accept(classVisitor, Opcodes.ASM5); + static final byte[] inject(byte[] classBytes) { + ClassReader classReader = new ClassReader(classBytes) + ClassWriter classWriter = new ClassWriter(classReader, ClassWriter.COMPUTE_MAXS) + ClassVisitor classVisitor = new MyClassVisitor(classWriter) + classReader.accept(classVisitor, Opcodes.ASM5) return classWriter.toByteArray() } private static class MyClassVisitor extends ClassVisitor { - public MyClassVisitor(ClassVisitor classVisitor) { - super(Opcodes.ASM5, classVisitor); + MyClassVisitor(ClassVisitor classVisitor) { + super(Opcodes.ASM5, classVisitor) } @Override - public MethodVisitor visitMethod(int access, + MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { if ("".equals(name)) { //get origin method - MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions); - //System.out.println(name + " | " + desc + " | " + signature); - MethodVisitor newMethod = new AsmMethodVisit(mv); - return newMethod; + MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions) + MethodVisitor newMethod = new AsmMethodVisit(mv) + return newMethod } else { - return super.visitMethod(access, name, desc, signature, exceptions); + return super.visitMethod(access, name, desc, signature, exceptions) } } } static class AsmMethodVisit extends MethodVisitor { - public AsmMethodVisit(MethodVisitor mv) { - super(Opcodes.ASM5, mv); + AsmMethodVisit(MethodVisitor mv) { + super(Opcodes.ASM5, mv) } @Override - public void visitInsn(int opcode) { + void visitInsn(int opcode) { if (opcode == Opcodes.RETURN) { - super.visitFieldInsn(GETSTATIC, "java/lang/Boolean", "FALSE", "Ljava/lang/Boolean;"); - super.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false); - Label l0 = new Label(); - super.visitJumpInsn(IFEQ, l0); - mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); - mv.visitFieldInsn(GETSTATIC, "fastdex/runtime/antilazyload/AntilazyLoad", "str", "Ljava/lang/String;"); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); - super.visitLabel(l0); + super.visitFieldInsn(GETSTATIC, "java/lang/Boolean", "FALSE", "Ljava/lang/Boolean;") + super.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false) + Label l0 = new Label() + super.visitJumpInsn(IFEQ, l0) + mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;") + mv.visitFieldInsn(GETSTATIC, "fastdex/runtime/antilazyload/AntilazyLoad", "str", "Ljava/lang/String;") + mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false) + super.visitLabel(l0) } - super.visitInsn(opcode); + super.visitInsn(opcode) } } } diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/util/Constants.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/util/Constants.groovy index 4b471121..e4d7d4e8 100644 --- a/fastdex-gradle/src/main/groovy/fastdex/build/util/Constants.groovy +++ b/fastdex-gradle/src/main/groovy/fastdex/build/util/Constants.groovy @@ -1,13 +1,13 @@ package fastdex.build.util -import fastdex.common.ShareConstants; +import fastdex.common.ShareConstants /** * Created by tong on 17/3/14. */ -public interface Constants extends ShareConstants { +interface Constants extends ShareConstants { String BUILD_DIR = "fastdex" - String R_TXT = "r.txt" + String R_TXT = "R.txt" String RESOURCE_PUBLIC_XML = "public.xml" String RESOURCE_IDX_XML = "idx.xml" String RUNTIME_DEX_FILENAME = "fastdex-runtime.dex" @@ -21,4 +21,5 @@ public interface Constants extends ShareConstants { String DEX_MERGE_JAR_FILENAME = "fastdex-dex-merge.jar" String STUDIO_INFO_SCRIPT_MACOS = "fastdex-studio-info-macos-%s.sh" String MIN_BUILD_CACHE_ENABLED_VERSION = "2.2.2" + String PATCH_JAR = "patch.jar" } diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/util/DexOperation.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/util/DexOperation.groovy index 9c0bac83..18209b67 100644 --- a/fastdex-gradle/src/main/groovy/fastdex/build/util/DexOperation.groovy +++ b/fastdex-gradle/src/main/groovy/fastdex/build/util/DexOperation.groovy @@ -9,7 +9,7 @@ import org.apache.tools.ant.taskdefs.condition.Os * dex操作 * Created by tong on 17/11/4. */ -public class DexOperation { +class DexOperation { /** * 生成补丁dex * @param fastdexVariant @@ -17,7 +17,7 @@ public class DexOperation { * @param patchJar * @param patchDex */ - public static final void generatePatchDex(FastdexVariant fastdexVariant, Transform base,File patchJar,File patchDex) { + static final void generatePatchDex(FastdexVariant fastdexVariant, Transform base,File patchJar,File patchDex) { FileUtils.deleteFile(patchDex) FileUtils.ensumeDir(patchDex.parentFile) @@ -44,18 +44,18 @@ public class DexOperation { FileUtils.copyResourceUsingStream("fastdex-dx",dxCommandFile) } - cmdArgs.add("sh"); - cmdArgs.add(dxCommandFile.absolutePath); - cmdArgs.add("--dex"); - cmdArgs.add("--no-optimize"); - cmdArgs.add("--force-jumbo"); - cmdArgs.add("--output=${patchDex}"); - cmdArgs.add(patchJar.absolutePath); + cmdArgs.add("sh") + cmdArgs.add(dxCommandFile.absolutePath) + cmdArgs.add("--dex") + cmdArgs.add("--no-optimize") + cmdArgs.add("--force-jumbo") + cmdArgs.add("--output=${patchDex}") + cmdArgs.add(patchJar.absolutePath) } //调用dx命令 FastdexUtils.runCommand(fastdexVariant.project, cmdArgs) - long end = System.currentTimeMillis(); + long end = System.currentTimeMillis() fastdexVariant.project.logger.error("==fastdex patch transform generate dex success. use: ${end - start}ms") } @@ -66,7 +66,7 @@ public class DexOperation { * @param patchDex 补丁dex路径 * @param cachedDex */ - public static void mergeDex(FastdexVariant fastdexVariant,File outputDex,File patchDex,File cachedDex) { + static void mergeDex(FastdexVariant fastdexVariant,File outputDex,File patchDex,File cachedDex) { long start = System.currentTimeMillis() def project = fastdexVariant.project File dexMergeJar = new File(FastdexUtils.getBuildDir(project),Constants.DEX_MERGE_JAR_FILENAME) @@ -75,16 +75,16 @@ public class DexOperation { } List cmdArgs = new ArrayList<>() - cmdArgs.add(FastdexUtils.getJavaCmdPath()); - cmdArgs.add("-jar"); - cmdArgs.add(dexMergeJar.absolutePath); - cmdArgs.add(outputDex.absolutePath); - cmdArgs.add(patchDex.absolutePath); - cmdArgs.add(cachedDex.absolutePath); + cmdArgs.add(FastdexUtils.getJavaCmdPath()) + cmdArgs.add("-jar") + cmdArgs.add(dexMergeJar.absolutePath) + cmdArgs.add(outputDex.absolutePath) + cmdArgs.add(patchDex.absolutePath) + cmdArgs.add(cachedDex.absolutePath) FastdexUtils.runCommand(fastdexVariant.project, cmdArgs) - long end = System.currentTimeMillis(); + long end = System.currentTimeMillis() project.logger.error("==fastdex merge dex success. use: ${end - start}ms") } } diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/util/FastdexBuildListener.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/util/FastdexBuildListener.groovy index 7ce48fba..419d939c 100644 --- a/fastdex-gradle/src/main/groovy/fastdex/build/util/FastdexBuildListener.groovy +++ b/fastdex-gradle/src/main/groovy/fastdex/build/util/FastdexBuildListener.groovy @@ -1,15 +1,15 @@ package fastdex.build.util import org.apache.tools.ant.taskdefs.condition.Os -import org.gradle.BuildListener; +import org.gradle.BuildListener import org.gradle.BuildResult import org.gradle.api.GradleException import org.gradle.api.Plugin -import org.gradle.api.Project; -import org.gradle.api.Task; -import org.gradle.api.execution.TaskExecutionListener; -import org.gradle.api.initialization.Settings; -import org.gradle.api.invocation.Gradle; +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.execution.TaskExecutionListener +import org.gradle.api.initialization.Settings +import org.gradle.api.invocation.Gradle import org.gradle.api.tasks.TaskState import fastdex.build.FastdexPlugin import com.github.typ0520.fastdex.Version @@ -119,11 +119,11 @@ class FastdexBuildListener implements TaskExecutionListener, BuildListener { } report.append("plugins : ${plugins}\n\n") try { - int keyLength = str.length(); + int keyLength = str.length() if (!map.isEmpty()) { for (String key : map.keySet()) { - int dsize = keyLength - key.length(); - report.append(key + getSpaceString(dsize) + ": " + map.get(key) + "\n"); + int dsize = keyLength - key.length() + report.append(key + getSpaceString(dsize) + ": " + map.get(key) + "\n") } if (!"true".equals(map.get("instant_run_disabled"))) { @@ -179,20 +179,20 @@ class FastdexBuildListener implements TaskExecutionListener, BuildListener { Throwable getRootThrowable(Throwable throwable) { if (throwable == null) { - return null; + return null } - Throwable cause = throwable.getCause(); + Throwable cause = throwable.getCause() if (cause == null) { - return throwable; + return throwable } if (cause == throwable) { - return throwable; + return throwable } - return getRootThrowable(throwable.getCause()); + return getRootThrowable(throwable.getCause()) } - public Map getStudioInfo() { + Map getStudioInfo() { Map map = new HashMap<>() if (Os.isFamily(Os.FAMILY_MAC)) { try { @@ -201,9 +201,9 @@ class FastdexBuildListener implements TaskExecutionListener, BuildListener { FileUtils.copyResourceUsingStream(Constants.STUDIO_INFO_SCRIPT_MACOS,script) } - int pid = getPid(); + int pid = getPid() if (pid == -1) { - return map; + return map } List cmdArgs = new ArrayList<>() @@ -219,31 +219,31 @@ class FastdexBuildListener implements TaskExecutionListener, BuildListener { return map } - public static String getSpaceString(int count) { + static String getSpaceString(int count) { if (count > 0) { - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new StringBuilder() for (int i = 0; i < count; i++) { - sb.append(" "); + sb.append(" ") } - return sb.toString(); + return sb.toString() } - return ""; + return "" } - public static int getPid() { - String name = ManagementFactory.getRuntimeMXBean().getName(); + static int getPid() { + String name = ManagementFactory.getRuntimeMXBean().getName() if (name != null) { - String[] arr = name.split("@"); + String[] arr = name.split("@") try { - return Integer.valueOf(arr[0]); + return Integer.valueOf(arr[0]) } catch (Throwable e) { } } - return -1; + return -1 } - public static void addByProject(Project pro) { + static void addByProject(Project pro) { FastdexBuildListener listener = new FastdexBuildListener(pro) pro.gradle.addListener(listener) } diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/util/FastdexInstantRun.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/util/FastdexInstantRun.groovy index db2baa61..b53d1189 100644 --- a/fastdex-gradle/src/main/groovy/fastdex/build/util/FastdexInstantRun.groovy +++ b/fastdex-gradle/src/main/groovy/fastdex/build/util/FastdexInstantRun.groovy @@ -9,7 +9,7 @@ import org.gradle.api.Project /** * Created by tong on 17/3/12. */ -public class FastdexInstantRun { +class FastdexInstantRun { FastdexVariant fastdexVariant File resourceApFile String resDir @@ -30,11 +30,11 @@ public class FastdexInstantRun { } private void waitForDevice(AndroidDebugBridge bridge) { - int count = 0; + int count = 0 while (!bridge.hasInitialDeviceList()) { try { - Thread.sleep(100); - count++; + Thread.sleep(100) + count++ } catch (InterruptedException ignored) { } if (count > 300) { @@ -98,29 +98,29 @@ public class FastdexInstantRun { /** * 如果资源发生变化会执行processResources */ - public void onResourceChanged() { + def onResourceChanged() { resourceChanged = true } /** * 如果执行了dexTransform则代码发生变化 */ - public void onSourceChanged() { + def onSourceChanged() { sourceChanged = true } /** * 如果assets发生变化会执行mergeAssets任务 */ - public void onAssetsChanged() { + def onAssetsChanged() { assetsChanged = true } - public void onManifestChanged() { + def onManifestChanged() { } - public void onFastdexPrepare() { + def onFastdexPrepare() { } @@ -200,33 +200,40 @@ public class FastdexInstantRun { def generateResourceApk(File resourcesApk) { if (GradleUtils.getAndroidGradlePluginVersion().compareTo("2.2") >= 0) { long start = System.currentTimeMillis() - File tempDir = new File(FastdexUtils.getResourceDir(project,fastdexVariant.variantName),"temp") - FileUtils.cleanDir(tempDir) - File tempResourcesApk = new File(tempDir,resourcesApk.getName()) - FileUtils.copyFileUsingStream(resourceApFile,tempResourcesApk) - - project.logger.error("==fastdex copy resources.ap_ \ncopy : ${resourceApFile} \ninto: ${tempResourcesApk}") - File assetsPath = fastdexVariant.androidVariant.getVariantData().getScope().getMergeAssetsOutputDir() + File assetsPath = fastdexVariant.androidVariant.getMergeAssets().outputDir List assetFiles = getAssetFiles(assetsPath) - File tempAssetsPath = new File(tempDir,"assets") - FileUtils.copyDir(assetsPath,tempAssetsPath) - - List cmdArgs = new ArrayList<>() - cmdArgs.add(FastdexUtils.getAaptCmdPath(project)) - cmdArgs.add("add") - cmdArgs.add("-f") - cmdArgs.add(tempResourcesApk.absolutePath) - for (int i = 0; i < assetFiles.size(); i++) { - cmdArgs.add("assets/" + assetFiles.get(i).toString()) + if (assetFiles.isEmpty()) { + project.logger.error("==fastdex \ncopy : ${resourceApFile} \ninto: ${resourcesApk}") + FileUtils.copyFileUsingStream(resourceApFile,resourcesApk) } + else { + File tempDir = new File(FastdexUtils.getResourceDir(project,fastdexVariant.variantName),"temp") + FileUtils.cleanDir(tempDir) + File tempResourcesApk = new File(tempDir,resourcesApk.getName()) + FileUtils.copyFileUsingStream(resourceApFile,tempResourcesApk) + project.logger.error("==fastdex copy resources.ap_ \ncopy : ${resourceApFile} \ninto: ${tempResourcesApk}") + + File tempAssetsPath = new File(tempDir,"assets") + FileUtils.copyDir(assetsPath,tempAssetsPath) + List cmdArgs = new ArrayList<>() + cmdArgs.add(FastdexUtils.getAaptCmdPath(project)) + cmdArgs.add("add") + cmdArgs.add("-f") + cmdArgs.add(tempResourcesApk.absolutePath) + + for (int i = 0; i < assetFiles.size(); i++) { + cmdArgs.add("assets/" + assetFiles.get(i).toString()) + } + + FastdexUtils.runCommand(project,cmdArgs,tempDir,false) - FastdexUtils.runCommand(project,cmdArgs,tempDir,false) - tempResourcesApk.renameTo(resourcesApk) - FileUtils.deleteDir(tempDir) + tempResourcesApk.renameTo(resourcesApk) + FileUtils.deleteDir(tempDir) + } - long end = System.currentTimeMillis(); + long end = System.currentTimeMillis() fastdexVariant.project.logger.error("==fastdex generate resources.apk success, use: ${end - start}ms") } else { @@ -235,7 +242,7 @@ public class FastdexInstantRun { } } - List getAssetFiles(File dir) { + def getAssetFiles(File dir) { ArrayList result = new ArrayList<>() if (dir == null || !FileUtils.dirExists(dir.getAbsolutePath())) { return result @@ -248,7 +255,7 @@ public class FastdexInstantRun { result.add(file.getName()) } } - return result; + return result } def startBootActivity() { diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/util/FastdexRuntimeException.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/util/FastdexRuntimeException.groovy index aa3e0cd0..41ae63f0 100644 --- a/fastdex-gradle/src/main/groovy/fastdex/build/util/FastdexRuntimeException.groovy +++ b/fastdex-gradle/src/main/groovy/fastdex/build/util/FastdexRuntimeException.groovy @@ -3,7 +3,7 @@ package fastdex.build.util /** * Created by tong on 17/4/18. */ -public class FastdexRuntimeException extends RuntimeException { +class FastdexRuntimeException extends RuntimeException { FastdexRuntimeException() { } diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/util/FastdexUtils.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/util/FastdexUtils.groovy index 1d7002fc..b07296f7 100644 --- a/fastdex-gradle/src/main/groovy/fastdex/build/util/FastdexUtils.groovy +++ b/fastdex-gradle/src/main/groovy/fastdex/build/util/FastdexUtils.groovy @@ -13,16 +13,16 @@ import java.nio.file.attribute.BasicFileAttributes /** * Created by tong on 17/3/14. */ -public class FastdexUtils { +class FastdexUtils { /** * 获取sdk路径 * @param project * @return */ - public static final String getSdkDirectory(Project project) { + static final String getSdkDirectory(Project project) { String sdkDirectory = project.android.getSdkDirectory() if (sdkDirectory.contains("\\")) { - sdkDirectory = sdkDirectory.replace("\\", "/"); + sdkDirectory = sdkDirectory.replace("\\", "/") } return sdkDirectory } @@ -32,7 +32,7 @@ public class FastdexUtils { * @param project * @return */ - public static final String getDxCmdPath(Project project) { + static final String getDxCmdPath(Project project) { File dx = new File(FastdexUtils.getSdkDirectory(project),"build-tools${File.separator}${project.android.buildToolsVersion.toString()}${File.separator}dx") if (Os.isFamily(Os.FAMILY_WINDOWS)) { return "${dx.absolutePath}.bat" @@ -45,7 +45,7 @@ public class FastdexUtils { * @param project * @return */ - public static final String getAaptCmdPath(Project project) { + static final String getAaptCmdPath(Project project) { File aapt = new File(FastdexUtils.getSdkDirectory(project),"build-tools${File.separator}${project.android.buildToolsVersion.toString()}${File.separator}aapt") if (Os.isFamily(Os.FAMILY_WINDOWS)) { return "${aapt.absolutePath}.exe" @@ -58,7 +58,7 @@ public class FastdexUtils { * @param project * @return */ - public static final String getAdbCmdPath(Project project) { + static final String getAdbCmdPath(Project project) { File adb = new File(FastdexUtils.getSdkDirectory(project),"platform-tools${File.separator}adb") if (Os.isFamily(Os.FAMILY_WINDOWS)) { return "${adb.absolutePath}.exe" @@ -70,7 +70,7 @@ public class FastdexUtils { * 获取当前jdk路径 * @return */ - public static final String getCurrentJdk() { + static final String getCurrentJdk() { String javaHomeProp = System.properties.'java.home' if (javaHomeProp) { int jreIndex = javaHomeProp.lastIndexOf("${File.separator}jre") @@ -88,7 +88,7 @@ public class FastdexUtils { * 获取java命令路径 * @return */ - public static final String getJavaCmdPath() { + static final String getJavaCmdPath() { StringBuilder cmd = new StringBuilder(getCurrentJdk()) if (!cmd.toString().endsWith(File.separator)) { cmd.append(File.separator) @@ -104,7 +104,7 @@ public class FastdexUtils { * 获取javac命令路径 * @return */ - public static final String getJavacCmdPath() { + static final String getJavacCmdPath() { StringBuilder cmd = new StringBuilder(getCurrentJdk()) if (!cmd.toString().endsWith(File.separator)) { cmd.append(File.separator) @@ -122,15 +122,15 @@ public class FastdexUtils { * @param variantName * @return */ - public static boolean hasDexCache(Project project, String variantName) { + static boolean hasDexCache(Project project, String variantName) { File cacheDexDir = getDexCacheDir(project,variantName) if (!FileUtils.dirExists(cacheDexDir.absolutePath)) { - return false; + return false } - FindDexFileVisitor visitor = new FindDexFileVisitor(); - Files.walkFileTree(cacheDexDir.toPath(),visitor); - return visitor.hasDex; + FindDexFileVisitor visitor = new FindDexFileVisitor() + Files.walkFileTree(cacheDexDir.toPath(),visitor) + return visitor.hasDex } /** @@ -138,9 +138,9 @@ public class FastdexUtils { * @param project * @return */ - public static final File getBuildDir(Project project) { - File file = new File(project.getBuildDir(),Constants.BUILD_DIR); - return file; + static final File getBuildDir(Project project) { + File file = new File(project.getBuildDir(),Constants.BUILD_DIR) + return file } /** @@ -148,9 +148,9 @@ public class FastdexUtils { * @param project * @return */ - public static final File getBuildDir(Project project,String variantName) { - File file = new File(getBuildDir(project),variantName); - return file; + static final File getBuildDir(Project project,String variantName) { + File file = new File(getBuildDir(project),variantName) + return file } /** @@ -158,9 +158,9 @@ public class FastdexUtils { * @param project * @return */ - public static final File getWorkDir(Project project,String variantName) { + static final File getWorkDir(Project project,String variantName) { File file = new File(getBuildDir(project,variantName),"work") - return file; + return file } /** @@ -169,9 +169,9 @@ public class FastdexUtils { * @param variantName * @return */ - public static getDexDir(Project project,String variantName) { - File file = new File(getBuildDir(project,variantName),"dex"); - return file; + static getDexDir(Project project,String variantName) { + File file = new File(getBuildDir(project,variantName),"dex") + return file } /** @@ -179,9 +179,9 @@ public class FastdexUtils { * @param project * @return */ - public static final File getDexCacheDir(Project project,String variantName) { - File file = new File(getDexDir(project,variantName),"cache"); - return file; + static final File getDexCacheDir(Project project,String variantName) { + File file = new File(getDexDir(project,variantName),"cache") + return file } /** @@ -189,9 +189,9 @@ public class FastdexUtils { * @param project * @return */ - public static final File getMergedPatchDexDir(Project project,String variantName) { - File file = new File(getDexDir(project,variantName),"merged-patch"); - return file; + static final File getMergedPatchDexDir(Project project,String variantName) { + File file = new File(getDexDir(project,variantName),"merged-patch") + return file } /** @@ -199,9 +199,9 @@ public class FastdexUtils { * @param project * @return */ - public static final File getMergedPatchDexFile(Project project,String variantName) { - File file = new File(getMergedPatchDexDir(project,variantName),Constants.CLASSES_DEX); - return file; + static final File getMergedPatchDexFile(Project project,String variantName) { + File file = new File(getMergedPatchDexDir(project,variantName),Constants.CLASSES_DEX) + return file } /** @@ -209,9 +209,9 @@ public class FastdexUtils { * @param project * @return */ - public static final File getPatchDexDir(Project project,String variantName) { - File file = new File(getDexDir(project,variantName),"patch"); - return file; + static final File getPatchDexDir(Project project,String variantName) { + File file = new File(getDexDir(project,variantName),"patch") + return file } /** @@ -219,9 +219,9 @@ public class FastdexUtils { * @param project * @return */ - public static final File getPatchDexFile(Project project,String variantName) { - File file = new File(getPatchDexDir(project,variantName),Constants.CLASSES_DEX); - return file; + static final File getPatchDexFile(Project project,String variantName) { + File file = new File(getPatchDexDir(project,variantName),Constants.CLASSES_DEX) + return file } /** @@ -230,9 +230,9 @@ public class FastdexUtils { * @param variantName * @return */ - public static final File getMergedPatchDex(Project project,String variantName) { - File file = new File(getMergedPatchDexDir(project,variantName),Constants.CLASSES_DEX); - return file; + static final File getMergedPatchDex(Project project,String variantName) { + File file = new File(getMergedPatchDexDir(project,variantName),Constants.CLASSES_DEX) + return file } /** @@ -240,9 +240,9 @@ public class FastdexUtils { * @param project * @return */ - public static final File getSourceSetSnapshootFile(Project project, String variantName) { - File file = new File(getBuildDir(project,variantName),Constants.SOURCESET_SNAPSHOOT_FILENAME); - return file; + static final File getSourceSetSnapshootFile(Project project, String variantName) { + File file = new File(getBuildDir(project,variantName),Constants.SOURCESET_SNAPSHOOT_FILENAME) + return file } /** @@ -251,7 +251,7 @@ public class FastdexUtils { * @param variantName * @return */ - public static boolean cleanCache(Project project,String variantName) { + static boolean cleanCache(Project project,String variantName) { File dir = getBuildDir(project,variantName) project.logger.error("==fastdex clean dir: ${dir}") return FileUtils.deleteDir(dir) @@ -263,7 +263,7 @@ public class FastdexUtils { * @param variantName * @return */ - public static boolean cleanAllCache(Project project) { + static boolean cleanAllCache(Project project) { File dir = getBuildDir(project) project.logger.error("==fastdex clean dir: ${dir}") return FileUtils.deleteDir(dir) @@ -275,17 +275,17 @@ public class FastdexUtils { * @param variantName * @return */ - public static File getResourceMappingFile(Project project, String variantName) { - File resourceMappingFile = new File(getBuildResourceDir(project,variantName),Constants.R_TXT) + static File getResourceMappingFile(Project project, String variantName) { + File resourceMappingFile = new File(getBuildDir(project,variantName),"symbols/" + Constants.R_TXT) return resourceMappingFile } - public static File getResourceDir(Project project, String variantName) { + static File getResourceDir(Project project, String variantName) { File resDir = new File(getBuildDir(project,variantName),"res") return resDir } - public static File getResourcesApk(Project project, String variantName) { + static File getResourcesApk(Project project, String variantName) { File resourcesApk = new File(getResourceDir(project,variantName),ShareConstants.RESOURCE_APK_FILE_NAME) return resourcesApk } @@ -296,8 +296,8 @@ public class FastdexUtils { * @param variantName * @return */ - public static File getIdxXmlFile(Project project, String variantName) { - File idxXmlFile = new File(getBuildResourceDir(project,variantName),Constants.RESOURCE_IDX_XML) + static File getIdxXmlFile(Project project, String variantName) { + File idxXmlFile = new File(getResourceKeepDir(project,variantName),Constants.RESOURCE_IDX_XML) return idxXmlFile } @@ -307,13 +307,13 @@ public class FastdexUtils { * @param variantName * @return */ - public static File getPublicXmlFile(Project project, String variantName) { - File publicXmlFile = new File(getBuildResourceDir(project,variantName),Constants.RESOURCE_PUBLIC_XML) + static File getPublicXmlFile(Project project, String variantName) { + File publicXmlFile = new File(getResourceKeepDir(project,variantName),Constants.RESOURCE_PUBLIC_XML) return publicXmlFile } - private static File getBuildResourceDir(Project project, String variantName) { - return new File(getBuildDir(project,variantName),"r") + static File getResourceKeepDir(Project project, String variantName) { + return new File(getBuildDir(project,variantName),"res-keep") } /** @@ -322,17 +322,17 @@ public class FastdexUtils { * @param variantName * @return */ - public static File getCachedDependListFile(Project project,String variantName) { + static File getCachedDependListFile(Project project,String variantName) { File cachedDependListFile = new File(getBuildDir(project,variantName),Constants.DEPENDENCIES_FILENAME) return cachedDependListFile } - public static File getAndroidManifestStatFile(Project project,String variantName) { + static File getAndroidManifestStatFile(Project project,String variantName) { File file = new File(getBuildDir(project,variantName),Constants.ANDROID_MANIFEST_FILENAME) return file } - public static File getMetaInfoFile(Project project,String variantName) { + static File getMetaInfoFile(Project project,String variantName) { File cachedDependListFile = new File(getBuildDir(project,variantName),Constants.META_INFO_FILENAME) return cachedDependListFile } @@ -343,7 +343,7 @@ public class FastdexUtils { * @param variantName * @return */ - public static File getDiffResultSetFile(Project project,String variantName) { + static File getDiffResultSetFile(Project project,String variantName) { File diffResultFile = new File(getBuildDir(project,variantName),Constants.LAST_DIFF_RESULT_SET_FILENAME) return diffResultFile } @@ -354,7 +354,7 @@ public class FastdexUtils { * @param sourceSetKey * @return */ - public static LinkedHashSet getSrcDirs(Project project,String sourceSetKey) { + static LinkedHashSet getSrcDirs(Project project,String sourceSetKey) { def srcDirs = new LinkedHashSet() def sourceSetsValue = project.android.sourceSets.findByName(sourceSetKey) if (sourceSetsValue) { @@ -363,15 +363,15 @@ public class FastdexUtils { return srcDirs } - public static File getManifestFile(Project project,String sourceSetKey) { + static File getManifestFile(Project project,String sourceSetKey) { def sourceSetsValue = project.android.sourceSets.findByName(sourceSetKey) if (sourceSetsValue) { - return sourceSetsValue.manifest.srcFile + return sourceSetsValue.manifest.srcFile } return null } - public static boolean isDataBindingEnabled(Project project) { + static boolean isDataBindingEnabled(Project project) { return project.android.dataBinding && project.android.dataBinding.enabled } @@ -384,7 +384,7 @@ public class FastdexUtils { * * @param dexDir */ - public static void incrementDexDir(File dexDir,int dsize) { + static void incrementDexDir(File dexDir,int dsize) { if (dsize <= 0) { throw new RuntimeException("dsize must be greater than 0!") } @@ -421,23 +421,23 @@ public class FastdexUtils { * 使用buildCache全量打包时hook dex输出目录 * @param dexOutputDir */ - public static File mergeDexOutputDir(File dexOutputDir, int dsize) { + static File mergeDexOutputDir(File dexOutputDir, int dsize) { final HashSet dexDirSet = new HashSet<>() Files.walkFileTree(dexOutputDir.toPath(),new SimpleFileVisitor() { @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { if (file.toFile().getName().endsWith(Constants.DEX_SUFFIX)) { dexDirSet.add(file.getParent().toFile()) } - return FileVisitResult.CONTINUE; + return FileVisitResult.CONTINUE } - }); + }) - File result = null; + File result = null int maxClassesDexIndex = 0 for (File dir : dexDirSet) { if (result == null) { - result = dir; + result = dir incrementDexDir(dir,dsize) maxClassesDexIndex = FastdexUtils.getMaxClassesDexIndex(dir) } @@ -454,7 +454,7 @@ public class FastdexUtils { * 使用buildCache全量打包时hook dex输出目录 * @param dexOutputDir */ - public static File mergeDexOutputDir(File dexOutputDir) { + static File mergeDexOutputDir(File dexOutputDir) { mergeDexOutputDir(dexOutputDir,1) } @@ -463,7 +463,7 @@ public class FastdexUtils { * @param dexDir * @return */ - public static int getMaxClassesDexIndex(File dexDir) { + static int getMaxClassesDexIndex(File dexDir) { return getClassesDexBoundary(dexDir)[1] } @@ -472,7 +472,7 @@ public class FastdexUtils { * @param dexDir * @return */ - public static int[] getClassesDexBoundary(File dexDir) { + static int[] getClassesDexBoundary(File dexDir) { int[] boundary = new int[2] if (dexDir.listFiles() == null) { @@ -515,13 +515,17 @@ public class FastdexUtils { * 清理dex输出目录,除了classes*.dex其它的文件全删掉,防止package任务把别的文件当成dex打进aak里面 * @param dexOutputDir */ - public static void clearDexOutputDir(File dexOutputDir) { + static void clearDexOutputDir(File dexOutputDir) { if (dexOutputDir == null) { return } dexOutputDir.listFiles().each { - if (it.isFile() && !(it.name.startsWith(ShareConstants.CLASSES) && it.name.endsWith(ShareConstants.DEX_SUFFIX))) { - //println("remove: " + it.absolutePath) +// if (it.isFile() && !(it.name.startsWith(ShareConstants.CLASSES) && it.name.endsWith(ShareConstants.DEX_SUFFIX))) { +// it.delete() +// } + + //避免删除3.0.0以后的__content__.json + if (it.isFile() && it.isHidden()) { it.delete() } } @@ -531,7 +535,7 @@ public class FastdexUtils { * 执行命令 * @param cmdArgs */ - public static void runCommand(Project project, List cmdArgs) { + static void runCommand(Project project, List cmdArgs) { runCommand(project, cmdArgs, false) } @@ -539,20 +543,20 @@ public class FastdexUtils { * 执行命令 * @param cmdArgs */ - public static void runCommand(Project project, List cmdArgs,boolean background) { - runCommand(project,cmdArgs,null,background) + static void runCommand(Project project, List cmdArgs,boolean background) { + runCommand(project,cmdArgs,null,background) } /** * 执行命令 * @param cmdArgs */ - public static void runCommand(Project project, List cmdArgs,File directory,boolean background) { + static void runCommand(Project project, List cmdArgs,File directory,boolean background) { if (!background) { StringBuilder cmd = new StringBuilder() for (int i = 0; i < cmdArgs.size(); i++) { if (i != 0) { - cmd.append(" "); + cmd.append(" ") } cmd.append(cmdArgs.get(i)) } @@ -574,11 +578,11 @@ public class FastdexUtils { } reader.close() status = process.waitFor() - reader = new BufferedReader(new InputStreamReader(process.getErrorStream())); + reader = new BufferedReader(new InputStreamReader(process.getErrorStream())) while ((line = reader.readLine()) != null) { - System.out.println(line); + System.out.println(line) } - reader.close(); + reader.close() process.destroy() } catch (Throwable e) { @@ -587,4 +591,4 @@ public class FastdexUtils { throw new FastdexRuntimeException("Command exec fail....") } } -} +} \ No newline at end of file diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/util/FindDexFileVisitor.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/util/FindDexFileVisitor.groovy index 44325f21..03a62ad4 100644 --- a/fastdex-gradle/src/main/groovy/fastdex/build/util/FindDexFileVisitor.groovy +++ b/fastdex-gradle/src/main/groovy/fastdex/build/util/FindDexFileVisitor.groovy @@ -1,23 +1,23 @@ -package fastdex.build.util; +package fastdex.build.util -import java.nio.file.FileVisitResult; -import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.attribute.BasicFileAttributes; -import fastdex.common.ShareConstants; +import java.nio.file.FileVisitResult +import java.nio.file.Path +import java.nio.file.SimpleFileVisitor +import java.nio.file.attribute.BasicFileAttributes +import fastdex.common.ShareConstants /** * Created by tong on 17/9/24. */ -public class FindDexFileVisitor extends SimpleFileVisitor { - public boolean hasDex; +class FindDexFileVisitor extends SimpleFileVisitor { + public boolean hasDex @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { if (file.toString().endsWith(ShareConstants.DEX_SUFFIX)) { - hasDex = true; - return FileVisitResult.TERMINATE; + hasDex = true + return FileVisitResult.TERMINATE } - return FileVisitResult.CONTINUE; + return FileVisitResult.CONTINUE } -} +} \ No newline at end of file diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/util/GradleUtils.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/util/GradleUtils.groovy index f7465b1a..2a830be7 100644 --- a/fastdex-gradle/src/main/groovy/fastdex/build/util/GradleUtils.groovy +++ b/fastdex-gradle/src/main/groovy/fastdex/build/util/GradleUtils.groovy @@ -1,6 +1,7 @@ package fastdex.build.util import com.android.build.gradle.api.ApplicationVariant +import com.android.build.gradle.api.BaseVariant import com.android.build.gradle.internal.pipeline.IntermediateFolderUtils import com.android.build.gradle.internal.pipeline.TransformManager import com.android.builder.model.Version @@ -10,12 +11,14 @@ import java.lang.reflect.Field import com.android.build.api.transform.TransformInvocation import org.gradle.api.Project import com.android.build.api.transform.QualifiedContent.ContentType +import com.android.build.gradle.internal.scope.VariantScope +import java.lang.reflect.Method /** * Created by tong on 17/3/14. */ -public class GradleUtils { - public static final String UTF8_BOM = "\uFEFF"; +class GradleUtils { + public static final String UTF8_BOM = "\uFEFF" /** * 获取指定variant的依赖列表 @@ -23,54 +26,71 @@ public class GradleUtils { * @param applicationVariant * @return */ - public static Set getCurrentDependList(Project project,Object applicationVariant) { - String buildTypeName = applicationVariant.getBuildType().buildType.getName() - + static Set getCurrentDependList(Project project,Object applicationVariant) { Set result = new HashSet<>() - - project.configurations.compile.each { File file -> - result.add(file.getAbsolutePath()) + if (GradleUtils.getAndroidGradlePluginVersion().compareTo("3.0") < 0) { + String buildTypeName = applicationVariant.getBuildType().buildType.getName() + project.configurations.compile.each { File file -> + result.add(file.getAbsolutePath()) + } + project.configurations."${buildTypeName}Compile".each { File file -> + result.add(file.getAbsolutePath()) + } } + else { + def variantScope = applicationVariant.variantData.getScope() - project.configurations."${buildTypeName}Compile".each { File file -> - result.add(file.getAbsolutePath()) - } - return result - } + //def artifacts = com.android.build.gradle.internal.ide.ArtifactDependencyGraph.getAllArtifacts(variantScope, com.android.build.gradle.internal.publishing.AndroidArtifacts.ConsumedConfigType.COMPILE_CLASSPATH,null); + //ArtifactDependencyGraph这个api3.0.0才有,fastdex依赖的是低版本的android gradle编译通不过,所以通过反射调用 + Class dependencyGraphClass = Class.forName("com.android.build.gradle.internal.ide.ArtifactDependencyGraph") + Class consumedConfigTypeClass = Class.forName("com.android.build.gradle.internal.publishing.AndroidArtifacts\$ConsumedConfigType") + Method getAllArtifactsMethod = dependencyGraphClass.getMethod("getAllArtifacts",VariantScope.class,consumedConfigTypeClass,Class.forName("com.android.build.gradle.internal.ide.DependencyFailureHandler")) + Object[] values = consumedConfigTypeClass.getMethod("values").invoke(null,null) + def artifacts = getAllArtifactsMethod.invoke(null,variantScope,values.find { it.getName().equals("compileClasspath") },null) - /** - * 获取transformClassesWithDexFor${variantName}任务的dex输出目录 - * @param transformInvocation - * @return - */ - public static File getDexOutputDir(TransformInvocation transformInvocation) { - File location = com.android.utils.FileUtils.join(transformInvocation.getOutputProvider().rootLocation, - IntermediateFolderUtils.FOLDERS, - typesToString(TransformManager.CONTENT_DEX)) + for (org.gradle.api.artifacts.result.ResolvedArtifactResult artifact : artifacts) { + if (artifact.getDependencyType().getExtension().equals(com.android.SdkConstants.EXT_JAR)) { + File jarFile = artifact.getFile() - return location + result.add(jarFile.getAbsolutePath()) + } + else { + final File explodedFolder = artifact.getFile() + File aarFile = artifact.bundleResult != null ? artifact.bundleResult.getFile() : explodedFolder + + result.add(aarFile.getAbsolutePath()) + } + } + } + return result } /** - * 获取transformClassesWithDexFor${variantName}任务的dex输出目录 + * 获取dex输出目录 * @param transformInvocation * @return */ - public static File getDexOutputDir(ApplicationVariant variant) { - File location = com.android.utils.FileUtils.join(variant.getVariantData().getOutputs().get(0).getScope().getVariantScope().getDexOutputFolder(), - IntermediateFolderUtils.FOLDERS, - typesToString(TransformManager.CONTENT_DEX)) + static File getDexOutputDir(TransformInvocation transformInvocation) { + if (GradleUtils.getAndroidGradlePluginVersion().compareTo("3.0") < 0) { + File location = com.android.utils.FileUtils.join(transformInvocation.getOutputProvider().rootLocation, + IntermediateFolderUtils.FOLDERS, + typesToString(TransformManager.CONTENT_DEX)) - return location + return location + } + else { + Field folderUtilsField = transformInvocation.getOutputProvider().getClass().getDeclaredField("folderUtils") + folderUtilsField.setAccessible(true) + return folderUtilsField.get(transformInvocation.getOutputProvider()).getRootFolder() + } } private static String typesToString(Set types) { - int value = 0; + int value = 0 for (ContentType type : types) { - value += type.getValue(); + value += type.getValue() } - - return String.format("%x", value); + return String.format("%x", value) } /** @@ -78,29 +98,28 @@ public class GradleUtils { * @param xmlPath * @return */ - public static Object parseXml(String xmlPath) { + static Object parseXml(String xmlPath) { byte[] bytes = FileUtils.readContents(new File(xmlPath)) try { def xml = new XmlParser().parse(new InputStreamReader(new ByteArrayInputStream(bytes), "utf-8")) return xml } catch (org.xml.sax.SAXParseException e) { - String msg = e.getMessage(); + String msg = e.getMessage() //从eclipse转过来的项目可能会有这个问题 if (msg != null && msg.contains("Content is not allowed in prolog.")) { - BufferedReader r = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(bytes), "UTF8")); + BufferedReader r = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(bytes), "UTF8")) - ByteArrayOutputStream fos = new ByteArrayOutputStream(); - Writer w = new BufferedWriter(new OutputStreamWriter(fos, "Cp1252")); + ByteArrayOutputStream fos = new ByteArrayOutputStream() + Writer w = new BufferedWriter(new OutputStreamWriter(fos, "Cp1252")) boolean firstLine = true for (String s = ""; (s = r.readLine()) != null;) { if (firstLine) { - s = removeUTF8BOM(s); - firstLine = false; + s = removeUTF8BOM(s) + firstLine = false } - w.write(s + System.getProperty("line.separator")); - w.flush(); + w.write(s + System.getProperty("line.separator")) + w.flush() } - def xml = new XmlParser().parse(new InputStreamReader(new ByteArrayInputStream(fos.toByteArray()), "utf-8")) return xml } @@ -112,9 +131,9 @@ public class GradleUtils { private static String removeUTF8BOM(String s) { if (s.startsWith(UTF8_BOM)) { - s = s.substring(1); + s = s.substring(1) } - return s; + return s } /** @@ -122,7 +141,7 @@ public class GradleUtils { * @param manifestPath * @return */ - public static String getPackageName(String manifestPath) { + static String getPackageName(String manifestPath) { def xml = parseXml(manifestPath) String packageName = xml.attribute('package') return packageName @@ -133,7 +152,7 @@ public class GradleUtils { * @param manifestPath * @return */ - public static String getBootActivity(String manifestPath) { + static String getBootActivity(String manifestPath) { def xml = parseXml(manifestPath) return getBootActivityByXmlNode(xml) } @@ -143,13 +162,13 @@ public class GradleUtils { * @param xml * @return */ - public static String getBootActivityByXmlNode(Node xml) { + static String getBootActivityByXmlNode(Node xml) { def bootActivityName = "" def application = xml.application[0] if (application) { def activities = application.activity - QName androidNameAttr = new QName("http://schemas.android.com/apk/res/android", 'name', 'android'); + QName androidNameAttr = new QName("http://schemas.android.com/apk/res/android", 'name', 'android') try { activities.each { activity-> @@ -202,7 +221,7 @@ public class GradleUtils { * 获取android gradle插件版本 * @return */ - public static String getAndroidGradlePluginVersion() { + static String getAndroidGradlePluginVersion() { return Version.ANDROID_GRADLE_PLUGIN_VERSION } @@ -211,7 +230,7 @@ public class GradleUtils { * @param variant * @return */ - public static File getAptOutputDir(ApplicationVariant variant) { + static File getAptOutputDir(ApplicationVariant variant) { if (GradleUtils.getAndroidGradlePluginVersion().compareTo("2.2") >= 0) { //2.2.0以后才有getAnnotationProcessorOutputDir()这个api return variant.getVariantData().getScope().getAnnotationProcessorOutputDir() @@ -227,7 +246,7 @@ public class GradleUtils { * @param key * @param value */ - public static void addDynamicProperty(Project project,Object key, Object value) { + static void addDynamicProperty(Project project,Object key, Object value) { Class defaultConventionClass = null try { defaultConventionClass = Class.forName("org.gradle.api.internal.plugins.DefaultConvention") @@ -258,4 +277,28 @@ public class GradleUtils { } } } + + /** + * 获取apk输出目录 + * @param variant + * @return + */ + static File getApkLocation(ApplicationVariant variant) { + if (GradleUtils.getAndroidGradlePluginVersion().compareTo("3.0") >= 0) { + return variant.variantData.getScope().getApkLocation() + } + else { + return variant.getVariantData().getScope().getGlobalScope().getApkLocation() + } + } + + /** + * 获取aar工程 + * @param project + * @param buildTypeName + * @return + */ + static BaseVariant getLibraryFirstVariant(Project project,String buildTypeName) { + return project.android.libraryVariants.find { it.getBuildType().buildType.getName().equals(buildTypeName) } + } } \ No newline at end of file diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/util/JarOperation.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/util/JarOperation.groovy index c25258d7..7495f9f3 100644 --- a/fastdex-gradle/src/main/groovy/fastdex/build/util/JarOperation.groovy +++ b/fastdex-gradle/src/main/groovy/fastdex/build/util/JarOperation.groovy @@ -22,9 +22,9 @@ import java.util.zip.ZipOutputStream * jar操作 * Created by tong on 17/11/4. */ -public class JarOperation implements Opcodes { - public static void generatePatchJar(FastdexVariant fastdexVariant, TransformInvocation transformInvocation, File patchJar) throws IOException { - Set libraryDependencies = fastdexVariant.libraryDependencies +class JarOperation implements Opcodes { + static void generatePatchJar(FastdexVariant fastdexVariant, TransformInvocation transformInvocation, File patchJar) throws IOException { + Set libraryDependencies = fastdexVariant.getLibraryDependencies() Map jarAndProjectPathMap = new HashMap<>() List projectJarFiles = new ArrayList<>() //获取所有依赖工程的输出jar (compile project(':xxx')) @@ -34,9 +34,9 @@ public class JarOperation implements Opcodes { } //所有的class目录 - Set directoryInputFiles = new HashSet<>(); + Set directoryInputFiles = new HashSet<>() //所有library工程输出的jar - Set jarInputFiles = new HashSet<>(); + Set jarInputFiles = new HashSet<>() for (TransformInput input : transformInvocation.getInputs()) { Collection directoryInputs = input.getDirectoryInputs() if (directoryInputs != null) { @@ -80,7 +80,7 @@ public class JarOperation implements Opcodes { directoryInputFiles.add(classesDir) } } - JarOperation.generatePatchJar(fastdexVariant,directoryInputFiles,moudleDirectoryInputFiles,patchJar); + JarOperation.generatePatchJar(fastdexVariant,directoryInputFiles,moudleDirectoryInputFiles,patchJar) } /** @@ -91,7 +91,7 @@ public class JarOperation implements Opcodes { * @param changedClassPatterns * @throws IOException */ - public static void generatePatchJar(FastdexVariant fastdexVariant, Set directoryInputFiles,Set moudleDirectoryInputFiles, File patchJar) throws IOException { + static void generatePatchJar(FastdexVariant fastdexVariant, Set directoryInputFiles,Set moudleDirectoryInputFiles, File patchJar) throws IOException { long start = System.currentTimeMillis() def project = fastdexVariant.project project.logger.error("==fastdex generate patch jar start") @@ -117,12 +117,13 @@ public class JarOperation implements Opcodes { } FileUtils.deleteFile(patchJar) + FileUtils.ensumeDir(patchJar.getParentFile()) boolean willExeDexMerge = fastdexVariant.willExecDexMerge() ZipOutputStream outputJarStream = null try { - outputJarStream = new ZipOutputStream(new FileOutputStream(patchJar)); + outputJarStream = new ZipOutputStream(new FileOutputStream(patchJar)) for (File classesDir : directoryInputFiles) { //fix library databinding bug if (!FileUtils.dirExists(classesDir.absolutePath)) { @@ -138,12 +139,12 @@ public class JarOperation implements Opcodes { @Override FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { if (!file.toFile().getName().endsWith(Constants.CLASS_SUFFIX)) { - return FileVisitResult.CONTINUE; + return FileVisitResult.CONTINUE } Path relativePath = classpath.relativize(file) String entryName = relativePath.toString() if (Os.isFamily(Os.FAMILY_WINDOWS)) { - entryName = entryName.replace("\\", "/"); + entryName = entryName.replace("\\", "/") } if (libraryClassesDirectory) { @@ -162,7 +163,7 @@ public class JarOperation implements Opcodes { outputJarStream.closeEntry() } else { - String className = relativePath.toString().substring(0,relativePath.toString().length() - Constants.CLASS_SUFFIX.length()); + String className = relativePath.toString().substring(0,relativePath.toString().length() - Constants.CLASS_SUFFIX.length()) className = className.replaceAll(Os.isFamily(Os.FAMILY_WINDOWS) ? "\\\\" : File.separator,"\\.") //假如发生变化的java文件是fastdex/sample/MainActivity.java, fastdex/sample/MainActivity.class和以fastdex/sample/MainActivity$开头的class会被加进去 @@ -194,14 +195,14 @@ public class JarOperation implements Opcodes { } finally { if (outputJarStream != null) { - outputJarStream.close(); + outputJarStream.close() } } if (!FileUtils.isLegalFile(patchJar)) { throw new GradleException("==fastdex generate patch jar fail: ${patchJar}") } - long end = System.currentTimeMillis(); - project.logger.error("==fastdex generate patch jar complete: ${patchJar} use: ${end - start}ms") + long end = System.currentTimeMillis() + project.logger.error("==fastdex generate patch jar complete, use: ${end - start}ms \n${patchJar}") } } diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/util/JumpException.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/util/JumpException.groovy index 7430e945..7b05de99 100644 --- a/fastdex-gradle/src/main/groovy/fastdex/build/util/JumpException.groovy +++ b/fastdex-gradle/src/main/groovy/fastdex/build/util/JumpException.groovy @@ -1,14 +1,13 @@ -package fastdex.build.util; +package fastdex.build.util /** * Created by tong on 17/5/2. */ - -public class JumpException extends RuntimeException { - public JumpException() { +class JumpException extends RuntimeException { + JumpException() { } - public JumpException(String s) { - super(s); + JumpException(String s) { + super(s) } } diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/util/LibDependency.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/util/LibDependency.groovy index 54bf9533..f3fa5b3f 100644 --- a/fastdex-gradle/src/main/groovy/fastdex/build/util/LibDependency.groovy +++ b/fastdex-gradle/src/main/groovy/fastdex/build/util/LibDependency.groovy @@ -1,18 +1,22 @@ -package fastdex.build.util; +package fastdex.build.util -import com.android.build.gradle.api.ApplicationVariant; +import com.android.build.gradle.api.ApplicationVariant import com.android.build.gradle.internal.dependency.VariantDependencies import com.android.builder.model.AndroidLibrary import org.gradle.api.Project -import org.gradle.platform.base.Library; +import org.gradle.api.artifacts.Configuration +import org.gradle.api.artifacts.ConfigurationContainer +import org.gradle.api.artifacts.Dependency +import org.gradle.api.artifacts.DependencySet +import org.gradle.platform.base.Library /** * Created by tong on 17/4/15. */ -public class LibDependency { - public final File jarFile; - public final Project dependencyProject; - public final boolean androidLibrary; +class LibDependency { + public final File jarFile + public final Project dependencyProject + public final boolean androidLibrary LibDependency(File jarFile, Project dependencyProject, boolean androidLibrary) { this.jarFile = jarFile @@ -36,18 +40,61 @@ public class LibDependency { } @Override - public String toString() { + String toString() { return "LibDependency{" + "jarFile=" + jarFile + ", dependencyProject=" + dependencyProject + ", androidLibrary=" + androidLibrary + - '}'; + '}' } private static Project getProjectByPath(Collection allprojects, String path) { return allprojects.find { it.path.equals(path) } } + private static void scanDependency_3_0(Project project, String applicationBuildTypeName, DependencySet dependencies, Set libDependencies, Set alreadyScanProjectSet) { + if (alreadyScanProjectSet.contains(project)) { + return + } + if (!project.plugins.hasPlugin("com.android.application")) { + if (project.plugins.hasPlugin("com.android.library")) { + + def libraryVariant = GradleUtils.getLibraryFirstVariant(project,applicationBuildTypeName) + + def variantScope = libraryVariant.variantData.getScope() + File jarFile = new File(variantScope.getIntermediateJarOutputFolder(),com.android.SdkConstants.FN_CLASSES_JAR) + libDependencies.add(new LibDependency(jarFile,project,true)) + } + else { + File jarFile = new File(project.getBuildDir(),"libs/${project.name}.jar") + libDependencies.add(new LibDependency(jarFile,project,false)) + } + alreadyScanProjectSet.add(project) + } + for (Dependency dependency : dependencies) { + if (dependency instanceof org.gradle.api.internal.artifacts.dependencies.DefaultProjectDependency) { + Project dependencyProject = dependency.getDependencyProject() + //dependencyProject.afterEvaluate { + if (dependencyProject.plugins.hasPlugin("com.android.library")) { + + def libraryVariant = GradleUtils.getLibraryFirstVariant(dependencyProject,applicationBuildTypeName) + VariantDependencies variantDeps = libraryVariant.getVariantData().getVariantDependency() + LibDependency.scanDependency_3_0(dependencyProject,applicationBuildTypeName,variantDeps.getCompileClasspath().getAllDependencies(),libDependencies,alreadyScanProjectSet) + } + else { + final ConfigurationContainer configurations = dependencyProject.getConfigurations() + final String compileClasspathName = "compileClasspath" + Configuration compileClasspath = configurations.findByName(compileClasspathName) + if (compileClasspath == null) { + compileClasspath = configurations.maybeCreate(compileClasspathName) + } + LibDependency.scanDependency_3_0(dependencyProject,applicationBuildTypeName,compileClasspath.getAllDependencies(),libDependencies,alreadyScanProjectSet) + } + //} + } + } + } + /** * 扫描依赖(<= 2.3.0) * @param library @@ -126,18 +173,26 @@ public class LibDependency { * @param project * @return */ - public static final Set resolveProjectDependency(Project project, ApplicationVariant apkVariant) { + static final Set resolveProjectDependency(Project project, ApplicationVariant apkVariant) { Set libraryDependencySet = new HashSet<>() - VariantDependencies variantDeps = apkVariant.getVariantData().getVariantDependency(); - if (GradleUtils.getAndroidGradlePluginVersion().compareTo("2.3.0") >= 0) { + VariantDependencies variantDeps = apkVariant.getVariantData().getVariantDependency() + if (GradleUtils.getAndroidGradlePluginVersion().compareTo("3.0.0") >= 0) { + libraryDependencySet = Collections.synchronizedSet(new HashSet()) + + Set alreadyScanProjectSet = Collections.synchronizedSet(new HashSet()) + String applicationBuildTypeName = apkVariant.getBuildType().buildType.getName() + + LibDependency.scanDependency_3_0(project,applicationBuildTypeName,variantDeps.getCompileClasspath().getAllDependencies(),libraryDependencySet,alreadyScanProjectSet) + } + else if (GradleUtils.getAndroidGradlePluginVersion().compareTo("2.3.0") >= 0) { def allDependencies = new HashSet<>() allDependencies.addAll(variantDeps.getCompileDependencies().getAllJavaDependencies()) allDependencies.addAll(variantDeps.getCompileDependencies().getAllAndroidDependencies()) for (Object dependency : allDependencies) { if (dependency.projectPath != null) { - def dependencyProject = getProjectByPath(project.rootProject.allprojects,dependency.projectPath); - boolean androidLibrary = dependency.getClass().getName().equals("com.android.builder.dependency.level2.AndroidDependency"); + def dependencyProject = getProjectByPath(project.rootProject.allprojects,dependency.projectPath) + boolean androidLibrary = dependency.getClass().getName().equals("com.android.builder.dependency.level2.AndroidDependency") File jarFile = null if (androidLibrary) { jarFile = dependency.getJarFile() @@ -160,15 +215,15 @@ public class LibDependency { } for (com.android.builder.model.Library library : librarySet) { - boolean isAndroidLibrary = (library instanceof AndroidLibrary); + boolean isAndroidLibrary = (library instanceof AndroidLibrary) File jarFile = null - def dependencyProject = getProjectByPath(project.rootProject.allprojects,library.getProject()); + def dependencyProject = getProjectByPath(project.rootProject.allprojects,library.getProject()) if (isAndroidLibrary) { - com.android.builder.dependency.LibraryDependency androidLibrary = library; + com.android.builder.dependency.LibraryDependency androidLibrary = library jarFile = androidLibrary.getJarFile() } else { - jarFile = library.getJarFile(); + jarFile = library.getJarFile() } LibDependency libraryDependency = new LibDependency(jarFile,dependencyProject,isAndroidLibrary) libraryDependencySet.add(libraryDependency) @@ -180,23 +235,22 @@ public class LibDependency { if (jarLibrary.getProjectPath() != null) { librarySet.add(jarLibrary) } - //scanDependency_2_0_0(jarLibrary,librarySet) } for (Object androidLibrary : variantDeps.getAndroidDependencies()) { scanDependency_2_0_0(androidLibrary,librarySet) } for (Object library : librarySet) { - boolean isAndroidLibrary = (library instanceof AndroidLibrary); + boolean isAndroidLibrary = (library instanceof AndroidLibrary) File jarFile = null def projectPath = (library instanceof com.android.builder.dependency.JarDependency) ? library.getProjectPath() : library.getProject() - def dependencyProject = getProjectByPath(project.rootProject.allprojects,projectPath); + def dependencyProject = getProjectByPath(project.rootProject.allprojects,projectPath) if (isAndroidLibrary) { - com.android.builder.dependency.LibraryDependency androidLibrary = library; + com.android.builder.dependency.LibraryDependency androidLibrary = library jarFile = androidLibrary.getJarFile() } else { - jarFile = library.getJarFile(); + jarFile = library.getJarFile() } LibDependency libraryDependency = new LibDependency(jarFile,dependencyProject,isAndroidLibrary) libraryDependencySet.add(libraryDependency) diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/util/MetaInfo.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/util/MetaInfo.groovy index 033d1cc0..f416619a 100644 --- a/fastdex-gradle/src/main/groovy/fastdex/build/util/MetaInfo.groovy +++ b/fastdex-gradle/src/main/groovy/fastdex/build/util/MetaInfo.groovy @@ -4,12 +4,12 @@ import fastdex.common.utils.SerializeUtils import fastdex.build.variant.FastdexVariant import com.google.gson.Gson import fastdex.common.utils.FileUtils -import org.gradle.api.Project; +import org.gradle.api.Project /** * Created by tong on 17/4/18. */ -public class MetaInfo { +class MetaInfo { /** * 全量编译时的工程路径 */ @@ -43,29 +43,28 @@ public class MetaInfo { * @param project * @return */ - public boolean isRootProjectDirChanged(String curRootProjectPath) { + def isRootProjectDirChanged(String curRootProjectPath) { return !curRootProjectPath.equals(rootProjectPath) } - public void save(FastdexVariant fastdexVariant) { + def save(FastdexVariant fastdexVariant) { File metaInfoFile = FastdexUtils.getMetaInfoFile(fastdexVariant.project,fastdexVariant.variantName) SerializeUtils.serializeTo(new FileOutputStream(metaInfoFile),this) } - public static MetaInfo load(Project project,String variantName) { - File metaInfoFile = FastdexUtils.getMetaInfoFile(project,variantName) - return new Gson().fromJson(new String(FileUtils.readContents(metaInfoFile)),MetaInfo.class) - } - - @Override - public String toString() { + String toString() { return "MetaInfo{" + "buildMillis=" + buildMillis + ", variantName='" + variantName + '\'' + ", mergedDexVersion=" + mergedDexVersion + ", patchDexVersion=" + patchDexVersion + ", resourcesVersion=" + resourcesVersion + - '}'; + '}' + } + + static MetaInfo load(Project project,String variantName) { + File metaInfoFile = FastdexUtils.getMetaInfoFile(project,variantName) + return new Gson().fromJson(new String(FileUtils.readContents(metaInfoFile)),MetaInfo.class) } } diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/util/ProjectSnapshoot.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/util/ProjectSnapshoot.groovy index 0693ffad..d5ec5de4 100644 --- a/fastdex-gradle/src/main/groovy/fastdex/build/util/ProjectSnapshoot.groovy +++ b/fastdex-gradle/src/main/groovy/fastdex/build/util/ProjectSnapshoot.groovy @@ -1,5 +1,6 @@ package fastdex.build.util +import com.android.build.gradle.api.BaseVariant import fastdex.build.lib.snapshoot.api.DiffResultSet import fastdex.build.lib.snapshoot.file.FileDiffInfo import fastdex.build.lib.snapshoot.res.AndManifestDirectorySnapshoot @@ -14,8 +15,10 @@ import fastdex.common.utils.FileUtils /** * Created by tong on 17/3/31. */ -public class ProjectSnapshoot { - FastdexVariant fastdexVariant +class ProjectSnapshoot { + private static final boolean DEBUG_SNAPSHOOT = true + + final FastdexVariant fastdexVariant SourceSetSnapshoot sourceSetSnapshoot SourceSetSnapshoot oldSourceSetSnapshoot SourceSetDiffResultSet diffResultSet @@ -62,7 +65,7 @@ public class ProjectSnapshoot { andManifestDirectorySnapshoot.addFile(it) } - for (LibDependency libDependency : fastdexVariant.libraryDependencies) { + for (LibDependency libDependency : fastdexVariant.getLibraryDependencies()) { if (libDependency.androidLibrary) { File file = libDependency.dependencyProject.android.sourceSets.main.manifest.srcFile andManifestDirectorySnapshoot.addFile(file) @@ -104,7 +107,7 @@ public class ProjectSnapshoot { */ def handleGeneratedSource(SourceSetSnapshoot snapshoot) { List androidLibDependencies = new ArrayList<>() - for (LibDependency libDependency : fastdexVariant.libraryDependencies) { + for (LibDependency libDependency : fastdexVariant.getLibraryDependencies()) { if (libDependency.androidLibrary) { androidLibDependencies.add(libDependency) } @@ -117,6 +120,10 @@ public class ProjectSnapshoot { } def libraryVariantdirName = Constants.DEFAULT_LIBRARY_VARIANT_DIR_NAME + if (GradleUtils.getAndroidGradlePluginVersion().compareTo("3.0") >= 0) { + //3.0之前默认依赖release,3.0依赖Application工程的buildType对应的library工程的buildType + libraryVariantdirName = fastdexVariant.androidVariant.getBuildType().buildType.getName() + } //dataBinding if (FastdexUtils.isDataBindingEnabled(fastdexVariant.project)) { @@ -131,33 +138,20 @@ public class ProjectSnapshoot { for (int i = 0;i < projectList.size();i++) { Project project = projectList.get(i) - //TODO 需要处理library工程包含flavor的场景 String packageName = (i == 0 ? fastdexVariant.getOriginPackageName() : GradleUtils.getPackageName(project.android.sourceSets.main.manifest.srcFile.absolutePath)) String packageNamePath = packageName.split("\\.").join(File.separator) //buildconfig String buildConfigJavaRelativePath = "${packageNamePath}${File.separator}BuildConfig.java" String rJavaRelativePath = "${packageNamePath}${File.separator}R.java" - File buildConfigDir = null - File rDir = null - File rsDir = null - File aidlDir = null - File aptDir = null - if (i == 0) { - buildConfigDir = fastdexVariant.androidVariant.getVariantData().getScope().getBuildConfigSourceOutputDir() - rDir = fastdexVariant.androidVariant.getVariantData().getScope().getRClassSourceOutputDir() - rsDir = fastdexVariant.androidVariant.getVariantData().getScope().getRenderscriptSourceOutputDir() - aidlDir = fastdexVariant.androidVariant.getVariantData().getScope().getAidlSourceOutputDir() - aptDir = GradleUtils.getAptOutputDir(fastdexVariant.androidVariant) - } - else { - //TODO 需要处理library工程包含flavor的场景 - buildConfigDir = new File(project.buildDir,"generated${File.separator}source${File.separator}buildConfig${File.separator}${libraryVariantdirName}${File.separator}") - rDir = new File(project.buildDir,"generated${File.separator}source${File.separator}r${File.separator}${libraryVariantdirName}${File.separator}") - rsDir = new File(project.buildDir,"generated${File.separator}source${File.separator}rs${File.separator}${libraryVariantdirName}${File.separator}") - aidlDir = new File(project.buildDir,"generated${File.separator}source${File.separator}aidl${File.separator}${libraryVariantdirName}${File.separator}") - aptDir = new File(project.buildDir,"generated${File.separator}source${File.separator}apt${File.separator}${libraryVariantdirName}${File.separator}") - } + BaseVariant baseVariant = (i == 0 ? fastdexVariant.androidVariant : GradleUtils.getLibraryFirstVariant(project,libraryVariantdirName)) + + File buildConfigDir = baseVariant.getVariantData().getScope().getBuildConfigSourceOutputDir() + File rDir = baseVariant.getVariantData().getScope().getRClassSourceOutputDir() + File rsDir = baseVariant.getVariantData().getScope().getRenderscriptSourceOutputDir() + File aidlDir = baseVariant.getVariantData().getScope().getAidlSourceOutputDir() + File aptDir = GradleUtils.getAptOutputDir(fastdexVariant.androidVariant) + //buildconfig File buildConfigJavaFile = new File(buildConfigDir,buildConfigJavaRelativePath) JavaDirectorySnapshoot buildConfigSnapshoot = new JavaDirectorySnapshoot(buildConfigDir,true,buildConfigJavaFile.absolutePath) @@ -199,7 +193,10 @@ public class ProjectSnapshoot { * @param snapshoot */ def handleLibraryDependencies(SourceSetSnapshoot snapshoot) { - for (LibDependency libDependency : fastdexVariant.libraryDependencies) { + if (DEBUG_SNAPSHOOT) { + fastdexVariant.project.logger.error("==fastdex: libraryDependencies: ${fastdexVariant.getLibraryDependencies()}") + } + for (LibDependency libDependency : fastdexVariant.getLibraryDependencies()) { Set srcDirSet = getProjectSrcDirSet(libDependency.dependencyProject) for (File file : srcDirSet) { @@ -255,7 +252,10 @@ public class ProjectSnapshoot { srcDirs.addAll(project.sourceSets.main.java.srcDirs.asList()) } - project.logger.error("==fastdex: sourceSets ${srcDirs}") + if (DEBUG_SNAPSHOOT) { + project.logger.error("==fastdex: sourceSets ${srcDirs}") + } + Set srcDirSet = new LinkedHashSet<>() if (srcDirs != null) { for (java.lang.Object src : srcDirs) { diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/variant/FastdexBuilder.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/variant/FastdexBuilder.groovy new file mode 100644 index 00000000..c7227711 --- /dev/null +++ b/fastdex-gradle/src/main/groovy/fastdex/build/variant/FastdexBuilder.groovy @@ -0,0 +1,272 @@ +package fastdex.build.variant + +import com.android.build.api.transform.JarInput +import com.android.build.api.transform.Transform +import com.android.build.api.transform.TransformInput +import com.android.build.api.transform.TransformInvocation +import fastdex.build.util.ClassInject +import fastdex.build.util.Constants +import fastdex.build.util.DexOperation +import fastdex.build.util.FastdexUtils +import fastdex.build.util.GradleUtils +import fastdex.common.utils.FileUtils +import fastdex.common.utils.SerializeUtils +import org.gradle.api.Project + +/** + * Created by tong on 17/10/31. + */ +class FastdexBuilder { + final FastdexVariant fastdexVariant + final Project project + final String variantName + + FastdexBuilder(FastdexVariant fastdexVariant) { + this.fastdexVariant = fastdexVariant + this.project = fastdexVariant.project + this.variantName = fastdexVariant.variantName + } + + /** + * 对输入的class打桩并且保存classpath + * @param transformInvocation + */ + def injectInputAndSaveClassPath(TransformInvocation transformInvocation) { + //所有输入的jar + Set jarInputFiles = new HashSet<>() + for (TransformInput input : transformInvocation.getInputs()) { + Collection jarInputs = input.getJarInputs() + if (jarInputs != null) { + for (JarInput jarInput : jarInputs) { + jarInputFiles.add(jarInput.getFile().absolutePath) + } + } + } + File classpathFile = new File(FastdexUtils.getBuildDir(fastdexVariant.project,fastdexVariant.variantName), Constants.CLASSPATH_FILENAME) + SerializeUtils.serializeTo(classpathFile,jarInputFiles) + + //inject dir input + ClassInject.injectTransformInvocation(fastdexVariant,transformInvocation) + } + + /** + * 全量打包时调用默认的transform,并且做后续处理 + * @param base + * @param transformInvocation + * @return + */ + def invokeNormalBuildTransform(Transform base,TransformInvocation transformInvocation) { + //调用默认转换方法 + base.transform(transformInvocation) + //获取dex输出路径 + File dexOutputDir = GradleUtils.getDexOutputDir(transformInvocation) + + project.logger.error("==fastdex dexOutputDir: ${dexOutputDir}") + //缓存dex + int dexCount = cacheNormalBuildDex(dexOutputDir) + + //复制全量打包的dex到输出路径 + hookNormalBuildDex(dexOutputDir) + + fastdexVariant.metaInfo.dexCount = dexCount + fastdexVariant.metaInfo.buildMillis = System.currentTimeMillis() + fastdexVariant.onDexGenerateSuccess(true,false) + } + + /** + * 补丁打包 + * @param patchJar + * @param dexOutputDir + */ + def patchBuild(Transform base,File patchJar,File dexOutputDir) { + File patchDex = FastdexUtils.getPatchDexFile(fastdexVariant.project,fastdexVariant.variantName) + DexOperation.generatePatchDex(fastdexVariant,base,patchJar,patchDex) + fastdexVariant.metaInfo.patchDexVersion += 1 + //merged dex + File mergedPatchDexDir = FastdexUtils.getMergedPatchDexDir(fastdexVariant.project,fastdexVariant.variantName) + + boolean willExecDexMerge = fastdexVariant.willExecDexMerge() + boolean firstMergeDex = fastdexVariant.metaInfo.mergedDexVersion == 0 + + if (willExecDexMerge) { + //merge dex + if (firstMergeDex) { + //第一次执行dex merge,直接保存patchDex + //copy 一份相同的,做冗余操作,如果直接移动文件,会丢失patch.dex造成免安装模块特别难处理 + FileUtils.copyFileUsingStream(patchDex,new File(mergedPatchDexDir,Constants.CLASSES_DEX)) + } + else { + //已经执行过一次dex merge + File mergedPatchDex = new File(mergedPatchDexDir,Constants.CLASSES_DEX) + //更新patch.dex + DexOperation.mergeDex(fastdexVariant,mergedPatchDex,patchDex,mergedPatchDex) + } + fastdexVariant.metaInfo.mergedDexVersion += 1 + } + fastdexVariant.metaInfo.save(fastdexVariant) + //复制补丁打包的dex到输出路径,为了触发package任务 + hookPatchBuildDex(dexOutputDir,willExecDexMerge) + fastdexVariant.onDexGenerateSuccess(false,willExecDexMerge) + } + + /** + * 缓存全量打包时生成的dex + * @param dexOutputDir dex输出路径 + */ + def cacheNormalBuildDex(File dexOutputDir) { + File cacheDexDir = FastdexUtils.getDexCacheDir(project,variantName) + return FileUtils.copyDir(dexOutputDir,cacheDexDir,Constants.DEX_SUFFIX) + } + + /** + * 全量打包时复制dex到指定位置 + * @param dexOutputDir dex输出路径 + */ + def hookNormalBuildDex(File dexOutputDir) { + //dexelements [fastdex-runtime.dex ${dex_cache}.listFiles] + //runtime.dex => classes.dex + //dex_cache.classes.dex => classes2.dex + //dex_cache.classes2.dex => classes3.dex + //dex_cache.classesN.dex => classes(N + 1).dex + + dexOutputDir = FastdexUtils.mergeDexOutputDir(dexOutputDir) + + project.logger.error(" ") + printLogWhenDexGenerateComplete(dexOutputDir,true) + + //fastdex-runtime.dex = > classes.dex + copyFastdexRuntimeDex(new File(dexOutputDir,Constants.CLASSES_DEX)) + printLogWhenDexGenerateComplete(dexOutputDir,true) + project.logger.error(" ") + + //清除除了classesN.dex以外的文件 + FastdexUtils.clearDexOutputDir(dexOutputDir) + return dexOutputDir + } + + /** + * 补丁打包时复制dex到指定位置 + * @param dexOutputDir dex输出路径 + */ + def hookPatchBuildDex(File dexOutputDir,boolean willExecDexMerge) { + //dexelements [fastdex-runtime.dex patch.dex ${dex_cache}.listFiles] + //runtime.dex => classes.dex + //patch.dex => classes2.dex + //dex_cache.classes.dex => classes3.dex + //dex_cache.classes2.dex => classes4.dex + //dex_cache.classesN.dex => classes(N + 2).dex + + project.logger.error(" ") + project.logger.error("==fastdex patch transform hook patch dex start") + + File cacheDexDir = FastdexUtils.getDexCacheDir(project,variantName) + + File patchDex = FastdexUtils.getPatchDexFile(fastdexVariant.project,fastdexVariant.variantName) + File mergedPatchDex = FastdexUtils.getMergedPatchDexFile(fastdexVariant.project,fastdexVariant.variantName) + + FileUtils.cleanDir(dexOutputDir) + FileUtils.copyDir(cacheDexDir,dexOutputDir,Constants.DEX_SUFFIX) + + int dsize = 1 + //如果本次打包触发了dexmerge就不需要patch.dex了 + boolean copyPatchDex = !willExecDexMerge && FileUtils.isLegalFile(patchDex) + if (copyPatchDex) { + dsize += 1 + } + boolean copyMergedPatchDex = FileUtils.isLegalFile(mergedPatchDex) + if (copyMergedPatchDex) { + dsize += 1 + } + + dexOutputDir = FastdexUtils.mergeDexOutputDir(dexOutputDir,dsize) + + printLogWhenDexGenerateComplete(dexOutputDir,false) + //copy fastdex-runtime.dex + copyFastdexRuntimeDex(new File(dexOutputDir,Constants.CLASSES_DEX)) + + int point = 2 + if (copyPatchDex) { + //copy patch.dex + FileUtils.copyFileUsingStream(patchDex,new File(dexOutputDir,"classes${point}.dex")) + project.logger.error("==fastdex patch.dex => " + new File(dexOutputDir,"classes${point}.dex")) + + point += 1 + } + if (copyMergedPatchDex) { + //copy merged-patch.dex + FileUtils.copyFileUsingStream(mergedPatchDex,new File(dexOutputDir,"classes${point}.dex")) + project.logger.error("==fastdex merged-patch.dex => " + new File(dexOutputDir,"classes${point}.dex")) + } + printLogWhenDexGenerateComplete(dexOutputDir,false) + + //清除除了classesN.dex以外的文件 + FastdexUtils.clearDexOutputDir(dexOutputDir) + project.logger.error(" ") + + return dexOutputDir + } + + /** + * 把runtime.dex复制到dex输出目录 + * @param dist + * @return + */ + def copyFastdexRuntimeDex(File dist) { + File buildDir = FastdexUtils.getBuildDir(project) + + File fastdexRuntimeDex = new File(buildDir, Constants.RUNTIME_DEX_FILENAME) + if (!FileUtils.isLegalFile(fastdexRuntimeDex)) { + FileUtils.copyResourceUsingStream(Constants.RUNTIME_DEX_FILENAME, fastdexRuntimeDex) + } + FileUtils.copyFileUsingStream(fastdexRuntimeDex, dist) + + project.logger.error("==fastdex fastdex-runtime.dex => " + dist) + } + + /** + * 当dex生成完成后打印日志 + * @param normalBuild + */ + def printLogWhenDexGenerateComplete(File dexOutputDir,boolean normalBuild) { + //log + StringBuilder sb = new StringBuilder() + File[] dexFiles = dexOutputDir.listFiles() + + if (dexFiles != null) { + if (dexFiles.length < 7) { + sb.append("dex-dir[") + int idx = 0 + for (File file : dexFiles) { + if (file.getName().endsWith(Constants.DEX_SUFFIX)) { + sb.append(file.getName()) + if (idx < (dexFiles.length - 1)) { + sb.append(",") + } + } + idx ++ + } + sb.append("]") + } + else { + int[] range = FastdexUtils.getClassesDexBoundary(dexOutputDir) + sb.append("dex-dir[") + if (range[0] == 1) { + sb.append("classes.dex") + } + else { + sb.append("classes${range[0]}.dex") + } + sb.append(" - ") + sb.append("classes${range[1]}.dex") + sb.append("]") + } + } + + if (normalBuild) { + project.logger.error("==fastdex first build ${sb}") + } + else { + project.logger.error("==fastdex patch build ${sb}") + } + } +} diff --git a/fastdex-gradle/src/main/groovy/fastdex/build/variant/FastdexVariant.groovy b/fastdex-gradle/src/main/groovy/fastdex/build/variant/FastdexVariant.groovy index d85e927d..e4ebedec 100755 --- a/fastdex-gradle/src/main/groovy/fastdex/build/variant/FastdexVariant.groovy +++ b/fastdex-gradle/src/main/groovy/fastdex/build/variant/FastdexVariant.groovy @@ -5,7 +5,7 @@ import com.android.build.gradle.api.ApplicationVariant import com.github.typ0520.fastdex.Version import fastdex.build.extension.FastdexExtension import fastdex.build.task.FastdexInstantRunTask -import fastdex.build.transform.FastdexTransform +import fastdex.build.transform.FastdexDexTransform import fastdex.build.util.Constants import fastdex.build.util.FastdexInstantRun import fastdex.build.util.FastdexRuntimeException @@ -17,11 +17,12 @@ import fastdex.build.util.ProjectSnapshoot import fastdex.build.util.FastdexUtils import fastdex.common.utils.FileUtils import org.gradle.api.Project +import fastdex.build.util.GradleUtils /** * Created by tong on 17/3/10. */ -public class FastdexVariant { +class FastdexVariant { final Project project final FastdexExtension configuration final ApplicationVariant androidVariant @@ -30,44 +31,61 @@ public class FastdexVariant { final File rootBuildDir final File buildDir final ProjectSnapshoot projectSnapshoot - final Set libraryDependencies + + Set libraryDependencies + + File textSymbolOutputFile + File dexBuilderOutputFolder + File dexMergerOutputFolder + File preDexOutputFolder boolean hasDexCache boolean firstPatchBuild boolean initialized boolean needExecDexMerge boolean hasJarMergingTask + boolean hasPreDexTask boolean compiledByCustomJavac boolean compiledByOriginJavac MetaInfo metaInfo - FastdexTransform fastdexTransform + FastdexDexTransform fastdexTransform FastdexInstantRun fastdexInstantRun FastdexInstantRunTask fastdexInstantRunTask TransformInvocation transformInvocation + FastdexBuilder fastdexBuilder - FastdexVariant(Project project, Object androidVariant) { + FastdexVariant(Project project, ApplicationVariant androidVariant) { this.project = project this.androidVariant = androidVariant this.configuration = project.fastdex this.variantName = androidVariant.name.capitalize() - this.manifestPath = androidVariant.outputs.first().processManifest.manifestOutputFile + def processManifest = androidVariant.outputs.first().processManifest + def processResources = androidVariant.outputs.first().processResources + + if (processManifest.properties['manifestOutputFile'] != null) { + this.manifestPath = processManifest.manifestOutputFile.absolutePath + } else if (processResources.properties['manifestFile'] != null) { + this.manifestPath = androidVariant.outputs.first().processResources.manifestFile.absolutePath + } + this.rootBuildDir = FastdexUtils.getBuildDir(project) this.buildDir = FastdexUtils.getBuildDir(project,variantName) projectSnapshoot = new ProjectSnapshoot(this) - libraryDependencies = LibDependency.resolveProjectDependency(project,androidVariant) if (configuration.dexMergeThreshold <= 1) { throw new FastdexRuntimeException("DexMergeThreshold must be greater than 1!!") } + + fastdexBuilder = new FastdexBuilder(this) } /* * 检查缓存是否过期,如果过期就删除 */ - void prepareEnv() { + def prepareEnv() { if (initialized) { return } @@ -168,22 +186,28 @@ public class FastdexVariant { classesDir.deleteDir() File transformsDir = new File(androidVariant.getVariantData().getScope().getGlobalScope().getIntermediatesDir(), "/transforms") transformsDir.deleteDir() - File apkLocationDir = androidVariant.getVariantData().getScope().getGlobalScope().getApkLocation() + File apkLocationDir = GradleUtils.getApkLocation(androidVariant) apkLocationDir.deleteDir() if (!(e instanceof JumpException) && configuration.debug) { e.printStackTrace() } - project.logger.error("==fastdex ${e.getMessage()}") - project.logger.error("==fastdex we will remove ${variantName.toLowerCase()} cache") project.logger.error("==fastdex delete ${classesDir}") project.logger.error("==fastdex delete ${transformsDir}") project.logger.error("==fastdex delete ${apkLocationDir}") + project.logger.error("==fastdex ${e.getMessage()}") + project.logger.error("==fastdex we will remove ${variantName.toLowerCase()} cache") } } if (hasDexCache && metaInfo != null) { project.logger.error("==fastdex discover dex cache for ${variantName.toLowerCase()}") + + try { + project.tasks.getByName("transformDexArchiveWithExternalLibsDexMergerFor${variantName}").enabled = false + } catch (Throwable e) { + + } } else { metaInfo = new MetaInfo() @@ -205,11 +229,19 @@ public class FastdexVariant { fastdexInstantRun.onFastdexPrepare() } + def getLibraryDependencies() { + if (libraryDependencies == null) { + libraryDependencies = LibDependency.resolveProjectDependency(project,androidVariant) + } + + return libraryDependencies + } + /** * 获取原始manifest文件的package节点的值 * @return */ - public String getOriginPackageName() { + def getOriginPackageName() { return androidVariant.getVariantData().getVariantConfiguration().getOriginalApplicationId() } @@ -217,7 +249,7 @@ public class FastdexVariant { * 获取合并以后的manifest文件的package节点的值 * @return */ - public String getMergedPackageName() { + def getMergedPackageName() { return androidVariant.getVariantData().getVariantConfiguration().getApplicationId() } @@ -225,7 +257,7 @@ public class FastdexVariant { * 当dex生成以后 * @param nornalBuild */ - public void onDexGenerateSuccess(boolean nornalBuild,boolean dexMerge) { + def onDexGenerateSuccess(boolean nornalBuild,boolean dexMerge) { if (nornalBuild) { saveMetaInfo() copyRTxt() @@ -261,7 +293,7 @@ public class FastdexVariant { def copyMetaInfo2Assets() { File metaInfoFile = FastdexUtils.getMetaInfoFile(project,variantName) if (FileUtils.isLegalFile(metaInfoFile)) { - File assetsPath = androidVariant.getVariantData().getScope().getMergeAssetsOutputDir() + File assetsPath = androidVariant.getMergeAssets().outputDir File dest = new File(assetsPath,metaInfoFile.getName()) project.logger.error("==fastdex copy meta info: \nfrom: " + metaInfoFile + "\ninto: " + dest) @@ -281,11 +313,7 @@ public class FastdexVariant { * 保存资源映射文件 */ def copyRTxt() { - File rtxtFile = new File(androidVariant.getVariantData().getScope().getSymbolLocation(),"R.txt") - if (!FileUtils.isLegalFile(rtxtFile)) { - rtxtFile = new File(project.buildDir,"${File.separator}intermediates${File.separator}symbols${File.separator}${androidVariant.dirName}${File.separator}R.txt") - } - FileUtils.copyFileUsingStream(rtxtFile,FastdexUtils.getResourceMappingFile(project,variantName)) + FileUtils.copyFileUsingStream(textSymbolOutputFile,FastdexUtils.getResourceMappingFile(project,variantName)) } /** diff --git a/gradle.properties b/gradle.properties index fbe66c27..4f61f1f8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -20,7 +20,7 @@ org.gradle.daemon=true groupId=com.github.typ0520 -version=0.7.4 +version=0.8.0 ANDROID_BUILD_MIN_SDK_VERSION=14 ANDROID_BUILD_TARGET_SDK_VERSION=22 diff --git a/sample/app/build.gradle b/sample/app/build.gradle index eaf9d455..94f626d4 100644 --- a/sample/app/build.gradle +++ b/sample/app/build.gradle @@ -1,6 +1,6 @@ apply plugin: 'com.android.application' apply plugin: 'me.tatarka.retrolambda' -apply plugin: 'com.jakewharton.butterknife' +//apply plugin: 'com.jakewharton.butterknife' //apply plugin: 'com.neenbedankt.android-apt' apply plugin: 'fastdex.app' @@ -24,7 +24,7 @@ fastdex { android { compileSdkVersion Integer.parseInt(project.ANDROID_BUILD_SDK_VERSION) - buildToolsVersion project.ANDROID_BUILD_TOOLS_VERSION + //buildToolsVersion project.ANDROID_BUILD_TOOLS_VERSION packagingOptions { exclude 'META-INF/DEPENDENCIES' @@ -43,7 +43,7 @@ android { applicationId "com.github.typ0520.fastdex.sample" versionCode 1 versionName "1.0.0" - multiDexEnabled true + multiDexEnabled false } signingConfigs { @@ -67,13 +67,6 @@ android { shrinkResources false signingConfig signingConfigs.config } - - //fastdex 会忽略开启混淆的buildType - product{ - minifyEnabled true - shrinkResources false - signingConfig signingConfigs.config - } } // productFlavors { @@ -84,18 +77,15 @@ android { // } // } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } +// compileOptions { +// sourceCompatibility JavaVersion.VERSION_1_8 +// targetCompatibility JavaVersion.VERSION_1_8 +// } } -println "##fastdex.injected.invoked.from.ide : ${project.hasProperty("fastdex.injected.invoked.from.ide")}" -println "##android.dexOptions.preDexLibraries: ${android.dexOptions.preDexLibraries}" - -retrolambda { - javaVersion JavaVersion.VERSION_1_7 -} +//retrolambda { +// javaVersion JavaVersion.VERSION_1_7 +//} dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) @@ -117,22 +107,22 @@ dependencies { compile 'org.xutils:xutils:3.3.36' compile 'de.hdodenhof:circleimageview:2.0.0' compile 'de.hdodenhof:circleimageview:2.0.0' - - compile 'com.squareup.retrofit:retrofit:1.9.0' - compile 'info.hoang8f:android-segmented:1.0.6' - compile 'com.squareup.okio:okio:1.0.1' - compile 'com.zhy:okhttputils:2.4.1' - compile 'joda-time:joda-time:2.6' - compile 'com.squareup.retrofit:retrofit:1.8.0' - compile 'com.squareup.okhttp:okhttp:2.2.0' - compile 'com.squareup.okhttp:okhttp-urlconnection:2.2.0' - - compile "org.greenrobot:eventbus:3.0.0" - compile "org.glassfish:javax.annotation:10.0-b28" - compile 'com.android.volley:volley:1.0.0' - compile 'com.dialonce:dialonce-android:2.3.1' - compile 'com.facebook.fresco:fresco:1.1.0' - compile 'com.google.guava:guava:18.0' +// +// compile 'com.squareup.retrofit:retrofit:1.9.0' +// compile 'info.hoang8f:android-segmented:1.0.6' +// compile 'com.squareup.okio:okio:1.0.1' +// compile 'com.zhy:okhttputils:2.4.1' +// compile 'joda-time:joda-time:2.6' +// compile 'com.squareup.retrofit:retrofit:1.8.0' +// compile 'com.squareup.okhttp:okhttp:2.2.0' +// compile 'com.squareup.okhttp:okhttp-urlconnection:2.2.0' +// +// compile "org.greenrobot:eventbus:3.0.0" +// compile "org.glassfish:javax.annotation:10.0-b28" +// compile 'com.android.volley:volley:1.0.0' +// compile 'com.dialonce:dialonce-android:2.3.1' +// compile 'com.facebook.fresco:fresco:1.1.0' +// compile 'com.google.guava:guava:18.0' // debugCompile 'com.squareup.leakcanary:leakcanary-android:1.4-beta2' // releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta2' @@ -144,7 +134,8 @@ project.afterEvaluate { def variantName = variant.name.capitalize() def variantOutput = variant.outputs.first() - if ("Debug".equals(variantName)) { + if (variantName.contains("Debug")) { + } } diff --git a/sample/app/src/main/java/fastdex/sample/MainActivity.java b/sample/app/src/main/java/fastdex/sample/MainActivity.java index 966f5e0f..3d0497e3 100644 --- a/sample/app/src/main/java/fastdex/sample/MainActivity.java +++ b/sample/app/src/main/java/fastdex/sample/MainActivity.java @@ -95,7 +95,7 @@ public void onClick(View view) { // sb.append("\n"); sb.append(getResources().getString(commonstr)); sb.append("\n"); - sb.append("1"); + sb.append("11"); Log.d(TAG,"sb: \n" + sb.toString()); Toast.makeText(this, sb.toString(),Toast.LENGTH_LONG).show(); diff --git a/sample/app/src/main/res/layout/activity_main.xml b/sample/app/src/main/res/layout/activity_main.xml index a5830f4e..5f502eae 100644 --- a/sample/app/src/main/res/layout/activity_main.xml +++ b/sample/app/src/main/res/layout/activity_main.xml @@ -15,6 +15,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" layout="@layout/my_view" /> + +