[Android] Set connection as Flow

Geoffrey Métais git at videolan.org
Fri Feb 21 14:34:08 CET 2020


vlc-android | branch: master | Geoffrey Métais <geoffrey.metais at gmail.com> | Tue Feb 18 11:23:46 2020 +0100| [719ef5f381470375c10f914882e4e37cd9fac472] | committer: Geoffrey Métais

Set connection as Flow

> https://code.videolan.org/videolan/vlc-android/commit/719ef5f381470375c10f914882e4e37cd9fac472
---

 .../main/java/org/videolan/tools/NetworkMonitor.kt | 44 ++++++++++------------
 .../src/org/videolan/vlc/RendererDelegate.kt       |  4 +-
 .../vlc/repository/BrowserFavRepository.kt         | 15 +++++---
 3 files changed, 31 insertions(+), 32 deletions(-)

diff --git a/application/tools/src/main/java/org/videolan/tools/NetworkMonitor.kt b/application/tools/src/main/java/org/videolan/tools/NetworkMonitor.kt
index bc176dd4e..532b80638 100644
--- a/application/tools/src/main/java/org/videolan/tools/NetworkMonitor.kt
+++ b/application/tools/src/main/java/org/videolan/tools/NetworkMonitor.kt
@@ -10,29 +10,25 @@ import android.net.ConnectivityManager
 import android.net.NetworkCapabilities
 import android.os.Build
 import androidx.lifecycle.*
-import kotlinx.coroutines.CoroutineStart
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.GlobalScope
-import kotlinx.coroutines.launch
+import kotlinx.coroutines.channels.ConflatedBroadcastChannel
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.consumeAsFlow
 import java.lang.ref.WeakReference
 import java.net.NetworkInterface
 import java.net.SocketException
 
-interface NetworkObserver {
-    fun onNetworkChanged()
-}
-
 class NetworkMonitor(private val context: Context) : LifecycleObserver {
     private var registered = false
     private val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
-    val connected = MutableLiveData<Boolean>()
-    @Volatile
-    var isMobile = true
-        private set
-    @Volatile
-    var isVPN = false
-        private set
-    private var networkObservers: MutableList<WeakReference<NetworkObserver>> = mutableListOf()
+    val connection = ConflatedBroadcastChannel(Connection(connected = false, mobile = true, vpn = false))
+    val connectionFlow : Flow<Connection>
+        get() = connection.openSubscription().consumeAsFlow()
+    val connected : Boolean
+        get() = connection.value.connected
+    val isLan : Boolean
+        get() = connection.value.run { connected && !mobile }
+    val lanAllowed : Boolean
+        get() = connection.value.run { connected && (!mobile || vpn) }
 
     init {
         ProcessLifecycleOwner.get().lifecycle.addObserver(this at NetworkMonitor)
@@ -82,18 +78,16 @@ class NetworkMonitor(private val context: Context) : LifecycleObserver {
                 ConnectivityManager.CONNECTIVITY_ACTION -> {
                     val networkInfo = cm.activeNetworkInfo
                     val isConnected = networkInfo != null && networkInfo.isConnected
-                    isMobile = isConnected && networkInfo!!.type == ConnectivityManager.TYPE_MOBILE
-                    isVPN = isConnected && updateVPNStatus()
-                    if (connected.value == null || isConnected != connected.value) {
-                        connected.value = isConnected
-                    }
-                    networkObservers.forEach { it.get()?.onNetworkChanged() }
+                    val isMobile = isConnected && networkInfo!!.type == ConnectivityManager.TYPE_MOBILE
+                    val isVPN = isConnected && updateVPNStatus()
+                    val conn = Connection(isConnected, isMobile, isVPN)
+                    if (connection.value != conn) connection.offer(conn)
                 }
 
             }
         }
-
     }
-
-    companion object : SingletonHolder<NetworkMonitor, Context>({ NetworkMonitor(it) })
+    companion object : SingletonHolder<NetworkMonitor, Context>({ NetworkMonitor(it.applicationContext) })
 }
