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'

Matyáš Latner's avatar
Matyáš Latner committed
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 {
Matyáš Latner's avatar
Matyáš Latner committed
37
        targetSdkVersion 21
38 39
        versionName tablexiaVersionName
        versionCode tablexiaVersionCode
40 41
        applicationId rootProject.applicationBaseId
        testApplicationId rootProject.applicationBaseId + ".test"
Matyáš Latner's avatar
Matyáš Latner committed
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
        }
    }

Matyáš Latner's avatar
Matyáš Latner committed
76 77
    sourceSets {
        main {
78
            manifest.srcFile 'src/main/AndroidManifest.xml'
79
            res.srcDirs = ['res/main']
Matyáš Latner's avatar
Matyáš Latner committed
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 {
Matyáš Latner's avatar
Matyáš Latner committed
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"
            }
        }
    }
Matyáš Latner's avatar
Matyáš Latner committed
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")
        }
    }
}

Matyáš Latner's avatar
Matyáš Latner committed
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() {
Matyáš Latner's avatar
Matyáš Latner committed
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) {
Matyáš Latner's avatar
Matyáš Latner committed
211 212 213 214 215 216 217 218
            copy {
                from zipTree(jar)
                into outputDir
                include "*.so"
            }
        }
    }
}
219

Matyáš Latner's avatar
Matyáš Latner committed
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() {
Matyáš Latner's avatar
Matyáš Latner committed
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"
Matyáš Latner's avatar
Matyáš Latner committed
244
}
245

Matyáš Latner's avatar
Matyáš Latner committed
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]]]
Matyáš Latner's avatar
Matyáš Latner committed
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")
Matyáš Latner's avatar
Matyáš Latner committed
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
}