import java.util.regex.Matcher import java.util.regex.Pattern apply plugin: 'com.android.application' android { compileSdkVersion 26 buildToolsVersion '26.0.0' defaultConfig { applicationId "se.leap.bitmaskclient" resValue "string", "app_name", "Bitmask" vectorDrawables.useSupportLibrary = true } signingConfigs { release { storeFile project.hasProperty('storeFileProperty') ? file(storeFileProperty) : null storePassword project.hasProperty('storePasswordProperty') ? storePasswordProperty : "" keyAlias project.hasProperty('keyAliasProperty') ? keyAliasProperty : "" keyPassword project.hasProperty('keyPasswordProperty') ? keyPasswordProperty : "" } } flavorDimensions "implementation" productFlavors { production { dimension "implementation" } insecure { dimension "implementation" } /* noovpn3 { //dimension "implementation" } normal { //dimension "implementation" } */ } buildTypes { release { //runProguard true if(signingConfigs.contains(release)) signingConfig signingConfigs.release.isSigningReady() ? signingConfigs.release : signingConfigs.debug } beta { initWith release applicationIdSuffix ".beta" resValue "string", "app_name", "Bitmask Beta" } } lintOptions { abortOnError false } sourceSets { main { assets.srcDirs = ['assets'/*, 'ovpnlibs/assets'*/] jniLibs.srcDirs = ['ovpnlibs/jniLibs'] jni.srcDirs = [] //disable automatic ndk-build } debug { assets.srcDirs = ['src/debug/assets'] } test { resources.srcDirs += ['src/test/resources'] } } } dependencies { testCompile 'junit:junit:4.12' testCompile 'org.mockito:mockito-core:2.8.0' testCompile 'org.powermock:powermock-api-mockito2:1.7.3' testCompile 'org.powermock:powermock-module-junit4:1.7.3' testCompile 'org.powermock:powermock-core:1.7.3' testCompile 'org.powermock:powermock-module-junit4-rule:1.7.3' //testCompile 'com.madgag.spongycastle:bctls-jdk15on:1.58.0.0' //testCompile 'com.madgag.spongycastle:bcpkix-jdk15on:1.58.0.0' //testCompile 'com.madgag.spongycastle:bcpg-jdk15on:1.58.0.0' androidTestCompile 'com.jayway.android.robotium:robotium-solo:5.6.3' testCompile 'junit:junit:4.12' testCompile 'org.json:json:20170516' debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.4' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4' betaCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4' annotationProcessor 'com.jakewharton:butterknife:6.1.0' annotationProcessor 'com.squareup.dagger:dagger-compiler:1.2.2' compile 'com.jakewharton:butterknife:6.1.0' provided 'com.squareup.dagger:dagger-compiler:1.2.2' compile 'com.github.pedrovgs:renderers:1.5' compile 'com.intellij:annotations:12.0' compile 'com.google.code.gson:gson:2.8.2' compile 'com.squareup.okhttp3:okhttp:3.9.0' compile 'mbanje.kurt:fabbutton:1.1.4' compile "com.android.support:support-core-utils:26.1.0" compile 'com.android.support:support-annotations:27.0.2' compile 'com.android.support:support-v4:26.1.0' compile 'com.android.support:appcompat-v7:26.1.0' compile 'com.android.support:design:26.1.0' compile 'com.android.support:support-fragment:26.1.0' compile 'com.android.support.constraint:constraint-layout:1.0.2' } // Ensure the no-op dependency is always used in JVM tests. configurations.all { config -> if (config.name.contains('UnitTest')) { config.resolutionStrategy.eachDependency { details -> if (details.requested.group == 'com.squareup.leakcanary' && details.requested.name == 'leakcanary-android') { details.useTarget(group: details.requested.group, name: 'leakcanary-android-no-op', version: details.requested.version) } } } } def processFileInplace(file, Closure processText) { def text = file.text file.write(processText(text)) } task copyIcsOpenVPNClasses( type: Copy ) { println "copyIcsOpenVPNClasses" from ('../ics-openvpn/main/') { include '**/LaunchVPN.java' include '**/OpenVPNSservice.java' include '**/VpnProfile.java' include '**/DisconnectVPN.java' include '**/VpnProfile.java' include '**/LogWindow.java' include '**/LogFragment.java' include '**/SeekBarTicks.java' include '**/log_window.xml' include '**/log_fragment.xml' include '**/log_silders.xml' include '**/vpnstatus.xml' include '**/logmenu.xml' include '**/core/**.java' include '**/activities/BaseActivity.java' include '**/APIVpnProfile.java' include '**/aidl/**/api/**.aidl' include '**/aidl/**/core/**.aidl' includeEmptyDirs = false filter { line -> line.replaceAll('de.blinkt.openvpn.R', 'se.leap.bitmaskclient.R') } filter { line -> line.replaceAll('de.blinkt.openvpn.BuildConfig', 'se.leap.bitmaskclient.BuildConfig') } filter { line -> line.replace('package de.blinkt.openvpn;', 'package de.blinkt.openvpn;\n\nimport se.leap.bitmaskclient.R;') } } into '.' } task copyIcsOpenVPNXml( type: Copy ) { println "copyIcsOpenVPNXml" from ('../ics-openvpn/main/') { include '**/strings.xml' include '**/log_*.xml' include '**/vpnstatus.xml' include '**/refs.xml' include '**/logmenu.xml' include '**/white_rect.xml' include '**/plurals.xml' includeEmptyDirs = false rename 'strings.xml', 'strings-icsopenvpn.xml' rename 'plurals.xml', 'plurals-icsopenvpn.xml' filter { line -> line.replaceAll('.*name="app".*', '') } } into '.' } task copyIcsOpenVPNImages( type: Copy ) { println "copyIcsOpenVPNImages" from ('../ics-openvpn/main/') { include '**/ic_filter*.png' include '**/ic_delete*.png' include '**/ic_share*.png' include '**/ic_close*.png' include '**/ic_edit*.png' include '**/ic_check*.png' include '**/ic_pause*.png' include '**/ic_play*.png' include '**/ic_content_copy_white_*.png' include '**/ic_add_circle_outline_white_*.png' include '**/ic_warning_black_*.png' include '**/ic_add_circle_outline_grey600_*.png' include '**/ic_archive_grey600_*.png' include '**/ic_receipt_white_*.png' include '**/ic_sort_white_*.png' include '**/ic_content_copy_white_*.png' include '**/ic_archive_white_*.png' include '**/ic_menu_archive*.png' include '**/vpn_item_settings*.png' include '**/ic_menu_log*.png' include '**/ic_menu_copy_holo_light*.png' includeEmptyDirs = false } into '.' } // thanks to http://pleac.sourceforge.net/pleac_groovy/fileaccess.html task removeDuplicatedStrings() { println "removeDuplicatedStrings" new File('.').eachFileRecurse { if(it.name.equals('strings.xml') || it.name.equals('plurals.xml')) { replaceDuplicatesForSource(it, it.name.substring(0, it.name.lastIndexOf('.'))) } } } def replaceDuplicatesForSource(File it, String type) { def ics_openvpn_file = file(it.absolutePath.replace(type+'.xml', type+'-icsopenvpn.xml')) if(ics_openvpn_file.exists()) { def ics_openvpn_strings_names = (new XmlParser()).parse(ics_openvpn_file) def current_file = it ics_openvpn_strings_names.string.each { processFileInplace(current_file) { text -> text.replaceAll('.*name=\"' + it.attribute('name') + '\".*(\n)*.*string>.*\n+', '') } } } } task mergeUntranslatable( type: Copy ) { println "mergeUntranslatable" from ('../ics-openvpn/main/') { include '**/untranslatable.xml' rename 'untranslatable.xml', 'untranslatable-icsopenvpn.xml' } into '.' def bitmask_untranslatable = file('src/main/res/values/untranslatable.xml') def ics_openvpn_untranslatable = new File(bitmask_untranslatable.path.replace('untranslatable.xml', 'untranslatable-icsopenvpn.xml')) ics_openvpn_untranslatable.createNewFile() def string_continuation = false; ics_openvpn_untranslatable.eachLine { text -> if(text.contains('string name=')) { if(!bitmask_untranslatable.text.contains(text)) bitmask_untranslatable << text if(text.contains('')) string_continuation = true } else if(string_continuation) { bitmask_untranslatable << text } if(text.contains('')) { string_continuation = false bitmask_untranslatable << System.getProperty("line.separator") } } bitmask_untranslatable.write(bitmask_untranslatable.text.replaceAll("", "")) bitmask_untranslatable << "" delete ics_openvpn_untranslatable } task copyIcsOpenVPNFiles( type: Copy ) { println "copyIcsOpenVPNFiles" //copyIcsOpenVPNClasses.execute() copyIcsOpenVPNXml.execute() copyIcsOpenVPNImages.execute() //mergeUntranslatable.execute() removeDuplicatedStrings.execute() } task updateIcsOpenVpn( type: Exec ) { commandLine 'git', 'submodule', 'sync' commandLine 'git', 'submodule', 'update', '--init', '--recursive' copyIcsOpenVPNFiles.execute() } /* task buildNative ( type: Exec ) { println "buildNative" //commandLine 'sh', 'misc/build-native.sh', 'USE_BREAKPAD=0', '-j 8' } */ task cleanNative( type: Delete ) { def shouldClean = getCurrentFlavorForBetaOrRelease() == "production" println "cleanNative: " + shouldClean if (shouldClean) { def dirName = "obj" file( dirName ).list().each{ f -> delete "${dirName}/${f}" } } } def getCurrentFlavorForBetaOrRelease() { Gradle gradle = getGradle() String tskReqStr = gradle.getStartParameter().getTaskRequests().toString() Pattern pattern; if( tskReqStr.contains( "assemble" ) ) pattern = Pattern.compile("assemble(\\w+)(Beta|Release)") else pattern = Pattern.compile("generate(\\w+)(Beta|Release)") Matcher matcher = pattern.matcher( tskReqStr ) if( matcher.find() ) return matcher.group(1).toLowerCase() else { return ""; } } //preBuild.dependsOn buildNative