[Android] OTG: Use a Flow for access
Geoffrey Métais
git at videolan.org
Fri Feb 21 14:34:17 CET 2020
vlc-android | branch: master | Geoffrey Métais <geoffrey.metais at gmail.com> | Wed Feb 19 11:40:28 2020 +0100| [a4baf9748b7522c12ab5bae90615d85a065c5dd0] | committer: Geoffrey Métais
OTG: Use a Flow for access
> https://code.videolan.org/videolan/vlc-android/commit/a4baf9748b7522c12ab5bae90615d85a065c5dd0
---
.../src/org/videolan/vlc/ExternalMonitor.kt | 4 +--
.../vlc/gui/browser/FileBrowserFragment.kt | 23 ++++++++--------
.../org/videolan/vlc/gui/helpers/hf/OtgAccess.kt | 31 ++++++++++++----------
3 files changed, 29 insertions(+), 29 deletions(-)
diff --git a/application/vlc-android/src/org/videolan/vlc/ExternalMonitor.kt b/application/vlc-android/src/org/videolan/vlc/ExternalMonitor.kt
index a1057efe7..b8c491d14 100644
--- a/application/vlc-android/src/org/videolan/vlc/ExternalMonitor.kt
+++ b/application/vlc-android/src/org/videolan/vlc/ExternalMonitor.kt
@@ -42,7 +42,6 @@ import kotlinx.coroutines.*
import kotlinx.coroutines.channels.BroadcastChannel
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.Channel.Factory.BUFFERED
-import kotlinx.coroutines.channels.Channel.Factory.UNLIMITED
import kotlinx.coroutines.channels.actor
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.consumeAsFlow
@@ -54,7 +53,6 @@ import org.videolan.tools.*
import org.videolan.tools.livedata.LiveDataset
import org.videolan.vlc.gui.helpers.UiTools
import org.videolan.vlc.gui.helpers.hf.OtgAccess
-import videolan.org.commontools.LiveEvent
import java.lang.ref.WeakReference
private const val TAG = "VLC/ExternalMonitor"
@@ -104,7 +102,7 @@ object ExternalMonitor : BroadcastReceiver(), LifecycleObserver, CoroutineScope
}
}
UsbManager.ACTION_USB_DEVICE_DETACHED -> if (intent.hasExtra(UsbManager.EXTRA_DEVICE)) {
- (OtgAccess.otgRoot as LiveEvent<Uri>).clear()
+ OtgAccess.otgRoot.offer(null)
val device = intent.getParcelableExtra<UsbDevice>(UsbManager.EXTRA_DEVICE)
devices.remove(device)
}
diff --git a/application/vlc-android/src/org/videolan/vlc/gui/browser/FileBrowserFragment.kt b/application/vlc-android/src/org/videolan/vlc/gui/browser/FileBrowserFragment.kt
index af34cc1e6..f75c0fee0 100644
--- a/application/vlc-android/src/org/videolan/vlc/gui/browser/FileBrowserFragment.kt
+++ b/application/vlc-android/src/org/videolan/vlc/gui/browser/FileBrowserFragment.kt
@@ -30,12 +30,13 @@ import android.view.Menu
import android.view.MenuInflater
import android.view.View
import androidx.fragment.app.Fragment
-import androidx.lifecycle.Observer
-import androidx.lifecycle.ViewModelProviders
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.ObsoleteCoroutinesApi
+import kotlinx.coroutines.flow.consumeAsFlow
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.first
import kotlinx.coroutines.withContext
import org.videolan.medialibrary.MLServiceLocator
import org.videolan.medialibrary.interfaces.media.MediaWrapper
@@ -47,8 +48,8 @@ import org.videolan.vlc.ExternalMonitor
import org.videolan.vlc.R
import org.videolan.vlc.gui.helpers.MedialibraryUtils
import org.videolan.vlc.gui.helpers.hf.OtgAccess
+import org.videolan.vlc.gui.helpers.hf.requestOtgRoot
import org.videolan.vlc.util.FileUtils
-import org.videolan.vlc.viewmodels.browser.BrowserModel
import org.videolan.vlc.viewmodels.browser.TYPE_FILE
import org.videolan.vlc.viewmodels.browser.getBrowserModel
@@ -115,18 +116,16 @@ open class FileBrowserFragment : BaseBrowserFragment() {
val mw = item as MediaWrapper
if ("otg://" == mw.location) {
val title = getString(R.string.otg_device_title)
- val otgRoot = OtgAccess.otgRoot
- val rootUri = otgRoot.value
+ val rootUri = OtgAccess.otgRoot.value
if (rootUri != null && ExternalMonitor.devices.size == 1) {
browseOtgDevice(rootUri, title)
} else {
- otgRoot.observeForever(object : Observer<Uri> {
- override fun onChanged(uri: Uri?) {
- OtgAccess.otgRoot.removeObserver(this)
- if (uri != null) browseOtgDevice(uri, title)
- }
- })
- OtgAccess.requestOtgRoot(requireActivity())
+ lifecycleScope.launchWhenStarted {
+ val otgRoot = OtgAccess.otgRoot.openSubscription().consumeAsFlow()
+ val uri = otgRoot.filterNotNull().first()
+ browseOtgDevice(uri, title)
+ }
+ requireActivity().requestOtgRoot()
}
return
}
diff --git a/application/vlc-android/src/org/videolan/vlc/gui/helpers/hf/OtgAccess.kt b/application/vlc-android/src/org/videolan/vlc/gui/helpers/hf/OtgAccess.kt
index 6ecedc817..6d352d623 100644
--- a/application/vlc-android/src/org/videolan/vlc/gui/helpers/hf/OtgAccess.kt
+++ b/application/vlc-android/src/org/videolan/vlc/gui/helpers/hf/OtgAccess.kt
@@ -31,10 +31,10 @@ import android.util.Log
import androidx.annotation.WorkerThread
import androidx.documentfile.provider.DocumentFile
import androidx.fragment.app.FragmentActivity
-import androidx.lifecycle.LiveData
+import kotlinx.coroutines.channels.ConflatedBroadcastChannel
import org.videolan.medialibrary.MLServiceLocator
import org.videolan.medialibrary.interfaces.media.MediaWrapper
-import videolan.org.commontools.LiveEvent
+import org.videolan.tools.safeOffer
const val SAF_REQUEST = 85
const val TAG = "OtgAccess"
@@ -47,31 +47,34 @@ class OtgAccess : BaseHeadlessFragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- val safIntent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
- try {
- startActivityForResult(safIntent, SAF_REQUEST)
- } catch (e: ActivityNotFoundException) {
- exit()
+ if (savedInstanceState == null) {
+ val safIntent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
+ try {
+ startActivityForResult(safIntent, SAF_REQUEST)
+ } catch (e: ActivityNotFoundException) {
+ exit()
+ }
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
- if (intent != null && requestCode == SAF_REQUEST) (otgRoot as LiveEvent).value = intent.data
+ if (intent != null && requestCode == SAF_REQUEST) otgRoot.safeOffer(intent.data)
else super.onActivityResult(requestCode, resultCode, intent)
exit()
}
companion object {
- fun requestOtgRoot(activity: FragmentActivity?) {
- activity?.supportFragmentManager?.beginTransaction()?.add(OtgAccess(), TAG)?.commitAllowingStateLoss()
- }
- var otgRoot : LiveData<Uri> = LiveEvent()
+ val otgRoot = ConflatedBroadcastChannel<Uri?>(null)
}
}
+fun FragmentActivity.requestOtgRoot() {
+ supportFragmentManager.beginTransaction().add(OtgAccess(), TAG).commitAllowingStateLoss()
+}
+
@WorkerThread
fun getDocumentFiles(context: Context, path: String) : List<MediaWrapper>? {
- val rootUri = OtgAccess.otgRoot.value ?: return null
+ val rootUri = OtgAccess.otgRoot.valueOrNull ?: return null
// else Uri.Builder().scheme("content")
// .authority(OTG_CONTENT_AUTHORITY)
// .path(path.substringBefore(':'))
@@ -107,4 +110,4 @@ fun getDocumentFiles(context: Context, path: String) : List<MediaWrapper>? {
}
}
return list
-}
\ No newline at end of file
+}
More information about the Android
mailing list