Updated on 2026-08-14

This commit is contained in:
Tangem 2023-02-28 11:23:39 +03:00
commit 79b98686e4
7 changed files with 158 additions and 1 deletions

View file

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

View file

@ -40,6 +40,7 @@ android {
dependencies {
/** Project */
implementation(project(":core:utils"))
implementation(project(":libs:auth"))
/** Tangem libraries */

View file

@ -1,2 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.tangem.datasource" />
<manifest package="com.tangem.datasource"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>

View file

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

View file

@ -0,0 +1,10 @@
package com.tangem.datasource.connection
/**
* Network connection status
*
[REDACTED_AUTHOR]
*/
enum class ConnectionStatus {
ONLINE, OFFLINE
}

View file

@ -0,0 +1,10 @@
package com.tangem.datasource.connection
import kotlinx.coroutines.flow.StateFlow
/** Network connection manager */
interface NetworkConnectionManager {
/** Connection status */
val connectionStatus: StateFlow<ConnectionStatus>
}

View file

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