From f9bb30deeca895a81a6a5ee16fae2e6c4c0cf824 Mon Sep 17 00:00:00 2001 From: Gregorio Date: Thu, 25 Jul 2024 19:17:14 -0300 Subject: [PATCH] Class to manage internet connection --- .../spruceid/wallet/sdk/ConnectionLiveData.kt | 86 +++++++++++++++++++ .../spruceid/walletsdkexample/MainActivity.kt | 18 +++- 2 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 WalletSdk/src/main/java/com/spruceid/wallet/sdk/ConnectionLiveData.kt diff --git a/WalletSdk/src/main/java/com/spruceid/wallet/sdk/ConnectionLiveData.kt b/WalletSdk/src/main/java/com/spruceid/wallet/sdk/ConnectionLiveData.kt new file mode 100644 index 0000000..e2cfb4d --- /dev/null +++ b/WalletSdk/src/main/java/com/spruceid/wallet/sdk/ConnectionLiveData.kt @@ -0,0 +1,86 @@ +package com.spruceid.wallet.sdk + +import android.content.Context +import android.content.Context.CONNECTIVITY_SERVICE +import android.net.ConnectivityManager +import android.net.Network +import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET +import android.net.NetworkCapabilities.TRANSPORT_CELLULAR +import android.net.NetworkCapabilities.TRANSPORT_WIFI +import android.net.NetworkRequest +import androidx.lifecycle.LiveData +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import java.io.IOException +import java.net.InetSocketAddress +import javax.net.SocketFactory + +class ConnectionLiveData(context: Context) : LiveData() { + + private lateinit var networkCallback: ConnectivityManager.NetworkCallback + private val connectivityManager = + context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager + private val validNetworks: MutableSet = HashSet() + + private fun checkValidNetworks() { + postValue(validNetworks.size > 0) + } + + override fun onActive() { + networkCallback = createNetworkCallback() + val networkRequest = NetworkRequest.Builder() + .addCapability(NET_CAPABILITY_INTERNET) + .addTransportType(TRANSPORT_WIFI) + .addTransportType(TRANSPORT_CELLULAR) + .build() + connectivityManager.registerNetworkCallback(networkRequest, networkCallback) + } + + override fun onInactive() { + connectivityManager.unregisterNetworkCallback(networkCallback) + } + + private fun createNetworkCallback() = object : ConnectivityManager.NetworkCallback() { + + override fun onAvailable(network: Network) { + val networkCapabilities = connectivityManager.getNetworkCapabilities(network) + val hasInternetCapability = networkCapabilities?.hasCapability(NET_CAPABILITY_INTERNET) + + if (hasInternetCapability == true) { + // Check if this network actually has internet + CoroutineScope(Dispatchers.IO).launch { + val hasInternet = DoesNetworkHaveInternet.execute(network.socketFactory) + if (hasInternet) { + withContext(Dispatchers.Main) { + validNetworks.add(network) + checkValidNetworks() + } + } + } + } + } + + override fun onLost(network: Network) { + validNetworks.remove(network) + checkValidNetworks() + } + } + + object DoesNetworkHaveInternet { + suspend fun execute(socketFactory: SocketFactory): Boolean { + // Make sure to execute this on a background thread. + delay(1000) + return try { + val socket = socketFactory.createSocket() ?: throw IOException("Socket is null.") + socket.connect(InetSocketAddress("8.8.8.8", 53), 1500) + socket.close() + true + } catch (e: IOException) { + false + } + } + } +} diff --git a/example/src/main/java/com/spruceid/walletsdkexample/MainActivity.kt b/example/src/main/java/com/spruceid/walletsdkexample/MainActivity.kt index 972b998..04fa704 100644 --- a/example/src/main/java/com/spruceid/walletsdkexample/MainActivity.kt +++ b/example/src/main/java/com/spruceid/walletsdkexample/MainActivity.kt @@ -26,12 +26,16 @@ import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.unit.dp import androidx.core.content.ContextCompat +import com.spruceid.wallet.sdk.ConnectionLiveData import com.spruceid.wallet.sdk.CredentialsViewModel import com.spruceid.wallet.sdk.MDoc import com.spruceid.wallet.sdk.PresentmentState @@ -47,10 +51,22 @@ import java.security.spec.PKCS8EncodedKeySpec import java.util.Base64 class MainActivity : ComponentActivity() { + private lateinit var connectionLiveData: ConnectionLiveData + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + setContent { val viewModel by viewModels() + var isConnected by remember { mutableStateOf(false) } + + connectionLiveData = ConnectionLiveData(this) + + connectionLiveData.observe(this) { isNetworkAvailable -> + isNetworkAvailable?.let { + isConnected = it + } + } viewModel.storeCredential(generateMDoc()) @@ -96,7 +112,7 @@ class MainActivity : ComponentActivity() { viewModel.present(getBluetoothManager(baseContext)!!) } ) { - Text(text = "Share via QR Code") + Text(text = "Share via QR Code " + isConnected) } } }