[Android] Improve headless fragments callback system
Geoffrey Métais
git at videolan.org
Tue Aug 7 18:48:33 CEST 2018
vlc-android | branch: master | Geoffrey Métais <geoffrey.metais at gmail.com> | Tue Aug 7 18:48:11 2018 +0200| [eb8586ad11f1529148ddc63b82b0f502a3e6bb9b] | committer: Geoffrey Métais
Improve headless fragments callback system
> https://code.videolan.org/videolan/vlc-android/commit/eb8586ad11f1529148ddc63b82b0f502a3e6bb9b
---
.../vlc/gui/helpers/hf/BaseHeadlessFragment.kt | 25 +++++++++++++---------
.../gui/helpers/hf/StoragePermissionsDelegate.kt | 12 ++++++++---
.../vlc/gui/helpers/hf/WriteExternalDelegate.kt | 19 ++++++++--------
3 files changed, 34 insertions(+), 22 deletions(-)
diff --git a/vlc-android/src/org/videolan/vlc/gui/helpers/hf/BaseHeadlessFragment.kt b/vlc-android/src/org/videolan/vlc/gui/helpers/hf/BaseHeadlessFragment.kt
index d6c6a07bd..6fe26b9b2 100644
--- a/vlc-android/src/org/videolan/vlc/gui/helpers/hf/BaseHeadlessFragment.kt
+++ b/vlc-android/src/org/videolan/vlc/gui/helpers/hf/BaseHeadlessFragment.kt
@@ -25,12 +25,16 @@ package org.videolan.vlc.gui.helpers.hf
import android.content.Context
import android.os.Bundle
-import android.os.Handler
import android.support.v4.app.Fragment
import android.support.v4.app.FragmentActivity
+import kotlinx.coroutines.experimental.android.UI
+import kotlinx.coroutines.experimental.channels.Channel
+import kotlinx.coroutines.experimental.channels.SendChannel
+import kotlinx.coroutines.experimental.launch
open class BaseHeadlessFragment : Fragment() {
protected var mActivity: FragmentActivity? = null
+ var channel: SendChannel<Unit>? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -51,17 +55,18 @@ open class BaseHeadlessFragment : Fragment() {
if (mActivity?.isFinishing == false) mActivity!!.supportFragmentManager.beginTransaction().remove(this).commitAllowingStateLoss()
}
+ fun executePendingAction() {
+ channel?.let { it.offer(Unit) }
+ channel = null
+ }
+
companion object {
- internal var callback: Runnable? = null
- internal fun executeCallback() {
- callback?.let {
- try {
- Handler().postDelayed(it, 500);
- } catch (ignored: Exception) {
- } finally {
- callback = null
- }
+ internal fun waitForIt(channel: Channel<Unit>, cb: Runnable) {
+ launch(UI.immediate) {
+ channel.receive()
+ channel.close()
+ cb.run()
}
}
}
diff --git a/vlc-android/src/org/videolan/vlc/gui/helpers/hf/StoragePermissionsDelegate.kt b/vlc-android/src/org/videolan/vlc/gui/helpers/hf/StoragePermissionsDelegate.kt
index 4a3770f64..2c1488a05 100644
--- a/vlc-android/src/org/videolan/vlc/gui/helpers/hf/StoragePermissionsDelegate.kt
+++ b/vlc-android/src/org/videolan/vlc/gui/helpers/hf/StoragePermissionsDelegate.kt
@@ -30,6 +30,7 @@ import android.os.Build
import android.os.Bundle
import android.support.v4.app.Fragment
import android.support.v4.app.FragmentActivity
+import kotlinx.coroutines.experimental.channels.Channel
import org.videolan.libvlc.util.AndroidUtil
import org.videolan.vlc.startMedialibrary
import org.videolan.vlc.util.Constants
@@ -90,7 +91,7 @@ class StoragePermissionsDelegate : BaseHeadlessFragment() {
exit()
}
}
- Permissions.PERMISSION_WRITE_STORAGE_TAG -> executeCallback()
+ Permissions.PERMISSION_WRITE_STORAGE_TAG -> executePendingAction()
}
}
@@ -102,15 +103,20 @@ class StoragePermissionsDelegate : BaseHeadlessFragment() {
if (activity.isFinishing) return
val fm = activity.supportFragmentManager
var fragment: Fragment? = fm.findFragmentByTag(TAG)
- callback = cb
+ val channel = if (cb != null) Channel<Unit>(1) else null
if (fragment == null) {
val args = Bundle()
args.putBoolean("write", write)
fragment = StoragePermissionsDelegate()
fragment.arguments = args
+ channel?.let { fragment.channel = it }
+
fm.beginTransaction().add(fragment, TAG).commitAllowingStateLoss()
- } else
+ } else {
+ channel?.let { (fragment as StoragePermissionsDelegate).channel = it }
(fragment as StoragePermissionsDelegate).requestStorageAccess(write)
+ }
+ channel?.let { waitForIt(it, cb!!) }
}
}
}
diff --git a/vlc-android/src/org/videolan/vlc/gui/helpers/hf/WriteExternalDelegate.kt b/vlc-android/src/org/videolan/vlc/gui/helpers/hf/WriteExternalDelegate.kt
index 25fc5f103..371ad0bda 100644
--- a/vlc-android/src/org/videolan/vlc/gui/helpers/hf/WriteExternalDelegate.kt
+++ b/vlc-android/src/org/videolan/vlc/gui/helpers/hf/WriteExternalDelegate.kt
@@ -12,6 +12,7 @@ import android.support.v4.provider.DocumentFile
import android.support.v7.app.AlertDialog
import android.support.v7.preference.PreferenceManager
import android.text.TextUtils
+import kotlinx.coroutines.experimental.channels.Channel
import org.videolan.libvlc.util.AndroidUtil
import org.videolan.vlc.R
import org.videolan.vlc.VLCApplication
@@ -32,14 +33,12 @@ class WriteExternalDelegate : BaseHeadlessFragment() {
val builder = AlertDialog.Builder(activity!!)
builder.setMessage(R.string.sdcard_permission_dialog_message)
.setTitle(R.string.sdcard_permission_dialog_title)
- .setPositiveButton(R.string.ok, { _, _ ->
+ .setPositiveButton(R.string.ok) { _, _ ->
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
arguments?.getString(KEY_STORAGE_PATH)?.let { intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, Uri.parse(it)) }
startActivityForResult(intent, REQUEST_CODE_STORAGE_ACCES)
- })
- .setNeutralButton(getString(R.string.dialog_sd_wizard), { _, _ ->
- showHelpDialog()
- }).create().show()
+ }
+ .setNeutralButton(getString(R.string.dialog_sd_wizard)) { _, _ -> showHelpDialog() }.create().show()
}
private fun showHelpDialog() {
@@ -52,6 +51,7 @@ class WriteExternalDelegate : BaseHeadlessFragment() {
}
}
+ @TargetApi(Build.VERSION_CODES.KITKAT)
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (data !== null && requestCode == REQUEST_CODE_STORAGE_ACCES) {
@@ -59,7 +59,7 @@ class WriteExternalDelegate : BaseHeadlessFragment() {
val context = context ?: return
val treeUri = data.data
PreferenceManager.getDefaultSharedPreferences(VLCApplication.getAppContext()).edit()
- .putString("tree_uri_"+ storage, treeUri.toString()).apply()
+ .putString("tree_uri_$storage", treeUri.toString()).apply()
val treeFile = DocumentFile.fromTreeUri(context, treeUri)
val contentResolver = context.contentResolver
@@ -76,11 +76,10 @@ class WriteExternalDelegate : BaseHeadlessFragment() {
// else set permission
contentResolver.takePersistableUriPermission(treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
permissions = contentResolver.persistedUriPermissions
- executeCallback()
+ executePendingAction()
return
}
}
- callback = null
}
companion object {
@@ -93,10 +92,12 @@ class WriteExternalDelegate : BaseHeadlessFragment() {
fun askForExtWrite(activity: FragmentActivity?, uri: Uri, cb: Runnable? = null) {
if (activity === null) return
val fragment = WriteExternalDelegate()
- callback = cb
+ val channel = if (cb != null) Channel<Unit>(1) else null
storage = FileUtils.getMediaStorage(uri) ?: return
fragment.arguments = Bundle(1).apply { putString(KEY_STORAGE_PATH, storage) }
+ channel?.let { fragment.channel = it }
activity.supportFragmentManager.beginTransaction().add(fragment, TAG).commitAllowingStateLoss()
+ channel?.let { waitForIt(it, cb!!) }
}
fun needsWritePermission(uri: Uri) : Boolean {
More information about the Android
mailing list