|  | import java.nio.file.Path | 
|  | import java.nio.file.Paths | 
|  |  | 
|  | import com.android.builder.model.AndroidProject | 
|  | import org.apache.tools.ant.taskdefs.condition.Os | 
|  | import org.gradle.api.DefaultTask | 
|  | import org.gradle.api.GradleException | 
|  | import org.gradle.api.Project | 
|  | import org.gradle.api.Plugin | 
|  | import org.gradle.api.Task | 
|  | import org.gradle.api.file.CopySpec | 
|  | import org.gradle.api.file.FileCollection | 
|  | import org.gradle.api.tasks.Copy | 
|  | import org.gradle.api.tasks.InputFiles | 
|  | import org.gradle.api.tasks.OutputDirectory | 
|  | import org.gradle.api.tasks.TaskAction | 
|  | import org.gradle.api.tasks.bundling.Jar | 
|  |  | 
|  | buildscript { | 
|  | repositories { | 
|  | jcenter() | 
|  | maven { | 
|  | url 'https://dl.google.com/dl/android/maven2' | 
|  | } | 
|  | } | 
|  | dependencies { | 
|  | classpath 'com.android.tools.build:gradle:3.2.1' | 
|  | } | 
|  | } | 
|  |  | 
|  | apply plugin: FlutterPlugin | 
|  |  | 
|  | class FlutterPlugin implements Plugin<Project> { | 
|  | private File flutterRoot | 
|  | private File flutterExecutable | 
|  | private String localEngine | 
|  | private String localEngineSrcPath | 
|  | private Properties localProperties | 
|  |  | 
|  | private File flutterJar | 
|  | private File flutterX86Jar | 
|  | private File debugFlutterJar | 
|  | private File profileFlutterJar | 
|  | private File releaseFlutterJar | 
|  | private File dynamicProfileFlutterJar | 
|  | private File dynamicReleaseFlutterJar | 
|  |  | 
|  | // The name prefix for flutter builds.  This is used to identify gradle tasks | 
|  | // where we expect the flutter tool to provide any error output, and skip the | 
|  | // standard Gradle error output in the FlutterEventLogger. If you change this, | 
|  | // be sure to change any instances of this string in symbols in the code below | 
|  | // to match. | 
|  | static final String flutterBuildPrefix = "flutterBuild" | 
|  |  | 
|  | private Properties readPropertiesIfExist(File propertiesFile) { | 
|  | Properties result = new Properties() | 
|  | if (propertiesFile.exists()) { | 
|  | propertiesFile.withReader('UTF-8') { reader -> result.load(reader) } | 
|  | } | 
|  | return result | 
|  | } | 
|  |  | 
|  | private String resolveProperty(Project project, String name, String defaultValue) { | 
|  | if (localProperties == null) { | 
|  | localProperties = readPropertiesIfExist(new File(project.projectDir.parentFile, "local.properties")) | 
|  | } | 
|  | String result | 
|  | if (project.hasProperty(name)) { | 
|  | result = project.property(name) | 
|  | } | 
|  | if (result == null) { | 
|  | result = localProperties.getProperty(name) | 
|  | } | 
|  | if (result == null) { | 
|  | result = defaultValue | 
|  | } | 
|  | return result | 
|  | } | 
|  |  | 
|  | @Override | 
|  | void apply(Project project) { | 
|  | // Add custom build types | 
|  | project.android.buildTypes { | 
|  | profile { | 
|  | initWith debug | 
|  | if (it.hasProperty('matchingFallbacks')) { | 
|  | matchingFallbacks = ['debug', 'release'] | 
|  | } | 
|  | } | 
|  | dynamicProfile { | 
|  | initWith debug | 
|  | if (it.hasProperty('matchingFallbacks')) { | 
|  | matchingFallbacks = ['debug', 'release'] | 
|  | } | 
|  | } | 
|  | dynamicRelease { | 
|  | initWith debug | 
|  | if (it.hasProperty('matchingFallbacks')) { | 
|  | matchingFallbacks = ['debug', 'release'] | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | String flutterRootPath = resolveProperty(project, "flutter.sdk", System.env.FLUTTER_ROOT) | 
|  | if (flutterRootPath == null) { | 
|  | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file or with a FLUTTER_ROOT environment variable.") | 
|  | } | 
|  | flutterRoot = project.file(flutterRootPath) | 
|  | if (!flutterRoot.isDirectory()) { | 
|  | throw new GradleException("flutter.sdk must point to the Flutter SDK directory") | 
|  | } | 
|  |  | 
|  | String flutterExecutableName = Os.isFamily(Os.FAMILY_WINDOWS) ? "flutter.bat" : "flutter" | 
|  | flutterExecutable = Paths.get(flutterRoot.absolutePath, "bin", flutterExecutableName).toFile(); | 
|  |  | 
|  | if (project.hasProperty('localEngineOut')) { | 
|  | String engineOutPath = project.property('localEngineOut') | 
|  | File engineOut = project.file(engineOutPath) | 
|  | if (!engineOut.isDirectory()) { | 
|  | throw new GradleException('localEngineOut must point to a local engine build') | 
|  | } | 
|  | flutterJar = Paths.get(engineOut.absolutePath, "flutter.jar").toFile() | 
|  | if (!flutterJar.isFile()) { | 
|  | throw new GradleException('Local engine build does not contain flutter.jar') | 
|  | } | 
|  |  | 
|  | localEngine = engineOut.name | 
|  | localEngineSrcPath = engineOut.parentFile.parent | 
|  |  | 
|  | project.dependencies { | 
|  | if (project.getConfigurations().findByName("api")) { | 
|  | api project.files(flutterJar) | 
|  | } else { | 
|  | compile project.files(flutterJar) | 
|  | } | 
|  | } | 
|  | } else { | 
|  | Path baseEnginePath = Paths.get(flutterRoot.absolutePath, "bin", "cache", "artifacts", "engine") | 
|  | String targetArch = 'arm' | 
|  | if (project.hasProperty('target-platform') && | 
|  | project.property('target-platform') == 'android-arm64') { | 
|  | targetArch = 'arm64' | 
|  | } | 
|  | debugFlutterJar = baseEnginePath.resolve("android-${targetArch}").resolve("flutter.jar").toFile() | 
|  | profileFlutterJar = baseEnginePath.resolve("android-${targetArch}-profile").resolve("flutter.jar").toFile() | 
|  | releaseFlutterJar = baseEnginePath.resolve("android-${targetArch}-release").resolve("flutter.jar").toFile() | 
|  | dynamicProfileFlutterJar = baseEnginePath.resolve("android-${targetArch}-dynamic-profile").resolve("flutter.jar").toFile() | 
|  | dynamicReleaseFlutterJar = baseEnginePath.resolve("android-${targetArch}-dynamic-release").resolve("flutter.jar").toFile() | 
|  | if (!debugFlutterJar.isFile()) { | 
|  | project.exec { | 
|  | executable flutterExecutable.absolutePath | 
|  | args "--suppress-analytics" | 
|  | args "precache" | 
|  | } | 
|  | if (!debugFlutterJar.isFile()) { | 
|  | throw new GradleException("Unable to find flutter.jar in SDK: ${debugFlutterJar}") | 
|  | } | 
|  | } | 
|  |  | 
|  | // Add x86/x86_64 native library. Debug mode only, for now. | 
|  | flutterX86Jar = project.file("${project.buildDir}/${AndroidProject.FD_INTERMEDIATES}/flutter/flutter-x86.jar") | 
|  | Task flutterX86JarTask = project.tasks.create("${flutterBuildPrefix}X86Jar", Jar) { | 
|  | destinationDir flutterX86Jar.parentFile | 
|  | archiveName flutterX86Jar.name | 
|  | from("${flutterRoot}/bin/cache/artifacts/engine/android-x86/libflutter.so") { | 
|  | into "lib/x86" | 
|  | } | 
|  | from("${flutterRoot}/bin/cache/artifacts/engine/android-x64/libflutter.so") { | 
|  | into "lib/x86_64" | 
|  | } | 
|  | } | 
|  | // Add flutter.jar dependencies to all <buildType>Api configurations, including custom ones | 
|  | // added after applying the Flutter plugin. | 
|  | project.android.buildTypes.each { addFlutterJarApiDependency(project, it, flutterX86JarTask) } | 
|  | project.android.buildTypes.whenObjectAdded { addFlutterJarApiDependency(project, it, flutterX86JarTask) } | 
|  | } | 
|  |  | 
|  | project.extensions.create("flutter", FlutterExtension) | 
|  | project.afterEvaluate this.&addFlutterTask | 
|  |  | 
|  | File pluginsFile = new File(project.projectDir.parentFile.parentFile, '.flutter-plugins') | 
|  | Properties plugins = readPropertiesIfExist(pluginsFile) | 
|  |  | 
|  | plugins.each { name, _ -> | 
|  | def pluginProject = project.rootProject.findProject(":$name") | 
|  | if (pluginProject != null) { | 
|  | project.dependencies { | 
|  | if (project.getConfigurations().findByName("implementation")) { | 
|  | implementation pluginProject | 
|  | } else { | 
|  | compile pluginProject | 
|  | } | 
|  | } | 
|  | pluginProject.afterEvaluate { | 
|  | pluginProject.android.buildTypes { | 
|  | profile { | 
|  | initWith debug | 
|  | } | 
|  | } | 
|  | } | 
|  | pluginProject.afterEvaluate this.&addFlutterJarCompileOnlyDependency | 
|  | } else { | 
|  | project.logger.error("Plugin project :$name not found. Please update settings.gradle.") | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | private void addFlutterJarCompileOnlyDependency(Project project) { | 
|  | if (project.state.failure) { | 
|  | return | 
|  | } | 
|  | project.dependencies { | 
|  | if (flutterJar != null) { | 
|  | if (project.getConfigurations().findByName("compileOnly")) { | 
|  | compileOnly project.files(flutterJar) | 
|  | } else { | 
|  | provided project.files(flutterJar) | 
|  | } | 
|  | } else { | 
|  | if (project.getConfigurations().findByName("debugCompileOnly")) { | 
|  | debugCompileOnly project.files(debugFlutterJar) | 
|  | profileCompileOnly project.files(profileFlutterJar) | 
|  | releaseCompileOnly project.files(releaseFlutterJar) | 
|  | } else { | 
|  | debugProvided project.files(debugFlutterJar) | 
|  | profileProvided project.files(profileFlutterJar) | 
|  | releaseProvided project.files(releaseFlutterJar) | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Adds suitable flutter.jar api dependencies to the specified buildType. | 
|  | * | 
|  | * Note: The BuildType DSL type is not public, and is therefore omitted from the signature. | 
|  | */ | 
|  | private void addFlutterJarApiDependency(Project project, buildType, Task flutterX86JarTask) { | 
|  | project.dependencies { | 
|  | String configuration; | 
|  | if (project.getConfigurations().findByName("api")) { | 
|  | configuration = buildType.name + "Api"; | 
|  | } else { | 
|  | configuration = buildType.name + "Compile"; | 
|  | } | 
|  | add(configuration, project.files { | 
|  | String buildMode = buildModeFor(buildType) | 
|  | if (buildMode == "debug") { | 
|  | [flutterX86JarTask, debugFlutterJar] | 
|  | } else if (buildMode == "profile") { | 
|  | profileFlutterJar | 
|  | } else if (buildMode == "dynamicProfile") { | 
|  | dynamicProfileFlutterJar | 
|  | } else if (buildMode == "dynamicRelease") { | 
|  | dynamicReleaseFlutterJar | 
|  | } else { | 
|  | releaseFlutterJar | 
|  | } | 
|  | }) | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns a Flutter build mode suitable for the specified Android buildType. | 
|  | * | 
|  | * Note: The BuildType DSL type is not public, and is therefore omitted from the signature. | 
|  | * | 
|  | * @return "debug", "profile", "dynamicProfile", "dynamicRelease", or "release" (fall-back). | 
|  | */ | 
|  | private static String buildModeFor(buildType) { | 
|  | if (buildType.name == "profile") { | 
|  | return "profile" | 
|  | } else if (buildType.name == "dynamicProfile") { | 
|  | return "dynamicProfile" | 
|  | } else if (buildType.name == "dynamicRelease") { | 
|  | return "dynamicRelease" | 
|  | } else if (buildType.debuggable) { | 
|  | return "debug" | 
|  | } | 
|  | return "release" | 
|  | } | 
|  |  | 
|  | private void addFlutterTask(Project project) { | 
|  | if (project.state.failure) { | 
|  | return | 
|  | } | 
|  | if (project.flutter.source == null) { | 
|  | throw new GradleException("Must provide Flutter source directory") | 
|  | } | 
|  |  | 
|  | String target = project.flutter.target | 
|  | if (target == null) { | 
|  | target = 'lib/main.dart' | 
|  | } | 
|  | if (project.hasProperty('target')) { | 
|  | target = project.property('target') | 
|  | } | 
|  |  | 
|  | Boolean verboseValue = null | 
|  | if (project.hasProperty('verbose')) { | 
|  | verboseValue = project.property('verbose').toBoolean() | 
|  | } | 
|  | String[] fileSystemRootsValue = null | 
|  | if (project.hasProperty('filesystem-roots')) { | 
|  | fileSystemRootsValue = project.property('filesystem-roots').split('\\|') | 
|  | } | 
|  | String fileSystemSchemeValue = null | 
|  | if (project.hasProperty('filesystem-scheme')) { | 
|  | fileSystemSchemeValue = project.property('filesystem-scheme') | 
|  | } | 
|  | Boolean trackWidgetCreationValue = false | 
|  | if (project.hasProperty('track-widget-creation')) { | 
|  | trackWidgetCreationValue = project.property('track-widget-creation').toBoolean() | 
|  | } | 
|  | String compilationTraceFilePathValue = null | 
|  | if (project.hasProperty('precompile')) { | 
|  | compilationTraceFilePathValue = project.property('precompile') | 
|  | } | 
|  | Boolean buildHotUpdateValue = false | 
|  | if (project.hasProperty('hotupdate')) { | 
|  | buildHotUpdateValue = project.property('hotupdate').toBoolean() | 
|  | } | 
|  | String extraFrontEndOptionsValue = null | 
|  | if (project.hasProperty('extra-front-end-options')) { | 
|  | extraFrontEndOptionsValue = project.property('extra-front-end-options') | 
|  | } | 
|  | String extraGenSnapshotOptionsValue = null | 
|  | if (project.hasProperty('extra-gen-snapshot-options')) { | 
|  | extraGenSnapshotOptionsValue = project.property('extra-gen-snapshot-options') | 
|  | } | 
|  | Boolean buildSharedLibraryValue = false | 
|  | if (project.hasProperty('build-shared-library')) { | 
|  | buildSharedLibraryValue = project.property('build-shared-library').toBoolean() | 
|  | } | 
|  | String targetPlatformValue = null | 
|  | if (project.hasProperty('target-platform')) { | 
|  | targetPlatformValue = project.property('target-platform') | 
|  | } | 
|  |  | 
|  | def addFlutterDeps = { variant -> | 
|  | String flutterBuildMode = buildModeFor(variant.buildType) | 
|  | if (flutterBuildMode == 'debug' && project.tasks.findByName('${flutterBuildPrefix}X86Jar')) { | 
|  | Task task = project.tasks.findByName("compile${variant.name.capitalize()}JavaWithJavac") | 
|  | if (task) { | 
|  | task.dependsOn project.flutterBuildX86Jar | 
|  | } | 
|  | task = project.tasks.findByName("compile${variant.name.capitalize()}Kotlin") | 
|  | if (task) { | 
|  | task.dependsOn project.flutterBuildX86Jar | 
|  | } | 
|  | } | 
|  |  | 
|  | FlutterTask flutterTask = project.tasks.create(name: "${flutterBuildPrefix}${variant.name.capitalize()}", type: FlutterTask) { | 
|  | flutterRoot this.flutterRoot | 
|  | flutterExecutable this.flutterExecutable | 
|  | buildMode flutterBuildMode | 
|  | localEngine this.localEngine | 
|  | localEngineSrcPath this.localEngineSrcPath | 
|  | targetPath target | 
|  | verbose verboseValue | 
|  | fileSystemRoots fileSystemRootsValue | 
|  | fileSystemScheme fileSystemSchemeValue | 
|  | trackWidgetCreation trackWidgetCreationValue | 
|  | compilationTraceFilePath compilationTraceFilePathValue | 
|  | buildHotUpdate buildHotUpdateValue | 
|  | buildSharedLibrary buildSharedLibraryValue | 
|  | targetPlatform targetPlatformValue | 
|  | sourceDir project.file(project.flutter.source) | 
|  | intermediateDir project.file("${project.buildDir}/${AndroidProject.FD_INTERMEDIATES}/flutter/${variant.name}") | 
|  | extraFrontEndOptions extraFrontEndOptionsValue | 
|  | extraGenSnapshotOptions extraGenSnapshotOptionsValue | 
|  | } | 
|  |  | 
|  | // We know that the flutter app is a subproject in another Android app when these tasks exist. | 
|  | Task packageAssets = project.tasks.findByPath(":flutter:package${variant.name.capitalize()}Assets") | 
|  | Task cleanPackageAssets = project.tasks.findByPath(":flutter:cleanPackage${variant.name.capitalize()}Assets") | 
|  | Task copyFlutterAssetsTask = project.tasks.create(name: "copyFlutterAssets${variant.name.capitalize()}", type: Copy) { | 
|  | dependsOn flutterTask | 
|  | dependsOn packageAssets ? packageAssets : variant.mergeAssets | 
|  | dependsOn cleanPackageAssets ? cleanPackageAssets : "clean${variant.mergeAssets.name.capitalize()}" | 
|  | into packageAssets ? packageAssets.outputDir : variant.mergeAssets.outputDir | 
|  | with flutterTask.assets | 
|  | } | 
|  | if (packageAssets) { | 
|  | // Only include configurations that exist in parent project. | 
|  | Task mergeAssets = project.tasks.findByPath(":app:merge${variant.name.capitalize()}Assets") | 
|  | if (mergeAssets) { | 
|  | mergeAssets.dependsOn(copyFlutterAssetsTask) | 
|  | } | 
|  | } else { | 
|  | variant.outputs[0].processResources.dependsOn(copyFlutterAssetsTask) | 
|  | } | 
|  | } | 
|  | if (project.android.hasProperty("applicationVariants")) { | 
|  | project.android.applicationVariants.all addFlutterDeps | 
|  | } else { | 
|  | project.android.libraryVariants.all addFlutterDeps | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | class FlutterExtension { | 
|  | String source | 
|  | String target | 
|  | } | 
|  |  | 
|  | abstract class BaseFlutterTask extends DefaultTask { | 
|  | File flutterRoot | 
|  | File flutterExecutable | 
|  | String buildMode | 
|  | String localEngine | 
|  | String localEngineSrcPath | 
|  | @Input | 
|  | String targetPath | 
|  | @Optional @Input | 
|  | Boolean verbose | 
|  | @Optional @Input | 
|  | String[] fileSystemRoots | 
|  | @Optional @Input | 
|  | String fileSystemScheme | 
|  | @Input | 
|  | Boolean trackWidgetCreation | 
|  | @Optional @Input | 
|  | String compilationTraceFilePath | 
|  | @Optional @Input | 
|  | Boolean buildHotUpdate | 
|  | @Optional @Input | 
|  | Boolean buildSharedLibrary | 
|  | @Optional @Input | 
|  | String targetPlatform | 
|  | File sourceDir | 
|  | File intermediateDir | 
|  | @Optional @Input | 
|  | String extraFrontEndOptions | 
|  | @Optional @Input | 
|  | String extraGenSnapshotOptions | 
|  |  | 
|  | @OutputFiles | 
|  | FileCollection getDependenciesFiles() { | 
|  | FileCollection depfiles = project.files() | 
|  |  | 
|  | // Include the kernel compiler depfile, since kernel compile is the | 
|  | // first stage of AOT build in this mode, and it includes all the Dart | 
|  | // sources. | 
|  | depfiles += project.files("${intermediateDir}/kernel_compile.d") | 
|  |  | 
|  | // Include Core JIT kernel compiler depfile, since kernel compile is | 
|  | // the first stage of JIT builds in this mode, and it includes all the | 
|  | // Dart sources. | 
|  | depfiles += project.files("${intermediateDir}/snapshot_blob.bin.d") | 
|  | return depfiles | 
|  | } | 
|  |  | 
|  | void buildBundle() { | 
|  | if (!sourceDir.isDirectory()) { | 
|  | throw new GradleException("Invalid Flutter source directory: ${sourceDir}") | 
|  | } | 
|  |  | 
|  | intermediateDir.mkdirs() | 
|  |  | 
|  | if (buildMode == "profile" || buildMode == "release") { | 
|  | project.exec { | 
|  | executable flutterExecutable.absolutePath | 
|  | workingDir sourceDir | 
|  | if (localEngine != null) { | 
|  | args "--local-engine", localEngine | 
|  | args "--local-engine-src-path", localEngineSrcPath | 
|  | } | 
|  | args "build", "aot" | 
|  | args "--suppress-analytics" | 
|  | args "--quiet" | 
|  | args "--target", targetPath | 
|  | args "--target-platform", "android-arm" | 
|  | args "--output-dir", "${intermediateDir}" | 
|  | if (trackWidgetCreation) { | 
|  | args "--track-widget-creation" | 
|  | } | 
|  | if (extraFrontEndOptions != null) { | 
|  | args "--extra-front-end-options", "${extraFrontEndOptions}" | 
|  | } | 
|  | if (extraGenSnapshotOptions != null) { | 
|  | args "--extra-gen-snapshot-options", "${extraGenSnapshotOptions}" | 
|  | } | 
|  | if (buildSharedLibrary) { | 
|  | args "--build-shared-library" | 
|  | } | 
|  | if (targetPlatform != null) { | 
|  | args "--target-platform", "${targetPlatform}" | 
|  | } | 
|  | args "--${buildMode}" | 
|  | } | 
|  | } | 
|  |  | 
|  | project.exec { | 
|  | executable flutterExecutable.absolutePath | 
|  | workingDir sourceDir | 
|  | if (localEngine != null) { | 
|  | args "--local-engine", localEngine | 
|  | args "--local-engine-src-path", localEngineSrcPath | 
|  | } | 
|  | args "build", "bundle" | 
|  | args "--suppress-analytics" | 
|  | args "--target", targetPath | 
|  | if (verbose) { | 
|  | args "--verbose" | 
|  | } | 
|  | if (fileSystemRoots != null) { | 
|  | for (root in fileSystemRoots) { | 
|  | args "--filesystem-root", root | 
|  | } | 
|  | } | 
|  | if (fileSystemScheme != null) { | 
|  | args "--filesystem-scheme", fileSystemScheme | 
|  | } | 
|  | if (trackWidgetCreation) { | 
|  | args "--track-widget-creation" | 
|  | } | 
|  | if (compilationTraceFilePath != null) { | 
|  | args "--precompile", compilationTraceFilePath | 
|  | } | 
|  | if (buildHotUpdate) { | 
|  | args "--hotupdate" | 
|  | } | 
|  | if (extraFrontEndOptions != null) { | 
|  | args "--extra-front-end-options", "${extraFrontEndOptions}" | 
|  | } | 
|  | if (extraGenSnapshotOptions != null) { | 
|  | args "--extra-gen-snapshot-options", "${extraGenSnapshotOptions}" | 
|  | } | 
|  | if (targetPlatform != null) { | 
|  | args "--target-platform", "${targetPlatform}" | 
|  | } | 
|  | if (buildMode == "release" || buildMode == "profile") { | 
|  | args "--precompiled" | 
|  | } else { | 
|  | args "--depfile", "${intermediateDir}/snapshot_blob.bin.d" | 
|  | } | 
|  | args "--asset-dir", "${intermediateDir}/flutter_assets" | 
|  | if (buildMode == "debug") { | 
|  | args "--debug" | 
|  | } | 
|  | if (buildMode == "profile" || buildMode == "dynamicProfile") { | 
|  | args "--profile" | 
|  | } | 
|  | if (buildMode == "release" || buildMode == "dynamicRelease") { | 
|  | args "--release" | 
|  | } | 
|  | if (buildMode == "dynamicProfile" || buildMode == "dynamicRelease") { | 
|  | args "--dynamic" | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | class FlutterTask extends BaseFlutterTask { | 
|  | @OutputDirectory | 
|  | File getOutputDirectory() { | 
|  | return intermediateDir | 
|  | } | 
|  |  | 
|  | CopySpec getAssets() { | 
|  | return project.copySpec { | 
|  | from "${intermediateDir}" | 
|  |  | 
|  | include "flutter_assets/**" // the working dir and its files | 
|  |  | 
|  | if (buildMode == 'release' || buildMode == 'profile') { | 
|  | if (buildSharedLibrary) { | 
|  | include "app.so" | 
|  | } else { | 
|  | include "vm_snapshot_data" | 
|  | include "vm_snapshot_instr" | 
|  | include "isolate_snapshot_data" | 
|  | include "isolate_snapshot_instr" | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | FileCollection readDependencies(File dependenciesFile) { | 
|  | if (dependenciesFile.exists()) { | 
|  | try { | 
|  | // Dependencies file has Makefile syntax: | 
|  | //   <target> <files>: <source> <files> <separated> <by> <non-escaped space> | 
|  | String depText = dependenciesFile.text | 
|  | // So we split list of files by non-escaped(by backslash) space, | 
|  | def matcher = depText.split(': ')[1] =~ /(\\ |[^\s])+/ | 
|  | // then we replace all escaped spaces with regular spaces | 
|  | def depList = matcher.collect{it[0].replaceAll("\\\\ ", " ")} | 
|  | return project.files(depList) | 
|  | } catch (Exception e) { | 
|  | logger.error("Error reading dependency file ${dependenciesFile}: ${e}") | 
|  | } | 
|  | } | 
|  | return project.files() | 
|  | } | 
|  |  | 
|  | @InputFiles | 
|  | FileCollection getSourceFiles() { | 
|  | FileCollection sources = project.files() | 
|  | for (File depfile in getDependenciesFiles()) { | 
|  | sources += readDependencies(depfile) | 
|  | } | 
|  | if (!sources.isEmpty()) { | 
|  | // We have a dependencies file. Add a dependency on gen_snapshot as well, since the | 
|  | // snapshots have to be rebuilt if it changes. | 
|  | sources += readDependencies(project.file("${intermediateDir}/gen_snapshot.d")) | 
|  | sources += readDependencies(project.file("${intermediateDir}/frontend_server.d")) | 
|  | if (localEngineSrcPath != null) { | 
|  | sources += project.files("$localEngineSrcPath/$localEngine") | 
|  | } | 
|  | // Finally, add a dependency on pubspec.yaml as well. | 
|  | return sources + project.files('pubspec.yaml') | 
|  | } | 
|  | // No dependencies file (or problems parsing it). Fall back to source files. | 
|  | return project.fileTree( | 
|  | dir: sourceDir, | 
|  | exclude: ['android', 'ios'], | 
|  | include: ['**/*.dart', 'pubspec.yaml'] | 
|  | ) | 
|  | } | 
|  |  | 
|  | @TaskAction | 
|  | void build() { | 
|  | buildBundle() | 
|  | } | 
|  | } | 
|  |  | 
|  | gradle.useLogger(new FlutterEventLogger()) | 
|  |  | 
|  | class FlutterEventLogger extends BuildAdapter implements TaskExecutionListener { | 
|  | String mostRecentTask = "" | 
|  |  | 
|  | void beforeExecute(Task task) { | 
|  | mostRecentTask = task.name | 
|  | } | 
|  |  | 
|  | void afterExecute(Task task, TaskState state) {} | 
|  |  | 
|  | void buildFinished(BuildResult result) { | 
|  | if (result.failure != null) { | 
|  | if (!(result.failure instanceof GradleException) || !mostRecentTask.startsWith(FlutterPlugin.flutterBuildPrefix)) { | 
|  | result.rethrowFailure() | 
|  | } | 
|  | } | 
|  | } | 
|  | } |