diff --git a/app/benchmark/.gitignore b/app/benchmark/.gitignore deleted file mode 100644 index 42afabfd..00000000 --- a/app/benchmark/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/app/benchmark/build.gradle b/app/benchmark/build.gradle deleted file mode 100644 index feba5bdd..00000000 --- a/app/benchmark/build.gradle +++ /dev/null @@ -1,58 +0,0 @@ -plugins { - id 'com.android.test' - id 'org.jetbrains.kotlin.android' -} - -android { - namespace 'illyan.jay.benchmark' - compileSdk 33 - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - - kotlinOptions { - jvmTarget = "1.8" - } - - defaultConfig { - minSdk 23 - targetSdk 33 - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - - buildTypes { - // This benchmark buildType is used for benchmarking, and should function like your - // release build (for example, with minification on). It's signed with a debug key - // for easy local/CI testing. - benchmark { - debuggable false - minifyEnabled true - shrinkResources true - buildConfigField 'String', "MapboxAccessToken", "\"$MAPBOX_ACCESS_TOKEN\"" - buildConfigField 'String', "MapboxDownloadsToken", "\"$MAPBOX_DOWNLOADS_TOKEN\"" - buildConfigField 'String', "MapboxSdkRegistryToken", "\"$SDK_REGISTRY_TOKEN\"" - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - signingConfig = debug.signingConfig - matchingFallbacks = ["release"] - } - } - - targetProjectPath = ":app" - experimentalProperties["android.experimental.self-instrumenting"] = true -} - -dependencies { - implementation 'androidx.test.ext:junit:1.1.5' - implementation 'androidx.test.espresso:espresso-core:3.5.1' - implementation 'androidx.test.uiautomator:uiautomator:2.2.0' - implementation 'androidx.benchmark:benchmark-macro-junit4:1.2.0-alpha09' -} - -androidComponents { - beforeVariants(selector().all()) { - enabled = buildType == "benchmark" - } -} \ No newline at end of file diff --git a/app/benchmark/src/main/AndroidManifest.xml b/app/benchmark/src/main/AndroidManifest.xml deleted file mode 100644 index 0b36bb5a..00000000 --- a/app/benchmark/src/main/AndroidManifest.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/app/benchmark/src/main/java/illyan/jay/benchmark/ExampleStartupBenchmark.kt b/app/benchmark/src/main/java/illyan/jay/benchmark/ExampleStartupBenchmark.kt deleted file mode 100644 index f69077f7..00000000 --- a/app/benchmark/src/main/java/illyan/jay/benchmark/ExampleStartupBenchmark.kt +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2023 Balázs Püspök-Kiss (Illyan) - * - * Jay is a driver behaviour analytics app. - * - * This file is part of Jay. - * - * Jay 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. - * Jay 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 Jay. - * If not, see . - */ - -package illyan.jay.benchmark - -import androidx.benchmark.macro.StartupMode -import androidx.benchmark.macro.StartupTimingMetric -import androidx.benchmark.macro.junit4.MacrobenchmarkRule -import androidx.test.ext.junit.runners.AndroidJUnit4 -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith - -/** - * This is an example startup benchmark. - * - * It navigates to the device's home screen, and launches the default activity. - * - * Before running this benchmark: - * 1) switch your app's active build variant in the Studio (affects Studio runs only) - * 2) add `` to your app's manifest, within the `` tag - * - * Run this benchmark from Studio to see startup measurements, and captured system traces - * for investigating your app's performance. - */ -@RunWith(AndroidJUnit4::class) -class ExampleStartupBenchmark { - @get:Rule - val benchmarkRule = MacrobenchmarkRule() - - @Test - fun startup() = benchmarkRule.measureRepeated( - packageName = "illyan.jay", - metrics = listOf(StartupTimingMetric()), - iterations = 5, - startupMode = StartupMode.COLD - ) { - pressHome() - startActivityAndWait() - } -} \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 9320a97a..b8638030 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -23,7 +23,7 @@ plugins { id 'kotlin-kapt' id 'kotlin-android' id 'com.google.dagger.hilt.android' - id 'com.google.devtools.ksp' version '1.8.0-1.0.9' // Depends on your kotlin version + id 'com.google.devtools.ksp' version "$kotlin_version-1.0.11-SNAPSHOT" // Depends on your kotlin version id 'de.mannodermaus.android-junit5' id 'kotlin-parcelize' id 'org.jetbrains.kotlin.plugin.serialization' @@ -40,8 +40,8 @@ android { applicationId "illyan.jay" minSdk 21 targetSdk 33 - versionCode 10 - versionName "0.2.7-alpha" + versionCode 13 + versionName "0.3.2-alpha" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { @@ -69,29 +69,36 @@ android { matchingFallbacks = ['release'] } } + compileOptions { sourceCompatibility JavaVersion.VERSION_17 targetCompatibility JavaVersion.VERSION_17 coreLibraryDesugaringEnabled true } + kotlin { jvmToolchain(17) } + buildFeatures { compose true } + composeOptions { - kotlinCompilerExtensionVersion "1.4.0" + kotlinCompilerExtensionVersion "1.4.5" } + packagingOptions { resources { excludes += '/META-INF/{AL2.0,LGPL2.1}' } } + testOptions { unitTests.returnDefaultValues = true animationsDisabled = true } + lint { // If set to true (default), stops the build if errors are found. // This is needed because CICD pipeline will flop without it. @@ -101,17 +108,17 @@ android { dependencies { // Core - implementation 'org.jetbrains.kotlin:kotlin-stdlib:1.8.10' - implementation "androidx.core:core-ktx:1.9.0" + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + implementation 'androidx.core:core-ktx:1.10.0' implementation "androidx.collection:collection-ktx:1.2.0" // The Collection extensions contain utility functions for working with Android's memory-efficient collection libraries, including ArrayMap, LongSparseArray, LruCache, and others. implementation "androidx.appcompat:appcompat:1.6.1" - implementation 'androidx.activity:activity-ktx:1.6.1' + implementation 'androidx.activity:activity-ktx:1.7.1' implementation "com.google.android.material:material:1.8.0" implementation fileTree(dir: 'libs', include: ['*.aar', '*.jar'], exclude: []) // Compose - def activity_version = '1.7.0-beta02' - def lifecycle_version = '2.6.0-rc01' + def activity_version = '1.7.0' + def lifecycle_version = '2.6.1' implementation "androidx.compose.ui:ui:$compose_version" implementation "androidx.compose.material:material:$compose_version" implementation 'androidx.compose.material3:material3:1.1.0-alpha07' @@ -119,7 +126,7 @@ dependencies { implementation "androidx.compose.ui:ui-util:$compose_version" implementation "androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version" implementation "androidx.lifecycle:lifecycle-runtime-compose:$lifecycle_version" - implementation "androidx.lifecycle:lifecycle-process:$lifecycle_version" + implementation "androidx.lifecycle:lifecycle-process:lifecycle_version" implementation "androidx.activity:activity-compose:$activity_version" androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version" debugImplementation "androidx.compose.ui:ui-tooling:$compose_version" @@ -128,7 +135,7 @@ dependencies { implementation "androidx.compose.foundation:foundation:$compose_version" // Baseline Profiles and benchmarking - implementation 'androidx.profileinstaller:profileinstaller:1.3.0-beta01' + implementation 'androidx.profileinstaller:profileinstaller:1.3.0' // Scrollbar implementation 'com.github.HLCaptain:compose-scrollbar:0.0.3-alpha' @@ -148,9 +155,9 @@ dependencies { implementation "me.saket.swipe:swipe:1.1.1" // Mapbox - implementation "com.mapbox.maps:android:10.11.0-beta.1" - implementation "com.mapbox.search:mapbox-search-android-ui:1.0.0-beta.44" - implementation "com.mapbox.navigation:android:2.11.0-beta.1" + implementation "com.mapbox.maps:android:10.13.0-beta.1" + implementation "com.mapbox.search:mapbox-search-android-ui:1.0.0-rc.3" + implementation "com.mapbox.navigation:android:2.13.0-beta.1" // Accompanist def accompanist_version = '0.29.1-alpha' @@ -159,7 +166,6 @@ dependencies { implementation "com.google.accompanist:accompanist-placeholder-material:$accompanist_version" // Hilt - def hilt_version = '2.44.2' implementation "com.google.dagger:hilt-android:$hilt_version" kapt "com.google.dagger:hilt-compiler:$hilt_version" implementation "androidx.hilt:hilt-navigation-compose:1.0.0" @@ -173,18 +179,13 @@ dependencies { ksp "io.github.raamcosta.compose-destinations:ksp:$compose_nav_version" // Coil - implementation "io.coil-kt:coil-compose:2.2.2" + implementation 'io.coil-kt:coil-compose:2.3.0' // Room - def room_version = '2.5.0' + def room_version = '2.5.1' implementation "androidx.room:room-ktx:$room_version" implementation "androidx.room:room-runtime:$room_version" kapt "androidx.room:room-compiler:$room_version" - implementation "androidx.room:room-rxjava2:$room_version" // optional - RxJava2 support for Room - implementation "androidx.room:room-rxjava3:$room_version" // optional - RxJava3 support for Room - implementation "androidx.room:room-guava:$room_version" // optional - Guava support for Room, including Optional and ListenableFuture - testImplementation "androidx.room:room-testing:$room_version" // optional - Test helpers - implementation "androidx.room:room-paging:$room_version" // optional - Paging 3 Integration // Serialization implementation "androidx.datastore:datastore:1.0.0" @@ -193,8 +194,8 @@ dependencies { implementation 'org.jetbrains.kotlinx:kotlinx-serialization-protobuf:1.5.0' // Compression - implementation 'com.github.luben:zstd-jni:1.5.4-2@aar' - testImplementation "com.github.luben:zstd-jni:1.5.4-2" + implementation 'com.github.luben:zstd-jni:1.5.5-2@aar' + testImplementation 'com.github.luben:zstd-jni:1.5.5-2' // Coroutine def coroutines_version = '1.6.4' @@ -204,13 +205,13 @@ dependencies { // Google services implementation 'com.google.android.gms:play-services-location:21.0.1' - implementation 'com.google.android.gms:play-services-auth:20.4.1' - implementation 'com.google.android.gms:play-services-ads:21.5.0' - implementation 'com.google.maps.android:android-maps-utils:2.4.0' + implementation 'com.google.android.gms:play-services-auth:20.5.0' + implementation 'com.google.android.gms:play-services-ads:22.0.0' + implementation 'com.google.maps.android:android-maps-utils:3.4.0' implementation 'com.google.maps.android:maps-utils-ktx:3.4.0' // Firebase - implementation platform('com.google.firebase:firebase-bom:31.0.3') + implementation platform('com.google.firebase:firebase-bom:31.5.0') implementation 'com.google.firebase:firebase-auth-ktx' implementation 'com.google.firebase:firebase-config-ktx' implementation 'com.google.firebase:firebase-analytics-ktx' @@ -232,7 +233,7 @@ dependencies { // MockK test tool def mockk_version = '1.13.2' testImplementation "io.mockk:mockk:$mockk_version" - androidTestImplementation "io.mockk:mockk-android:$mockk_version" + androidTestImplementation "io.mockk:mockk-android:mockk_version" // Other testing tools androidTestImplementation 'androidx.test.ext:junit:1.1.5' @@ -243,7 +244,7 @@ dependencies { androidTestImplementation 'androidx.test:rules:1.5.0' // Desugaring - coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.2.2' + coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3' } kapt { diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index cdc313f0..9b65471b 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -14,8 +14,18 @@ # Uncomment this to preserve the line number information for # debugging stack traces. --keepattributes SourceFile,LineNumberTable +-keepattributes SourceFile,LineNumberTable,Signature # If you keep the line number information, uncomment this to # hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file +#-renamesourcefileattribute SourceFile + +# Keep custom model classes +# TODO: remove this line when implemented Flows with Firestore +-keep class illyan.jay.data.firestore.model.** { *; } + +# Needed for Kotlin suspend functions according to https://r8.googlesource.com/r8/+/refs/heads/master/compatibility-faq.md#kotlin-suspend-functions-and-generic-signatures +-keep class kotlin.coroutines.Continuation + +# Needed for Firebase Auth to not crash when user signs in +-keep class com.google.android.gms.internal.** { *; } diff --git a/app/src/main/java/illyan/jay/MainApplication.kt b/app/src/main/java/illyan/jay/MainApplication.kt index 76de7ebf..fa9eeaf7 100644 --- a/app/src/main/java/illyan/jay/MainApplication.kt +++ b/app/src/main/java/illyan/jay/MainApplication.kt @@ -25,16 +25,18 @@ import com.google.firebase.analytics.FirebaseAnalytics import com.google.firebase.crashlytics.FirebaseCrashlytics import com.google.firebase.perf.FirebasePerformance import dagger.hilt.android.HiltAndroidApp -import illyan.jay.data.disk.model.AppSettings +import illyan.jay.data.datastore.model.AppSettings import illyan.jay.di.CoroutineScopeIO import illyan.jay.domain.interactor.AuthInteractor import illyan.jay.domain.interactor.SettingsInteractor import illyan.jay.util.log.CrashlyticsTree import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch import timber.log.Timber import javax.inject.Inject +import kotlin.coroutines.cancellation.CancellationException @HiltAndroidApp class MainApplication : Application() { @@ -48,6 +50,8 @@ class MainApplication : Application() { @Inject lateinit var settingsInteractor: SettingsInteractor @Inject @CoroutineScopeIO lateinit var coroutineScopeIO: CoroutineScope + private var logJob: Job? = null + override fun onCreate() { super.onCreate() @@ -64,25 +68,26 @@ class MainApplication : Application() { Timber.plant(debugTree) Timber.d("Planting debugTree") } - coroutineScopeIO.launch { + logJob?.cancel(CancellationException("Existing job to listen to preferences changes cancelled to avoid multiple threads listening to the same data")) + logJob = coroutineScopeIO.launch { settingsInteractor.userPreferences.collectLatest { preferences -> preferences?.let { crashlytics.setUserId(it.userUUID ?: "") analytics.setUserId(it.userUUID) val collectingData = Timber.forest().contains(crashlyticsTree) if (it.analyticsEnabled && !collectingData) { - Timber.d("Analytics On, Planting crashlyticsTree") Timber.plant(crashlyticsTree) + Timber.d("Analytics On, planted crashlyticsTree") crashlytics.setCrashlyticsCollectionEnabled(true) analytics.setAnalyticsCollectionEnabled(true) performance.isPerformanceCollectionEnabled = !BuildConfig.DEBUG // Don't measure performance in DEBUG mode } else if (!it.analyticsEnabled && collectingData) { + Timber.d("Analytics Off, uprooting crashlyticsTree") Timber.uproot(crashlyticsTree) + crashlytics.sendUnsentReports() crashlytics.setCrashlyticsCollectionEnabled(false) analytics.setAnalyticsCollectionEnabled(false) performance.isPerformanceCollectionEnabled = false - crashlytics.deleteUnsentReports() - Timber.d("Analytics Off, Uprooting crashlyticsTree") } } } diff --git a/app/src/main/java/illyan/jay/data/disk/model/AppSettings.kt b/app/src/main/java/illyan/jay/data/datastore/model/AppSettings.kt similarity index 75% rename from app/src/main/java/illyan/jay/data/disk/model/AppSettings.kt rename to app/src/main/java/illyan/jay/data/datastore/model/AppSettings.kt index 13a6a40f..9b9a86e6 100644 --- a/app/src/main/java/illyan/jay/data/disk/model/AppSettings.kt +++ b/app/src/main/java/illyan/jay/data/datastore/model/AppSettings.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022-2023 Balázs Püspök-Kiss (Illyan) + * Copyright (c) 2023 Balázs Püspök-Kiss (Illyan) * * Jay is a driver behaviour analytics app. * @@ -16,7 +16,7 @@ * If not, see . */ -package illyan.jay.data.disk.model +package illyan.jay.data.datastore.model import illyan.jay.domain.model.DomainPreferences import kotlinx.serialization.Serializable @@ -29,7 +29,4 @@ data class AppSettings( companion object { val default = AppSettings() } - // TODO: "Press this