// Adapted from https://raw.githubusercontent.com/facebook/react-native/master/local-cli/generator-android/templates/src/app/react.gradle import java.nio.file.Paths; def config = project.hasProperty("react") ? project.react : []; def bundleAssetName = config.bundleAssetName ?: "index.android.bundle" def elvisFile(thing) { return thing ? file(thing) : null; } void runBefore(String dependentTaskName, Task task) { Task dependentTask = tasks.findByPath(dependentTaskName); if (dependentTask != null) { dependentTask.dependsOn task } } gradle.projectsEvaluated { def buildTypes = android.buildTypes.collect { type -> type.name } android.buildTypes.each { // to prevent incorrect long value restoration from strings.xml we need to wrap it with double quotes // https://github.com/Microsoft/cordova-plugin-code-push/issues/264 it.resValue 'string', "CODE_PUSH_APK_BUILD_TIME", String.format("\"%d\"", System.currentTimeMillis()) } def productFlavors = android.productFlavors.collect { flavor -> flavor.name } if (!productFlavors) productFlavors.add('') def nodeModulesPath; if (config.root) { nodeModulesPath = Paths.get(config.root, "/node_modules"); } else if (project.hasProperty('nodeModulesPath')) { nodeModulesPath = project.nodeModulesPath } else { nodeModulesPath = "../../node_modules"; } productFlavors.each { productFlavorName -> buildTypes.each { buildTypeName -> def targetName = "${productFlavorName.capitalize()}${buildTypeName.capitalize()}" def targetPath = productFlavorName ? "${productFlavorName}/${buildTypeName}" : "${buildTypeName}" def jsBundleDirConfigName = "jsBundleDir${targetName}" def jsBundleDir = elvisFile(config."$jsBundleDirConfigName") ?: file("$buildDir/intermediates/assets/${targetPath}") def resourcesDirConfigName = "resourcesDir${targetName}" def resourcesDir = elvisFile(config."${resourcesDirConfigName}") ?: file("$buildDir/intermediates/res/merged/${targetPath}") // In case version of 'Android Plugin for Gradle'' is lower than 1.3.0 // '$buildDir' has slightly different structure - 'merged' folder // does not exists so '${targetPath}' folder contains directly in 'res' folder. if (!resourcesDir.exists() && file("$buildDir/intermediates/res/${targetPath}").exists()) { resourcesDir = file("$buildDir/intermediates/res/${targetPath}") } def jsBundleFile = file("$jsBundleDir/$bundleAssetName") def resourcesMapTempFileName = "CodePushResourcesMap-" + java.util.UUID.randomUUID().toString().substring(0,8) + ".json" // Additional node commandline arguments def nodeExecutableAndArgs = config.nodeExecutableAndArgs ?: ["node"] // Make this task run right before the bundle task def recordFilesBeforeBundleCommand = tasks.create( name: "recordFilesBeforeBundleCommand${targetName}", type: Exec) { commandLine (*nodeExecutableAndArgs, "${nodeModulesPath}/react-native-code-push/scripts/recordFilesBeforeBundleCommand.js", resourcesDir, resourcesMapTempFileName) } recordFilesBeforeBundleCommand.dependsOn("merge${targetName}Resources") recordFilesBeforeBundleCommand.dependsOn("merge${targetName}Assets") runBefore("bundle${targetName}JsAndAssets", recordFilesBeforeBundleCommand) // Make this task run right after the bundle task def generateBundledResourcesHash = tasks.create( name: "generateBundledResourcesHash${targetName}", type: Exec) { commandLine (*nodeExecutableAndArgs, "${nodeModulesPath}/react-native-code-push/scripts/generateBundledResourcesHash.js", resourcesDir, "$jsBundleDir/$bundleAssetName", jsBundleDir, resourcesMapTempFileName) } // We need to generate and record the resources map, but we use it to generate the bundle hash generateBundledResourcesHash.dependsOn("recordFilesBeforeBundleCommand${targetName}") generateBundledResourcesHash.dependsOn("bundle${targetName}JsAndAssets") runBefore("processArmeabi-v7a${targetName}Resources", generateBundledResourcesHash) runBefore("processX86${targetName}Resources", generateBundledResourcesHash) runBefore("processUniversal${targetName}Resources", generateBundledResourcesHash) runBefore("process${targetName}Resources", generateBundledResourcesHash) } } }