Updated on 2026-08-14

This commit is contained in:
Tangem 2024-07-01 16:31:14 +04:00
parent c4af41a48a
commit 1c6a173362
7 changed files with 104 additions and 42 deletions

View file

@ -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)
}

View file

@ -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())
}

View file

@ -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")

View file

@ -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
}

View file

@ -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)
}

View file

@ -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)
}

View file

@ -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(