[Android] Workaround for IllegalStateException on Pie
Geoffrey Métais
git at videolan.org
Mon Nov 25 11:52:16 CET 2019
vlc-android | branch: master | Geoffrey Métais <geoffrey at videolan.org> | Mon Nov 25 11:52:15 2019 +0100| [3d7f70e694abecab048b6a393bcff529374eb945] | committer: Nicolas Pomepuy
Workaround for IllegalStateException on Pie
Android 9 has a bug, sometimes, service cannot be started as soon as app
is:
https://issuetracker.google.com/issues/113122354
This fix creates a suspend function which will wait for the app to go
foreground, and use it to launch the service only when we can
> https://code.videolan.org/videolan/vlc-android/commit/3d7f70e694abecab048b6a393bcff529374eb945
---
.../java/org/videolan/tools/KotlinExtensions.kt | 25 ++++++++++++++++++++++
.../src/org/videolan/vlc/RendererDelegate.kt | 6 +++++-
vlc-android/src/org/videolan/vlc/StartActivity.kt | 8 +++++++
.../providers/medialibrary/MedialibraryProvider.kt | 6 +++++-
.../src/org/videolan/vlc/util/Kextensions.kt | 12 -----------
5 files changed, 43 insertions(+), 14 deletions(-)
diff --git a/tools/src/main/java/org/videolan/tools/KotlinExtensions.kt b/tools/src/main/java/org/videolan/tools/KotlinExtensions.kt
index fb8b945e3..fc94db43d 100644
--- a/tools/src/main/java/org/videolan/tools/KotlinExtensions.kt
+++ b/tools/src/main/java/org/videolan/tools/KotlinExtensions.kt
@@ -1,5 +1,7 @@
package org.videolan.tools
+import android.app.ActivityManager
+import android.app.ActivityManager.RunningAppProcessInfo
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
@@ -79,3 +81,26 @@ fun Context.copy(label: String, text: String) {
setPrimaryClip(ClipData.newPlainText(label, text))
}
}
+
+suspend fun retry (
+ times: Int = 3,
+ delayTime: Long = 500L,
+ block: suspend () -> Boolean): Boolean
+{
+ repeat(times - 1) {
+ if (block()) return true
+ if (delayTime > 0L) delay(delayTime)
+ }
+ return block() // last attempt
+}
+
+suspend fun Context.awaitAppIsForegroung() : Boolean {
+ val activityManager = applicationContext.getSystemService(Context.ACTIVITY_SERVICE) as? ActivityManager ?: return false
+ repeat(times = 2) {
+ if (activityManager.isAppForeground()) return true
+ else yield() //dispatch next try
+ }
+ return activityManager.isAppForeground()
+}
+
+private fun ActivityManager.isAppForeground() = runningAppProcesses[0].importance <= RunningAppProcessInfo.IMPORTANCE_FOREGROUND
\ No newline at end of file
diff --git a/vlc-android/src/org/videolan/vlc/RendererDelegate.kt b/vlc-android/src/org/videolan/vlc/RendererDelegate.kt
index 11dd9d60b..26c623176 100644
--- a/vlc-android/src/org/videolan/vlc/RendererDelegate.kt
+++ b/vlc-android/src/org/videolan/vlc/RendererDelegate.kt
@@ -22,7 +22,11 @@ package org.videolan.vlc
import kotlinx.coroutines.*
import org.videolan.libvlc.RendererDiscoverer
import org.videolan.libvlc.RendererItem
-import org.videolan.vlc.util.*
+import org.videolan.tools.retry
+import org.videolan.vlc.util.AppScope
+import org.videolan.vlc.util.LiveDataset
+import org.videolan.vlc.util.VLCInstance
+import org.videolan.vlc.util.isAppStarted
import java.util.*
@ObsoleteCoroutinesApi
diff --git a/vlc-android/src/org/videolan/vlc/StartActivity.kt b/vlc-android/src/org/videolan/vlc/StartActivity.kt
index 0f554a0a4..de1dbc661 100644
--- a/vlc-android/src/org/videolan/vlc/StartActivity.kt
+++ b/vlc-android/src/org/videolan/vlc/StartActivity.kt
@@ -26,6 +26,7 @@ package org.videolan.vlc
import android.content.Context
import android.content.Intent
import android.net.Uri
+import android.os.Build
import android.os.Bundle
import android.provider.MediaStore
import android.text.TextUtils
@@ -35,6 +36,7 @@ import androidx.fragment.app.FragmentActivity
import kotlinx.coroutines.*
import org.videolan.libvlc.util.AndroidUtil
import org.videolan.medialibrary.MLServiceLocator
+import org.videolan.tools.awaitAppIsForegroung
import org.videolan.vlc.gui.BetaWelcomeActivity
import org.videolan.vlc.gui.MainActivity
import org.videolan.vlc.gui.SearchActivity
@@ -196,6 +198,12 @@ class StartActivity : FragmentActivity(), CoroutineScope by MainScope() {
}
private fun startPlaybackFromApp(intent: Intent) = launch(start = CoroutineStart.UNDISPATCHED) {
+ // workaround for a Android 9 bug
+ // https://issuetracker.google.com/issues/113122354
+ if (Build.VERSION.SDK_INT == Build.VERSION_CODES.P && !awaitAppIsForegroung()) {
+ finish()
+ return at launch
+ }
if (Permissions.canReadStorage(applicationContext) || getStoragePermission()) when {
intent.type?.startsWith("video") == true -> try {
startActivity(intent.setClass(this at StartActivity, VideoPlayerActivity::class.java))
diff --git a/vlc-android/src/org/videolan/vlc/providers/medialibrary/MedialibraryProvider.kt b/vlc-android/src/org/videolan/vlc/providers/medialibrary/MedialibraryProvider.kt
index 3efaeceab..b3300123a 100644
--- a/vlc-android/src/org/videolan/vlc/providers/medialibrary/MedialibraryProvider.kt
+++ b/vlc-android/src/org/videolan/vlc/providers/medialibrary/MedialibraryProvider.kt
@@ -33,8 +33,12 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.videolan.medialibrary.interfaces.AbstractMedialibrary
import org.videolan.medialibrary.media.MediaLibraryItem
+import org.videolan.tools.retry
import org.videolan.vlc.providers.HeaderProvider
-import org.videolan.vlc.util.*
+import org.videolan.vlc.util.MEDIALIBRARY_PAGE_SIZE
+import org.videolan.vlc.util.ModelsHelper
+import org.videolan.vlc.util.Settings
+import org.videolan.vlc.util.SortModule
import org.videolan.vlc.viewmodels.SortableModel
abstract class MedialibraryProvider<T : MediaLibraryItem>(val context: Context, val model: SortableModel) : HeaderProvider(),
diff --git a/vlc-android/src/org/videolan/vlc/util/Kextensions.kt b/vlc-android/src/org/videolan/vlc/util/Kextensions.kt
index 6d7b0afb5..135efe35b 100644
--- a/vlc-android/src/org/videolan/vlc/util/Kextensions.kt
+++ b/vlc-android/src/org/videolan/vlc/util/Kextensions.kt
@@ -66,18 +66,6 @@ inline fun <reified T : ViewModel> Fragment.getModelWithActivity() = ViewModelPr
inline fun <reified T : ViewModel> Fragment.getModel() = ViewModelProviders.of(this).get(T::class.java)
inline fun <reified T : ViewModel> FragmentActivity.getModel() = ViewModelProviders.of(this).get(T::class.java)
-suspend fun retry (
- times: Int = 3,
- delayTime: Long = 500L,
- block: suspend () -> Boolean): Boolean
-{
- repeat(times - 1) {
- if (block()) return true
- delay(delayTime)
- }
- return block() // last attempt
-}
-
fun Media?.canExpand() = this != null && (type == Media.Type.Directory || type == Media.Type.Playlist)
suspend fun AppCompatActivity.share(media: AbstractMediaWrapper) {
val intentShareFile = Intent(Intent.ACTION_SEND)
More information about the Android
mailing list