[Android] Services: Stop with stopService()

Geoffrey Métais git at videolan.org
Thu Jan 23 13:54:00 CET 2020


vlc-android | branch: master | Geoffrey Métais <geoffrey at videolan.org> | Thu Jan 23 13:53:59 2020 +0100| [95f5017d4db7e5e5a0e722beb69d5e6688112da8] | committer: Nicolas Pomepuy

Services: Stop with stopService()

Calling stopSelf() could cause the service to be destroyed before
calling setForeground() and lead to a RemoteException

> https://code.videolan.org/videolan/vlc-android/commit/95f5017d4db7e5e5a0e722beb69d5e6688112da8
---

 .../src/org/videolan/vlc/MediaParsingService.kt    | 22 ++++++++++------------
 .../src/org/videolan/vlc/PlaybackService.kt        |  6 +++---
 2 files changed, 13 insertions(+), 15 deletions(-)

diff --git a/vlc-android/src/org/videolan/vlc/MediaParsingService.kt b/vlc-android/src/org/videolan/vlc/MediaParsingService.kt
index 03a15e079..01dc193cc 100644
--- a/vlc-android/src/org/videolan/vlc/MediaParsingService.kt
+++ b/vlc-android/src/org/videolan/vlc/MediaParsingService.kt
@@ -35,7 +35,6 @@ import android.os.IBinder
 import android.os.PowerManager
 import android.text.TextUtils
 import android.util.Log
-import androidx.core.app.NotificationManagerCompat
 import androidx.core.content.ContextCompat
 import androidx.lifecycle.*
 import kotlinx.coroutines.*
@@ -73,7 +72,6 @@ class MediaParsingService : LifecycleService(), DevicesDiscoveryCb, LifecycleOwn
     private var reload = 0
     private var currentDiscovery: String? = null
     @Volatile private var lastNotificationTime = 0L
-    private var notificationJob: Job? = null
     @Volatile private var scanActivated = false
 
     private val settings by lazy { Settings.getInstance(this) }
@@ -139,9 +137,8 @@ class MediaParsingService : LifecycleService(), DevicesDiscoveryCb, LifecycleOwn
         registerReceiver(receiver, filter)
         val pm = applicationContext.getSystemService(Context.POWER_SERVICE) as PowerManager
         wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "VLC:MediaParsigService")
-        wakeLock.acquire()
 
-        if (lastNotificationTime == 5L) stopSelf()
+        if (lastNotificationTime == 5L) stopService(Intent(applicationContext, MediaParsingService.javaClass))
         Medialibrary.getState().observe(this, Observer<Boolean> { running ->
             if (!running && !scanPaused) {
                 exitCommand()
@@ -160,7 +157,7 @@ class MediaParsingService : LifecycleService(), DevicesDiscoveryCb, LifecycleOwn
         // Set 1s delay before displaying scan icon
         // Except for Android 8+ which expects startForeground immediately
         if (AndroidUtil.isOOrLater) forceForeground()
-        else if (lastNotificationTime <= 0L) lastNotificationTime = System.currentTimeMillis()
+        if (lastNotificationTime <= 0L) lastNotificationTime = if (AndroidUtil.isOOrLater) 0L else System.currentTimeMillis()
         super.onStartCommand(intent, flags, startId)
         dispatcher.onServicePreSuperOnStart()
         when (intent.action) {
@@ -179,6 +176,7 @@ class MediaParsingService : LifecycleService(), DevicesDiscoveryCb, LifecycleOwn
                 return START_NOT_STICKY
             }
         }
+        if (!wakeLock.isHeld) wakeLock.acquire()
         return START_NOT_STICKY
     }
 
@@ -333,9 +331,9 @@ class MediaParsingService : LifecycleService(), DevicesDiscoveryCb, LifecycleOwn
             }
             val progressText = sb.toString()
             if (!isActive) return at withContext ""
