From c0935caaf4c901fd0d4f1964c0f35217a3adc016 Mon Sep 17 00:00:00 2001 From: Hasib Prince Date: Wed, 17 Jan 2024 21:57:16 +0600 Subject: [PATCH] fixed: checking interent connectivity --- .../java/foundation/e/apps/MainActivity.kt | 19 ++-- .../e/apps/ui/MainActivityViewModel.kt | 73 +-------------- .../e/apps/utils/NetworkStatusManager.kt | 91 +++++++++++++++++++ 3 files changed, 102 insertions(+), 81 deletions(-) create mode 100644 app/src/main/java/foundation/e/apps/utils/NetworkStatusManager.kt diff --git a/app/src/main/java/foundation/e/apps/MainActivity.kt b/app/src/main/java/foundation/e/apps/MainActivity.kt index 1ff39c88c..51757f7ba 100644 --- a/app/src/main/java/foundation/e/apps/MainActivity.kt +++ b/app/src/main/java/foundation/e/apps/MainActivity.kt @@ -80,8 +80,6 @@ class MainActivity : AppCompatActivity() { val (bottomNavigationView, navController) = setupBootomNav() - var hasInternet = true - setupViewModels() setupNavigations(navController) @@ -94,13 +92,14 @@ class MainActivity : AppCompatActivity() { viewModel.createNotificationChannels() } + viewModel.setupConnectivityManager(this.applicationContext) - hasInternet = observeInternetConnections(hasInternet) + observeInternetConnections() observeAuthObjects(navController) - setupDestinationChangedListener(navController, hasInternet, bottomNavigationView) + setupDestinationChangedListener(navController, bottomNavigationView) observePurchaseAppPage() @@ -121,6 +120,7 @@ class MainActivity : AppCompatActivity() { observeEvents() } + private fun setupNavigations(navController: NavController) { val navOptions = NavOptions.Builder() .setPopUpTo(R.id.navigation_resource, true) @@ -207,25 +207,22 @@ class MainActivity : AppCompatActivity() { } } - private fun observeInternetConnections(hasInternet: Boolean): Boolean { - var mutableHasInternet = hasInternet - viewModel.internetConnection.observe(this) { isInternetAvailable -> - mutableHasInternet = isInternetAvailable + private fun observeInternetConnections() { + viewModel.internetConnection.distinctUntilChanged().observe(this) { isInternetAvailable -> + Timber.d("Observe internetConnection: $isInternetAvailable") if (isInternetAvailable) { binding.noInternet.visibility = View.GONE binding.fragment.visibility = View.VISIBLE } } - return mutableHasInternet } private fun setupDestinationChangedListener( navController: NavController, - hasInternet: Boolean, bottomNavigationView: BottomNavigationView ) { navController.addOnDestinationChangedListener { _, destination, _ -> - if (!hasInternet) { + if (viewModel.internetConnection.value == false) { showNoInternet() } when (destination.id) { diff --git a/app/src/main/java/foundation/e/apps/ui/MainActivityViewModel.kt b/app/src/main/java/foundation/e/apps/ui/MainActivityViewModel.kt index ff5070959..57bd34bfe 100644 --- a/app/src/main/java/foundation/e/apps/ui/MainActivityViewModel.kt +++ b/app/src/main/java/foundation/e/apps/ui/MainActivityViewModel.kt @@ -21,9 +21,6 @@ package foundation.e.apps.ui import android.content.Context import android.content.Intent import android.net.ConnectivityManager -import android.net.Network -import android.net.NetworkCapabilities -import android.net.NetworkRequest import android.os.Build import androidx.annotation.RequiresApi import androidx.appcompat.app.AlertDialog @@ -31,7 +28,6 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.asLiveData -import androidx.lifecycle.distinctUntilChanged import androidx.lifecycle.viewModelScope import com.aurora.gplayapi.data.models.AuthData import dagger.hilt.android.lifecycle.HiltViewModel @@ -50,9 +46,7 @@ import foundation.e.apps.install.pkg.PWAManager import foundation.e.apps.install.pkg.AppLoungePackageManager import foundation.e.apps.install.workmanager.AppInstallProcessor import foundation.e.apps.data.preference.getSync -import kotlinx.coroutines.channels.ProducerScope -import kotlinx.coroutines.channels.awaitClose -import kotlinx.coroutines.flow.callbackFlow +import foundation.e.apps.utils.NetworkStatusManager import kotlinx.coroutines.launch import javax.inject.Inject @@ -74,6 +68,7 @@ class MainActivityViewModel @Inject constructor( val purchaseAppLiveData: LiveData = _purchaseAppLiveData val isAppPurchased: MutableLiveData = MutableLiveData() val purchaseDeclined: MutableLiveData = MutableLiveData() + lateinit var internetConnection: LiveData var gPlayAuthData = AuthData("", "") @@ -210,69 +205,7 @@ class MainActivityViewModel @Inject constructor( } fun setupConnectivityManager(context: Context) { - connectivityManager = - context.getSystemService(ConnectivityManager::class.java) as ConnectivityManager - } - - val internetConnection = - callbackFlow { - if (!this@MainActivityViewModel::connectivityManager.isInitialized) { - awaitClose { } - return@callbackFlow - } - - sendInternetStatus(connectivityManager) - val networkCallback = getNetworkCallback(this) - connectivityManager.registerNetworkCallback(networkRequest, networkCallback) - - awaitClose { - connectivityManager.unregisterNetworkCallback(networkCallback) - } - }.asLiveData().distinctUntilChanged() - - private val networkRequest = NetworkRequest.Builder() - .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) - .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) - .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) - .build() - - private fun getNetworkCallback( - callbackFlowScope: ProducerScope, - ): ConnectivityManager.NetworkCallback { - return object : ConnectivityManager.NetworkCallback() { - - override fun onAvailable(network: Network) { - super.onAvailable(network) - callbackFlowScope.sendInternetStatus(connectivityManager) - } - - override fun onCapabilitiesChanged( - network: Network, - networkCapabilities: NetworkCapabilities - ) { - super.onCapabilitiesChanged(network, networkCapabilities) - callbackFlowScope.sendInternetStatus(connectivityManager) - } - - override fun onLost(network: Network) { - super.onLost(network) - callbackFlowScope.sendInternetStatus(connectivityManager) - } - } - } - - // protected to avoid SyntheticAccessor - protected fun ProducerScope.sendInternetStatus(connectivityManager: ConnectivityManager) { - - val capabilities = - connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork) - - val hasInternet = - capabilities != null && - capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && - capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) - - trySend(hasInternet) + internetConnection = NetworkStatusManager.init(context) } fun updateStatusOfFusedApps( diff --git a/app/src/main/java/foundation/e/apps/utils/NetworkStatusManager.kt b/app/src/main/java/foundation/e/apps/utils/NetworkStatusManager.kt new file mode 100644 index 000000000..0473a1bce --- /dev/null +++ b/app/src/main/java/foundation/e/apps/utils/NetworkStatusManager.kt @@ -0,0 +1,91 @@ +/* + * Copyright MURENA SAS 2024 + * Apps Quickly and easily install Android apps onto your device! + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package foundation.e.apps.utils + +import android.content.Context +import android.net.ConnectivityManager +import android.net.Network +import android.net.NetworkCapabilities +import android.net.NetworkRequest +import androidx.lifecycle.MutableLiveData +import timber.log.Timber + +object NetworkStatusManager { + + private lateinit var connectivityManager: ConnectivityManager + private var internetConnectionLiveData: MutableLiveData = MutableLiveData() + + /** + * Registers for network callback with [ConnectivityManager] + * @param context should be applicationContext + * @return [MutableLiveData], holds the [Boolean] value as status of internet availability + */ + fun init(context: Context): MutableLiveData { + connectivityManager = + context.getSystemService(ConnectivityManager::class.java) as ConnectivityManager + + val networkRequest = NetworkRequest.Builder() + .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) + .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) + .build() + + connectivityManager.registerNetworkCallback(networkRequest, createNetworkCallback()) + + return internetConnectionLiveData + } + + private fun createNetworkCallback( + ): ConnectivityManager.NetworkCallback { + return object : ConnectivityManager.NetworkCallback() { + + override fun onAvailable(network: Network) { + super.onAvailable(network) + Timber.d("Network: onAvailable: ${network.networkHandle}") + sendInternetStatus(true) + } + + override fun onCapabilitiesChanged( + network: Network, + networkCapabilities: NetworkCapabilities + ) { + super.onCapabilitiesChanged(network, networkCapabilities) + val hasInternet = + networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && + networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) + + Timber.d("Network: onCapabilitiesChanged: ${network.networkHandle}, hasInternet: $hasInternet") + sendInternetStatus(hasInternet) + } + + override fun onLost(network: Network) { + super.onLost(network) + Timber.d("Network: onLost: ${network.networkHandle}") + sendInternetStatus(false) + } + + private fun sendInternetStatus(hasInternet: Boolean?) { + hasInternet?.let { + internetConnectionLiveData.postValue(it) + } + } + } + } +} -- GitLab