Another Attempt at Auto

This commit is contained in:
James Wells 2021-07-04 16:42:18 -04:00
parent 04de4544ee
commit db0669098c
No known key found for this signature in database
GPG Key ID: DB1528F6EED16127
3 changed files with 130 additions and 139 deletions

View File

@ -56,6 +56,12 @@
<service
android:name=".service.MediaPlayerService"
android:label="Ultrasonic Media Player Service"
android:exported="false">
</service>
<service
android:name=".service.AutoMediaPlayerService"
android:label="Ultrasonic Auto Media Player Service"
android:exported="true">
<intent-filter>

View File

@ -1,6 +1,5 @@
package org.moire.ultrasonic.util
package org.moire.ultrasonic.service
import android.app.Application
import android.os.Bundle
import android.support.v4.media.MediaBrowserCompat
import android.support.v4.media.MediaDescriptionCompat
@ -8,24 +7,26 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.media.MediaBrowserServiceCompat
import androidx.media.utils.MediaConstants
import org.moire.ultrasonic.api.subsonic.models.AlbumListType
import org.moire.ultrasonic.domain.ArtistOrIndex
import org.moire.ultrasonic.domain.MusicDirectory
import org.moire.ultrasonic.domain.PlayerState
import org.moire.ultrasonic.fragment.AlbumListModel
import org.moire.ultrasonic.fragment.ArtistListModel
import org.moire.ultrasonic.util.Constants
import org.moire.ultrasonic.util.Pair
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.ObjectInputStream
import java.io.ObjectOutputStream
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import org.moire.ultrasonic.api.subsonic.models.AlbumListType
import org.moire.ultrasonic.domain.Artist
import org.moire.ultrasonic.domain.ArtistOrIndex
import org.moire.ultrasonic.domain.MusicDirectory
import org.moire.ultrasonic.fragment.AlbumListModel
import org.moire.ultrasonic.fragment.ArtistListModel
import org.moire.ultrasonic.service.MusicServiceFactory
class AndroidAutoMediaBrowser(application: Application) {
class AutoMediaPlayerService: MediaBrowserServiceCompat() {
val albumListModel: AlbumListModel = AlbumListModel(application)
val artistListModel: ArtistListModel = ArtistListModel(application)
val mediaPlayerService : MediaPlayerService = MediaPlayerService()
var albumListModel: AlbumListModel? = null
var artistListModel: ArtistListModel? = null
val executorService: ExecutorService = Executors.newFixedThreadPool(4)
var maximumRootChildLimit: Int = 4
@ -135,11 +136,17 @@ class AndroidAutoMediaBrowser(application: Application) {
}
}
fun getRoot(
clientPackageName: String,
clientUid: Int,
rootHints: Bundle?
): MediaBrowserServiceCompat.BrowserRoot {
override fun onCreate() {
super.onCreate()
albumListModel = AlbumListModel(application)
artistListModel = ArtistListModel(application)
mediaPlayerService.onCreate()
mediaPlayerService.updateMediaSession(null, PlayerState.IDLE)
}
override fun onGetRoot(clientPackageName: String, clientUid: Int, rootHints: Bundle?): BrowserRoot? {
if (rootHints != null) {
maximumRootChildLimit = rootHints.getInt(
MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_LIMIT,
@ -154,14 +161,10 @@ class AndroidAutoMediaBrowser(application: Application) {
return MediaBrowserServiceCompat.BrowserRoot(MEDIA_BROWSER_ROOT_ID, extras)
}
fun loadChildren(
parentMediaId: String,
result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>
) {
override fun onLoadChildren(parentId: String, result: Result<List<MediaBrowserCompat.MediaItem>>) {
val mediaItems: MutableList<MediaBrowserCompat.MediaItem> = mutableListOf()
if (MEDIA_BROWSER_ROOT_ID == parentMediaId) {
if (MEDIA_BROWSER_ROOT_ID == parentId) {
// Build the MediaItem objects for the top level,
// and put them in the mediaItems list...
@ -189,24 +192,24 @@ class AndroidAutoMediaBrowser(application: Application) {
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE
)
)
} else if (MEDIA_BROWSER_RECENT_LIST_ROOT == parentMediaId) {
} else if (MEDIA_BROWSER_RECENT_LIST_ROOT == parentId) {
fetchAlbumList(AlbumListType.RECENT, MEDIA_BROWSER_RECENT_PREFIX, result)
return
} else if (MEDIA_BROWSER_ALBUM_LIST_ROOT == parentMediaId) {
} else if (MEDIA_BROWSER_ALBUM_LIST_ROOT == parentId) {
fetchAlbumList(AlbumListType.SORTED_BY_NAME, MEDIA_BROWSER_ALBUM_PREFIX, result)
return
} else if (MEDIA_BROWSER_ARTIST_LIST_ROOT == parentMediaId) {
} else if (MEDIA_BROWSER_ARTIST_LIST_ROOT == parentId) {
fetchArtistList(MEDIA_BROWSER_ARTIST_PREFIX, result)
return
} else if (parentMediaId.startsWith(MEDIA_BROWSER_RECENT_PREFIX)) {
fetchTrackList(parentMediaId.substring(MEDIA_BROWSER_RECENT_PREFIX.length), result)
} else if (parentId.startsWith(MEDIA_BROWSER_RECENT_PREFIX)) {
fetchTrackList(parentId.substring(MEDIA_BROWSER_RECENT_PREFIX.length), result)
return
} else if (parentMediaId.startsWith(MEDIA_BROWSER_ALBUM_PREFIX)) {
fetchTrackList(parentMediaId.substring(MEDIA_BROWSER_ALBUM_PREFIX.length), result)
} else if (parentId.startsWith(MEDIA_BROWSER_ALBUM_PREFIX)) {
fetchTrackList(parentId.substring(MEDIA_BROWSER_ALBUM_PREFIX.length), result)
return
} else if (parentMediaId.startsWith(MEDIA_BROWSER_ARTIST_PREFIX)) {
} else if (parentId.startsWith(MEDIA_BROWSER_ARTIST_PREFIX)) {
fetchArtistAlbumList(
parentMediaId.substring(MEDIA_BROWSER_ARTIST_PREFIX.length),
parentId.substring(MEDIA_BROWSER_ARTIST_PREFIX.length),
result
)
return
@ -217,6 +220,7 @@ class AndroidAutoMediaBrowser(application: Application) {
result.sendResult(mediaItems)
}
fun getBundleData(bundle: Bundle?): Pair<String, List<MusicDirectory.Entry>>? {
if (bundle == null) {
return null
@ -241,14 +245,14 @@ class AndroidAutoMediaBrowser(application: Application) {
idPrefix: String,
result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>
) {
AlbumListObserver(
AutoMediaPlayerService.AlbumListObserver(
idPrefix, result,
albumListModel.albumList
albumListModel!!.albumList
)
val args: Bundle = Bundle()
args.putString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE, type.toString())
albumListModel.getAlbumList(false, null, args)
albumListModel!!.getAlbumList(false, null, args)
result.detach()
}
@ -256,9 +260,9 @@ class AndroidAutoMediaBrowser(application: Application) {
idPrefix: String,
result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>
) {
ArtistListObserver(idPrefix, result, artistListModel.artists)
AutoMediaPlayerService.ArtistListObserver(idPrefix, result, artistListModel!!.artists)
artistListModel.getItems(false, null)
artistListModel!!.getItems(false, null)
result.detach()
}

View File

@ -7,15 +7,13 @@
package org.moire.ultrasonic.service
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.*
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.os.IBinder
import android.support.v4.media.MediaBrowserCompat
import android.support.v4.media.MediaMetadataCompat
import android.support.v4.media.session.MediaSessionCompat
@ -39,11 +37,7 @@ import org.moire.ultrasonic.provider.UltrasonicAppWidgetProvider4X3
import org.moire.ultrasonic.provider.UltrasonicAppWidgetProvider4X4
import org.moire.ultrasonic.receiver.MediaButtonIntentReceiver
import org.moire.ultrasonic.service.MusicServiceFactory.getMusicService
import org.moire.ultrasonic.util.AndroidAutoMediaBrowser
import org.moire.ultrasonic.util.Constants
import org.moire.ultrasonic.util.NowPlayingEventDistributor
import org.moire.ultrasonic.util.ShufflePlayBuffer
import org.moire.ultrasonic.util.Util
import org.moire.ultrasonic.util.*
import timber.log.Timber
/**
@ -51,7 +45,8 @@ import timber.log.Timber
* while the rest of the Ultrasonic App is in the background.
*/
@Suppress("LargeClass")
class MediaPlayerService : MediaBrowserServiceCompat() {
class MediaPlayerService : Service() {
private val binder: IBinder = SimpleServiceBinder(this)
private val scrobbler = Scrobbler()
private val jukeboxMediaPlayer by inject<JukeboxMediaPlayer>()
@ -62,20 +57,21 @@ class MediaPlayerService : MediaBrowserServiceCompat() {
private val nowPlayingEventDistributor by inject<NowPlayingEventDistributor>()
private val mediaPlayerLifecycleSupport by inject<MediaPlayerLifecycleSupport>()
private var autoMediaBrowser: AndroidAutoMediaBrowser? = null
private var mediaSession: MediaSessionCompat? = null
private var mediaSessionToken: MediaSessionCompat.Token? = null
private var isInForeground = false
private var notificationBuilder: NotificationCompat.Builder? = null
private val repeatMode: RepeatMode
get() = Util.getRepeatMode()
override fun onBind(intent: Intent): IBinder {
return binder
}
override fun onCreate() {
super.onCreate()
autoMediaBrowser = AndroidAutoMediaBrowser(application)
updateMediaSession(null, PlayerState.IDLE)
downloader.onCreate()
shufflePlayBuffer.onCreate()
localMediaPlayer.init()
@ -136,21 +132,6 @@ class MediaPlayerService : MediaBrowserServiceCompat() {
}
}
override fun onGetRoot(
clientPackageName: String,
clientUid: Int,
rootHints: Bundle?
): MediaBrowserServiceCompat.BrowserRoot {
return autoMediaBrowser!!.getRoot(clientPackageName, clientUid, rootHints)
}
override fun onLoadChildren(
parentMediaId: String,
result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>
) {
autoMediaBrowser!!.loadChildren(parentMediaId, result)
}
@Synchronized
fun seekTo(position: Int) {
if (jukeboxMediaPlayer.isEnabled) {
@ -483,7 +464,7 @@ class MediaPlayerService : MediaBrowserServiceCompat() {
}
}
private fun updateMediaSession(currentPlaying: DownloadFile?, playerState: PlayerState) {
fun updateMediaSession(currentPlaying: DownloadFile?, playerState: PlayerState) {
Timber.d("Updating the MediaSession")
if (mediaSession == null) initMediaSessions()
@ -645,8 +626,8 @@ class MediaPlayerService : MediaBrowserServiceCompat() {
// Use the Media Style, to enable native Android support for playback notification
val style = androidx.media.app.NotificationCompat.MediaStyle()
if (getSessionToken() != null) {
style.setMediaSession(getSessionToken())
if (mediaSessionToken != null) {
style.setMediaSession(mediaSessionToken)
}
// Clear old actions
@ -813,7 +794,7 @@ class MediaPlayerService : MediaBrowserServiceCompat() {
Timber.w("Creating media session")
mediaSession = MediaSessionCompat(applicationContext, "UltrasonicService")
setSessionToken(mediaSession!!.sessionToken)
mediaSessionToken = mediaSession!!.sessionToken
updateMediaButtonReceiver()
@ -829,7 +810,7 @@ class MediaPlayerService : MediaBrowserServiceCompat() {
Timber.v("Media Session Callback: onPlay")
}
/*
override fun onPlayFromMediaId(mediaId: String?, extras: Bundle?) {
super.onPlayFromMediaId(mediaId, extras)
@ -857,7 +838,7 @@ class MediaPlayerService : MediaBrowserServiceCompat() {
}
Timber.v("Media Session Callback: onPlayFromMediaId")
}
*/
override fun onPause() {
super.onPause()
getPendingIntentForMediaAction(