build.gradle 12.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 * Copyright (C) 2016 CZ.NIC, z.s.p.o. (http://www.nic.cz/)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

18 19 20 21 22
final ASSETS_CHECKSUM_FIELD_TYPE = "String";
final ASSETS_CHECKSUM_FIELD_NAME = "ASSETS_CHECKSUMS";
final BUILD_CONFIG_DIR           = "${buildDir}/generated/source/buildConfig/"
final BUILD_CONFIG_ENCODING      = 'UTF-8'

23
android {
24
    buildToolsVersion '24.0.3'
25
    compileSdkVersion 21
26

27 28 29 30 31
    packagingOptions {
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/LICENSE'
    }

32 33 34
    lintOptions {
        abortOnError false
    }
35

36
    defaultConfig {
37
        targetSdkVersion 21
38 39
        versionName tablexiaVersionName
        versionCode tablexiaVersionCode
40 41
        applicationId rootProject.applicationBaseId
        testApplicationId rootProject.applicationBaseId + ".test"
42 43 44
	    jackOptions {
            enabled true
	    }
45
    }
46 47 48

    buildTypes {
        debug {
49
            applicationIdSuffix rootProject.applicationIdBranch + rootProject.applicationIdDebugSuffix
50
            buildConfigField ASSETS_CHECKSUM_FIELD_TYPE, ASSETS_CHECKSUM_FIELD_NAME, rootProject.ext.assetsChecksumPattern
51
            resValue "string", "app_name", "${tablexiaAppName}"
52
            resValue "string", "sentry_dsn", project.sentryDSN
53 54 55
        }
        release {
            debuggable false
56
            applicationIdSuffix rootProject.applicationIdBranch
57
            buildConfigField ASSETS_CHECKSUM_FIELD_TYPE, ASSETS_CHECKSUM_FIELD_NAME, rootProject.ext.assetsChecksumPattern
58
            resValue "string", "app_name", "${tablexiaAppName}"
59
            resValue "string", "sentry_dsn", project.sentryDSN
60
        }
61 62 63 64 65 66
        iTest.initWith(buildTypes.debug)
        iTest {
            applicationIdSuffix rootProject.applicationIdITestSuffix
            buildConfigField ASSETS_CHECKSUM_FIELD_TYPE, ASSETS_CHECKSUM_FIELD_NAME, rootProject.ext.assetsChecksumPattern
            resValue "string", "app_name", "${tablexiaAppName}"
        }
67 68 69
        devel.initWith(buildTypes.debug)
        devel {
            applicationIdSuffix rootProject.applicationIdDevelSuffix
70
            buildConfigField ASSETS_CHECKSUM_FIELD_TYPE, ASSETS_CHECKSUM_FIELD_NAME, rootProject.ext.assetsChecksumPattern
71
            resValue "string", "app_name", "${tablexiaAppName}"
72
            resValue "string", "sentry_dsn", project.sentryDSNFallbackValue
73 74 75
        }
    }

76 77
    sourceSets {
        main {
78
            manifest.srcFile 'src/main/AndroidManifest.xml'
79
            res.srcDirs = ['res/main']
80
            assets.srcDirs = ['assets']
81
            java.srcDirs = ['src/main/java']
82
            jniLibs.srcDirs = ['libs']
83 84 85 86 87
        }
        test {
            java.srcDir file('src/test/java')
        }

88 89 90 91 92 93
        release {
            res.srcDirs = ['res/release']
        }
        debug {
            res.srcDirs = ['res/debug']
        }
94 95
        iTest {
            manifest.srcFile 'src/iTest/AndroidManifest.xml'
96
            java.srcDirs = ['src/main/java', 'src/iTest/java', '../itest/src/']
97 98
            res.srcDirs = ['res/iTest']
        }
99 100 101
        devel {
            res.srcDirs = ['res/devel']
        }
102 103
    }

104
    assemble.dependsOn = ['assembleRelease', 'assembleDebug', 'assembleITest']
105 106

    applicationVariants.all { variant ->
107
        if (!variant.buildType.name.equals("devel")) {
108 109
            variant.outputs.each { output ->
                def file = output.outputFile
110
                output.outputFile = new File(file.parent, file.name.replace(".apk", "-" + tablexiaVersionName + ".apk").replace("android", tablexiaAppName))
111
            }
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
        }
    }

    if (project.hasProperty('TABLEXIA_RELEASE_KEYSTORE') && project.hasProperty('TABLEXIA_RELEASE_KEYSTORE_PASSWORD')
            && project.hasProperty('TABLEXIA_RELEASE_KEY_ALIAS') && project.hasProperty('TABLEXIA_RELEASE_KEY_PASSWORD')) {
        signingConfigs {
            release {
                storeFile file(TABLEXIA_RELEASE_KEYSTORE)
                storePassword TABLEXIA_RELEASE_KEYSTORE_PASSWORD
                keyAlias TABLEXIA_RELEASE_KEY_ALIAS
                keyPassword TABLEXIA_RELEASE_KEY_PASSWORD
            }
        }

        buildTypes {
            release {
                signingConfig signingConfigs.release
            }
        }
    }
132
    compileOptions {
133 134
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
135
    }
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156

    command {
        // list manufacturer and model for all attached devices
        task('uninstallAllDevices') << {
            devices().each {
                applicationVariants.all { variant ->
                    if (variant.buildType.name.equals("debug")) {
                        variant.outputs.each { output ->
                            print "Uninstalling " + variant.name + "(" + variant.applicationId + ") from device " + it.id + ": .. "
                            [adb, '-s', it.id, 'shell', 'pm', 'uninstall', variant.applicationId].execute()
                            println "done"
                        }
                    }
                }
                // Uninstall test apk
                print "Uninstalling test(" + defaultConfig.testApplicationId + ") from device " + it.id + ": .. "
                [adb, '-s', it.id, 'shell', 'pm', 'uninstall', defaultConfig.testApplicationId].execute()
                println "done"
            }
        }
    }
157
}
158

159 160 161 162 163 164 165 166 167 168 169 170 171
// hack to add assets checksum to BuildConfig -> build config fields are generated at script startup
// -> calculated values from script runtime have to be added to file manually
tasks.whenTaskAdded { compileTask ->
    // select all "compile{BUILD_TYPE}Java" android tasks
    def matcher = (compileTask.name =~ 'compile(.+)Java')
    if (matcher.matches()) {
        String buildName = matcher[0][1]
        // without test tasks
        if (!buildName.contains("Test")) {

            // for all selected tasks create dependency task "checksum{BUILD_TYPE}Assets"
            task("checksum${buildName}Assets") {
                // calculated checksum is dependency
172
                dependsOn(':util:checksum:runChecksum')
173 174 175 176 177 178 179 180 181 182 183 184
                // wait for generating android sources
                dependsOn("generate${buildName}Sources")

                // modify BuildConfig.java -> write checksum in
                doLast{
                    ConfigurableFileTree cft = getProject().fileTree(BUILD_CONFIG_DIR + buildName.toLowerCase())
                    cft.include("**/BuildConfig.java")
                    Iterator<File> iter = cft.iterator()
                    while (iter.hasNext()){
                        File buildConfigFile = iter.next()
                        String buildConfigContent = buildConfigFile.getText(BUILD_CONFIG_ENCODING)

185
                        buildConfigContent = buildConfigContent.replace(rootProject.ext.assetsChecksumPattern, '\"' + getMapConvertedToString(rootProject.ext.assetsChecksum) + '\"')
186 187 188 189 190 191 192 193 194 195 196
                        buildConfigFile.write(buildConfigContent, BUILD_CONFIG_ENCODING)
                    }
                }
            }

            // set as dependency for "compile{BUILD_TYPE}Java" task
            compileTask.dependsOn("checksum${buildName}Assets")
        }
    }
}

197 198 199
// called every time gradle gets executed, takes the native dependencies of
// the natives configuration, and extracts them to the proper libs/ folders
// so they get packed with the APK.
200
task copyAndroidNatives() {
201 202 203 204 205 206
    file("libs/armeabi/").mkdirs();
    file("libs/armeabi-v7a/").mkdirs();
    file("libs/x86/").mkdirs();

    configurations.natives.files.each { jar ->
        def outputDir = null
207 208 209 210
        if (jar.name.endsWith("natives-armeabi-v7a.jar")) outputDir = file("libs/armeabi-v7a")
        if (jar.name.endsWith("natives-armeabi.jar")) outputDir = file("libs/armeabi")
        if (jar.name.endsWith("natives-x86.jar")) outputDir = file("libs/x86")
        if (outputDir != null) {
211 212 213 214 215 216 217 218
            copy {
                from zipTree(jar)
                into outputDir
                include "*.so"
            }
        }
    }
}
219

220
task run(type: Exec) {
221 222 223 224 225
    def adb = doAndroidSettings()
    commandLine "$adb", 'shell', 'am', 'start', '-n', 'cz.nic.tablexia.android/cz.nic.tablexia.android.AndroidLauncher'
}

def doAndroidSettings() {
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
    def path
    def localProperties = project.file("../local.properties")
    if (localProperties.exists()) {
        Properties properties = new Properties()
        localProperties.withInputStream { instr ->
            properties.load(instr)
        }
        def sdkDir = properties.getProperty('sdk.dir')
        if (sdkDir) {
            path = sdkDir
        } else {
            path = "$System.env.ANDROID_HOME"
        }
    } else {
        path = "$System.env.ANDROID_HOME"
    }

243
    return path + "/platform-tools/adb"
244
}
245

246 247 248 249
// sets up the Android Idea project, using the old Ant based build.
idea {
    module {
        sourceDirs += file("src");
250
        scopes = [COMPILE: [plus: [project.configurations.compile]]]
251 252 253 254 255 256 257 258 259

        iml {
            withXml {
                def node = it.asNode()
                def builder = NodeBuilder.newInstance();
                builder.current = node;
                builder.component(name: "FacetManager") {
                    facet(type: "android", name: "Android") {
                        configuration {
260
                            option(name: "UPDATE_PROPERTY_FILES", value: "true")
261 262 263 264 265 266 267
                        }
                    }
                }
            }
        }
    }
}
268

269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
def runTest(String iTestName) {
    println "[iTest] STARTING TEST: " + iTestName
    def adb = doAndroidSettings()
    exec {
        commandLine "$adb", 'shell', 'am', 'start', '-n', 'cz.nic.tablexia.itest/cz.nic.tablexia.android.AndroidITestLauncher', '-e', 'testClassName',  iTestName
    }


    def adbStdOut = new ByteArrayOutputStream()
    while(true) {
        //TODO test ends in PROCESSING state (nothing found with: adb shell ps cz.nic.tablexia.itest)
        /*if(adbStdOut.toString().trim().contains("PROCESSING")){
            def adbPS = new ByteArrayOutputStream()
            exec {
                commandLine "$adb", 'shell', "ps", "cz.nic.tablexia.itest"
                standardOutput = adbPS
            }
            if(!adbPS.toString().contains("cz.nic.tablexia.itest")) return
        }*/
        if(adbStdOut.toString().trim().contains("OK")) return
        if(adbStdOut.toString().trim().contains("FAIL")) return
        exec {
            commandLine "$adb", 'shell', "ls", "/sdcard/iTest_results"
            standardOutput = adbStdOut
        }
    }
}

297 298 299 300
task runAndroidITestBundle {
    doLast{
        int testsCount = 0;
        int successfulTestsCount = 0;
301

302 303
        println "[iTest] CREATING NEW iTest OUTPUT DIRECTORY"
        def iTestOutputFile = new File("${project(':android').projectDir}/build/outputs/apk/iTest_results/")
304 305 306 307
        if (iTestOutputFile.exists()) {
            println "[iTest] REMOVING OLD iTest OUTPUT DIRECTORY"
            iTestOutputFile.deleteDir()
        }
308

309 310 311 312
        def adb = doAndroidSettings()
        println "[iTest] INSTALLING Tablexia (iTest) into connected Android device"
        exec {
            commandLine "$adb", 'install', '-r', "${project(':android').projectDir}/build/outputs/apk/" + "Tablexia (androidITest-gradle)-iTest-" + "$tablexiaVersionName" + ".apk"
313
        }
314 315 316
        println "[iTest] INSTALLING Tablexia (iTest) into connected Android device complete"

        new File("${project(':itest').projectDir}/iTestBundle.txt").eachLine { iTestName ->
317 318 319 320
            exec {
                commandLine "$adb", 'shell', 'rm', '-r', '/sdcard/iTest_results'
            }
            println "[iTest] OLD FILES on SDCARD REMOVED"
321
            testsCount++
322 323
            runTest(iTestName)
            println "[iTest] TEST: " + iTestName + " FINISHED"
324
            exec {
325
                commandLine "$adb", 'pull', '/sdcard/iTest_results', "${project(':android').projectDir}/build/outputs/apk/"
326
            }
327
            println "[iTest] LOG FILES WERE MOVED INTO " + iTestOutputFile.toString()
328 329
        }

330 331 332
        file("$iTestOutputFile").eachFile  { logFile ->
            if(logFile.toString().contains("OK")) successfulTestsCount++;
        }
333

334 335
        if (testsCount != successfulTestsCount) throw new GradleException("Failed to complete all iTests! Check iTest log files in: " + TestOutputFile.toString())
    }
336
}