buildscript { repositories { google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:4.0.1' classpath 'com.google.firebase:firebase-crashlytics-gradle:2.2.0' classpath 'com.google.gms:google-services:4.3.3' } } allprojects { repositories { google() mavenCentral() jcenter() } } repositories { maven { url 'https://maven.fabric.io/public' } maven { url 'https://s3.amazonaws.com/moat-sdk-builds' } maven { url 'https://www.jitpack.io' } maven { url 'https://maven.google.com' } maven { url 'https://dl.bintray.com/google/flexbox-layout/' } maven { url 'https://dl.bintray.com/google/exoplayer/' } } apply plugin: 'com.android.application' apply plugin: 'com.google.gms.google-services' apply plugin: 'com.google.firebase.crashlytics' apply from: 'secure.properties' dependencies { implementation 'androidx.multidex:multidex:' + propMultiDexVersion implementation 'com.google.android.gms:play-services-location:17.0.0' implementation 'com.google.android.gms:play-services-analytics:17.0.0' implementation 'com.google.android.gms:play-services-gcm:17.0.0' implementation 'com.google.android.gms:play-services-auth:17.0.0' implementation 'com.google.android.gms:play-services-basement:17.1.1' // statistics implementation 'com.flurry.android:analytics:12.1.0@aar' // crash reporting implementation 'com.google.firebase:firebase-analytics:17.4.4' implementation 'com.google.firebase:firebase-crashlytics:17.1.1' implementation 'com.google.firebase:firebase-crashlytics-ndk:17.1.1' // 3-party implementation 'com.facebook.android:facebook-android-sdk:5.15.0' implementation 'com.facebook.android:audience-network-sdk:5.6.1' implementation 'com.mopub.mediation:facebookaudiencenetwork:5.6.1.0' implementation 'com.google.code.gson:gson:2.6.1' implementation 'com.pushwoosh:pushwoosh:5.19.7' implementation ('com.my.target:mytarget-sdk:5.2.2') { exclude group: 'com.google.android.exoplayer', module:'exoplayer-core' exclude group: 'com.google.android.exoplayer', module:'exoplayer-dash' exclude group: 'com.google.android.exoplayer', module:'exoplayer-hls' } implementation('com.mopub:mopub-sdk-native-static:5.10.0@aar') { transitive = true; } // BottomSheet implementation 'com.cocosw:bottomsheet:1.5.0@aar' implementation 'com.timehop.stickyheadersrecyclerview:library:0.4.3@aar' // Glide implementation 'com.github.bumptech.glide:glide:3.7.0' // Java concurrency annotations implementation 'net.jcip:jcip-annotations:1.0' implementation 'com.appsflyer:af-android-sdk:4.9.0' implementation 'com.android.installreferrer:installreferrer:1.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.work:work-runtime:2.2.0' implementation 'com.android.billingclient:billing:1.1' implementation('uk.co.samuelwall:material-tap-target-prompt:3.1.0', { exclude group: 'androidx.lifecycle', module: 'lifecycle-extensions' }) implementation 'com.firebase:firebase-jobdispatcher:0.8.5' implementation 'com.google.android:flexbox:1.0.0' implementation 'com.trafi:anchor-bottom-sheet-behavior:0.13-alpha' implementation 'com.google.firebase:firebase-messaging:17.0.0' implementation 'com.github.yoksnod:MPAndroidChart:3.2.0-alpha' implementation 'com.google.android.material:material:1.3.0-alpha03' implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'androidx.legacy:legacy-preference-v14:1.0.0' implementation 'androidx.preference:preference:1.1.0' implementation 'androidx.fragment:fragment:1.1.0' } def getDate() { def date = new Date() def formattedDate = date.format('yyMMdd') return formattedDate } def osName = System.properties['os.name'].toLowerCase() project.ext.versionCodes = ['armeabi-v7a': 30, 'x86': 40, 'arm64-v8a': 50, 'x86_64' : 60] project.ext.appId = 'com.mapswithme.maps.pro' configurations.all { if (it.getName().contains("lint")) return resolutionStrategy { force 'com.android.support:multidex:' + propMultiDexVersion force 'com.google.android.gms:play-services-location:17.0.0' force 'com.google.android.gms:play-services-analytics:17.0.0' force 'com.google.android.gms:play-services-plus:17.0.0' force 'com.google.android.gms:play-services-gcm:17.0.0' force 'com.google.android.gms:play-services-auth:17.0.0' force 'com.google.android.gms:play-services-basement:17.1.1' force 'com.google.android.gms:play-services-base:17.0.0' force 'com.google.android.gms:play-services-tasks:17.0.0' force 'com.google.android.gms:play-services-stats:17.0.0' force 'android.arch.core:runtime:1.1.1' force 'android.arch.core:common:1.1.1' force 'androidx.legacy:legacy-support-core-utils:1.0.0-rc01' force 'androidx.loader:loader:1.0.0-rc01' force 'androidx.lifecycle:lifecycle-viewmodel:2.1.0' force 'androidx.lifecycle:lifecycle-common:2.1.0' force 'androidx.arch.core:core-common:2.0.0-rc01' force 'androidx.arch.core:core-runtime:2.0.0-rc01' force 'androidx.lifecycle:lifecycle-runtime:2.1.0' force 'androidx.lifecycle:lifecycle-livedata-core:2.1.0' force 'androidx.lifecycle:lifecycle-extensions:2.1.0' force 'androidx.work:work-runtime:2.2.0' force "org.jetbrains.kotlin:kotlin-stdlib:1.3.31" force "com.google.code.gson:gson:2.8.5" force "com.google.guava:guava:27.0.1-jre" force "com.android.installreferrer:installreferrer:1.1" force "com.google.firebase:firebase-iid:16.0.0" force "com.google.firebase:firebase-measurement-connector:18.0.0" force "com.google.firebase:firebase-iid-interop:17.0.0" force "com.google.firebase:firebase-common:19.3.0" force "com.google.android.material:material:1.3.0-alpha03" force "androidx.constraintlayout:constraintlayout:1.1.3" force "androidx.vectordrawable:vectordrawable:1.1.0" force "androidx.coordinatorlayout:coordinatorlayout:1.1.0" force "androidx.collection:collection:1.1.0" force "androidx.fragment:fragment:1.1.0" force "androidx.preference:preference:1.1.0" force "androidx.appcompat:appcompat:1.2.0" force "androidx.annotation:annotation:1.1.0" force "androidx.core:core:1.3.1" force "androidx.versionedparcelable:versionedparcelable:1.1.0" force "androidx.recyclerview:recyclerview:1.2.0-alpha02" failOnVersionConflict(); } } android { ndkVersion = "21.3.6528147" dataBinding { enabled = true } // All properties are read from gradle.properties file compileSdkVersion propCompileSdkVersion.toInteger() defaultConfig { vectorDrawables.useSupportLibrary = true // Default package name is taken from the manifest and should be com.mapswithme.maps versionCode propVersionCode.toInteger() versionName propVersionName minSdkVersion propMinSdkVersion.toInteger() targetSdkVersion propTargetSdkVersion.toInteger() applicationId project.ext.appId buildConfigField 'String', 'SUPPORT_MAIL', '"android@maps.me"' buildConfigField 'String', 'REVIEW_URL', '"market://details?id=com.mapswithme.maps.pro"' buildConfigField 'int', 'RATING_THRESHOLD', '5' // PushWoosh keys Properties pwProps = new Properties() pwProps.load(new FileInputStream("${projectDir}/pushwoosh.properties")); manifestPlaceholders += ['PW_APPID': pwProps['pwAppId']] buildConfigField 'String', 'PW_APPID', /"${pwProps['pwAppId']}"/ def pwProjectIdKey = 'PW_PROJECT_ID' manifestPlaceholders += [pwProjectId : pwProps['pwProjectId']] manifestPlaceholders += ['PW_PROJECT_ID_KEY' : pwProjectIdKey] resValue 'string', 'pw_project_id', pwProps['pwProjectId'] buildConfigField "String", 'PW_PROJECT_ID', "\"" + pwProjectIdKey + "\"" multiDexEnabled true multiDexKeepFile file('multidex-config.txt') externalNativeBuild { def pchFlag = 'OFF' if (project.hasProperty('pch')) pchFlag = 'ON' cmake { version "3.8.0+" cppFlags '-fexceptions', '-frtti', '-std=c++17' cFlags '-ffunction-sections', '-fdata-sections', '-Wno-extern-c-compat' arguments '-DANDROID_TOOLCHAIN=clang', '-DANDROID_STL=c++_static', "-DOS=$osName", '-DSKIP_TESTS=ON', "-DUSE_PCH=$pchFlag" } } ndk { abiFilters = new HashSet<>() if (project.hasProperty("arm32")) { println("Building for the ARM32 architecture") abiFilters.add("armeabi-v7a") } else if (project.hasProperty("arm64")) { println("Building for the ARM64 architecture") abiFilters.add("arm64-v8a") } else if (project.hasProperty("x86_64")) { println("Building for the x86_64 architecture") abiFilters.add("x86_64") } else if (project.hasProperty("x86")) { println("Building for the x86 architecture") abiFilters.add("x86") } else { if (!project.hasProperty('splitApk')) { println("Building for the ARM and x86 architectures") abiFilters.add("x86") abiFilters.add("x86_64") abiFilters.add("armeabi-v7a") abiFilters.add("arm64-v8a") } } } } sourceSets.main { manifest.srcFile 'AndroidManifest.xml' res.srcDirs = ['res'] java.srcDirs = ['src', '../3party/Alohalytics/src/android/java'] // assets folder is auto-generated by tools/android/update_assets.sh, so we keep all static resources in separate folders. assets.srcDirs = ['assets'] jniLibs.srcDirs = [android.getNdkDirectory().toString() + '/sources/third_party/vulkan/src/build-android/jniLibs'] } flavorDimensions "default" productFlavors { final int HUAWEI_VERSION_CODE_BASE = 20000; final int TENCENT_VERSION_CODE_BASE = 10000; google { dimension "default" versionName = android.defaultConfig.versionName + '-Google' buildConfigField 'String', 'SUPPORT_MAIL', '"googleplay@maps.me"' } samsung { dimension "default" versionName = android.defaultConfig.versionName + '-Samsung' buildConfigField 'String', 'REVIEW_URL', '"samsungapps://ProductDetail/com.mapswithme.maps.pro"' buildConfigField 'String', 'SUPPORT_MAIL', '"samsung@maps.me"' android.sourceSets.samsung.assets.srcDirs = ['flavors/mwm-ttf-assets'] } amazon { dimension "default" versionName = android.defaultConfig.versionName + '-Amazon' buildConfigField 'String', 'REVIEW_URL', '"amzn://apps/android?p=com.mapswithme.maps.pro"' buildConfigField 'String', 'SUPPORT_MAIL', '"amazon@maps.me"' buildConfigField 'int', 'RATING_THRESHOLD', '4' android.sourceSets.amazon.assets.srcDirs = ['flavors/mwm-ttf-assets'] } yandex { dimension "default" versionName = android.defaultConfig.versionName + '-Yandex' buildConfigField 'String', 'REVIEW_URL', '"yastore://details?id=com.mapswithme.maps.pro"' android.sourceSets.yandex.assets.srcDirs = ['flavors/mwm-ttf-assets'] } preinstall { dimension "default" versionName = android.defaultConfig.versionName + '-Preinstall' buildConfigField 'String', 'SUPPORT_MAIL', '"googleplay@maps.me"' } cipherlab { dimension "default" versionName = android.defaultConfig.versionName + '-CipherLab' android.sourceSets.cipherlab.assets.srcDirs = ['flavors/mwm-ttf-assets'] } xiaomi { dimension "default" versionName = android.defaultConfig.versionName + '-Xiaomi' buildConfigField 'String', 'REVIEW_URL', '"http://app.mi.com/detail/85835?ref=search"' android.sourceSets.xiaomi.assets.srcDirs = ['flavors/mwm-ttf-assets'] } lenovo { dimension "default" versionName = android.defaultConfig.versionName + '-Lenovo' android.sourceSets.lenovo.assets.srcDirs = ['flavors/mwm-ttf-assets'] } web { dimension "default" versionName = android.defaultConfig.versionName + '-Web' buildConfigField 'String', 'SUPPORT_MAIL', '"googleplay@maps.me"' android.sourceSets.web.assets.srcDirs = ['flavors/mwm-ttf-assets'] } nineApp { dimension "default" versionName = android.defaultConfig.versionName + '-9app' buildConfigField 'String', 'REVIEW_URL', '"http://www.9apps.com/android-apps/mapswithme-maps-pro/"' android.sourceSets.nineApp.assets.srcDirs = ['flavors/mwm-ttf-assets'] } mobogenie { dimension "default" versionName = android.defaultConfig.versionName + '-Mobogenie' android.sourceSets.mobogenie.assets.srcDirs = ['flavors/mwm-ttf-assets'] buildConfigField 'String', 'REVIEW_URL', '"http://www.mobogenie.com/download-maps-me-4240212.html"' } tencent { dimension "default" versionName = android.defaultConfig.versionName + '-Tencent' versionCode TENCENT_VERSION_CODE_BASE + android.defaultConfig.versionCode android.sourceSets.tencent.assets.srcDirs = ['flavors/mwm-ttf-assets'] buildConfigField 'String', 'REVIEW_URL', '"http://android.myapp.com/myapp/detail.htm?apkName=com.mapswithme.maps.pro"' } baidu { dimension "default" versionName = android.defaultConfig.versionName + '-Baidu' android.sourceSets.baidu.assets.srcDirs = ['flavors/mwm-ttf-assets'] buildConfigField 'String', 'REVIEW_URL', '"http://shouji.baidu.com/software/item?docid=7999892&f=sug@software"' } appChina { dimension "default" versionName = android.defaultConfig.versionName + '-AppChina' android.sourceSets.appChina.assets.srcDirs = ['flavors/mwm-ttf-assets'] buildConfigField 'String', 'REVIEW_URL', '"http://www.appchina.com/app/com.mapswithme.maps.pro"' } moboMarket { dimension "default" versionName = android.defaultConfig.versionName + '-MoboMarket' android.sourceSets.moboMarket.assets.srcDirs = ['flavors/mwm-ttf-assets'] // TODO While store url is unknown, force all rating reviews to be sent to our email. // Change it in the next version after publishing app to the store. buildConfigField 'int', 'RATING_THRESHOLD', '6' } blackberry { dimension "default" versionName = android.defaultConfig.versionName + '-Blackberry' android.sourceSets.blackberry.assets.srcDirs = ['flavors/mwm-ttf-assets'] buildConfigField 'String', 'REVIEW_URL', '"https://appworld.blackberry.com/webstore/content/51013892"' } huawei { dimension "default" versionName = android.defaultConfig.versionName + '-Huawei' versionCode = HUAWEI_VERSION_CODE_BASE + android.defaultConfig.versionCode buildConfigField 'String', 'SUPPORT_MAIL', '"huawei@maps.me"' android.sourceSets.huawei.assets.srcDirs = ['flavors/mwm-ttf-assets'] } } variantFilter { variant -> if (!variant.getFlavors().get(0).name.equals("web") && !variant.getFlavors().get(0).name.equals("google") && !project.hasProperty("anyVariant")) { println("Variant '" + variant.name + "' is ignored. If you want to build it please " + "add gradle parameter '-PanyVariant'") variant.setIgnore(true) } } splits.abi { boolean enabled = project.hasProperty('splitApk'); println ("Create separate apks: " + enabled) enable enabled reset() include 'x86', 'armeabi-v7a', 'arm64-v8a', 'x86_64' universalApk true } // TODO: Fix a lot of lint errors in our code lintOptions { abortOnError false } gradle.projectsEvaluated { android.applicationVariants.all { variant -> def task = variant.name.capitalize() project.task(type: Exec, "run${task}", dependsOn: "install${task}") { commandLine android.getAdbExe(), 'shell', 'am', 'start', '-n', "${applicationId}/com.mapswithme.maps.SplashActivity" } variant.outputs.all { output -> if (output.outputFile != null && output.outputFile.name.endsWith('.apk')) { def file = output.outputFile // version at the end of each built apk outputFileName = "../../" + file.name.replace(".apk", "-" + android.defaultConfig.versionName + "-" + getDate() + ".apk") // set different versionCodes for different ABIs int abiVersionCode = project.ext.versionCodes.get(output.getFilter(com.android.build.OutputFile.ABI)) ?: 0 output.versionCodeOverride = (abiVersionCode * 1000) + variant.versionCode } } } } signingConfigs { mapswithme { storeFile file(spropStoreFile) storePassword spropStorePassword keyAlias spropKeyAlias keyPassword spropKeyPassword } mapswithmeDebug { storeFile file('../tools/android/debug.keystore') storePassword '12345678' keyAlias 'debug' keyPassword '12345678' } } buildTypes { debug { applicationIdSuffix '.debug' // Allows to install debug and release builds together versionNameSuffix '-debug' jniDebuggable true // Enable jni debug build zipAlignEnabled true signingConfig signingConfigs.mapswithmeDebug android.sourceSets.debug.setRoot('flavors/debug') resValue 'string', 'app_id', android.defaultConfig.applicationId + applicationIdSuffix } release { signingConfig signingConfigs.mapswithme minifyEnabled true shrinkResources true proguardFile('proguard-mwm.txt') resValue 'string', 'app_id', android.defaultConfig.applicationId firebaseCrashlytics { nativeSymbolUploadEnabled true } } beta { applicationIdSuffix '.beta' versionNameSuffix '-beta' signingConfig signingConfigs.mapswithme android.sourceSets.beta.setRoot('flavors/beta') matchingFallbacks = ['debug', 'release'] resValue 'string', 'app_id', android.defaultConfig.applicationId + applicationIdSuffix firebaseCrashlytics { nativeSymbolUploadEnabled true } } } externalNativeBuild { cmake { version "3.8.0+" buildStagingDirectory "./nativeOutputs" path "../CMakeLists.txt" } } // We don't compress these extensions in assets/ because our random FileReader can't read zip-compressed files from apk. // TODO: Load all minor files via separate call to ReadAsString which can correctly handle compressed files in zip containers. aaptOptions { noCompress 'txt', 'bin', 'html', 'png', 'json', 'mwm', 'ttf', 'sdf', 'ui', 'config', 'csv', 'spv' ignoreAssetsPattern "!.svn:!.git:!.DS_Store:!*.scc:.*:_*:!CVS:!thumbs.db:!picasa.ini:!*~" } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } packagingOptions { exclude 'lib/armeabi/libcrashlytics.so' exclude 'lib/mips64/libcrashlytics.so' exclude 'lib/mips/libcrashlytics.so' exclude 'lib/armeabi/libVkLayer_core_validation.so' exclude 'lib/armeabi/libVkLayer_threading.so' exclude 'lib/armeabi/libVkLayer_image.so' exclude 'lib/armeabi/libVkLayer_parameter_validation.so' exclude 'lib/armeabi/libVkLayer_object_tracker.so' exclude 'lib/armeabi/libVkLayer_swapchain.so' exclude 'lib/armeabi/libVkLayer_unique_objects.so' exclude 'lib/mips64/libVkLayer_core_validation.so' exclude 'lib/mips64/libVkLayer_threading.so' exclude 'lib/mips64/libVkLayer_image.so' exclude 'lib/mips64/libVkLayer_parameter_validation.so' exclude 'lib/mips64/libVkLayer_object_tracker.so' exclude 'lib/mips64/libVkLayer_swapchain.so' exclude 'lib/mips64/libVkLayer_unique_objects.so' exclude 'lib/mips/libVkLayer_core_validation.so' exclude 'lib/mips/libVkLayer_threading.so' exclude 'lib/mips/libVkLayer_image.so' exclude 'lib/mips/libVkLayer_parameter_validation.so' exclude 'lib/mips/libVkLayer_object_tracker.so' exclude 'lib/mips/libVkLayer_swapchain.so' exclude 'lib/mips/libVkLayer_unique_objects.so' } } // Tasks needed to compile NDK part apply plugin: 'base' project.ext.PARAM_PARALLEL_TASK_COUNT = '-j' + (Runtime.runtime.availableProcessors() + 1) project.ext.NDK_BUILD = android.getNdkDirectory().toString() + '/ndk-build' if (System.properties['os.name'].toLowerCase().contains('windows')) project.ext.NDK_BUILD += ".cmd" // Tasks for generating obb files for Google Play def unalignedFonts = "${propObbFontsOutput}.unaligned" def unalignedWorlds = "${propObbWorldsOutput}.unaligned" task obbClean(type: Delete) { doLast { [propObbFontsOutput, propObbWorldsOutput, unalignedFonts, unalignedWorlds].each { file -> delete file } } } task obbGenerate() { createObbGenerateTask('Main', propObbFonts.split(' '), unalignedFonts) createObbGenerateTask('Patch', propObbWorlds.split(' '), unalignedWorlds) createObbAlignTask('Main', unalignedFonts, propObbFontsOutput) createObbAlignTask('Patch', unalignedWorlds, propObbWorldsOutput) } obbGenerate.dependsOn obbClean, obbMainGenerate, obbPatchGenerate, obbMainAlign, obbPatchAlign def createObbGenerateTask(type, data, name) { return tasks.create(name: "obb${type}Generate", type: Exec, description: 'Generate obb files') { commandLine((['zip', '-0', '-j', name, data]).flatten()) } } def createObbAlignTask(type, rawObb, alignedObb) { def sdkDir = "${android.getSdkDirectory().getAbsolutePath()}" def zipalignPath = sdkDir + File.separator + "build-tools" + File.separator + propBuildToolsVersion + File.separator + "zipalign"; return tasks.create(name: "obb${type}Align", dependsOn: "obb${type}Generate", type: Exec, description: 'Align obb files') { commandLine zipalignPath, '-v', '8', rawObb, alignedObb } } task obbPush(dependsOn: ['obbGenerate', 'obbPushMain', 'obbPushPatch']) { def obbPath = "/mnt/sdcard/Android/obb/${project.ext.appId}/" tasks.create(type: Exec, name: 'obbRemoveOnDevice') { commandLine android.getAdbExe(), 'shell', 'rm', "${obbPath}*.obb" } tasks.create(type: Exec, name: 'obbPushMain', dependsOn: 'obbRemoveOnDevice') { commandLine android.getAdbExe(), 'push', propObbFontsOutput, "${obbPath}fonts.obb" } tasks.create(type: Exec, name: 'obbPushPatch', dependsOn: 'obbRemoveOnDevice') { commandLine android.getAdbExe(), 'push', propObbWorldsOutput, "${obbPath}worlds.obb" } } android.buildTypes.all { buildType -> def suffix = applicationIdSuffix != null ? applicationIdSuffix : ""; def authorityValue = android.defaultConfig.applicationId + suffix + ".provider" def authority = "\"" + authorityValue + "\"" buildConfigField 'String', 'FILE_PROVIDER_AUTHORITY', authority manifestPlaceholders += [FILE_PROVIDER_PLACEHOLDER : authorityValue] }