buildscript { repositories { google() jcenter() maven { url 'https://maven.fabric.io/public' } } dependencies { classpath 'com.android.tools.build:gradle:3.3.1' classpath 'io.fabric.tools:gradle:1.+' } } allprojects { repositories { google() mavenCentral() jcenter() maven { url 'https://jitpack.io' } } } repositories { maven { url 'https://maven.fabric.io/public' } maven { url 'https://dl.bintray.com/libverify/android' } maven { url 'https://s3.amazonaws.com/moat-sdk-builds' } maven { url 'https://dl.bintray.com/google/flexbox-layout/' } maven { url 'https://dl.bintray.com/google/exoplayer/' } } apply plugin: 'com.android.application' apply from: 'secure.properties' apply plugin: 'io.fabric' dependencies { implementation 'com.android.support:multidex:' + propMultiDexVersion implementation 'com.android.support:support-v4:' + propSupportLibraryVersion implementation 'com.android.support:appcompat-v7:' + propSupportLibraryVersion implementation 'com.android.support:recyclerview-v7:'+ propSupportLibraryVersion implementation 'com.android.support:design:'+ propSupportLibraryVersion implementation 'com.android.support:cardview-v7:'+ propSupportLibraryVersion implementation 'com.android.support:preference-v7:'+ propSupportLibraryVersion implementation 'com.android.support:preference-v14:'+ propSupportLibraryVersion implementation 'com.android.support:customtabs:'+ propSupportLibraryVersion implementation 'com.android.support:support-annotations:'+ propSupportLibraryVersion implementation 'com.android.support:support-compat:27.1.1'+ propSupportLibraryVersion implementation 'com.google.android.gms:play-services-location:' + propPlayServicesVersion implementation 'com.google.android.gms:play-services-analytics:' + propPlayServicesVersion implementation 'com.google.android.gms:play-services-gcm:' + propPlayServicesVersion implementation 'com.google.android.gms:play-services-auth:' + propPlayServicesVersion implementation 'com.google.android.gms:play-services-basement:' + propPlayServicesVersion // statistics implementation 'com.flurry.android:analytics:11.0.0@aar' // crash reporting implementation('com.crashlytics.sdk.android:crashlytics:2.9.4@aar') { transitive = true } implementation('com.crashlytics.sdk.android:crashlytics-ndk:2.0.4@aar') { transitive = true } // 3-party implementation 'com.facebook.android:facebook-android-sdk:4.40.0' implementation 'com.facebook.android:audience-network-sdk:4.28.2' implementation 'com.google.code.gson:gson:2.6.1' implementation 'com.pushwoosh:pushwoosh:5.9.0' implementation 'com.pushwoosh:pushwoosh-gcm:5.9.0' implementation 'com.my.tracker:mytracker-sdk:1.5.3' 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.0.0@aar') { transitive = true; } implementation fileTree(dir: '3rd_party', include: '*.jar') // BottomSheet implementation 'com.cocosw:bottomsheet:1.3.1@aar' // LinearLayoutManager allowing wrap_content of RecyclerView-s // TODO remove this library when default LinearLayoutManager will be fixed. implementation 'org.solovyev.android.views:linear-layout-manager:0.5@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 ("ru.mail:libnotify:0.1.177-notify-support-v107-sdk-26@aar") { transitive = true changing = true } implementation ("ru.mail:libnotify-debug:0.1.177-notify-support-v107-sdk-26@aar") { transitive = true changing = true } implementation 'com.android.support.constraint:constraint-layout:1.1.0' implementation 'com.android.billingclient:billing:1.1' implementation 'uk.co.samuelwall:material-tap-target-prompt:2.12.1' 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' } 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': 1, 'x86': 2, 'arm64-v8a': 3] project.ext.appId = 'com.mapswithme.maps.pro' crashlytics { enableNdk true } configurations.all { if (it.getName().contains("lint")) return resolutionStrategy { force 'com.android.support:multidex:' + propMultiDexVersion force 'com.android.support:support-v4:' + propSupportLibraryVersion force 'com.android.support:appcompat-v7:' + propSupportLibraryVersion force 'com.android.support:recyclerview-v7:' + propSupportLibraryVersion force 'com.android.support:design:' + propSupportLibraryVersion force 'com.android.support:cardview-v7:' + propSupportLibraryVersion force 'com.android.support:preference-v7:' + propSupportLibraryVersion force 'com.android.support:preference-v14:' + propSupportLibraryVersion force 'com.android.support:customtabs:' + propSupportLibraryVersion force 'com.android.support:support-core-utils:' + propSupportLibraryVersion force 'com.android.support:support-annotations:' + propSupportLibraryVersion force 'com.android.support:support-compat:' + propSupportLibraryVersion force 'com.google.android.gms:play-services-ads:' + propPlayServicesVersion force 'com.google.android.gms:play-services-location:' + propPlayServicesVersion force 'com.google.android.gms:play-services-analytics:' + propPlayServicesVersion force 'com.google.android.gms:play-services-plus:' + propPlayServicesVersion force 'com.google.android.gms:play-services-gcm:' + propPlayServicesVersion force 'com.google.android.gms:play-services-ads:' + propPlayServicesVersion force 'com.google.android.gms:play-services-auth:' + propPlayServicesVersion force 'com.google.android.gms:play-services-basement:' + propPlayServicesVersion failOnVersionConflict(); } } android { // All properties are read from gradle.properties file compileSdkVersion propCompileSdkVersion.toInteger() defaultConfig { // 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' // Crashlytics API key Properties props = new Properties() props.load(new FileInputStream("${projectDir}/fabric.properties")); manifestPlaceholders = ['FABRIC_API_KEY': props['apiKey']] buildConfigField 'String', 'FABRIC_API_KEY', /"${props['apiKey']}"/ // 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 + "\"" // Libnotify keys Properties lnProps = new Properties() lnProps.load(new FileInputStream("${projectDir}/libnotify.properties")); manifestPlaceholders += ['LIBNOTIFY_APP_ID': lnProps['appId']] manifestPlaceholders += ['LIBNOTIFY_PROJECT_ID': lnProps['projectId']] multiDexEnabled true multiDexKeepFile file('multidex-config.txt') externalNativeBuild { def pchFlag = 'OFF' if (project.hasProperty('pch')) pchFlag = 'ON' cmake { cppFlags '-fexceptions', '-frtti' 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")) { 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("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 { 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' 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"' } } 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' 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) + android.defaultConfig.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') manifestPlaceholders += ['LIBNOTIFY_APP_ID': 'MapsMeDebug'] 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 } beta { applicationIdSuffix '.beta' versionNameSuffix '-beta' signingConfig signingConfigs.mapswithme android.sourceSets.beta.setRoot('flavors/beta') matchingFallbacks = ['debug', 'release'] manifestPlaceholders += ['LIBNOTIFY_APP_ID': 'MapsMeBeta'] resValue 'string', 'app_id', android.defaultConfig.applicationId + applicationIdSuffix } } externalNativeBuild { cmake { 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:!*~" } // Enables new Java features in KitKat+ but needs Java 1.7 installed compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } packagingOptions { exclude 'lib/armeabi/libcrashlytics-envelope.so' exclude 'lib/armeabi/libcrashlytics.so' exclude 'lib/mips64/libcrashlytics-envelope.so' exclude 'lib/mips64/libcrashlytics.so' exclude 'lib/mips/libcrashlytics-envelope.so' exclude 'lib/mips/libcrashlytics.so' exclude 'lib/x86_64/libcrashlytics-envelope.so' exclude 'lib/x86_64/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/x86_64/libVkLayer_core_validation.so' exclude 'lib/x86_64/libVkLayer_threading.so' exclude 'lib/x86_64/libVkLayer_image.so' exclude 'lib/x86_64/libVkLayer_parameter_validation.so' exclude 'lib/x86_64/libVkLayer_object_tracker.so' exclude 'lib/x86_64/libVkLayer_swapchain.so' exclude 'lib/x86_64/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] }