From de2e10d3106d2964593c9c1de5d1184ef0fe60cf Mon Sep 17 00:00:00 2001 From: Sayantan Roychowdhury Date: Mon, 20 Feb 2023 17:10:39 +0530 Subject: [PATCH 01/16] change connectivity check with ConnectivityManager --- .../java/foundation/e/apps/MainActivity.kt | 4 +-- .../e/apps/MainActivityViewModel.kt | 34 +++++++++++-------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/MainActivity.kt b/app/src/main/java/foundation/e/apps/MainActivity.kt index e8d578f91..9be05038e 100644 --- a/app/src/main/java/foundation/e/apps/MainActivity.kt +++ b/app/src/main/java/foundation/e/apps/MainActivity.kt @@ -104,7 +104,7 @@ class MainActivity : AppCompatActivity() { } } - viewModel.internetConnection.observe(this) { isInternetAvailable -> + viewModel.internetConnection(this).observe(this) { isInternetAvailable -> hasInternet = isInternetAvailable if (isInternetAvailable) { binding.noInternet.visibility = View.GONE @@ -259,7 +259,7 @@ class MainActivity : AppCompatActivity() { viewModel.updateUnAvailable(it) return@launch } - if (viewModel.internetConnection.value == false) { + if (viewModel.internetConnection(this@MainActivity).value == false) { showNoInternet() viewModel.updateUnAvailable(it) return@launch diff --git a/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt b/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt index 03ae34b07..f02653c9e 100644 --- a/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt +++ b/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt @@ -21,6 +21,8 @@ package foundation.e.apps import android.content.Context import android.content.Intent import android.graphics.Bitmap +import android.net.ConnectivityManager +import android.net.NetworkCapabilities import android.os.Build import android.util.Base64 import android.widget.ImageView @@ -51,13 +53,10 @@ import foundation.e.apps.utils.enums.isInitialized import foundation.e.apps.utils.enums.isUnFiltered import foundation.e.apps.utils.modules.DataStoreModule import foundation.e.apps.utils.modules.PWAManagerModule -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import ru.beryukhov.reactivenetwork.ReactiveNetwork -import ru.beryukhov.reactivenetwork.internet.observing.InternetObservingSettings -import ru.beryukhov.reactivenetwork.internet.observing.strategy.SocketInternetObservingStrategy import java.io.ByteArrayOutputStream import javax.inject.Inject +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch @HiltViewModel class MainActivityViewModel @Inject constructor( @@ -332,17 +331,24 @@ class MainActivityViewModel @Inject constructor( return Base64.encodeToString(byteArrayOS.toByteArray(), Base64.DEFAULT) } - val internetConnection = liveData { - emitSource( - ReactiveNetwork().observeInternetConnectivity( - InternetObservingSettings.builder() - .host("http://204.ecloud.global") - .strategy(SocketInternetObservingStrategy()) - .build() - ).asLiveData(Dispatchers.Default) - ) + fun internetConnection(context: Context) = liveData { + while (true) { + emit(checkNetworkConnection(context)) + delay(2000) + } } + private fun checkNetworkConnection(context: Context): Boolean { + val cm = context.getSystemService(ConnectivityManager::class.java) + val capabilities = cm.getNetworkCapabilities(cm.activeNetwork) + + return (capabilities != null + && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) + && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)) + } + + fun updateStatusOfFusedApps( fusedAppList: List, fusedDownloadList: List -- GitLab From 10349b78216a0baa5ef8e2cb73fdb64ef34b2fd9 Mon Sep 17 00:00:00 2001 From: Sayantan Roychowdhury Date: Mon, 20 Feb 2023 17:25:10 +0530 Subject: [PATCH 02/16] move connectivity check function to CommonUtilsFunctions --- .../main/java/foundation/e/apps/MainActivity.kt | 2 +- .../foundation/e/apps/MainActivityViewModel.kt | 15 ++------------- .../e/apps/utils/modules/CommonUtilsFunctions.kt | 13 +++++++++++++ 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/MainActivity.kt b/app/src/main/java/foundation/e/apps/MainActivity.kt index 9be05038e..8463410a1 100644 --- a/app/src/main/java/foundation/e/apps/MainActivity.kt +++ b/app/src/main/java/foundation/e/apps/MainActivity.kt @@ -259,7 +259,7 @@ class MainActivity : AppCompatActivity() { viewModel.updateUnAvailable(it) return@launch } - if (viewModel.internetConnection(this@MainActivity).value == false) { + if (!CommonUtilsFunctions.checkNetworkConnection(this@MainActivity)) { showNoInternet() viewModel.updateUnAvailable(it) return@launch diff --git a/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt b/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt index f02653c9e..12431ac1e 100644 --- a/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt +++ b/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt @@ -21,8 +21,6 @@ package foundation.e.apps import android.content.Context import android.content.Intent import android.graphics.Bitmap -import android.net.ConnectivityManager -import android.net.NetworkCapabilities import android.os.Build import android.util.Base64 import android.widget.ImageView @@ -51,6 +49,7 @@ import foundation.e.apps.utils.enums.Type import foundation.e.apps.utils.enums.User import foundation.e.apps.utils.enums.isInitialized import foundation.e.apps.utils.enums.isUnFiltered +import foundation.e.apps.utils.modules.CommonUtilsFunctions import foundation.e.apps.utils.modules.DataStoreModule import foundation.e.apps.utils.modules.PWAManagerModule import java.io.ByteArrayOutputStream @@ -333,21 +332,11 @@ class MainActivityViewModel @Inject constructor( fun internetConnection(context: Context) = liveData { while (true) { - emit(checkNetworkConnection(context)) + emit(CommonUtilsFunctions.checkNetworkConnection(context)) delay(2000) } } - private fun checkNetworkConnection(context: Context): Boolean { - val cm = context.getSystemService(ConnectivityManager::class.java) - val capabilities = cm.getNetworkCapabilities(cm.activeNetwork) - - return (capabilities != null - && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) - && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) - && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)) - } - fun updateStatusOfFusedApps( fusedAppList: List, diff --git a/app/src/main/java/foundation/e/apps/utils/modules/CommonUtilsFunctions.kt b/app/src/main/java/foundation/e/apps/utils/modules/CommonUtilsFunctions.kt index 6dcf53f9b..60a5b2664 100644 --- a/app/src/main/java/foundation/e/apps/utils/modules/CommonUtilsFunctions.kt +++ b/app/src/main/java/foundation/e/apps/utils/modules/CommonUtilsFunctions.kt @@ -20,6 +20,9 @@ package foundation.e.apps.utils.modules import android.annotation.SuppressLint import android.content.ClipData import android.content.ClipboardManager +import android.content.Context +import android.net.ConnectivityManager +import android.net.NetworkCapabilities import android.os.Build import foundation.e.apps.BuildConfig import org.json.JSONObject @@ -63,4 +66,14 @@ object CommonUtilsFunctions { } return descriptionJson.toString() } + + fun checkNetworkConnection(context: Context): Boolean { + val cm = context.getSystemService(ConnectivityManager::class.java) + val capabilities = cm.getNetworkCapabilities(cm.activeNetwork) + + return (capabilities != null + && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) + && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)) + } } -- GitLab From 4ab6332113416f98ba5115ad0b3bbad548e6a482 Mon Sep 17 00:00:00 2001 From: Sayantan Roychowdhury Date: Mon, 20 Feb 2023 18:56:51 +0530 Subject: [PATCH 03/16] use already existing CommonUtilsModule.isNetworkAvailable method --- app/src/main/java/foundation/e/apps/MainActivity.kt | 2 +- .../java/foundation/e/apps/MainActivityViewModel.kt | 4 ++-- .../e/apps/utils/modules/CommonUtilsFunctions.kt | 13 ------------- 3 files changed, 3 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/MainActivity.kt b/app/src/main/java/foundation/e/apps/MainActivity.kt index 8463410a1..2dbb71825 100644 --- a/app/src/main/java/foundation/e/apps/MainActivity.kt +++ b/app/src/main/java/foundation/e/apps/MainActivity.kt @@ -259,7 +259,7 @@ class MainActivity : AppCompatActivity() { viewModel.updateUnAvailable(it) return@launch } - if (!CommonUtilsFunctions.checkNetworkConnection(this@MainActivity)) { + if (!CommonUtilsModule.isNetworkAvailable(this@MainActivity)) { showNoInternet() viewModel.updateUnAvailable(it) return@launch diff --git a/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt b/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt index 12431ac1e..b88896e5d 100644 --- a/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt +++ b/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt @@ -49,7 +49,7 @@ import foundation.e.apps.utils.enums.Type import foundation.e.apps.utils.enums.User import foundation.e.apps.utils.enums.isInitialized import foundation.e.apps.utils.enums.isUnFiltered -import foundation.e.apps.utils.modules.CommonUtilsFunctions +import foundation.e.apps.utils.modules.CommonUtilsModule import foundation.e.apps.utils.modules.DataStoreModule import foundation.e.apps.utils.modules.PWAManagerModule import java.io.ByteArrayOutputStream @@ -332,7 +332,7 @@ class MainActivityViewModel @Inject constructor( fun internetConnection(context: Context) = liveData { while (true) { - emit(CommonUtilsFunctions.checkNetworkConnection(context)) + emit(CommonUtilsModule.isNetworkAvailable(context)) delay(2000) } } diff --git a/app/src/main/java/foundation/e/apps/utils/modules/CommonUtilsFunctions.kt b/app/src/main/java/foundation/e/apps/utils/modules/CommonUtilsFunctions.kt index 60a5b2664..6dcf53f9b 100644 --- a/app/src/main/java/foundation/e/apps/utils/modules/CommonUtilsFunctions.kt +++ b/app/src/main/java/foundation/e/apps/utils/modules/CommonUtilsFunctions.kt @@ -20,9 +20,6 @@ package foundation.e.apps.utils.modules import android.annotation.SuppressLint import android.content.ClipData import android.content.ClipboardManager -import android.content.Context -import android.net.ConnectivityManager -import android.net.NetworkCapabilities import android.os.Build import foundation.e.apps.BuildConfig import org.json.JSONObject @@ -66,14 +63,4 @@ object CommonUtilsFunctions { } return descriptionJson.toString() } - - fun checkNetworkConnection(context: Context): Boolean { - val cm = context.getSystemService(ConnectivityManager::class.java) - val capabilities = cm.getNetworkCapabilities(cm.activeNetwork) - - return (capabilities != null - && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) - && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) - && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)) - } } -- GitLab From 1b14fe851106a9e9f2303e526c3ae994494d157c Mon Sep 17 00:00:00 2001 From: Sayantan Roychowdhury Date: Mon, 20 Feb 2023 20:08:56 +0530 Subject: [PATCH 04/16] check connectivity in LoadingViewModel --- .../main/java/foundation/e/apps/MainActivityViewModel.kt | 6 ++++-- .../e/apps/utils/parentFragment/LoadingViewModel.kt | 3 +++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt b/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt index b88896e5d..e57226b42 100644 --- a/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt +++ b/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt @@ -88,7 +88,7 @@ class MainActivityViewModel @Inject constructor( companion object { private const val TAG = "MainActivityViewModel" - private var isGoogleLoginRunning = false + var hasInternet = true } fun getUser(): User { @@ -332,7 +332,9 @@ class MainActivityViewModel @Inject constructor( fun internetConnection(context: Context) = liveData { while (true) { - emit(CommonUtilsModule.isNetworkAvailable(context)) + emit(CommonUtilsModule.isNetworkAvailable(context).apply { + hasInternet = this + }) delay(2000) } } diff --git a/app/src/main/java/foundation/e/apps/utils/parentFragment/LoadingViewModel.kt b/app/src/main/java/foundation/e/apps/utils/parentFragment/LoadingViewModel.kt index cbd0ab493..7a87a3512 100644 --- a/app/src/main/java/foundation/e/apps/utils/parentFragment/LoadingViewModel.kt +++ b/app/src/main/java/foundation/e/apps/utils/parentFragment/LoadingViewModel.kt @@ -19,6 +19,7 @@ package foundation.e.apps.utils.parentFragment import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import foundation.e.apps.MainActivityViewModel import foundation.e.apps.login.AuthObject import foundation.e.apps.utils.exceptions.GPlayValidationException import foundation.e.apps.utils.exceptions.UnknownSourceException @@ -47,6 +48,8 @@ abstract class LoadingViewModel : ViewModel() { retryBlock: (failedObjects: List) -> Boolean, ) { + if (!MainActivityViewModel.hasInternet) return + exceptionsList.clear() val successAuthList = authObjectList.filter { it.result.isSuccess() } -- GitLab From d3b2e8286c3675c2bf44571d528b5ab5ef73cc0c Mon Sep 17 00:00:00 2001 From: Sayantan Roychowdhury Date: Mon, 20 Feb 2023 20:23:14 +0530 Subject: [PATCH 05/16] remove reactive network library --- app/build.gradle | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 35ed7284f..b37cd54b5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -229,9 +229,6 @@ dependencies { // JSoup implementation 'org.jsoup:jsoup:1.13.1' - // Flow reactive network - implementation 'ru.beryukhov:flowreactivenetwork:1.0.4' - // elib implementation 'foundation.e:elib:0.0.1-alpha11' } -- GitLab From d8be549ca67ba8c80db12f73f9f9214fc39571ca Mon Sep 17 00:00:00 2001 From: Sayantan Roychowdhury Date: Mon, 20 Feb 2023 22:45:13 +0530 Subject: [PATCH 06/16] use network callback --- .../e/apps/MainActivityViewModel.kt | 48 +++++++++++++++---- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt b/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt index e57226b42..c94c84dcc 100644 --- a/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt +++ b/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt @@ -21,6 +21,10 @@ package foundation.e.apps import android.content.Context import android.content.Intent import android.graphics.Bitmap +import android.net.ConnectivityManager +import android.net.Network +import android.net.NetworkCapabilities +import android.net.NetworkRequest import android.os.Build import android.util.Base64 import android.widget.ImageView @@ -31,7 +35,6 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.asLiveData -import androidx.lifecycle.liveData import androidx.lifecycle.viewModelScope import com.aurora.gplayapi.data.models.AuthData import com.aurora.gplayapi.exceptions.ApiException @@ -54,7 +57,9 @@ import foundation.e.apps.utils.modules.DataStoreModule import foundation.e.apps.utils.modules.PWAManagerModule import java.io.ByteArrayOutputStream import javax.inject.Inject -import kotlinx.coroutines.delay +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.channels.trySendBlocking +import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.launch @HiltViewModel @@ -330,15 +335,38 @@ class MainActivityViewModel @Inject constructor( return Base64.encodeToString(byteArrayOS.toByteArray(), Base64.DEFAULT) } - fun internetConnection(context: Context) = liveData { - while (true) { - emit(CommonUtilsModule.isNetworkAvailable(context).apply { - hasInternet = this - }) - delay(2000) - } - } + fun internetConnection(context: Context) = + callbackFlow { + + hasInternet = CommonUtilsModule.isNetworkAvailable(context) + trySendBlocking(hasInternet) + + val networkRequest = NetworkRequest.Builder() + .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) + .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) + .build() + + val networkCallback = object : ConnectivityManager.NetworkCallback() { + + override fun onCapabilitiesChanged( + network: Network, + networkCapabilities: NetworkCapabilities + ) { + super.onCapabilitiesChanged(network, networkCapabilities) + hasInternet = CommonUtilsModule.isNetworkAvailable(context) + trySend(hasInternet) + } + } + + val connectivityManager = + context.getSystemService(ConnectivityManager::class.java) as ConnectivityManager + connectivityManager.requestNetwork(networkRequest, networkCallback) + // An awaitClose block is always required. + // If the callback needs to be closed, it can be done inside awaitClose. + awaitClose { } + }.asLiveData() fun updateStatusOfFusedApps( fusedAppList: List, -- GitLab From b473ea5d65ec44b52e984ea1ac78d5056a64a070 Mon Sep 17 00:00:00 2001 From: Sayantan Roychowdhury Date: Tue, 21 Feb 2023 16:16:27 +0530 Subject: [PATCH 07/16] further improvement --- .../e/apps/MainActivityViewModel.kt | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt b/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt index c94c84dcc..ae70abfcf 100644 --- a/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt +++ b/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt @@ -35,6 +35,7 @@ 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 com.aurora.gplayapi.exceptions.ApiException @@ -57,8 +58,8 @@ import foundation.e.apps.utils.modules.DataStoreModule import foundation.e.apps.utils.modules.PWAManagerModule import java.io.ByteArrayOutputStream import javax.inject.Inject +import kotlinx.coroutines.channels.ProducerScope import kotlinx.coroutines.channels.awaitClose -import kotlinx.coroutines.channels.trySendBlocking import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.launch @@ -338,8 +339,7 @@ class MainActivityViewModel @Inject constructor( fun internetConnection(context: Context) = callbackFlow { - hasInternet = CommonUtilsModule.isNetworkAvailable(context) - trySendBlocking(hasInternet) + sendInternetStatus(context) val networkRequest = NetworkRequest.Builder() .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) @@ -349,13 +349,22 @@ class MainActivityViewModel @Inject constructor( val networkCallback = object : ConnectivityManager.NetworkCallback() { + override fun onAvailable(network: Network) { + super.onAvailable(network) + sendInternetStatus(context) + } + override fun onCapabilitiesChanged( network: Network, networkCapabilities: NetworkCapabilities ) { super.onCapabilitiesChanged(network, networkCapabilities) - hasInternet = CommonUtilsModule.isNetworkAvailable(context) - trySend(hasInternet) + sendInternetStatus(context) + } + + override fun onLost(network: Network) { + super.onLost(network) + sendInternetStatus(context) } } @@ -366,7 +375,12 @@ class MainActivityViewModel @Inject constructor( // An awaitClose block is always required. // If the callback needs to be closed, it can be done inside awaitClose. awaitClose { } - }.asLiveData() + }.asLiveData().distinctUntilChanged() + + private fun ProducerScope.sendInternetStatus(context: Context) { + hasInternet = CommonUtilsModule.isNetworkAvailable(context) + trySend(hasInternet) + } fun updateStatusOfFusedApps( fusedAppList: List, -- GitLab From dcdc6671b830ff2e7ce49900c2d9f49a9a2b893e Mon Sep 17 00:00:00 2001 From: Sayantan Roychowdhury Date: Tue, 21 Feb 2023 16:53:50 +0530 Subject: [PATCH 08/16] no need for context for observing internetConnection --- .../java/foundation/e/apps/MainActivity.kt | 4 ++- .../e/apps/MainActivityViewModel.kt | 35 ++++++++++++++----- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/MainActivity.kt b/app/src/main/java/foundation/e/apps/MainActivity.kt index 2dbb71825..15d858bc7 100644 --- a/app/src/main/java/foundation/e/apps/MainActivity.kt +++ b/app/src/main/java/foundation/e/apps/MainActivity.kt @@ -104,7 +104,9 @@ class MainActivity : AppCompatActivity() { } } - viewModel.internetConnection(this).observe(this) { isInternetAvailable -> + viewModel.setupConnectivityManager(this) + + viewModel.internetConnection.observe(this) { isInternetAvailable -> hasInternet = isInternetAvailable if (isInternetAvailable) { binding.noInternet.visibility = View.GONE diff --git a/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt b/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt index ae70abfcf..01a44212a 100644 --- a/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt +++ b/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt @@ -92,6 +92,8 @@ class MainActivityViewModel @Inject constructor( private val _errorMessageStringResource = MutableLiveData() val errorMessageStringResource: LiveData = _errorMessageStringResource + lateinit var connectivityManager: ConnectivityManager + companion object { private const val TAG = "MainActivityViewModel" var hasInternet = true @@ -336,10 +338,20 @@ class MainActivityViewModel @Inject constructor( return Base64.encodeToString(byteArrayOS.toByteArray(), Base64.DEFAULT) } - fun internetConnection(context: Context) = + fun setupConnectivityManager(context: Context) { + connectivityManager = + context.getSystemService(ConnectivityManager::class.java) as ConnectivityManager + } + + val internetConnection = callbackFlow { - sendInternetStatus(context) + if (!this@MainActivityViewModel::connectivityManager.isInitialized) { + awaitClose { } + return@callbackFlow + } + + sendInternetStatus(connectivityManager) val networkRequest = NetworkRequest.Builder() .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) @@ -351,7 +363,7 @@ class MainActivityViewModel @Inject constructor( override fun onAvailable(network: Network) { super.onAvailable(network) - sendInternetStatus(context) + sendInternetStatus(connectivityManager) } override fun onCapabilitiesChanged( @@ -359,17 +371,15 @@ class MainActivityViewModel @Inject constructor( networkCapabilities: NetworkCapabilities ) { super.onCapabilitiesChanged(network, networkCapabilities) - sendInternetStatus(context) + sendInternetStatus(connectivityManager) } override fun onLost(network: Network) { super.onLost(network) - sendInternetStatus(context) + sendInternetStatus(connectivityManager) } } - val connectivityManager = - context.getSystemService(ConnectivityManager::class.java) as ConnectivityManager connectivityManager.requestNetwork(networkRequest, networkCallback) // An awaitClose block is always required. @@ -377,8 +387,15 @@ class MainActivityViewModel @Inject constructor( awaitClose { } }.asLiveData().distinctUntilChanged() - private fun ProducerScope.sendInternetStatus(context: Context) { - hasInternet = CommonUtilsModule.isNetworkAvailable(context) + private fun ProducerScope.sendInternetStatus(connectivityManager: ConnectivityManager) { + + val capabilities = connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork) + + hasInternet = + capabilities != null + && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) + trySend(hasInternet) } -- GitLab From 5112885658f15f343d2a646b5f0759e449733ffc Mon Sep 17 00:00:00 2001 From: Sayantan Roychowdhury Date: Wed, 22 Feb 2023 15:10:42 +0530 Subject: [PATCH 09/16] remove static hasInternet --- app/src/main/java/foundation/e/apps/MainActivityViewModel.kt | 3 +-- .../foundation/e/apps/utils/parentFragment/LoadingViewModel.kt | 3 --- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt b/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt index 01a44212a..fea430916 100644 --- a/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt +++ b/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt @@ -96,7 +96,6 @@ class MainActivityViewModel @Inject constructor( companion object { private const val TAG = "MainActivityViewModel" - var hasInternet = true } fun getUser(): User { @@ -391,7 +390,7 @@ class MainActivityViewModel @Inject constructor( val capabilities = connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork) - hasInternet = + val hasInternet = capabilities != null && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) diff --git a/app/src/main/java/foundation/e/apps/utils/parentFragment/LoadingViewModel.kt b/app/src/main/java/foundation/e/apps/utils/parentFragment/LoadingViewModel.kt index 7a87a3512..cbd0ab493 100644 --- a/app/src/main/java/foundation/e/apps/utils/parentFragment/LoadingViewModel.kt +++ b/app/src/main/java/foundation/e/apps/utils/parentFragment/LoadingViewModel.kt @@ -19,7 +19,6 @@ package foundation.e.apps.utils.parentFragment import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import foundation.e.apps.MainActivityViewModel import foundation.e.apps.login.AuthObject import foundation.e.apps.utils.exceptions.GPlayValidationException import foundation.e.apps.utils.exceptions.UnknownSourceException @@ -48,8 +47,6 @@ abstract class LoadingViewModel : ViewModel() { retryBlock: (failedObjects: List) -> Boolean, ) { - if (!MainActivityViewModel.hasInternet) return - exceptionsList.clear() val successAuthList = authObjectList.filter { it.result.isSuccess() } -- GitLab From 81d7ac913a5b84c6ab3273b24161326fdf55ae1a Mon Sep 17 00:00:00 2001 From: Sayantan Roychowdhury Date: Wed, 22 Feb 2023 15:41:01 +0530 Subject: [PATCH 10/16] remove use of CommonUtilsModule.isNetworkAvailable --- app/src/main/java/foundation/e/apps/MainActivity.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/MainActivity.kt b/app/src/main/java/foundation/e/apps/MainActivity.kt index 15d858bc7..67efd606d 100644 --- a/app/src/main/java/foundation/e/apps/MainActivity.kt +++ b/app/src/main/java/foundation/e/apps/MainActivity.kt @@ -207,7 +207,7 @@ class MainActivity : AppCompatActivity() { } } - if (!CommonUtilsModule.isNetworkAvailable(this)) { + if (viewModel.internetConnection.value != true) { showNoInternet() } @@ -261,7 +261,7 @@ class MainActivity : AppCompatActivity() { viewModel.updateUnAvailable(it) return@launch } - if (!CommonUtilsModule.isNetworkAvailable(this@MainActivity)) { + if (viewModel.internetConnection.value == false) { showNoInternet() viewModel.updateUnAvailable(it) return@launch -- GitLab From 1c46864bc26ac83919f2f9223cd0737de07dea54 Mon Sep 17 00:00:00 2001 From: Sayantan Roychowdhury Date: Wed, 22 Feb 2023 16:15:30 +0530 Subject: [PATCH 11/16] abstract mainActivityViewModel in TimeoutFragment --- .../java/foundation/e/apps/application/ApplicationFragment.kt | 2 +- .../e/apps/applicationlist/ApplicationListFragment.kt | 2 +- app/src/main/java/foundation/e/apps/categories/AppsFragment.kt | 2 +- .../main/java/foundation/e/apps/categories/GamesFragment.kt | 2 +- app/src/main/java/foundation/e/apps/home/HomeFragment.kt | 2 +- app/src/main/java/foundation/e/apps/search/SearchFragment.kt | 2 +- app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt | 2 +- .../foundation/e/apps/utils/parentFragment/TimeoutFragment.kt | 3 +++ 8 files changed, 10 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/application/ApplicationFragment.kt b/app/src/main/java/foundation/e/apps/application/ApplicationFragment.kt index 6802c84c7..ca79c3321 100644 --- a/app/src/main/java/foundation/e/apps/application/ApplicationFragment.kt +++ b/app/src/main/java/foundation/e/apps/application/ApplicationFragment.kt @@ -119,7 +119,7 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { private val applicationViewModel: ApplicationViewModel by viewModels() private val privacyInfoViewModel: PrivacyInfoViewModel by viewModels() private val appInfoFetchViewModel: AppInfoFetchViewModel by viewModels() - private val mainActivityViewModel: MainActivityViewModel by activityViewModels() + override val mainActivityViewModel: MainActivityViewModel by activityViewModels() private var applicationIcon: ImageView? = null diff --git a/app/src/main/java/foundation/e/apps/applicationlist/ApplicationListFragment.kt b/app/src/main/java/foundation/e/apps/applicationlist/ApplicationListFragment.kt index 186d7b617..c3848093a 100644 --- a/app/src/main/java/foundation/e/apps/applicationlist/ApplicationListFragment.kt +++ b/app/src/main/java/foundation/e/apps/applicationlist/ApplicationListFragment.kt @@ -67,7 +67,7 @@ class ApplicationListFragment : private val viewModel: ApplicationListViewModel by viewModels() private val privacyInfoViewModel: PrivacyInfoViewModel by viewModels() private val appInfoFetchViewModel: AppInfoFetchViewModel by viewModels() - private val mainActivityViewModel: MainActivityViewModel by activityViewModels() + override val mainActivityViewModel: MainActivityViewModel by activityViewModels() private val appProgressViewModel: AppProgressViewModel by viewModels() private var _binding: FragmentApplicationListBinding? = null diff --git a/app/src/main/java/foundation/e/apps/categories/AppsFragment.kt b/app/src/main/java/foundation/e/apps/categories/AppsFragment.kt index 07497a782..e7defbb21 100644 --- a/app/src/main/java/foundation/e/apps/categories/AppsFragment.kt +++ b/app/src/main/java/foundation/e/apps/categories/AppsFragment.kt @@ -40,7 +40,7 @@ class AppsFragment : TimeoutFragment(R.layout.fragment_apps) { private val binding get() = _binding!! private val categoriesViewModel: CategoriesViewModel by viewModels() - private val mainActivityViewModel: MainActivityViewModel by activityViewModels() + override val mainActivityViewModel: MainActivityViewModel by activityViewModels() override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) diff --git a/app/src/main/java/foundation/e/apps/categories/GamesFragment.kt b/app/src/main/java/foundation/e/apps/categories/GamesFragment.kt index f5d9fe62b..275c30266 100644 --- a/app/src/main/java/foundation/e/apps/categories/GamesFragment.kt +++ b/app/src/main/java/foundation/e/apps/categories/GamesFragment.kt @@ -40,7 +40,7 @@ class GamesFragment : TimeoutFragment(R.layout.fragment_games) { private val binding get() = _binding!! private val categoriesViewModel: CategoriesViewModel by viewModels() - private val mainActivityViewModel: MainActivityViewModel by activityViewModels() + override val mainActivityViewModel: MainActivityViewModel by activityViewModels() override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) diff --git a/app/src/main/java/foundation/e/apps/home/HomeFragment.kt b/app/src/main/java/foundation/e/apps/home/HomeFragment.kt index 61b941c3c..d09f1d3f0 100644 --- a/app/src/main/java/foundation/e/apps/home/HomeFragment.kt +++ b/app/src/main/java/foundation/e/apps/home/HomeFragment.kt @@ -64,7 +64,7 @@ class HomeFragment : TimeoutFragment(R.layout.fragment_home), FusedAPIInterface private val binding get() = _binding!! private val homeViewModel: HomeViewModel by viewModels() - private val mainActivityViewModel: MainActivityViewModel by activityViewModels() + override val mainActivityViewModel: MainActivityViewModel by activityViewModels() private val appProgressViewModel: AppProgressViewModel by viewModels() private val appInfoFetchViewModel: AppInfoFetchViewModel by viewModels() diff --git a/app/src/main/java/foundation/e/apps/search/SearchFragment.kt b/app/src/main/java/foundation/e/apps/search/SearchFragment.kt index dec405a72..5b76536b2 100644 --- a/app/src/main/java/foundation/e/apps/search/SearchFragment.kt +++ b/app/src/main/java/foundation/e/apps/search/SearchFragment.kt @@ -78,7 +78,7 @@ class SearchFragment : private val searchViewModel: SearchViewModel by viewModels() private val privacyInfoViewModel: PrivacyInfoViewModel by viewModels() private val appInfoFetchViewModel: AppInfoFetchViewModel by viewModels() - private val mainActivityViewModel: MainActivityViewModel by activityViewModels() + override val mainActivityViewModel: MainActivityViewModel by activityViewModels() private val appProgressViewModel: AppProgressViewModel by viewModels() private val SUGGESTION_KEY = "suggestion" diff --git a/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt b/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt index eeb5d8774..19fef7836 100644 --- a/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt +++ b/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt @@ -77,7 +77,7 @@ class UpdatesFragment : TimeoutFragment(R.layout.fragment_updates), FusedAPIInte private val updatesViewModel: UpdatesViewModel by viewModels() private val privacyInfoViewModel: PrivacyInfoViewModel by viewModels() private val appInfoFetchViewModel: AppInfoFetchViewModel by viewModels() - private val mainActivityViewModel: MainActivityViewModel by activityViewModels() + override val mainActivityViewModel: MainActivityViewModel by activityViewModels() private val appProgressViewModel: AppProgressViewModel by viewModels() private var isDownloadObserverAdded = false diff --git a/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt b/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt index 0744b390e..8cfae5f4c 100644 --- a/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt +++ b/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt @@ -23,6 +23,7 @@ import androidx.core.view.isVisible import androidx.fragment.app.Fragment import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModelProvider +import foundation.e.apps.MainActivityViewModel import foundation.e.apps.R import foundation.e.apps.databinding.DialogErrorLogBinding import foundation.e.apps.login.AuthObject @@ -49,6 +50,8 @@ abstract class TimeoutFragment(@LayoutRes layoutId: Int) : Fragment(layoutId) { ViewModelProvider(requireActivity())[LoginViewModel::class.java] } + abstract val mainActivityViewModel: MainActivityViewModel + /** * Fragments observe this list to load data. * Fragments should not observe [loginViewModel]'s authObjects. -- GitLab From 29ad3833a88051c1b2a90f518c4191fbb4781bcd Mon Sep 17 00:00:00 2001 From: Sayantan Roychowdhury Date: Wed, 22 Feb 2023 16:17:03 +0530 Subject: [PATCH 12/16] call loadDataWhenNetworkAvailable instead of loadData --- .../e/apps/application/ApplicationFragment.kt | 2 +- .../ApplicationListFragment.kt | 2 +- .../e/apps/categories/AppsFragment.kt | 2 +- .../e/apps/categories/GamesFragment.kt | 2 +- .../foundation/e/apps/home/HomeFragment.kt | 2 +- .../e/apps/search/SearchFragment.kt | 2 +- .../e/apps/updates/UpdatesFragment.kt | 2 +- .../utils/parentFragment/TimeoutFragment.kt | 26 +++++++++++++++++-- 8 files changed, 31 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/application/ApplicationFragment.kt b/app/src/main/java/foundation/e/apps/application/ApplicationFragment.kt index ca79c3321..12a9f3bd5 100644 --- a/app/src/main/java/foundation/e/apps/application/ApplicationFragment.kt +++ b/app/src/main/java/foundation/e/apps/application/ApplicationFragment.kt @@ -139,7 +139,7 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { authObjects.observe(viewLifecycleOwner) { if (it == null) return@observe - loadData(it) + loadDataWhenNetworkAvailable(it) } applicationViewModel.exceptionsLiveData.observe(viewLifecycleOwner) { diff --git a/app/src/main/java/foundation/e/apps/applicationlist/ApplicationListFragment.kt b/app/src/main/java/foundation/e/apps/applicationlist/ApplicationListFragment.kt index c3848093a..881919e63 100644 --- a/app/src/main/java/foundation/e/apps/applicationlist/ApplicationListFragment.kt +++ b/app/src/main/java/foundation/e/apps/applicationlist/ApplicationListFragment.kt @@ -87,7 +87,7 @@ class ApplicationListFragment : authObjects.observe(viewLifecycleOwner) { if (it == null) return@observe - loadData(it) + loadDataWhenNetworkAvailable(it) } viewModel.exceptionsLiveData.observe(viewLifecycleOwner) { diff --git a/app/src/main/java/foundation/e/apps/categories/AppsFragment.kt b/app/src/main/java/foundation/e/apps/categories/AppsFragment.kt index e7defbb21..bf34cab5c 100644 --- a/app/src/main/java/foundation/e/apps/categories/AppsFragment.kt +++ b/app/src/main/java/foundation/e/apps/categories/AppsFragment.kt @@ -50,7 +50,7 @@ class AppsFragment : TimeoutFragment(R.layout.fragment_apps) { authObjects.observe(viewLifecycleOwner) { if (it == null) return@observe - loadData(it) + loadDataWhenNetworkAvailable(it) } categoriesViewModel.exceptionsLiveData.observe(viewLifecycleOwner) { diff --git a/app/src/main/java/foundation/e/apps/categories/GamesFragment.kt b/app/src/main/java/foundation/e/apps/categories/GamesFragment.kt index 275c30266..a7c2614e2 100644 --- a/app/src/main/java/foundation/e/apps/categories/GamesFragment.kt +++ b/app/src/main/java/foundation/e/apps/categories/GamesFragment.kt @@ -50,7 +50,7 @@ class GamesFragment : TimeoutFragment(R.layout.fragment_games) { authObjects.observe(viewLifecycleOwner) { if (it == null) return@observe - loadData(it) + loadDataWhenNetworkAvailable(it) } categoriesViewModel.exceptionsLiveData.observe(viewLifecycleOwner) { diff --git a/app/src/main/java/foundation/e/apps/home/HomeFragment.kt b/app/src/main/java/foundation/e/apps/home/HomeFragment.kt index d09f1d3f0..ab8e94b95 100644 --- a/app/src/main/java/foundation/e/apps/home/HomeFragment.kt +++ b/app/src/main/java/foundation/e/apps/home/HomeFragment.kt @@ -116,7 +116,7 @@ class HomeFragment : TimeoutFragment(R.layout.fragment_home), FusedAPIInterface authObjects.observe(viewLifecycleOwner) { if (it == null) return@observe - loadData(it) + loadDataWhenNetworkAvailable(it) } homeViewModel.exceptionsLiveData.observe(viewLifecycleOwner) { diff --git a/app/src/main/java/foundation/e/apps/search/SearchFragment.kt b/app/src/main/java/foundation/e/apps/search/SearchFragment.kt index 5b76536b2..f89298ed1 100644 --- a/app/src/main/java/foundation/e/apps/search/SearchFragment.kt +++ b/app/src/main/java/foundation/e/apps/search/SearchFragment.kt @@ -119,7 +119,7 @@ class SearchFragment : authObjects.observe(viewLifecycleOwner) { val currentQuery = searchView?.query?.toString() ?: "" if (it == null || (currentQuery.isNotEmpty() && lastSearch == currentQuery)) return@observe - loadData(it) + loadDataWhenNetworkAvailable(it) } searchViewModel.exceptionsLiveData.observe(viewLifecycleOwner) { diff --git a/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt b/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt index 19fef7836..b40ecd8a7 100644 --- a/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt +++ b/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt @@ -94,7 +94,7 @@ class UpdatesFragment : TimeoutFragment(R.layout.fragment_updates), FusedAPIInte if (!updatesViewModel.updatesList.value?.first.isNullOrEmpty()) { return@observe } - loadData(it) + loadDataWhenNetworkAvailable(it) } updatesViewModel.exceptionsLiveData.observe(viewLifecycleOwner) { diff --git a/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt b/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt index 8cfae5f4c..6d8e05f2f 100644 --- a/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt +++ b/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt @@ -35,6 +35,7 @@ import foundation.e.apps.utils.exceptions.GPlayException import foundation.e.apps.utils.exceptions.GPlayLoginException import foundation.e.apps.utils.exceptions.GPlayValidationException import foundation.e.apps.utils.exceptions.UnknownSourceException +import timber.log.Timber /** * Parent class of all fragments. @@ -58,12 +59,33 @@ abstract class TimeoutFragment(@LayoutRes layoutId: Int) : Fragment(layoutId) { */ val authObjects: MutableLiveData?> = MutableLiveData() + /** + * Function to loadData using the fragment's viewmodel. + */ abstract fun loadData(authObjectList: List) abstract fun showLoadingUI() abstract fun stopLoadingUI() + /** + * Call this function instead of directly calling [loadData]. + * This function takes care of checking network availability. + */ + fun loadDataWhenNetworkAvailable(authObjectList: List) { + Timber.i("class name: ${this::class.simpleName} " + + "internet: ${mainActivityViewModel.internetConnection.value}") + if (mainActivityViewModel.internetConnection.value == true) { + loadData(authObjectList) + } else { + mainActivityViewModel.internetConnection.observe(this) { + if (it) { + loadData(authObjectList) + } + } + } + } + /** * Override to contain code to execute in case of timeout. * Do not call this function directly, use [showTimeout] for that. @@ -120,7 +142,7 @@ abstract class TimeoutFragment(@LayoutRes layoutId: Int) : Fragment(layoutId) { * 1. Dialog title set to [R.string.data_load_error]. * 2. Dialog content set to [R.string.data_load_error_desc]. * 3. Dialog can show technical error info on clicking "More Info" - * 4. Has a positive button "Retry" which calls [loadData]. + * 4. Has a positive button "Retry" which calls [loadDataWhenNetworkAvailable]. * 5. Has a negative button "Close" which just closes the dialog. * 6. Dialog is cancellable. */ @@ -301,7 +323,7 @@ abstract class TimeoutFragment(@LayoutRes layoutId: Int) : Fragment(layoutId) { setView(dialogView.root) setPositiveButton(R.string.retry) { _, _ -> showLoadingUI() - authObjects.value?.let { loadData(it) } + authObjects.value?.let { loadDataWhenNetworkAvailable(it) } } setNegativeButton(R.string.close, null) setCancelable(true) -- GitLab From 37e7942fb343ed8db322998fc7f56b75b6f1ad9b Mon Sep 17 00:00:00 2001 From: Sayantan Roychowdhury Date: Wed, 22 Feb 2023 16:42:31 +0530 Subject: [PATCH 13/16] create livedata extension function loadDataOnce --- .../utils/parentFragment/TimeoutFragment.kt | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt b/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt index 6d8e05f2f..0e98d5696 100644 --- a/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt +++ b/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt @@ -21,7 +21,10 @@ import androidx.annotation.LayoutRes import androidx.appcompat.app.AlertDialog import androidx.core.view.isVisible import androidx.fragment.app.Fragment +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider import foundation.e.apps.MainActivityViewModel import foundation.e.apps.R @@ -78,7 +81,7 @@ abstract class TimeoutFragment(@LayoutRes layoutId: Int) : Fragment(layoutId) { if (mainActivityViewModel.internetConnection.value == true) { loadData(authObjectList) } else { - mainActivityViewModel.internetConnection.observe(this) { + mainActivityViewModel.internetConnection.loadDataOnce(this) { if (it) { loadData(authObjectList) } @@ -86,6 +89,21 @@ abstract class TimeoutFragment(@LayoutRes layoutId: Int) : Fragment(layoutId) { } } + /** + * This function will help prevent loading data multiple times if network + * is disconnected and reconnected multiple times. + */ + private fun LiveData.loadDataOnce(lifecycleOwner: LifecycleOwner, observer: Observer) { + observe(lifecycleOwner, object : Observer { + override fun onChanged(t: Boolean) { + observer.onChanged(t) + if (t) { + removeObserver(this) + } + } + }) + } + /** * Override to contain code to execute in case of timeout. * Do not call this function directly, use [showTimeout] for that. -- GitLab From fc1b16dea2dab82121611b2a68576d090cf83820 Mon Sep 17 00:00:00 2001 From: Sayantan Roychowdhury Date: Wed, 22 Feb 2023 17:45:19 +0530 Subject: [PATCH 14/16] refresh authobjects if they failed due to unavailable network --- .../e/apps/utils/parentFragment/TimeoutFragment.kt | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt b/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt index 0e98d5696..870e5e9a1 100644 --- a/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt +++ b/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt @@ -76,14 +76,19 @@ abstract class TimeoutFragment(@LayoutRes layoutId: Int) : Fragment(layoutId) { * This function takes care of checking network availability. */ fun loadDataWhenNetworkAvailable(authObjectList: List) { - Timber.i("class name: ${this::class.simpleName} " + - "internet: ${mainActivityViewModel.internetConnection.value}") - if (mainActivityViewModel.internetConnection.value == true) { + val hasInternet = mainActivityViewModel.internetConnection.value + Timber.d("class name: ${this::class.simpleName} internet: $hasInternet") + if (hasInternet == true) { loadData(authObjectList) } else { mainActivityViewModel.internetConnection.loadDataOnce(this) { if (it) { - loadData(authObjectList) + if (authObjectList.any { !it.result.isSuccess() }) { + Timber.d("Refreshing authObjects failed due to unavailable network") + loginViewModel.startLoginFlow() + } else { + loadData(authObjectList) + } } } } -- GitLab From 17351978575e06589891f2ba8dccf90c658e0ff7 Mon Sep 17 00:00:00 2001 From: Sayantan Roychowdhury Date: Wed, 22 Feb 2023 18:30:41 +0530 Subject: [PATCH 15/16] register and unregister network callback --- .../main/java/foundation/e/apps/MainActivityViewModel.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt b/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt index fea430916..00e295101 100644 --- a/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt +++ b/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt @@ -379,11 +379,11 @@ class MainActivityViewModel @Inject constructor( } } - connectivityManager.requestNetwork(networkRequest, networkCallback) + connectivityManager.registerNetworkCallback(networkRequest, networkCallback) - // An awaitClose block is always required. - // If the callback needs to be closed, it can be done inside awaitClose. - awaitClose { } + awaitClose { + connectivityManager.unregisterNetworkCallback(networkCallback) + } }.asLiveData().distinctUntilChanged() private fun ProducerScope.sendInternetStatus(connectivityManager: ConnectivityManager) { -- GitLab From 39c69b7c740234de61bb683feba263cbf20e4587 Mon Sep 17 00:00:00 2001 From: Sayantan Roychowdhury Date: Thu, 23 Feb 2023 18:42:36 +0530 Subject: [PATCH 16/16] suggestion --- .../e/apps/MainActivityViewModel.kt | 57 ++++++++++--------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt b/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt index 00e295101..901d86692 100644 --- a/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt +++ b/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt @@ -344,47 +344,50 @@ class MainActivityViewModel @Inject constructor( val internetConnection = callbackFlow { - if (!this@MainActivityViewModel::connectivityManager.isInitialized) { awaitClose { } return@callbackFlow } sendInternetStatus(connectivityManager) + val networkCallback = getNetworkCallback(this) + connectivityManager.registerNetworkCallback(networkRequest, networkCallback) - val networkRequest = NetworkRequest.Builder() - .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) - .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) - .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) - .build() - - val networkCallback = object : ConnectivityManager.NetworkCallback() { + awaitClose { + connectivityManager.unregisterNetworkCallback(networkCallback) + } + }.asLiveData().distinctUntilChanged() - override fun onAvailable(network: Network) { - super.onAvailable(network) - sendInternetStatus(connectivityManager) - } + private val networkRequest = NetworkRequest.Builder() + .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) + .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) + .build() - override fun onCapabilitiesChanged( - network: Network, - networkCapabilities: NetworkCapabilities - ) { - super.onCapabilitiesChanged(network, networkCapabilities) - sendInternetStatus(connectivityManager) - } + private fun getNetworkCallback( + callbackFlowScope: ProducerScope, + ): ConnectivityManager.NetworkCallback { + return object : ConnectivityManager.NetworkCallback() { - override fun onLost(network: Network) { - super.onLost(network) - sendInternetStatus(connectivityManager) - } + override fun onAvailable(network: Network) { + super.onAvailable(network) + callbackFlowScope.sendInternetStatus(connectivityManager) } - connectivityManager.registerNetworkCallback(networkRequest, networkCallback) + override fun onCapabilitiesChanged( + network: Network, + networkCapabilities: NetworkCapabilities + ) { + super.onCapabilitiesChanged(network, networkCapabilities) + callbackFlowScope.sendInternetStatus(connectivityManager) + } - awaitClose { - connectivityManager.unregisterNetworkCallback(networkCallback) + override fun onLost(network: Network) { + super.onLost(network) + callbackFlowScope.sendInternetStatus(connectivityManager) } - }.asLiveData().distinctUntilChanged() + } + } private fun ProducerScope.sendInternetStatus(connectivityManager: ConnectivityManager) { -- GitLab