[Android] Prevent crash on Oreo when loadlastplaylist fails

Geoffrey Métais git at videolan.org
Thu Apr 12 17:21:31 CEST 2018


vlc-android | branch: 3.0.x | Geoffrey Métais <geoffrey.metais at gmail.com> | Thu Apr 12 17:21:09 2018 +0200| [57ebfe3fc744ffda6c378b64e4cb26dc3771b535] | committer: Geoffrey Métais

Prevent crash on Oreo when loadlastplaylist fails

> https://code.videolan.org/videolan/vlc-android/commit/57ebfe3fc744ffda6c378b64e4cb26dc3771b535
---

 .../src/org/videolan/vlc/PlaybackService.java      | 45 +++++++++++++++++-----
 .../src/org/videolan/vlc/media/PlaylistManager.kt  | 32 ++++++++-------
 2 files changed, 51 insertions(+), 26 deletions(-)

diff --git a/vlc-android/src/org/videolan/vlc/PlaybackService.java b/vlc-android/src/org/videolan/vlc/PlaybackService.java
index 92931f089..87cba3c81 100644
--- a/vlc-android/src/org/videolan/vlc/PlaybackService.java
+++ b/vlc-android/src/org/videolan/vlc/PlaybackService.java
@@ -250,6 +250,7 @@ public class PlaybackService extends MediaBrowserServiceCompat{
 
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
+        if (AndroidUtil.isOOrLater && !VLCApplication.isForeground()) forceForeground();
         if (intent == null) return START_NOT_STICKY;
         final String action = intent.getAction();
         if (Intent.ACTION_MEDIA_BUTTON.equals(action)) {
@@ -263,8 +264,7 @@ public class PlaybackService extends MediaBrowserServiceCompat{
             if (playlistManager.hasCurrentMedia()) play();
             else loadLastAudioPlaylist();
         } else if (Constants.ACTION_PLAY_FROM_SEARCH.equals(action)) {
-            if (mMediaSession == null)
-                initMediaSession();
+            if (mMediaSession == null) initMediaSession();
             final Bundle extras = intent.getBundleExtra(Constants.EXTRA_SEARCH_BUNDLE);
             mMediaSession.getController().getTransportControls()
                     .playFromSearch(extras.getString(SearchManager.QUERY), extras);
@@ -1194,13 +1194,40 @@ public class PlaybackService extends MediaBrowserServiceCompat{
 
     private void loadLastAudioPlaylist() {
         if (AndroidDevices.isAndroidTv) return;
-        if (mMedialibrary.isInitiated() && mLibraryReceiver == null) playlistManager.loadLastPlaylist(Constants.PLAYLIST_TYPE_AUDIO);
-        else registerMedialibrary(new Runnable() {
-                @Override
-                public void run() {
-                    playlistManager.loadLastPlaylist(Constants.PLAYLIST_TYPE_AUDIO);
-                }
-            });
+        if (mMedialibrary.isInitiated() && mLibraryReceiver == null) {
+            if (!playlistManager.loadLastPlaylist(Constants.PLAYLIST_TYPE_AUDIO)) stopSelf();
+        } else registerMedialibrary(new Runnable() {
+            @Override
+            public void run() {
+                if (!playlistManager.loadLastPlaylist(Constants.PLAYLIST_TYPE_AUDIO)) stopSelf();
+            }
+        });
+    }
+
+    private void forceForeground() {
+        final Context ctx = PlaybackService.this;
+        final MediaSessionCompat.Token sessionToken = mMediaSession.getSessionToken();
+        final Notification notification = NotificationHelper.createPlaybackNotification(ctx,
+                false, ctx.getResources().getString(R.string.loading), "", "",
+                null, false, sessionToken, getSessionPendingIntent());
+        PlaybackService.this.startForeground(3, notification);
+        mIsForeground = true;
+        ExecutorHolder.executorService.execute(new Runnable() {
+            @Override
+            public void run() {
+                final Bitmap cover = BitmapFactory.decodeResource(ctx.getResources(), R.drawable.ic_no_media);
+                VLCApplication.runOnMainThread(new Runnable() {
+                    @Override
+                    public void run() {
+                        final Notification notification = NotificationHelper.createPlaybackNotification(ctx,
+                                false, ctx.getResources().getString(R.string.loading), "", "",
+                                cover, false, sessionToken, getSessionPendingIntent());
+                        PlaybackService.this.startForeground(3, notification);
+                        mIsForeground = true;
+                    }
+                });
+            }
+        });
     }
 
     public void loadLastPlaylist(int type) {
diff --git a/vlc-android/src/org/videolan/vlc/media/PlaylistManager.kt b/vlc-android/src/org/videolan/vlc/media/PlaylistManager.kt
index 7440148a2..7e4c047da 100644
--- a/vlc-android/src/org/videolan/vlc/media/PlaylistManager.kt
+++ b/vlc-android/src/org/videolan/vlc/media/PlaylistManager.kt
@@ -26,13 +26,12 @@ import org.videolan.vlc.gui.video.VideoPlayerActivity
 import org.videolan.vlc.util.*
 import java.util.*
 
+private const val TAG = "VLC/PlaylistManager"
+private const val PREVIOUS_LIMIT_DELAY = 5000L
+private const val AUDIO_REPEAT_MODE_KEY = "audio_repeat_mode"
 
 class PlaylistManager(val service: PlaybackService) : MediaWrapperList.EventListener, Media.EventListener {
 
-    private val TAG = "VLC/PlaylistManager"
-    private val PREVIOUS_LIMIT_DELAY = 5000L
-    private val AUDIO_REPEAT_MODE_KEY = "audio_repeat_mode"
-
     private val medialibrary by lazy(LazyThreadSafetyMode.NONE) { Medialibrary.getInstance() }
     val player by lazy(LazyThreadSafetyMode.NONE) { PlayerController() }
     private val settings by lazy(LazyThreadSafetyMode.NONE) { PreferenceManager.getDefaultSharedPreferences(service) }
@@ -83,11 +82,11 @@ class PlaylistManager(val service: PlaybackService) : MediaWrapperList.EventList
             var mediaWrapper = medialibrary.getMedia(location)
             if (mediaWrapper === null) {
                 if (!location.validateLocation()) {
-                    Log.w(TAG, "Invalid location " + location)
+                    Log.w(TAG, "Invalid location $location")
                     service.showToast(service.resources.getString(R.string.invalid_location, location), Toast.LENGTH_SHORT)
                     continue
                 }
-                Log.v(TAG, "Creating on-the-fly Media object for " + location)
+                Log.v(TAG, "Creating on-the-fly Media object for $location")
                 mediaWrapper = MediaWrapper(Uri.parse(location))
             }
             mediaList.add(mediaWrapper)
@@ -114,15 +113,15 @@ class PlaylistManager(val service: PlaybackService) : MediaWrapperList.EventList
 
     @Volatile
     private var loadingLastPlaylist = false
-    fun loadLastPlaylist(type: Int) {
-        if (loadingLastPlaylist) return
+    fun loadLastPlaylist(type: Int) : Boolean {
+        if (loadingLastPlaylist) return false
         loadingLastPlaylist = true
+        val audio = type == Constants.PLAYLIST_TYPE_AUDIO
+        val currentMedia = settings.getString(if (audio) "current_song" else "current_media", "")
+        if ("" == currentMedia) return false
+        val locations = settings.getString(if (audio) "audio_list" else "media_list", "").split(" ".toRegex()).dropLastWhile({ it.isEmpty() }).toTypedArray()
+        if (Util.isArrayEmpty(locations)) return false
         launch(UI, CoroutineStart.UNDISPATCHED) {
-            val audio = type == Constants.PLAYLIST_TYPE_AUDIO
-            val currentMedia = settings.getString(if (audio) "current_song" else "current_media", "")
-            if ("" == currentMedia) return at launch
-            val locations = settings.getString(if (audio) "audio_list" else "media_list", "").split(" ".toRegex()).dropLastWhile({ it.isEmpty() }).toTypedArray()
-            if (Util.isArrayEmpty(locations)) return at launch
             val playList = async {
                 locations.map { Uri.decode(it) }.mapTo(ArrayList(locations.size)) { MediaWrapper(Uri.parse(it)) }
             }.await()
@@ -141,6 +140,7 @@ class PlaylistManager(val service: PlaybackService) : MediaWrapperList.EventList
             load(playList, position)
             loadingLastPlaylist = false
         }
+        return true
     }
 
     private fun onPlaylistLoaded() {
@@ -274,12 +274,10 @@ class PlaylistManager(val service: PlaybackService) : MediaWrapperList.EventList
                     var id = mw.id
                     if (id == 0L) {
                         var internalMedia = medialibrary.findMedia(mw)
-                        if (internalMedia != null && internalMedia.id != 0L)
-                            id = internalMedia.id
+                        if (internalMedia != null && internalMedia.id != 0L) id = internalMedia.id
                         else {
                             internalMedia = medialibrary.addMedia(Uri.decode(mw.uri.toString()))
-                            if (internalMedia != null)
-                                id = internalMedia.id
+                            if (internalMedia != null) id = internalMedia.id
                         }
                     }
                     medialibrary.increasePlayCount(id)



More information about the Android mailing list