diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index cd0d0540d80..e146779449b 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -70,6 +70,7 @@ dependencies {
implementation(libs.androidx.splashscreen)
implementation(libs.androidx.exifInterface)
implementation(libs.androidx.biometric)
+ implementation(libs.androidx.startup)
implementation(libs.ktx.dateTime)
implementation(libs.material)
diff --git a/app/src/dev/kotlin/com/wire/android/util/DataDogLogger.kt b/app/src/dev/kotlin/com/wire/android/util/DataDogLogger.kt
index 8eaf3265325..fd84a0bfccd 100644
--- a/app/src/dev/kotlin/com/wire/android/util/DataDogLogger.kt
+++ b/app/src/dev/kotlin/com/wire/android/util/DataDogLogger.kt
@@ -29,8 +29,8 @@ object DataDogLogger : LogWriter() {
private val logger = Logger.Builder()
.setNetworkInfoEnabled(true)
- .setLogcatLogsEnabled(true)
.setLogcatLogsEnabled(false) // we already use platformLogWriter() along with DataDogLogger, don't need duplicates in LogCat
+ .setDatadogLogsEnabled(true)
.setBundleWithTraceEnabled(true)
.setLoggerName("DATADOG")
.build()
diff --git a/app/src/internal/kotlin/com/wire/android/util/DataDogLogger.kt b/app/src/internal/kotlin/com/wire/android/util/DataDogLogger.kt
index 8eaf3265325..fd84a0bfccd 100644
--- a/app/src/internal/kotlin/com/wire/android/util/DataDogLogger.kt
+++ b/app/src/internal/kotlin/com/wire/android/util/DataDogLogger.kt
@@ -29,8 +29,8 @@ object DataDogLogger : LogWriter() {
private val logger = Logger.Builder()
.setNetworkInfoEnabled(true)
- .setLogcatLogsEnabled(true)
.setLogcatLogsEnabled(false) // we already use platformLogWriter() along with DataDogLogger, don't need duplicates in LogCat
+ .setDatadogLogsEnabled(true)
.setBundleWithTraceEnabled(true)
.setLoggerName("DATADOG")
.build()
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index f60f99354dc..385b88f5933 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -229,17 +229,34 @@
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/kotlin/com/wire/android/WireApplication.kt b/app/src/main/kotlin/com/wire/android/WireApplication.kt
index 7924cbf3153..5554a2e5614 100644
--- a/app/src/main/kotlin/com/wire/android/WireApplication.kt
+++ b/app/src/main/kotlin/com/wire/android/WireApplication.kt
@@ -24,14 +24,11 @@ import android.os.Build
import android.os.StrictMode
import androidx.work.Configuration
import co.touchlab.kermit.platformLogWriter
-import com.google.firebase.FirebaseApp
-import com.google.firebase.FirebaseOptions
import com.wire.android.datastore.GlobalDataStore
import com.wire.android.di.ApplicationScope
import com.wire.android.di.KaliumCoreLogic
import com.wire.android.util.DataDogLogger
import com.wire.android.util.LogFileWriter
-import com.wire.android.util.extension.isGoogleServicesAvailable
import com.wire.android.util.getGitBuildId
import com.wire.android.util.lifecycle.ConnectionPolicyManager
import com.wire.android.workmanager.WireWorkerFactory
@@ -39,6 +36,7 @@ import com.wire.kalium.logger.KaliumLogLevel
import com.wire.kalium.logger.KaliumLogger
import com.wire.kalium.logic.CoreLogger
import com.wire.kalium.logic.CoreLogic
+import dagger.Lazy
import dagger.hilt.android.HiltAndroidApp
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.first
@@ -50,29 +48,29 @@ class WireApplication : Application(), Configuration.Provider {
@Inject
@KaliumCoreLogic
- lateinit var coreLogic: CoreLogic
+ lateinit var coreLogic: Lazy
@Inject
- lateinit var logFileWriter: LogFileWriter
+ lateinit var logFileWriter: Lazy
@Inject
- lateinit var connectionPolicyManager: ConnectionPolicyManager
+ lateinit var connectionPolicyManager: Lazy
@Inject
- lateinit var wireWorkerFactory: WireWorkerFactory
+ lateinit var wireWorkerFactory: Lazy
@Inject
- lateinit var globalObserversManager: GlobalObserversManager
+ lateinit var globalObserversManager: Lazy
@Inject
- lateinit var globalDataStore: GlobalDataStore
+ lateinit var globalDataStore: Lazy
@Inject
@ApplicationScope
lateinit var globalAppScope: CoroutineScope
override fun getWorkManagerConfiguration(): Configuration {
return Configuration.Builder()
- .setWorkerFactory(wireWorkerFactory)
+ .setWorkerFactory(wireWorkerFactory.get())
.build()
}
@@ -81,23 +79,19 @@ class WireApplication : Application(), Configuration.Provider {
enableStrictMode()
- if (this.isGoogleServicesAvailable()) {
- val firebaseOptions = FirebaseOptions.Builder()
- .setApplicationId(BuildConfig.FIREBASE_APP_ID)
- .setGcmSenderId(BuildConfig.FIREBASE_PUSH_SENDER_ID)
- .setApiKey(BuildConfig.GOOGLE_API_KEY)
- .setProjectId(BuildConfig.FCM_PROJECT_ID)
- .build()
- FirebaseApp.initializeApp(this, firebaseOptions)
- }
+ globalAppScope.launch {
+ initializeApplicationLoggingFrameworks()
- initializeApplicationLoggingFrameworks()
- connectionPolicyManager.startObservingAppLifecycle()
+ appLogger.i("$TAG app lifecycle")
+ connectionPolicyManager.get().startObservingAppLifecycle()
- // TODO: Can be handled in one of Sync steps
- coreLogic.updateApiVersionsScheduler.schedulePeriodicApiVersionUpdate()
+ appLogger.i("$TAG api version update")
+ // TODO: Can be handled in one of Sync steps
+ coreLogic.get().updateApiVersionsScheduler.schedulePeriodicApiVersionUpdate()
- globalObserversManager.observe()
+ appLogger.i("$TAG global observers")
+ globalObserversManager.get().observe()
+ }
}
private fun enableStrictMode() {
@@ -121,29 +115,27 @@ class WireApplication : Application(), Configuration.Provider {
}
}
- private fun initializeApplicationLoggingFrameworks() {
- globalAppScope.launch {
- // 1. Datadog should be initialized first
- ExternalLoggerManager.initDatadogLogger(applicationContext, globalDataStore)
- // 2. Initialize our internal logging framework
- val isLoggingEnabled = globalDataStore.isLoggingEnabled().first()
- val config = if (isLoggingEnabled) {
- KaliumLogger.Config.DEFAULT.apply {
- setLogLevel(KaliumLogLevel.VERBOSE)
- setLogWriterList(listOf(DataDogLogger, platformLogWriter()))
- }
- } else {
- KaliumLogger.Config.disabled()
+ private suspend fun initializeApplicationLoggingFrameworks() {
+ // 1. Datadog should be initialized first
+ ExternalLoggerManager.initDatadogLogger(applicationContext, globalDataStore.get())
+ // 2. Initialize our internal logging framework
+ val isLoggingEnabled = globalDataStore.get().isLoggingEnabled().first()
+ val config = if (isLoggingEnabled) {
+ KaliumLogger.Config.DEFAULT.apply {
+ setLogLevel(KaliumLogLevel.VERBOSE)
+ setLogWriterList(listOf(DataDogLogger, platformLogWriter()))
}
- // 2. Initialize our internal logging framework
- AppLogger.init(config)
- CoreLogger.init(config)
- // 3. Initialize our internal FILE logging framework
- logFileWriter.start()
- // 4. Everything ready, now we can log device info
- appLogger.i("Logger enabled")
- logDeviceInformation()
+ } else {
+ KaliumLogger.Config.disabled()
}
+ // 2. Initialize our internal logging framework
+ AppLogger.init(config)
+ CoreLogger.init(config)
+ // 3. Initialize our internal FILE logging framework
+ logFileWriter.get().start()
+ // 4. Everything ready, now we can log device info
+ appLogger.i("Logger enabled")
+ logDeviceInformation()
}
private fun logDeviceInformation() {
@@ -169,7 +161,7 @@ class WireApplication : Application(), Configuration.Provider {
override fun onLowMemory() {
super.onLowMemory()
appLogger.w("onLowMemory called - Stopping logging, buckling the seatbelt and hoping for the best!")
- logFileWriter.stop()
+ logFileWriter.get().stop()
}
private companion object {
@@ -190,5 +182,6 @@ class WireApplication : Application(), Configuration.Provider {
values().firstOrNull { it.level == value } ?: TRIM_MEMORY_UNKNOWN
}
}
+ private const val TAG = "WireApplication"
}
}
diff --git a/app/src/main/kotlin/com/wire/android/initializer/FirebaseInitializer.kt b/app/src/main/kotlin/com/wire/android/initializer/FirebaseInitializer.kt
new file mode 100644
index 00000000000..2a5f62a33ad
--- /dev/null
+++ b/app/src/main/kotlin/com/wire/android/initializer/FirebaseInitializer.kt
@@ -0,0 +1,40 @@
+/*
+ * Wire
+ * Copyright (C) 2024 Wire Swiss GmbH
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see http://www.gnu.org/licenses/.
+ */
+package com.wire.android.initializer
+
+import android.content.Context
+import androidx.startup.Initializer
+import com.google.firebase.FirebaseApp
+import com.google.firebase.FirebaseOptions
+import com.wire.android.BuildConfig
+import com.wire.android.util.extension.isGoogleServicesAvailable
+
+class FirebaseInitializer : Initializer {
+ override fun create(context: Context) {
+ if (context.isGoogleServicesAvailable()) {
+ val firebaseOptions = FirebaseOptions.Builder()
+ .setApplicationId(BuildConfig.FIREBASE_APP_ID)
+ .setGcmSenderId(BuildConfig.FIREBASE_PUSH_SENDER_ID)
+ .setApiKey(BuildConfig.GOOGLE_API_KEY)
+ .setProjectId(BuildConfig.FCM_PROJECT_ID)
+ .build()
+ FirebaseApp.initializeApp(context, firebaseOptions)
+ }
+ }
+ override fun dependencies(): List>> = emptyList() // no dependencies on other libraries
+}
diff --git a/app/src/main/kotlin/com/wire/android/initializer/InitializerEntryPoint.kt b/app/src/main/kotlin/com/wire/android/initializer/InitializerEntryPoint.kt
new file mode 100644
index 00000000000..365ce3eac6b
--- /dev/null
+++ b/app/src/main/kotlin/com/wire/android/initializer/InitializerEntryPoint.kt
@@ -0,0 +1,37 @@
+/*
+ * Wire
+ * Copyright (C) 2024 Wire Swiss GmbH
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see http://www.gnu.org/licenses/.
+ */
+package com.wire.android.initializer
+
+import android.content.Context
+import dagger.hilt.EntryPoint
+import dagger.hilt.InstallIn
+import dagger.hilt.android.EntryPointAccessors
+import dagger.hilt.components.SingletonComponent
+
+@EntryPoint
+@InstallIn(SingletonComponent::class)
+interface InitializerEntryPoint {
+
+ companion object {
+ // a helper method to resolve the InitializerEntryPoint from the context
+ fun resolve(context: Context): InitializerEntryPoint {
+ val appContext = context.applicationContext ?: throw IllegalStateException()
+ return EntryPointAccessors.fromApplication(appContext, InitializerEntryPoint::class.java)
+ }
+ }
+}
diff --git a/app/src/main/kotlin/com/wire/android/ui/WireActivity.kt b/app/src/main/kotlin/com/wire/android/ui/WireActivity.kt
index 5e7381dae30..e1b4e05ae21 100644
--- a/app/src/main/kotlin/com/wire/android/ui/WireActivity.kt
+++ b/app/src/main/kotlin/com/wire/android/ui/WireActivity.kt
@@ -97,6 +97,7 @@ import com.wire.android.util.debug.FeatureVisibilityFlags
import com.wire.android.util.debug.LocalFeatureVisibilityFlags
import com.wire.android.util.deeplink.DeepLinkResult
import com.wire.android.util.ui.updateScreenSettings
+import dagger.Lazy
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.collectLatest
@@ -117,7 +118,7 @@ class WireActivity : AppCompatActivity() {
lateinit var proximitySensorManager: ProximitySensorManager
@Inject
- lateinit var lockCodeTimeManager: LockCodeTimeManager
+ lateinit var lockCodeTimeManager: Lazy
private val viewModel: WireActivityViewModel by viewModels()
@@ -133,26 +134,39 @@ class WireActivity : AppCompatActivity() {
private var shouldKeepSplashOpen = true
override fun onCreate(savedInstanceState: Bundle?) {
+
+ appLogger.i("$TAG splash install")
// We need to keep the splash screen open until the first screen is drawn.
// Otherwise a white screen is displayed.
// It's an API limitation, at some point we may need to remove it
- installSplashScreen().setKeepOnScreenCondition {
- shouldKeepSplashOpen
- }
+ val splashScreen = installSplashScreen()
super.onCreate(savedInstanceState)
- proximitySensorManager.initialize()
+ splashScreen.setKeepOnScreenCondition { shouldKeepSplashOpen }
+
lifecycle.addObserver(currentScreenManager)
WindowCompat.setDecorFitsSystemWindows(window, false)
- viewModel.observePersistentConnectionStatus()
- val startDestination = when (viewModel.initialAppState) {
- InitialAppState.NOT_MIGRATED -> MigrationScreenDestination
- InitialAppState.NOT_LOGGED_IN -> WelcomeScreenDestination
- InitialAppState.LOGGED_IN -> HomeScreenDestination
- }
- setComposableContent(startDestination) {
- shouldKeepSplashOpen = false
- handleDeepLink(intent, savedInstanceState)
+ appLogger.i("$TAG proximity sensor")
+ proximitySensorManager.initialize()
+
+ lifecycleScope.launch {
+
+ appLogger.i("$TAG persistent connection status")
+ viewModel.observePersistentConnectionStatus()
+
+ appLogger.i("$TAG start destination")
+ val startDestination = when (viewModel.initialAppState) {
+ InitialAppState.NOT_MIGRATED -> MigrationScreenDestination
+ InitialAppState.NOT_LOGGED_IN -> WelcomeScreenDestination
+ InitialAppState.LOGGED_IN -> HomeScreenDestination
+ }
+
+ appLogger.i("$TAG composable content")
+ setComposableContent(startDestination) {
+ appLogger.i("$TAG splash hide")
+ shouldKeepSplashOpen = false
+ handleDeepLink(intent, savedInstanceState)
+ }
}
}
@@ -412,7 +426,7 @@ class WireActivity : AppCompatActivity() {
super.onResume()
lifecycleScope.launch {
- lockCodeTimeManager.observeAppLock()
+ lockCodeTimeManager.get().observeAppLock()
// Listen to one flow in a lifecycle-aware manner using flowWithLifecycle
.flowWithLifecycle(lifecycle, Lifecycle.State.STARTED)
.first().let {
@@ -506,6 +520,7 @@ class WireActivity : AppCompatActivity() {
companion object {
private const val HANDLED_DEEPLINK_FLAG = "deeplink_handled_flag_key"
+ private const val TAG = "WireActivity"
}
}
diff --git a/app/src/main/kotlin/com/wire/android/ui/calling/ProximitySensorManager.kt b/app/src/main/kotlin/com/wire/android/ui/calling/ProximitySensorManager.kt
index cd688f23720..d72a972fb9b 100644
--- a/app/src/main/kotlin/com/wire/android/ui/calling/ProximitySensorManager.kt
+++ b/app/src/main/kotlin/com/wire/android/ui/calling/ProximitySensorManager.kt
@@ -31,6 +31,7 @@ import com.wire.android.di.KaliumCoreLogic
import com.wire.kalium.logic.CoreLogic
import com.wire.kalium.logic.feature.session.CurrentSessionResult
import com.wire.kalium.logic.feature.session.CurrentSessionUseCase
+import dagger.Lazy
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import javax.inject.Inject
@@ -39,8 +40,8 @@ import javax.inject.Singleton
@Singleton
class ProximitySensorManager @Inject constructor(
private val context: Context,
- private val currentSession: CurrentSessionUseCase,
- @KaliumCoreLogic private val coreLogic: CoreLogic,
+ private val currentSession: Lazy,
+ @KaliumCoreLogic private val coreLogic: Lazy,
@ApplicationScope private val appCoroutineScope: CoroutineScope
) {
@@ -69,11 +70,11 @@ class ProximitySensorManager @Inject constructor(
override fun onSensorChanged(event: SensorEvent) {
appCoroutineScope.launch {
- coreLogic.globalScope {
- when (val currentSession = currentSession()) {
+ coreLogic.get().globalScope {
+ when (val currentSession = currentSession.get().invoke()) {
is CurrentSessionResult.Success -> {
val userId = currentSession.accountInfo.userId
- val isCallRunning = coreLogic.getSessionScope(userId).calls.isCallRunning()
+ val isCallRunning = coreLogic.get().getSessionScope(userId).calls.isCallRunning()
val distance = event.values.first()
val shouldTurnOffScreen = distance == NEAR_DISTANCE && isCallRunning
appLogger.i(
diff --git a/app/src/main/res/drawable/ic_launcher_wire_logo.xml b/app/src/main/res/drawable/ic_launcher_wire_logo.xml
new file mode 100644
index 00000000000..afddf1deab2
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_wire_logo.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/src/staging/kotlin/com/wire/android/util/DataDogLogger.kt b/app/src/staging/kotlin/com/wire/android/util/DataDogLogger.kt
index 8eaf3265325..fd84a0bfccd 100644
--- a/app/src/staging/kotlin/com/wire/android/util/DataDogLogger.kt
+++ b/app/src/staging/kotlin/com/wire/android/util/DataDogLogger.kt
@@ -29,8 +29,8 @@ object DataDogLogger : LogWriter() {
private val logger = Logger.Builder()
.setNetworkInfoEnabled(true)
- .setLogcatLogsEnabled(true)
.setLogcatLogsEnabled(false) // we already use platformLogWriter() along with DataDogLogger, don't need duplicates in LogCat
+ .setDatadogLogsEnabled(true)
.setBundleWithTraceEnabled(true)
.setLoggerName("DATADOG")
.build()
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 90f4c21fb1b..6969257997c 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -36,6 +36,7 @@ androidx-splashscreen = "1.0.1"
androidx-workManager = "2.8.1"
androidx-browser = "1.5.0"
androidx-biometric = "1.1.0"
+androidx-startup = "1.1.1"
# Compose
composeBom = "2023.10.01" # TODO check if in new version [anchoredDraggable] is available
@@ -158,6 +159,7 @@ androidx-exifInterface = { module = "androidx.exifinterface:exifinterface", vers
androidx-splashscreen = { module = "androidx.core:core-splashscreen", version.ref = "androidx-splashscreen" }
androidx-profile-installer = { group = "androidx.profileinstaller", name = "profileinstaller", version.ref = "profileinstaller" }
androidx-biometric = { group = "androidx.biometric", name = "biometric", version.ref = "androidx-biometric" }
+androidx-startup = { group = "androidx.startup", name = "startup-runtime", version.ref = "androidx-startup" }
# Dependency Injection
hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hilt" }