Refactoring NetworkMonitor to be more Java friendly

Signed-off-by: rapterjet2004 <juliuslinus1@gmail.com>
This commit is contained in:
rapterjet2004 2024-11-19 09:08:08 -06:00
parent 29dd0231ae
commit c084fbd5ee
No known key found for this signature in database
GPG key ID: 3AA5FDFED7944099
3 changed files with 52 additions and 74 deletions

View file

@ -7,11 +7,20 @@
package com.nextcloud.talk.data.network package com.nextcloud.talk.data.network
import androidx.lifecycle.LiveData
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
/** /**
* Utility for reporting app connectivity status. * Utility for reporting app connectivity status.
*/ */
interface NetworkMonitor { interface NetworkMonitor {
/**
* Returns the device's current connectivity status.
*/
val isOnline: Flow<Boolean> val isOnline: Flow<Boolean>
/**
* Returns the device's current connectivity status as LiveData for better interop with Java code.
*/
val isOnlineLiveData: LiveData<Boolean>
} }

View file

@ -11,10 +11,10 @@ import android.content.Context
import android.net.ConnectivityManager import android.net.ConnectivityManager
import android.net.Network import android.net.Network
import android.net.NetworkCapabilities import android.net.NetworkCapabilities
import android.net.NetworkRequest
import android.net.NetworkRequest.Builder import android.net.NetworkRequest.Builder
import androidx.core.content.getSystemService 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.Dispatchers
import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@ -29,8 +29,10 @@ import javax.inject.Singleton
class NetworkMonitorImpl @Inject constructor( class NetworkMonitorImpl @Inject constructor(
private val context: Context private val context: Context
) : NetworkMonitor { ) : NetworkMonitor {
override val isOnlineLiveData: LiveData<Boolean>
get() = isOnline.asLiveData()
override val isOnline: Flow<Boolean> = callbackFlow { override val isOnline: Flow<Boolean> = callbackFlow {
trace("NetworkMonitorImpl.callbackFlow") {
val connectivityManager = context.getSystemService<ConnectivityManager>() val connectivityManager = context.getSystemService<ConnectivityManager>()
if (connectivityManager == null) { if (connectivityManager == null) {
channel.trySend(false) channel.trySend(false)
@ -38,12 +40,11 @@ class NetworkMonitorImpl @Inject constructor(
return@callbackFlow return@callbackFlow
} }
/** val networkRequest = Builder()
* The callback's methods are invoked on changes to *any* network matching the [NetworkRequest], .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
* not just the active network. So we can simply track the presence (or absence) of such [Network]. .build()
*/
val callback = object : ConnectivityManager.NetworkCallback() {
val networkCallback = object : ConnectivityManager.NetworkCallback() {
private val networks = mutableSetOf<Network>() private val networks = mutableSetOf<Network>()
override fun onAvailable(network: Network) { override fun onAvailable(network: Network) {
@ -57,21 +58,12 @@ class NetworkMonitorImpl @Inject constructor(
} }
} }
trace("NetworkMonitorImpl.registerNetworkCallback") { connectivityManager.registerNetworkCallback(networkRequest, networkCallback)
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()) channel.trySend(connectivityManager.isCurrentlyConnected())
awaitClose { awaitClose {
connectivityManager.unregisterNetworkCallback(callback) connectivityManager.unregisterNetworkCallback(networkCallback)
}
} }
} }
.distinctUntilChanged() .distinctUntilChanged()

View file

@ -10,11 +10,7 @@ package com.nextcloud.talk.ui.dialog;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Dialog; import android.app.Dialog;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; 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.api.NcApi;
import com.nextcloud.talk.application.NextcloudTalkApplication; import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.conversationlist.ConversationsListActivity; 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.data.user.model.User;
import com.nextcloud.talk.databinding.DialogChooseAccountBinding; import com.nextcloud.talk.databinding.DialogChooseAccountBinding;
import com.nextcloud.talk.extensions.ImageViewExtensionsKt; import com.nextcloud.talk.extensions.ImageViewExtensionsKt;
@ -87,6 +84,9 @@ public class ChooseAccountDialogFragment extends DialogFragment {
@Inject @Inject
InvitationsRepository invitationsRepository; InvitationsRepository invitationsRepository;
@Inject
NetworkMonitor networkMonitor;
private DialogChooseAccountBinding binding; private DialogChooseAccountBinding binding;
private View dialogView; private View dialogView;
@ -115,7 +115,7 @@ public class ChooseAccountDialogFragment extends DialogFragment {
setupCurrentUser(user); setupCurrentUser(user);
setupListeners(); setupListeners();
setupAdapter(); setupAdapter();
prepareViews(); networkMonitor.isOnlineLiveData().observe(this, this::prepareViews);
} }
private void setupCurrentUser(User user) { private void setupCurrentUser(User user) {
@ -265,29 +265,6 @@ public class ChooseAccountDialogFragment extends DialogFragment {
viewThemeUtils.dialog.colorDialogMenuText(binding.manageSettings); 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) { private void loadCurrentStatus(User user) {
String credentials = ApiUtils.getCredentials(user.getUsername(), user.getToken()); 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) { if (getActivity() != null) {
LinearLayoutManager layoutManager = new SmoothScrollLinearLayoutManager(getActivity()); LinearLayoutManager layoutManager = new SmoothScrollLinearLayoutManager(getActivity());
binding.accountsList.setLayoutManager(layoutManager); binding.accountsList.setLayoutManager(layoutManager);
@ -344,7 +321,7 @@ public class ChooseAccountDialogFragment extends DialogFragment {
binding.accountsList.setHasFixedSize(true); binding.accountsList.setHasFixedSize(true);
binding.accountsList.setAdapter(adapter); binding.accountsList.setAdapter(adapter);
if (!isNetworkAvailable(getContext())) { if (!isOnline) {
binding.addAccount.setVisibility(View.GONE); binding.addAccount.setVisibility(View.GONE);
} }
} }