+
+class Connection(val connected: Boolean, val mobile: Boolean, val vpn: Boolean)
diff --git a/application/vlc-android/src/org/videolan/vlc/RendererDelegate.kt b/application/vlc-android/src/org/videolan/vlc/RendererDelegate.kt
index 06b08974d..491f0fb7a 100644
--- a/application/vlc-android/src/org/videolan/vlc/RendererDelegate.kt
+++ b/application/vlc-android/src/org/videolan/vlc/RendererDelegate.kt
@@ -20,6 +20,8 @@
 package org.videolan.vlc
 
 import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
 import org.videolan.libvlc.RendererDiscoverer
 import org.videolan.libvlc.RendererItem
 import org.videolan.resources.AppContextProvider
@@ -42,7 +44,7 @@ object RendererDelegate : RendererDiscoverer.EventListener {
     @Volatile private var started = false
 
     init {
-        NetworkMonitor.getInstance(AppContextProvider.appContext).connected.observeForever { AppScope.launch { if (it == true) start() else stop() } }
+        NetworkMonitor.getInstance(AppContextProvider.appContext).connectionFlow.onEach { if (it.connected) start() else stop() }.launchIn(AppScope)
     }
 
     suspend fun start() {
diff --git a/application/vlc-android/src/org/videolan/vlc/repository/BrowserFavRepository.kt b/application/vlc-android/src/org/videolan/vlc/repository/BrowserFavRepository.kt
index 0913bcd7e..976e71df8 100644
--- a/application/vlc-android/src/org/videolan/vlc/repository/BrowserFavRepository.kt
+++ b/application/vlc-android/src/org/videolan/vlc/repository/BrowserFavRepository.kt
@@ -24,12 +24,15 @@ import android.content.Context
 import android.net.Uri
 import androidx.annotation.WorkerThread
 import androidx.lifecycle.MediatorLiveData
+import androidx.lifecycle.asLiveData
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.launch
 import org.videolan.medialibrary.interfaces.media.MediaWrapper
+import org.videolan.resources.AppContextProvider
 import org.videolan.resources.TYPE_LOCAL_FAV
 import org.videolan.resources.TYPE_NETWORK_FAV
 import org.videolan.tools.IOScopedObject
+import org.videolan.tools.NetworkMonitor
 import org.videolan.tools.SingletonHolder
 import org.videolan.vlc.ExternalMonitor
 import org.videolan.vlc.database.BrowserFavDao
@@ -41,6 +44,8 @@ import java.util.*
 
 class BrowserFavRepository(private val browserFavDao: BrowserFavDao) : IOScopedObject() {
 
+    private val networkMonitor = NetworkMonitor.getInstance(AppContextProvider.appContext)
+
     private val networkFavs by lazy { browserFavDao.getAllNetwrokFavs() }
 
     val browserFavorites by lazy { browserFavDao.getAll() }
@@ -58,11 +63,9 @@ class BrowserFavRepository(private val browserFavDao: BrowserFavDao) : IOScopedO
     val networkFavorites by lazy {
         MediatorLiveData<List<MediaWrapper>>().apply {
             addSource(networkFavs) { value = convertFavorites(it).filterNetworkFavs() }
-            addSource(ExternalMonitor.connected) {
-                launch(Dispatchers.Main.immediate) {
-                    val favList = convertFavorites(networkFavs.value)
-                    if (favList.isNotEmpty()) value = if (it == true) favList.filterNetworkFavs() else emptyList()
-                }
+            addSource(networkMonitor.connectionFlow.asLiveData()) {
+                val favList = convertFavorites(networkFavs.value)
+                if (favList.isNotEmpty()) value = if (it.connected) favList.filterNetworkFavs() else emptyList()
             }
         }
     }
@@ -75,7 +78,7 @@ class BrowserFavRepository(private val browserFavDao: BrowserFavDao) : IOScopedO
     private fun List<MediaWrapper>.filterNetworkFavs() : List<MediaWrapper> {
         return when {
             isEmpty() -> this
-            !ExternalMonitor.isConnected -> emptyList()
+            !networkMonitor.connected -> emptyList()
             !ExternalMonitor.allowLan() -> {
                 val schemes = Arrays.asList("ftp", "sftp", "ftps", "http", "https")
                 mutableListOf<MediaWrapper>().apply { this at filterNetworkFavs.filterTo(this) { schemes.contains(it.uri.scheme) } }



More information about the Android mailing list