diff --git a/.adjust_token b/.adjust_token new file mode 100644 index 000000000..7489accbf --- /dev/null +++ b/.adjust_token @@ -0,0 +1 @@ +-- \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 796fc4244..ff111960b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -106,6 +106,11 @@ android { } android.applicationVariants.all { variant -> + +// ------------------------------------------------------------------------------------------------- +// Set up kotlin-allopen plugin for writing tests +// ------------------------------------------------------------------------------------------------- + boolean hasTest = gradle.startParameter.taskNames.find {it.contains("test") || it.contains("Test")} != null if (hasTest) { apply plugin: 'kotlin-allopen' @@ -113,12 +118,14 @@ android.applicationVariants.all { variant -> annotation("org.mozilla.fenix.test.Mockable") } } -} -android.applicationVariants.all { variant -> +// ------------------------------------------------------------------------------------------------- +// Generate version codes for builds +// ------------------------------------------------------------------------------------------------- + def buildType = variant.buildType.name - if (buildType == "release" || buildType == "nightly") { + if (buildType == "release") { def versionCode = generatedVersionCode // The Google Play Store does not allow multiple APKs for the same app that all have the @@ -144,6 +151,57 @@ android.applicationVariants.all { variant -> println("Build type: " + buildType) println("Flavor: " + variant.flavorName) println("Version code: " + variant.mergedFlavor.versionCode) + +// ------------------------------------------------------------------------------------------------- +// BuildConfig: Set variables for Sentry, Crash Reporting, and Telemetry +// ------------------------------------------------------------------------------------------------- + + // Reading sentry token from local file (if it exists). In a release task on taskcluster it will be available. + try { + def token = new File("${rootDir}/.sentry_token").text.trim() + buildConfigField 'String', 'SENTRY_TOKEN', '"' + token + '"' + } catch (FileNotFoundException ignored) { + buildConfigField 'String', 'SENTRY_TOKEN', 'null' + } + + // Activating crash reporting only if command line parameter was provided (in automation) + if (project.hasProperty("crashReports") && project.property("crashReports") == "true") { + buildConfigField 'boolean', 'CRASH_REPORTING', 'true' + } else { + buildConfigField 'boolean', 'CRASH_REPORTING', 'false' + } + + // Activating telemetry only if command line parameter was provided (in automation) + if (project.hasProperty("telemetry") && project.property("telemetry") == "true") { + buildConfigField 'boolean', 'TELEMETRY', 'true' + } else { + buildConfigField 'boolean', 'TELEMETRY', 'false' + } + + def buildDate = Config.generateBuildDate() + buildConfigField 'String', 'BUILD_DATE', '"' + buildDate + '"' + +// ------------------------------------------------------------------------------------------------- +// Adjust: Read token from locale file if it exists (Only release builds) +// ------------------------------------------------------------------------------------------------- + + def variantName = variant.getName() + + print("Adjust token: ") + + if (variantName.contains("Release")) { + try { + def token = new File("${rootDir}/.adjust_token").text.trim() + buildConfigField 'String', 'ADJUST_TOKEN', '"' + token + '"' + println "(Added from .adjust_token file)" + } catch (FileNotFoundException ignored) { + buildConfigField 'String', 'ADJUST_TOKEN', 'null' + println("X_X") + } + } else { + buildConfigField 'String', 'ADJUST_TOKEN', 'null' + println("--") + } } androidExtensions { @@ -219,6 +277,9 @@ dependencies { implementation Deps.autodispose + implementation Deps.adjust + implementation Deps.installreferrer // Required by Adjust + androidTestImplementation Deps.tools_test_runner androidTestImplementation Deps.tools_espresso_core @@ -234,34 +295,6 @@ dependencies { annotationProcessor Deps.glideAnnotationProcessor } - -android.applicationVariants.all { variant -> - // Reading sentry token from local file (if it exists). In a release task on taskcluster it will be available. - try { - def token = new File("${rootDir}/.sentry_token").text.trim() - buildConfigField 'String', 'SENTRY_TOKEN', '"' + token + '"' - } catch (FileNotFoundException ignored) { - buildConfigField 'String', 'SENTRY_TOKEN', 'null' - } - - // Activating crash reporting only if command line parameter was provided (in automation) - if (project.hasProperty("crashReports") && project.property("crashReports") == "true") { - buildConfigField 'boolean', 'CRASH_REPORTING', 'true' - } else { - buildConfigField 'boolean', 'CRASH_REPORTING', 'false' - } - - // Activating telemetry only if command line parameter was provided (in automation) - if (project.hasProperty("telemetry") && project.property("telemetry") == "true") { - buildConfigField 'boolean', 'TELEMETRY', 'true' - } else { - buildConfigField 'boolean', 'TELEMETRY', 'false' - } - - def buildDate = Config.generateBuildDate() - buildConfigField 'String', 'BUILD_DATE', '"' + buildDate + '"' -} - if (project.hasProperty("raptor")) { android.defaultConfig.manifestPlaceholders.isRaptorEnabled = "true" } diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index ff1532348..56243ecb5 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -40,4 +40,35 @@ # Mozilla Application Services #################################################################################################### --keep class mozilla.appservices.FenixMegazord { *; } \ No newline at end of file +-keep class mozilla.appservices.FenixMegazord { *; } + +#################################################################################################### +# Adjust +#################################################################################################### + +-keep public class com.adjust.sdk.** { *; } +-keep class com.google.android.gms.common.ConnectionResult { + int SUCCESS; +} +-keep class com.google.android.gms.ads.identifier.AdvertisingIdClient { + com.google.android.gms.ads.identifier.AdvertisingIdClient$Info getAdvertisingIdInfo(android.content.Context); +} +-keep class com.google.android.gms.ads.identifier.AdvertisingIdClient$Info { + java.lang.String getId(); + boolean isLimitAdTrackingEnabled(); +} +-keep public class com.android.installreferrer.** { *; } +-keep class dalvik.system.VMRuntime { + java.lang.String getRuntime(); +} +-keep class android.os.Build { + java.lang.String[] SUPPORTED_ABIS; + java.lang.String CPU_ABI; +} +-keep class android.content.res.Configuration { + android.os.LocaledList getLocales(); + java.util.Locale locale; +} +-keep class android.os.LocaleList { + java.util.Locale get(int); +} diff --git a/app/src/debug/java/org/mozilla/fenix/AdjustHelper.kt b/app/src/debug/java/org/mozilla/fenix/AdjustHelper.kt new file mode 100644 index 000000000..7f51065c7 --- /dev/null +++ b/app/src/debug/java/org/mozilla/fenix/AdjustHelper.kt @@ -0,0 +1,13 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix + +import android.content.Context + +object AdjustHelper { + fun setupAdjustIfNeeded(context: Context) { + // DEBUG: No Adjust - This class has different implementations for all build types. + } +} diff --git a/app/src/main/java/org/mozilla/fenix/FenixApplication.kt b/app/src/main/java/org/mozilla/fenix/FenixApplication.kt index 1eec80a5b..27b92b9e1 100644 --- a/app/src/main/java/org/mozilla/fenix/FenixApplication.kt +++ b/app/src/main/java/org/mozilla/fenix/FenixApplication.kt @@ -20,6 +20,7 @@ import mozilla.components.support.base.log.Log import mozilla.components.support.base.log.logger.Logger import mozilla.components.support.base.log.sink.AndroidLogSink import mozilla.components.support.rustlog.RustLog +import org.mozilla.fenix.AdjustHelper.setupAdjustIfNeeded import org.mozilla.fenix.components.Components import java.io.File @@ -47,6 +48,7 @@ open class FenixApplication : Application() { setupLeakCanary() setupGlean(this) loadExperiments() + setupAdjustIfNeeded(this) } protected open fun setupLeakCanary() { diff --git a/app/src/release/java/org/mozilla/fenix/AdjustHelper.kt b/app/src/release/java/org/mozilla/fenix/AdjustHelper.kt new file mode 100644 index 000000000..5a6b46d9f --- /dev/null +++ b/app/src/release/java/org/mozilla/fenix/AdjustHelper.kt @@ -0,0 +1,62 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix + +import android.app.Activity +import android.app.Application +import android.os.Bundle +import android.text.TextUtils + +import com.adjust.sdk.Adjust +import com.adjust.sdk.AdjustConfig +import com.adjust.sdk.LogLevel +import mozilla.components.service.glean.Glean + +object AdjustHelper { + fun setupAdjustIfNeeded(application: FenixApplication) { + // RELEASE: Enable Adjust - This class has different implementations for all build types. + + if (TextUtils.isEmpty(BuildConfig.ADJUST_TOKEN)) { + throw IllegalStateException("No adjust token defined for release build") + } + + if (!Glean.getUploadEnabled()) { + return + } + + val config = AdjustConfig( + application, + BuildConfig.ADJUST_TOKEN, + AdjustConfig.ENVIRONMENT_PRODUCTION, + true + ) + + config.setLogLevel(LogLevel.SUPRESS) + + Adjust.onCreate(config) + + application.registerActivityLifecycleCallbacks(AdjustLifecycleCallbacks()) + } + + private class AdjustLifecycleCallbacks : Application.ActivityLifecycleCallbacks { + override fun onActivityResumed(activity: Activity) { + Adjust.onResume() + } + + override fun onActivityPaused(activity: Activity) { + Adjust.onPause() + } + + override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle) {} + + override fun onActivityStarted(activity: Activity) {} + + override fun onActivityStopped(activity: Activity) {} + + override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {} + + override fun onActivityDestroyed(activity: Activity) {} + } +} diff --git a/automation/taskcluster/decision_task_nightly.py b/automation/taskcluster/decision_task_nightly.py index a573e0ba9..313b1c7a7 100644 --- a/automation/taskcluster/decision_task_nightly.py +++ b/automation/taskcluster/decision_task_nightly.py @@ -53,7 +53,8 @@ def generate_build_task(apks, is_staging): checkout + ' && python automation/taskcluster/helper/get-secret.py' ' -s {} -k dsn -f .sentry_token'.format(sentry_secret) + - ' && ./gradlew --no-daemon -PcrashReports=true clean test assembleRelease'), + ' && python automation/taskcluster/adjust/get-secret.py get-secret.py -s project/mobile/fenix/adjust -k Greenfield -f .adjust_token' if not is_staging else '' + + ' && ./gradlew --no-daemon -PcrashReports=true clean test assembleGreenfieldRelease'), features={ "chainOfTrust": True, "taskclusterProxy": True diff --git a/buildSrc/src/main/java/Dependencies.kt b/buildSrc/src/main/java/Dependencies.kt index 870c5fa8c..106f75a7f 100644 --- a/buildSrc/src/main/java/Dependencies.kt +++ b/buildSrc/src/main/java/Dependencies.kt @@ -30,6 +30,8 @@ private object Versions { const val android_arch_navigation = "1.0.0-rc02" const val autodispose = "1.1.0" + const val adjust = "4.11.4" + const val installreferrer = "1.0" const val junit_jupiter = "5.3.2" const val mockito = "2.23.0" @@ -128,6 +130,9 @@ object Deps { const val autodispose_android_aac = "com.uber.autodispose:autodispose-android-archcomponents:${Versions.autodispose}" const val autodispose_android_aac_test = "com.uber.autodispose:autodispose-android-archcomponents-test:${Versions.autodispose}" + const val adjust = "com.adjust.sdk:adjust-android:${Versions.adjust}" + const val installreferrer = "com.android.installreferrer:installreferrer:${Versions.installreferrer}" + const val junit_jupiter_api = "org.junit.jupiter:junit-jupiter-api:${Versions.junit_jupiter}" const val junit_jupiter_params = "org.junit.jupiter:junit-jupiter-params:${Versions.junit_jupiter}" const val junit_jupiter_engine = "org.junit.jupiter:junit-jupiter-engine:${Versions.junit_jupiter}"