From 13c534368317fef895b0ed2d7b6116018f0d39aa Mon Sep 17 00:00:00 2001 From: Artem Egorov Date: Wed, 28 Feb 2018 14:38:12 +0300 Subject: [PATCH 1/4] AAPT2-compatible Android build process integration --- android/codepush.gradle | 91 +++++++++++++------------ scripts/generateBundledResourcesHash.js | 12 ++-- 2 files changed, 56 insertions(+), 47 deletions(-) diff --git a/android/codepush.gradle b/android/codepush.gradle index 2c4ae27d9..4e8ad4197 100644 --- a/android/codepush.gradle +++ b/android/codepush.gradle @@ -5,6 +5,7 @@ import java.nio.file.Paths; def config = project.hasProperty("react") ? project.react : []; def bundleAssetName = config.bundleAssetName ?: "index.android.bundle" +// because elvis operator def elvisFile(thing) { return thing ? file(thing) : null; } @@ -17,37 +18,47 @@ void runBefore(String dependentTaskName, Task 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"; - } + android.applicationVariants.all { variant -> + def nodeModulesPath; + if (config.root) { + nodeModulesPath = Paths.get(config.root, "/node_modules"); + } else if (project.hasProperty('nodeModulesPath')) { + nodeModulesPath = project.nodeModulesPath + } else { + nodeModulesPath = "../../node_modules"; + } + + def targetName = variant.name.capitalize() + def targetPath = variant.dirName - productFlavors.each { productFlavorName -> - buildTypes.each { buildTypeName -> - def targetName = "${productFlavorName.capitalize()}${buildTypeName.capitalize()}" - def targetPath = productFlavorName ? - "${productFlavorName}/${buildTypeName}" : - "${buildTypeName}" + def jsBundleDir; + def resourcesDir; + def jsBundleFile; + // Additional node commandline arguments + def nodeExecutableAndArgs = config.nodeExecutableAndArgs ?: ["node"] + def extraPackagerArgs = config.extraPackagerArgs ?: [] + + // Make this task run right after the bundle task + def generateBundledResourcesHash; + + if (variant.hasProperty("bundleJsAndAssets")) { + jsBundleDir = file("$buildDir/generated/assets/react/${targetPath}") + resourcesDir = file("$buildDir/generated/res/react/${targetPath}") + jsBundleFile = file("$jsBundleDir/$bundleAssetName") + + generateBundledResourcesHash = tasks.create( + name: "generateBundledResourcesHash${targetName}", + type: Exec) { + commandLine (*nodeExecutableAndArgs, "${nodeModulesPath}/react-native-code-push/scripts/generateBundledResourcesHash.js", resourcesDir, jsBundleFile, jsBundleDir) + } + } else { def jsBundleDirConfigName = "jsBundleDir${targetName}" - def jsBundleDir = elvisFile(config."$jsBundleDirConfigName") ?: + jsBundleDir = elvisFile(config."$jsBundleDirConfigName") ?: file("$buildDir/intermediates/assets/${targetPath}") def resourcesDirConfigName = "resourcesDir${targetName}" - def resourcesDir = elvisFile(config."${resourcesDirConfigName}") ?: + resourcesDir = elvisFile(config."${resourcesDirConfigName}") ?: file("$buildDir/intermediates/res/merged/${targetPath}") // In case version of 'Android Plugin for Gradle'' is lower than 1.3.0 @@ -56,13 +67,16 @@ gradle.projectsEvaluated { if (!resourcesDir.exists() && file("$buildDir/intermediates/res/${targetPath}").exists()) { resourcesDir = file("$buildDir/intermediates/res/${targetPath}") } - - def jsBundleFile = file("$jsBundleDir/$bundleAssetName") + + 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"] + generateBundledResourcesHash = tasks.create( + name: "generateBundledResourcesHash${targetName}", + type: Exec) { + commandLine (*nodeExecutableAndArgs, "${nodeModulesPath}/react-native-code-push/scripts/generateBundledResourcesHash.js", resourcesDir, jsBundleFile, jsBundleDir, resourcesMapTempFileName) + } // Make this task run right before the bundle task def recordFilesBeforeBundleCommand = tasks.create( @@ -75,21 +89,14 @@ gradle.projectsEvaluated { 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) } + + 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) } } diff --git a/scripts/generateBundledResourcesHash.js b/scripts/generateBundledResourcesHash.js index 876f8a729..4c1cf090a 100644 --- a/scripts/generateBundledResourcesHash.js +++ b/scripts/generateBundledResourcesHash.js @@ -27,12 +27,16 @@ var jsBundleFilePath = process.argv[3]; var assetsDir = process.argv[4]; var tempFileName = process.argv[5]; -var tempFileLocalPath = path.join(require("os").tmpdir(), tempFileName); +var oldFileToModifiedTimeMap = {}; +if (tempFileName) { + var tempFileLocalPath = path.join(require("os").tmpdir(), tempFileName); + oldFileToModifiedTimeMap = require(tempFileLocalPath); + fs.unlinkSync(tempFileLocalPath); +} var resourceFiles = []; getFilesInFolder(resourcesDir, resourceFiles); -var oldFileToModifiedTimeMap = require(tempFileLocalPath); var newFileToModifiedTimeMap = {}; resourceFiles.forEach(function(resourceFile) { @@ -114,6 +118,4 @@ function addFileToManifest(folder, assetFile, manifest, done) { function fileExists(file) { try { return fs.statSync(file).isFile(); } catch (e) { return false; } -} - -fs.unlinkSync(tempFileLocalPath); +} \ No newline at end of file From 6afd68ce1ae989763f1e6c9ce416b74b1d76b7ce Mon Sep 17 00:00:00 2001 From: Artem Egorov Date: Wed, 28 Feb 2018 15:14:50 +0300 Subject: [PATCH 2/4] enhancement --- android/codepush.gradle | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/android/codepush.gradle b/android/codepush.gradle index 4e8ad4197..c8e44de1a 100644 --- a/android/codepush.gradle +++ b/android/codepush.gradle @@ -1,4 +1,4 @@ -// Adapted from https://raw.githubusercontent.com/facebook/react-native/master/local-cli/generator-android/templates/src/app/react.gradle +// Adapted from https://raw.githubusercontent.com/facebook/react-native/d16ff3bd8b92fa84a9007bf5ebedd8153e4c089d/react.gradle import java.nio.file.Paths; @@ -43,8 +43,9 @@ gradle.projectsEvaluated { def generateBundledResourcesHash; if (variant.hasProperty("bundleJsAndAssets")) { - jsBundleDir = file("$buildDir/generated/assets/react/${targetPath}") - resourcesDir = file("$buildDir/generated/res/react/${targetPath}") + def reactBundleTask = variant.bundleJsAndAssets + jsBundleDir = reactBundleTask.generatedAssetsFolders[0].absolutePath + resourcesDir = reactBundleTask.generatedResFolders[0].absolutePath jsBundleFile = file("$jsBundleDir/$bundleAssetName") generateBundledResourcesHash = tasks.create( From aa012e70f23eee1d06229d0487c5ddc77be04fdc Mon Sep 17 00:00:00 2001 From: Artem Egorov Date: Wed, 28 Feb 2018 18:59:26 +0300 Subject: [PATCH 3/4] enhancement --- android/codepush.gradle | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/android/codepush.gradle b/android/codepush.gradle index c8e44de1a..ef0751ca0 100644 --- a/android/codepush.gradle +++ b/android/codepush.gradle @@ -18,6 +18,12 @@ void runBefore(String dependentTaskName, Task task) { } gradle.projectsEvaluated { + 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()) + } + android.applicationVariants.all { variant -> def nodeModulesPath; if (config.root) { From 9c57da73e9686ad87358722fb9df3109ae70ed3d Mon Sep 17 00:00:00 2001 From: Artem Egorov Date: Wed, 28 Feb 2018 20:41:10 +0300 Subject: [PATCH 4/4] fix assembleDebug --- android/codepush.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/android/codepush.gradle b/android/codepush.gradle index ef0751ca0..3f7e37310 100644 --- a/android/codepush.gradle +++ b/android/codepush.gradle @@ -58,6 +58,10 @@ gradle.projectsEvaluated { name: "generateBundledResourcesHash${targetName}", type: Exec) { commandLine (*nodeExecutableAndArgs, "${nodeModulesPath}/react-native-code-push/scripts/generateBundledResourcesHash.js", resourcesDir, jsBundleFile, jsBundleDir) + + enabled config."bundleIn${targetName}" || + config."bundleIn${variant.buildType.name.capitalize()}" ?: + targetName.toLowerCase().contains("release") } } else { def jsBundleDirConfigName = "jsBundleDir${targetName}"