diff --git a/app/src/main/java/com/nextcloud/talk/data/network/NetworkMonitor.kt b/app/src/main/java/com/nextcloud/talk/data/network/NetworkMonitor.kt index b83f4e2b5..2257c7f7c 100644 --- a/app/src/main/java/com/nextcloud/talk/data/network/NetworkMonitor.kt +++ b/app/src/main/java/com/nextcloud/talk/data/network/NetworkMonitor.kt @@ -7,11 +7,20 @@ package com.nextcloud.talk.data.network +import androidx.lifecycle.LiveData import kotlinx.coroutines.flow.Flow /** * Utility for reporting app connectivity status. */ interface NetworkMonitor { + /** + * Returns the device's current connectivity status. + */ val isOnline: Flow + + /** + * Returns the device's current connectivity status as LiveData for better interop with Java code. + */ + val isOnlineLiveData: LiveData } diff --git a/app/src/main/java/com/nextcloud/talk/data/network/NetworkMonitorImpl.kt b/app/src/main/java/com/nextcloud/talk/data/network/NetworkMonitorImpl.kt index 3f27c20f9..05b3bcd48 100644 --- a/app/src/main/java/com/nextcloud/talk/data/network/NetworkMonitorImpl.kt +++ b/app/src/main/java/com/nextcloud/talk/data/network/NetworkMonitorImpl.kt @@ -11,10 +11,10 @@ import android.content.Context import android.net.ConnectivityManager import android.net.Network import android.net.NetworkCapabilities -import android.net.NetworkRequest import android.net.NetworkRequest.Builder import androidx.core.content.getSystemService -import androidx.core.os.trace +import androidx.lifecycle.LiveData +import androidx.lifecycle.asLiveData import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow @@ -29,54 +29,46 @@ import javax.inject.Singleton class NetworkMonitorImpl @Inject constructor( private val context: Context ) : NetworkMonitor { + override val isOnlineLiveData: LiveData + get() = isOnline.asLiveData() + override val isOnline: Flow = callbackFlow { - trace("NetworkMonitorImpl.callbackFlow") { - val connectivityManager = context.getSystemService() - if (connectivityManager == null) { - channel.trySend(false) - channel.close() - return@callbackFlow + val connectivityManager = context.getSystemService() + if (connectivityManager == null) { + channel.trySend(false) + channel.close() + return@callbackFlow + } + + val networkRequest = Builder() + .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + .build() + + val networkCallback = object : ConnectivityManager.NetworkCallback() { + private val networks = mutableSetOf() + + override fun onAvailable(network: Network) { + networks += network + channel.trySend(true) } - /** - * The callback's methods are invoked on changes to *any* network matching the [NetworkRequest], - * not just the active network. So we can simply track the presence (or absence) of such [Network]. - */ - val callback = object : ConnectivityManager.NetworkCallback() { - - private val networks = mutableSetOf() - - override fun onAvailable(network: Network) { - networks += network - channel.trySend(true) - } - - override fun onLost(network: Network) { - networks -= network - channel.trySend(networks.isNotEmpty()) - } - } - - trace("NetworkMonitorImpl.registerNetworkCallback") { - val request = Builder() - .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) - .build() - connectivityManager.registerNetworkCallback(request, callback) - } - - /** - * Sends the latest connectivity status to the underlying channel. - */ - channel.trySend(connectivityManager.isCurrentlyConnected()) - - awaitClose { - connectivityManager.unregisterNetworkCallback(callback) + override fun onLost(network: Network) { + networks -= network + channel.trySend(networks.isNotEmpty()) } } + + connectivityManager.registerNetworkCallback(networkRequest, networkCallback) + + channel.trySend(connectivityManager.isCurrentlyConnected()) + + awaitClose { + connectivityManager.unregisterNetworkCallback(networkCallback) + } } - .distinctUntilChanged() - .flowOn(Dispatchers.IO) - .conflate() + .distinctUntilChanged() + .flowOn(Dispatchers.IO) + .conflate() private fun ConnectivityManager.isCurrentlyConnected() = activeNetwork diff --git a/app/src/main/java/com/nextcloud/talk/ui/dialog/ChooseAccountDialogFragment.java b/app/src/main/java/com/nextcloud/talk/ui/dialog/ChooseAccountDialogFragment.java index b680fca9c..8a2f7574a 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/dialog/ChooseAccountDialogFragment.java +++ b/app/src/main/java/com/nextcloud/talk/ui/dialog/ChooseAccountDialogFragment.java @@ -10,11 +10,7 @@ package com.nextcloud.talk.ui.dialog; import android.annotation.SuppressLint; import android.app.Dialog; -import android.content.Context; import android.content.Intent; -import android.net.ConnectivityManager; -import android.net.Network; -import android.net.NetworkCapabilities; import android.net.Uri; import android.os.Bundle; import android.util.Log; @@ -28,6 +24,7 @@ import com.nextcloud.talk.adapters.items.AdvancedUserItem; import com.nextcloud.talk.api.NcApi; import com.nextcloud.talk.application.NextcloudTalkApplication; import com.nextcloud.talk.conversationlist.ConversationsListActivity; +import com.nextcloud.talk.data.network.NetworkMonitor; import com.nextcloud.talk.data.user.model.User; import com.nextcloud.talk.databinding.DialogChooseAccountBinding; import com.nextcloud.talk.extensions.ImageViewExtensionsKt; @@ -87,6 +84,9 @@ public class ChooseAccountDialogFragment extends DialogFragment { @Inject InvitationsRepository invitationsRepository; + @Inject + NetworkMonitor networkMonitor; + private DialogChooseAccountBinding binding; private View dialogView; @@ -115,7 +115,7 @@ public class ChooseAccountDialogFragment extends DialogFragment { setupCurrentUser(user); setupListeners(); setupAdapter(); - prepareViews(); + networkMonitor.isOnlineLiveData().observe(this, this::prepareViews); } private void setupCurrentUser(User user) { @@ -265,29 +265,6 @@ public class ChooseAccountDialogFragment extends DialogFragment { viewThemeUtils.dialog.colorDialogMenuText(binding.manageSettings); } - // Would have preferred to use NetworkMonitor but java with kotlin flows is ugly - public static boolean isNetworkAvailable(Context context) { - ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - if (connectivityManager == null) { - return false; - } - - Network network = connectivityManager.getActiveNetwork(); - if (network == null) { - return false; - } - - NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(network); - if (capabilities == null) { - return false; - } - - return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) || - capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) || - capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN) || - capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET); - } - private void loadCurrentStatus(User user) { String credentials = ApiUtils.getCredentials(user.getUsername(), user.getToken()); @@ -336,7 +313,7 @@ public class ChooseAccountDialogFragment extends DialogFragment { } } - private void prepareViews() { + private void prepareViews(Boolean isOnline) { if (getActivity() != null) { LinearLayoutManager layoutManager = new SmoothScrollLinearLayoutManager(getActivity()); binding.accountsList.setLayoutManager(layoutManager); @@ -344,7 +321,7 @@ public class ChooseAccountDialogFragment extends DialogFragment { binding.accountsList.setHasFixedSize(true); binding.accountsList.setAdapter(adapter); - if (!isNetworkAvailable(getContext())) { + if (!isOnline) { binding.addAccount.setVisibility(View.GONE); } }