diff --git a/app/src/main/java/com/tangem/tap/MainActivity.kt b/app/src/main/java/com/tangem/tap/MainActivity.kt index 982967b3ea..6753d90394 100644 --- a/app/src/main/java/com/tangem/tap/MainActivity.kt +++ b/app/src/main/java/com/tangem/tap/MainActivity.kt @@ -37,7 +37,7 @@ import com.tangem.core.navigation.email.EmailSender import com.tangem.core.ui.event.StateEvent import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.resolveReference -import com.tangem.data.card.sdk.CardSdkLifecycleObserver +import com.tangem.data.card.sdk.CardSdkOwner import com.tangem.domain.apptheme.model.AppThemeMode import com.tangem.domain.card.ScanCardUseCase import com.tangem.domain.card.repository.CardSdkConfigRepository @@ -108,7 +108,7 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac lateinit var testerRouter: TesterRouter @Inject - lateinit var cardSdkLifecycleObserver: CardSdkLifecycleObserver + lateinit var cardSdkOwner: CardSdkOwner @Inject lateinit var cardSdkConfigRepository: CardSdkConfigRepository @@ -218,7 +218,7 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac private fun installActivityDependencies() { store.dispatch(NavigationAction.ActivityCreated(WeakReference(this))) - cardSdkLifecycleObserver.onCreate(context = this) + cardSdkOwner.register(activity = this) tangemSdkManager = injectedTangemSdkManager appStateHolder.tangemSdkManager = tangemSdkManager backupService = BackupService.init(cardSdkConfigRepository.sdk, this) @@ -327,7 +327,6 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac override fun onDestroy() { store.dispatch(NavigationAction.ActivityDestroyed(WeakReference(this))) intentProcessor.removeAll() - cardSdkLifecycleObserver.onDestroy(this) super.onDestroy() } @@ -363,12 +362,6 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) - /* - * FIXME: Test functionality. TangemSdk is null on some devices when HomeAction.Read is called - * inside IntentHandler. - */ - cardSdkLifecycleObserver.onCreate(context = this) - lifecycleScope.launch { intentProcessor.handleIntent(intent, true) } diff --git a/app/src/main/java/com/tangem/tap/TangemApplication.kt b/app/src/main/java/com/tangem/tap/TangemApplication.kt index 73e4bcd76f..d9b90a7bb9 100644 --- a/app/src/main/java/com/tangem/tap/TangemApplication.kt +++ b/app/src/main/java/com/tangem/tap/TangemApplication.kt @@ -353,6 +353,7 @@ abstract class TangemApplication : Application(), ImageLoaderFactory { Log.Level.Network, Log.Level.Error, Log.Level.Biometric, + Log.Level.Info, ) return TangemLogCollector(logLevels, LogFormat.StairsFormatter()) } diff --git a/app/src/main/java/com/tangem/tap/features/welcome/ui/components/WelcomeScreenContent.kt b/app/src/main/java/com/tangem/tap/features/welcome/ui/components/WelcomeScreenContent.kt index 5aca214e93..7fb08b3681 100644 --- a/app/src/main/java/com/tangem/tap/features/welcome/ui/components/WelcomeScreenContent.kt +++ b/app/src/main/java/com/tangem/tap/features/welcome/ui/components/WelcomeScreenContent.kt @@ -13,8 +13,8 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import com.tangem.core.ui.components.* -import com.tangem.core.ui.res.TangemThemePreview import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TangemThemePreview import com.tangem.wallet.R @Suppress("LongMethod") diff --git a/data/card/src/main/java/com/tangem/data/card/di/CardSdkModule.kt b/data/card/src/main/java/com/tangem/data/card/di/CardSdkModule.kt index c88f2dbfc2..891c418cb1 100644 --- a/data/card/src/main/java/com/tangem/data/card/di/CardSdkModule.kt +++ b/data/card/src/main/java/com/tangem/data/card/di/CardSdkModule.kt @@ -1,6 +1,6 @@ package com.tangem.data.card.di -import com.tangem.data.card.sdk.CardSdkLifecycleObserver +import com.tangem.data.card.sdk.CardSdkOwner import com.tangem.data.card.sdk.CardSdkProvider import com.tangem.data.card.sdk.DefaultCardSdkProvider import dagger.Binds @@ -19,5 +19,5 @@ internal interface CardSdkModule { @Binds @Singleton - fun providerCardSdkLifecycleObserver(defaultCardSdkProvider: DefaultCardSdkProvider): CardSdkLifecycleObserver + fun providerCardSdkLifecycleObserver(defaultCardSdkProvider: DefaultCardSdkProvider): CardSdkOwner } \ No newline at end of file diff --git a/data/card/src/main/java/com/tangem/data/card/sdk/CardSdkLifecycleObserver.kt b/data/card/src/main/java/com/tangem/data/card/sdk/CardSdkLifecycleObserver.kt deleted file mode 100644 index 212ff3a8bf..0000000000 --- a/data/card/src/main/java/com/tangem/data/card/sdk/CardSdkLifecycleObserver.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.tangem.data.card.sdk - -import android.content.Context - -/** - * Lifecycle observer for creating Card SDK instance - * -[REDACTED_AUTHOR] - */ -interface CardSdkLifecycleObserver { - - /** Callback of creating activity [context] */ - fun onCreate(context: Context) - - /** Callback of destroying activity [context] */ - fun onDestroy(context: Context) -} \ No newline at end of file diff --git a/data/card/src/main/java/com/tangem/data/card/sdk/CardSdkOwner.kt b/data/card/src/main/java/com/tangem/data/card/sdk/CardSdkOwner.kt new file mode 100644 index 0000000000..a5654ef6ec --- /dev/null +++ b/data/card/src/main/java/com/tangem/data/card/sdk/CardSdkOwner.kt @@ -0,0 +1,13 @@ +package com.tangem.data.card.sdk + +import androidx.fragment.app.FragmentActivity + +/** + * Lifecycle observer for creating Card SDK instance + * +[REDACTED_AUTHOR] + */ +interface CardSdkOwner { + + fun register(activity: FragmentActivity) +} \ No newline at end of file diff --git a/data/card/src/main/java/com/tangem/data/card/sdk/DefaultCardSdkProvider.kt b/data/card/src/main/java/com/tangem/data/card/sdk/DefaultCardSdkProvider.kt index 8c91326d64..cdc3c2e305 100644 --- a/data/card/src/main/java/com/tangem/data/card/sdk/DefaultCardSdkProvider.kt +++ b/data/card/src/main/java/com/tangem/data/card/sdk/DefaultCardSdkProvider.kt @@ -1,12 +1,21 @@ package com.tangem.data.card.sdk -import android.content.Context import androidx.fragment.app.FragmentActivity +import androidx.lifecycle.DefaultLifecycleObserver +import androidx.lifecycle.LifecycleObserver +import androidx.lifecycle.LifecycleOwner +import com.tangem.Log import com.tangem.TangemSdk import com.tangem.common.CardFilter +import com.tangem.common.authentication.AuthenticationManager import com.tangem.common.card.FirmwareVersion import com.tangem.common.core.Config -import com.tangem.sdk.extensions.initWithBiometrics +import com.tangem.common.services.secure.SecureStorage +import com.tangem.crypto.bip39.Wordlist +import com.tangem.sdk.DefaultSessionViewDelegate +import com.tangem.sdk.extensions.* +import com.tangem.sdk.nfc.NfcManager +import com.tangem.sdk.storage.create import javax.inject.Inject import javax.inject.Singleton @@ -16,24 +25,87 @@ import javax.inject.Singleton [REDACTED_AUTHOR] */ @Singleton -internal class DefaultCardSdkProvider @Inject constructor() : CardSdkProvider, CardSdkLifecycleObserver { +internal class DefaultCardSdkProvider @Inject constructor() : CardSdkProvider, CardSdkOwner { override val sdk: TangemSdk - get() = requireNotNull(value = _sdk) { "Impossible to get the TangemSdk when activity is destroyed" } + get() = requireNotNull(value = holder?.sdk) { + "Impossible to get the TangemSdk when activity is destroyed" + } - private var _sdk: TangemSdk? = null + private val observer: LifecycleObserver = Observer() - override fun onCreate(context: Context) { - _sdk = TangemSdk.initWithBiometrics(activity = context as FragmentActivity, config = config) + private var holder: Holder? = null + + override fun register(activity: FragmentActivity) { + Log.info { "Tangem SDK owner registered" } + + if (holder != null) { + unsubscribeAndCleanup() + } + + initialize(activity) + + activity.lifecycle.addObserver(observer) } - override fun onDestroy(context: Context) { - // Commented out to prevent crash on getting sdk when it's null. - // FIXME: We still should find the real cause and fix it properly. - // idea: pass everywhere DefaultCardSdkProvider instead sdk to reach lazy access to sdk property - // _sdk = null + private fun initialize(activity: FragmentActivity) { + val secureStorage = SecureStorage.create(activity) + val nfcManager = TangemSdk.initNfcManager(activity) + val authenticationManager = TangemSdk.initAuthenticationManager(activity) + val keystoreManager = TangemSdk.initKeystoreManager(authenticationManager, secureStorage) + + val viewDelegate = DefaultSessionViewDelegate(nfcManager, activity) + viewDelegate.sdkConfig = config + + val sdk = TangemSdk( + reader = nfcManager.reader, + viewDelegate = viewDelegate, + secureStorage = secureStorage, + authenticationManager = authenticationManager, + keystoreManager = keystoreManager, + wordlist = Wordlist.getWordlist(activity), + config = config, + ) + + holder = Holder( + activity = activity, + nfcManager = nfcManager, + authenticationManager = authenticationManager, + sdk = sdk, + ) + + Log.info { "Tangem SDK initialized" } } + private fun unsubscribeAndCleanup() { + with(receiver = holder ?: return) { + nfcManager.unsubscribe(activity) + authenticationManager.unsubscribe(activity) + + activity.lifecycle.removeObserver(observer) + } + + holder = null + + Log.info { "Tangem SDK unsubscribed and cleaned up" } + } + + inner class Observer : DefaultLifecycleObserver { + + override fun onDestroy(owner: LifecycleOwner) { + Log.info { "Tangem SDK owner destroyed" } + + unsubscribeAndCleanup() + } + } + + data class Holder( + val activity: FragmentActivity, + val sdk: TangemSdk, + val nfcManager: NfcManager, + val authenticationManager: AuthenticationManager, + ) + private companion object { val config = Config(