-            val notification = NotificationHelper.createScanNotification(applicationContext, progressText, scanPaused)
             if (lastNotificationTime != -1L) {
                 try {
+                    val notification = NotificationHelper.createScanNotification(applicationContext, progressText, scanPaused)
                     startForeground(43, notification)
                 } catch (ignored: IllegalArgumentException) {}
                 progressText
@@ -344,10 +342,9 @@ class MediaParsingService : LifecycleService(), DevicesDiscoveryCb, LifecycleOwn
         showProgress(parsing, discovery)
     }
 
-    private suspend fun hideNotification() {
-        notificationJob?.cancelAndJoin()
+    private fun hideNotification() {
         lastNotificationTime = -1L
-        NotificationManagerCompat.from(this at MediaParsingService).cancel(43)
+        stopForeground(true)
         showProgress(-1, "")
     }
 
@@ -386,22 +383,23 @@ class MediaParsingService : LifecycleService(), DevicesDiscoveryCb, LifecycleOwn
     private fun exitCommand() {
         if (!medialibrary.isWorking && !serviceLock && !discoverTriggered) {
             lastNotificationTime = 0L
+            if (wakeLock.isHeld) wakeLock.release()
             //todo reenable entry point when ready
             if (BuildConfig.DEBUG) try {
                 indexingListeners.forEach { it.onIndexingDone() }
             } catch (e: Exception) {
                 if (BuildConfig.DEBUG) Log.d(this::class.java.simpleName, "${e.cause}")
             }
-            stopSelf()
+            notificationActor.offer(Hide)
+            stopForeground(true)
+            stopService(Intent(applicationContext, MediaParsingService.javaClass))
         }
     }
 
     override fun onDestroy() {
         dispatcher.onServicePreSuperOnDestroy()
-        notificationActor.offer(Hide)
         medialibrary.removeDeviceDiscoveryCb(this)
         unregisterReceiver(receiver)
-        if (wakeLock.isHeld) wakeLock.release()
         medialibrary.exceptionHandler = null
         super.onDestroy()
     }
diff --git a/vlc-android/src/org/videolan/vlc/PlaybackService.kt b/vlc-android/src/org/videolan/vlc/PlaybackService.kt
index 015565523..b7f51700e 100644
--- a/vlc-android/src/org/videolan/vlc/PlaybackService.kt
+++ b/vlc-android/src/org/videolan/vlc/PlaybackService.kt
@@ -562,7 +562,7 @@ class PlaybackService : MediaBrowserServiceCompat(), LifecycleOwner {
     }
 
     override fun onTaskRemoved(rootIntent: Intent) {
-        if (settings.getBoolean("audio_task_removed", false)) stopSelf()
+        if (settings.getBoolean("audio_task_removed", false)) stopService(Intent(applicationContext, PlaybackService.javaClass))
     }
 
     override fun onDestroy() {
@@ -718,7 +718,7 @@ class PlaybackService : MediaBrowserServiceCompat(), LifecycleOwner {
                         cover = BitmapFactory.decodeResource(ctx.resources, R.drawable.ic_no_media)
 
                     notification = NotificationHelper.createPlaybackNotification(ctx,
-                            mw.hasFlag(MediaWrapper.MEDIA_FORCE_AUDIO), title, artist, album,
+                            canSwitchToVideo(), title, artist, album,
                             cover, playing, isPausable, sessionToken, sessionPendingIntent)
                     if (isPlayingPopup) return at launch
                     if (!AndroidUtil.isLolliPopOrLater || playing || audioFocusHelper.lossTransient) {
@@ -997,7 +997,7 @@ class PlaybackService : MediaBrowserServiceCompat(), LifecycleOwner {
         if (AndroidDevices.isAndroidTv) return
         scope.launch {
             awaitMedialibraryStarted()
-            if (!playlistManager.loadLastPlaylist()) stopSelf()
+            if (!playlistManager.loadLastPlaylist()) stopService(Intent(applicationContext, PlaybackService.javaClass))
         }
     }
 



More information about the Android mailing list