From dd3b69e61dd1f31958523a198e702c24c08ef607 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 28 Feb 2023 12:11:17 +0800 Subject: [PATCH] Updated on 2026-08-14 --- .../tangem/tap/network/NetworkConnectivity.kt | 1 + core/datasource/build.gradle.kts | 1 + core/datasource/src/main/AndroidManifest.xml | 6 +- .../AndroidNetworkConnectionManager.kt | 111 ++++++++++++++++++ .../datasource/connection/ConnectionStatus.kt | 10 ++ .../connection/NetworkConnectionManager.kt | 10 ++ .../datasource/di/NetworkConnectionModule.kt | 20 ++++ 7 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 core/datasource/src/main/java/com/tangem/datasource/connection/AndroidNetworkConnectionManager.kt create mode 100644 core/datasource/src/main/java/com/tangem/datasource/connection/ConnectionStatus.kt create mode 100644 core/datasource/src/main/java/com/tangem/datasource/connection/NetworkConnectionManager.kt create mode 100644 core/datasource/src/main/java/com/tangem/datasource/di/NetworkConnectionModule.kt diff --git a/app/src/main/java/com/tangem/tap/network/NetworkConnectivity.kt b/app/src/main/java/com/tangem/tap/network/NetworkConnectivity.kt index 71d0ed9206..bf61064eaa 100644 --- a/app/src/main/java/com/tangem/tap/network/NetworkConnectivity.kt +++ b/app/src/main/java/com/tangem/tap/network/NetworkConnectivity.kt @@ -14,6 +14,7 @@ import java.lang.ref.WeakReference /** [REDACTED_AUTHOR] */ +@Deprecated("Use com.tangem.datasource.connection.NetworkConnectionManager") class NetworkConnectivity( private val store: Store<*>, context: Context, diff --git a/core/datasource/build.gradle.kts b/core/datasource/build.gradle.kts index e355c638cf..4cd3a19a15 100644 --- a/core/datasource/build.gradle.kts +++ b/core/datasource/build.gradle.kts @@ -40,6 +40,7 @@ android { dependencies { /** Project */ + implementation(project(":core:utils")) implementation(project(":libs:auth")) /** Tangem libraries */ diff --git a/core/datasource/src/main/AndroidManifest.xml b/core/datasource/src/main/AndroidManifest.xml index d6401c6174..b7e7790e14 100644 --- a/core/datasource/src/main/AndroidManifest.xml +++ b/core/datasource/src/main/AndroidManifest.xml @@ -1,2 +1,6 @@ - \ No newline at end of file + + + + \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/connection/AndroidNetworkConnectionManager.kt b/core/datasource/src/main/java/com/tangem/datasource/connection/AndroidNetworkConnectionManager.kt new file mode 100644 index 0000000000..d5bff89d3b --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/connection/AndroidNetworkConnectionManager.kt @@ -0,0 +1,111 @@ +package com.tangem.datasource.connection + +import android.app.Activity +import android.app.Application +import android.app.Application.ActivityLifecycleCallbacks +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.net.NetworkCapabilities +import android.os.Build +import android.os.Bundle +import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import dagger.hilt.android.qualifiers.ApplicationContext +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.launch +import timber.log.Timber +import javax.inject.Inject +import javax.inject.Singleton +import android.net.ConnectivityManager as AndroidConnectivityManager + +/** + * Network connection manager implementation using Android connectivity service + * + * @property context application context for registration lifecycle callbacks + * @property dispatchers coroutine dispatcher provider + * +[REDACTED_AUTHOR] + */ +@Singleton +internal class AndroidNetworkConnectionManager @Inject constructor( + @ApplicationContext private val context: Context, + private val dispatchers: CoroutineDispatcherProvider, +) : NetworkConnectionManager { + + override val connectionStatus: StateFlow get() = _connectionStatus + + private val _connectionStatus = MutableStateFlow(ConnectionStatus.OFFLINE) + private val callbacks = NetworkConnectionManagerCallbacks() + private val receiver = NetworkConnectionBroadcastReceiver() + + init { + (context as? Application)?.registerActivityLifecycleCallbacks(callbacks) + } + + private inner class NetworkConnectionManagerCallbacks : ActivityLifecycleCallbacks { + + override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { + val intentFilter = IntentFilter().apply { + addAction(AndroidConnectivityManager.CONNECTIVITY_ACTION) + } + + activity.registerReceiver(receiver, intentFilter) + } + + override fun onActivityStarted(activity: Activity) = Unit + override fun onActivityResumed(activity: Activity) = Unit + override fun onActivityPaused(activity: Activity) = Unit + override fun onActivityStopped(activity: Activity) = Unit + override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) = Unit + + override fun onActivityDestroyed(activity: Activity) { + activity.unregisterReceiver(receiver) + (context as? Application)?.unregisterActivityLifecycleCallbacks(callbacks) + } + } + + private inner class NetworkConnectionBroadcastReceiver : BroadcastReceiver() { + + private val connectivityManager: android.net.ConnectivityManager? = + context.getSystemService(Context.CONNECTIVITY_SERVICE) as? android.net.ConnectivityManager + + override fun onReceive(c: Context?, intent: Intent?) { + val pendingResult = goAsync() + + CoroutineScope(SupervisorJob()).launch(dispatchers.io) { + try { + val status = getCurrentStatus() + + _connectionStatus.emit(value = status) + Timber.i("Status changed to $status") + } finally { + pendingResult.finish() + } + } + } + + private fun getCurrentStatus(): ConnectionStatus { + connectivityManager ?: return ConnectionStatus.OFFLINE + + val isConnected = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + val capabilities = connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork) + capabilities != null && capabilities.hasNetworkTransport() + } else { + val networkInfo = connectivityManager.activeNetworkInfo + networkInfo != null && networkInfo.isConnectedOrConnecting + } + + return if (isConnected) ConnectionStatus.ONLINE else ConnectionStatus.OFFLINE + } + + private fun NetworkCapabilities.hasNetworkTransport(): Boolean { + return hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) || + hasTransport(NetworkCapabilities.TRANSPORT_WIFI) || + hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) + } + } +} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/connection/ConnectionStatus.kt b/core/datasource/src/main/java/com/tangem/datasource/connection/ConnectionStatus.kt new file mode 100644 index 0000000000..b59aa6f4df --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/connection/ConnectionStatus.kt @@ -0,0 +1,10 @@ +package com.tangem.datasource.connection + +/** + * Network connection status + * +[REDACTED_AUTHOR] + */ +enum class ConnectionStatus { + ONLINE, OFFLINE +} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/connection/NetworkConnectionManager.kt b/core/datasource/src/main/java/com/tangem/datasource/connection/NetworkConnectionManager.kt new file mode 100644 index 0000000000..9d6c73849d --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/connection/NetworkConnectionManager.kt @@ -0,0 +1,10 @@ +package com.tangem.datasource.connection + +import kotlinx.coroutines.flow.StateFlow + +/** Network connection manager */ +interface NetworkConnectionManager { + + /** Connection status */ + val connectionStatus: StateFlow +} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/di/NetworkConnectionModule.kt b/core/datasource/src/main/java/com/tangem/datasource/di/NetworkConnectionModule.kt new file mode 100644 index 0000000000..d112c7ccab --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/di/NetworkConnectionModule.kt @@ -0,0 +1,20 @@ +package com.tangem.datasource.di + +import com.tangem.datasource.connection.AndroidNetworkConnectionManager +import com.tangem.datasource.connection.NetworkConnectionManager +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +internal interface NetworkConnectionModule { + + @Binds + @Singleton + fun bindNetworkConnectionManager( + androidNetworkConnectionManager: AndroidNetworkConnectionManager, + ): NetworkConnectionManager +} \ No newline at end of file