Another Attempt at Auto
This commit is contained in:
parent
04de4544ee
commit
db0669098c
|
@ -56,6 +56,12 @@
|
||||||
<service
|
<service
|
||||||
android:name=".service.MediaPlayerService"
|
android:name=".service.MediaPlayerService"
|
||||||
android:label="Ultrasonic Media Player Service"
|
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">
|
android:exported="true">
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package org.moire.ultrasonic.util
|
package org.moire.ultrasonic.service
|
||||||
|
|
||||||
import android.app.Application
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.support.v4.media.MediaBrowserCompat
|
import android.support.v4.media.MediaBrowserCompat
|
||||||
import android.support.v4.media.MediaDescriptionCompat
|
import android.support.v4.media.MediaDescriptionCompat
|
||||||
|
@ -8,24 +7,26 @@ import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import androidx.media.MediaBrowserServiceCompat
|
import androidx.media.MediaBrowserServiceCompat
|
||||||
import androidx.media.utils.MediaConstants
|
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.ByteArrayInputStream
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.io.ObjectInputStream
|
import java.io.ObjectInputStream
|
||||||
import java.io.ObjectOutputStream
|
import java.io.ObjectOutputStream
|
||||||
import java.util.concurrent.ExecutorService
|
import java.util.concurrent.ExecutorService
|
||||||
import java.util.concurrent.Executors
|
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 mediaPlayerService : MediaPlayerService = MediaPlayerService()
|
||||||
val artistListModel: ArtistListModel = ArtistListModel(application)
|
var albumListModel: AlbumListModel? = null
|
||||||
|
var artistListModel: ArtistListModel? = null
|
||||||
|
|
||||||
val executorService: ExecutorService = Executors.newFixedThreadPool(4)
|
val executorService: ExecutorService = Executors.newFixedThreadPool(4)
|
||||||
var maximumRootChildLimit: Int = 4
|
var maximumRootChildLimit: Int = 4
|
||||||
|
@ -44,11 +45,11 @@ class AndroidAutoMediaBrowser(application: Application) {
|
||||||
private val MEDIA_BROWSER_EXTRA_MEDIA_ID = "_Ultrasonic_mb_extra_media_id_"
|
private val MEDIA_BROWSER_EXTRA_MEDIA_ID = "_Ultrasonic_mb_extra_media_id_"
|
||||||
|
|
||||||
class AlbumListObserver(
|
class AlbumListObserver(
|
||||||
val idPrefix: String,
|
val idPrefix: String,
|
||||||
val result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>,
|
val result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>,
|
||||||
data: LiveData<List<MusicDirectory.Entry>>
|
data: LiveData<List<MusicDirectory.Entry>>
|
||||||
) :
|
) :
|
||||||
Observer<List<MusicDirectory.Entry>> {
|
Observer<List<MusicDirectory.Entry>> {
|
||||||
|
|
||||||
private var liveData: LiveData<List<MusicDirectory.Entry>>? = null
|
private var liveData: LiveData<List<MusicDirectory.Entry>>? = null
|
||||||
|
|
||||||
|
@ -73,15 +74,15 @@ class AndroidAutoMediaBrowser(application: Application) {
|
||||||
val mediaItems: MutableList<MediaBrowserCompat.MediaItem> = mutableListOf()
|
val mediaItems: MutableList<MediaBrowserCompat.MediaItem> = mutableListOf()
|
||||||
for (item in albumList) {
|
for (item in albumList) {
|
||||||
val entryBuilder: MediaDescriptionCompat.Builder =
|
val entryBuilder: MediaDescriptionCompat.Builder =
|
||||||
MediaDescriptionCompat.Builder()
|
MediaDescriptionCompat.Builder()
|
||||||
entryBuilder
|
entryBuilder
|
||||||
.setTitle(item.title)
|
.setTitle(item.title)
|
||||||
.setMediaId(idPrefix + item.id)
|
.setMediaId(idPrefix + item.id)
|
||||||
mediaItems.add(
|
mediaItems.add(
|
||||||
MediaBrowserCompat.MediaItem(
|
MediaBrowserCompat.MediaItem(
|
||||||
entryBuilder.build(),
|
entryBuilder.build(),
|
||||||
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE
|
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,11 +91,11 @@ class AndroidAutoMediaBrowser(application: Application) {
|
||||||
}
|
}
|
||||||
|
|
||||||
class ArtistListObserver(
|
class ArtistListObserver(
|
||||||
val idPrefix: String,
|
val idPrefix: String,
|
||||||
val result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>,
|
val result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>,
|
||||||
data: LiveData<List<ArtistOrIndex>>
|
data: LiveData<List<ArtistOrIndex>>
|
||||||
) :
|
) :
|
||||||
Observer<List<ArtistOrIndex>> {
|
Observer<List<ArtistOrIndex>> {
|
||||||
|
|
||||||
private var liveData: LiveData<List<ArtistOrIndex>>? = null
|
private var liveData: LiveData<List<ArtistOrIndex>>? = null
|
||||||
|
|
||||||
|
@ -119,15 +120,15 @@ class AndroidAutoMediaBrowser(application: Application) {
|
||||||
val mediaItems: MutableList<MediaBrowserCompat.MediaItem> = mutableListOf()
|
val mediaItems: MutableList<MediaBrowserCompat.MediaItem> = mutableListOf()
|
||||||
for (item in artistList) {
|
for (item in artistList) {
|
||||||
val entryBuilder: MediaDescriptionCompat.Builder =
|
val entryBuilder: MediaDescriptionCompat.Builder =
|
||||||
MediaDescriptionCompat.Builder()
|
MediaDescriptionCompat.Builder()
|
||||||
entryBuilder
|
entryBuilder
|
||||||
.setTitle(item.name)
|
.setTitle(item.name)
|
||||||
.setMediaId(idPrefix + item.id)
|
.setMediaId(idPrefix + item.id)
|
||||||
mediaItems.add(
|
mediaItems.add(
|
||||||
MediaBrowserCompat.MediaItem(
|
MediaBrowserCompat.MediaItem(
|
||||||
entryBuilder.build(),
|
entryBuilder.build(),
|
||||||
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE
|
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,15 +136,21 @@ class AndroidAutoMediaBrowser(application: Application) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getRoot(
|
override fun onCreate() {
|
||||||
clientPackageName: String,
|
super.onCreate()
|
||||||
clientUid: Int,
|
|
||||||
rootHints: Bundle?
|
albumListModel = AlbumListModel(application)
|
||||||
): MediaBrowserServiceCompat.BrowserRoot {
|
artistListModel = ArtistListModel(application)
|
||||||
|
|
||||||
|
mediaPlayerService.onCreate()
|
||||||
|
mediaPlayerService.updateMediaSession(null, PlayerState.IDLE)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onGetRoot(clientPackageName: String, clientUid: Int, rootHints: Bundle?): BrowserRoot? {
|
||||||
if (rootHints != null) {
|
if (rootHints != null) {
|
||||||
maximumRootChildLimit = rootHints.getInt(
|
maximumRootChildLimit = rootHints.getInt(
|
||||||
MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_LIMIT,
|
MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_LIMIT,
|
||||||
4
|
4
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// opt into the root tabs (because it's gonna be non-optional
|
// opt into the root tabs (because it's gonna be non-optional
|
||||||
|
@ -154,60 +161,56 @@ class AndroidAutoMediaBrowser(application: Application) {
|
||||||
return MediaBrowserServiceCompat.BrowserRoot(MEDIA_BROWSER_ROOT_ID, extras)
|
return MediaBrowserServiceCompat.BrowserRoot(MEDIA_BROWSER_ROOT_ID, extras)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadChildren(
|
override fun onLoadChildren(parentId: String, result: Result<List<MediaBrowserCompat.MediaItem>>) {
|
||||||
parentMediaId: String,
|
|
||||||
result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>
|
|
||||||
) {
|
|
||||||
|
|
||||||
val mediaItems: MutableList<MediaBrowserCompat.MediaItem> = mutableListOf()
|
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,
|
// Build the MediaItem objects for the top level,
|
||||||
// and put them in the mediaItems list...
|
// and put them in the mediaItems list...
|
||||||
|
|
||||||
var recentList: MediaDescriptionCompat.Builder = MediaDescriptionCompat.Builder()
|
var recentList: MediaDescriptionCompat.Builder = MediaDescriptionCompat.Builder()
|
||||||
recentList.setTitle("Recent").setMediaId(MEDIA_BROWSER_RECENT_LIST_ROOT)
|
recentList.setTitle("Recent").setMediaId(MEDIA_BROWSER_RECENT_LIST_ROOT)
|
||||||
mediaItems.add(
|
mediaItems.add(
|
||||||
MediaBrowserCompat.MediaItem(
|
MediaBrowserCompat.MediaItem(
|
||||||
recentList.build(),
|
recentList.build(),
|
||||||
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE
|
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
var albumList: MediaDescriptionCompat.Builder = MediaDescriptionCompat.Builder()
|
var albumList: MediaDescriptionCompat.Builder = MediaDescriptionCompat.Builder()
|
||||||
albumList.setTitle("Albums").setMediaId(MEDIA_BROWSER_ALBUM_LIST_ROOT)
|
albumList.setTitle("Albums").setMediaId(MEDIA_BROWSER_ALBUM_LIST_ROOT)
|
||||||
mediaItems.add(
|
mediaItems.add(
|
||||||
MediaBrowserCompat.MediaItem(
|
MediaBrowserCompat.MediaItem(
|
||||||
albumList.build(),
|
albumList.build(),
|
||||||
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE
|
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
var artistList: MediaDescriptionCompat.Builder = MediaDescriptionCompat.Builder()
|
var artistList: MediaDescriptionCompat.Builder = MediaDescriptionCompat.Builder()
|
||||||
artistList.setTitle("Artists").setMediaId(MEDIA_BROWSER_ARTIST_LIST_ROOT)
|
artistList.setTitle("Artists").setMediaId(MEDIA_BROWSER_ARTIST_LIST_ROOT)
|
||||||
mediaItems.add(
|
mediaItems.add(
|
||||||
MediaBrowserCompat.MediaItem(
|
MediaBrowserCompat.MediaItem(
|
||||||
artistList.build(),
|
artistList.build(),
|
||||||
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE
|
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)
|
fetchAlbumList(AlbumListType.RECENT, MEDIA_BROWSER_RECENT_PREFIX, result)
|
||||||
return
|
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)
|
fetchAlbumList(AlbumListType.SORTED_BY_NAME, MEDIA_BROWSER_ALBUM_PREFIX, result)
|
||||||
return
|
return
|
||||||
} else if (MEDIA_BROWSER_ARTIST_LIST_ROOT == parentMediaId) {
|
} else if (MEDIA_BROWSER_ARTIST_LIST_ROOT == parentId) {
|
||||||
fetchArtistList(MEDIA_BROWSER_ARTIST_PREFIX, result)
|
fetchArtistList(MEDIA_BROWSER_ARTIST_PREFIX, result)
|
||||||
return
|
return
|
||||||
} else if (parentMediaId.startsWith(MEDIA_BROWSER_RECENT_PREFIX)) {
|
} else if (parentId.startsWith(MEDIA_BROWSER_RECENT_PREFIX)) {
|
||||||
fetchTrackList(parentMediaId.substring(MEDIA_BROWSER_RECENT_PREFIX.length), result)
|
fetchTrackList(parentId.substring(MEDIA_BROWSER_RECENT_PREFIX.length), result)
|
||||||
return
|
return
|
||||||
} else if (parentMediaId.startsWith(MEDIA_BROWSER_ALBUM_PREFIX)) {
|
} else if (parentId.startsWith(MEDIA_BROWSER_ALBUM_PREFIX)) {
|
||||||
fetchTrackList(parentMediaId.substring(MEDIA_BROWSER_ALBUM_PREFIX.length), result)
|
fetchTrackList(parentId.substring(MEDIA_BROWSER_ALBUM_PREFIX.length), result)
|
||||||
return
|
return
|
||||||
} else if (parentMediaId.startsWith(MEDIA_BROWSER_ARTIST_PREFIX)) {
|
} else if (parentId.startsWith(MEDIA_BROWSER_ARTIST_PREFIX)) {
|
||||||
fetchArtistAlbumList(
|
fetchArtistAlbumList(
|
||||||
parentMediaId.substring(MEDIA_BROWSER_ARTIST_PREFIX.length),
|
parentId.substring(MEDIA_BROWSER_ARTIST_PREFIX.length),
|
||||||
result
|
result
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
|
@ -217,13 +220,14 @@ class AndroidAutoMediaBrowser(application: Application) {
|
||||||
result.sendResult(mediaItems)
|
result.sendResult(mediaItems)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun getBundleData(bundle: Bundle?): Pair<String, List<MusicDirectory.Entry>>? {
|
fun getBundleData(bundle: Bundle?): Pair<String, List<MusicDirectory.Entry>>? {
|
||||||
if (bundle == null) {
|
if (bundle == null) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bundle.containsKey(MEDIA_BROWSER_EXTRA_ALBUM_LIST) ||
|
if (!bundle.containsKey(MEDIA_BROWSER_EXTRA_ALBUM_LIST) ||
|
||||||
!bundle.containsKey(MEDIA_BROWSER_EXTRA_MEDIA_ID)
|
!bundle.containsKey(MEDIA_BROWSER_EXTRA_MEDIA_ID)
|
||||||
) {
|
) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
@ -231,58 +235,58 @@ class AndroidAutoMediaBrowser(application: Application) {
|
||||||
val byteArrayInputStream = ByteArrayInputStream(bytes)
|
val byteArrayInputStream = ByteArrayInputStream(bytes)
|
||||||
val objectInputStream = ObjectInputStream(byteArrayInputStream)
|
val objectInputStream = ObjectInputStream(byteArrayInputStream)
|
||||||
return Pair(
|
return Pair(
|
||||||
bundle.getString(MEDIA_BROWSER_EXTRA_MEDIA_ID),
|
bundle.getString(MEDIA_BROWSER_EXTRA_MEDIA_ID),
|
||||||
objectInputStream.readObject() as List<MusicDirectory.Entry>
|
objectInputStream.readObject() as List<MusicDirectory.Entry>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fetchAlbumList(
|
private fun fetchAlbumList(
|
||||||
type: AlbumListType,
|
type: AlbumListType,
|
||||||
idPrefix: String,
|
idPrefix: String,
|
||||||
result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>
|
result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>
|
||||||
) {
|
) {
|
||||||
AlbumListObserver(
|
AutoMediaPlayerService.AlbumListObserver(
|
||||||
idPrefix, result,
|
idPrefix, result,
|
||||||
albumListModel.albumList
|
albumListModel!!.albumList
|
||||||
)
|
)
|
||||||
|
|
||||||
val args: Bundle = Bundle()
|
val args: Bundle = Bundle()
|
||||||
args.putString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE, type.toString())
|
args.putString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE, type.toString())
|
||||||
albumListModel.getAlbumList(false, null, args)
|
albumListModel!!.getAlbumList(false, null, args)
|
||||||
result.detach()
|
result.detach()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fetchArtistList(
|
private fun fetchArtistList(
|
||||||
idPrefix: String,
|
idPrefix: String,
|
||||||
result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>
|
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()
|
result.detach()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fetchArtistAlbumList(
|
private fun fetchArtistAlbumList(
|
||||||
id: String,
|
id: String,
|
||||||
result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>
|
result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>
|
||||||
) {
|
) {
|
||||||
executorService.execute {
|
executorService.execute {
|
||||||
val musicService = MusicServiceFactory.getMusicService()
|
val musicService = MusicServiceFactory.getMusicService()
|
||||||
|
|
||||||
val musicDirectory = musicService.getMusicDirectory(
|
val musicDirectory = musicService.getMusicDirectory(
|
||||||
id, "", false
|
id, "", false
|
||||||
)
|
)
|
||||||
val mediaItems: MutableList<MediaBrowserCompat.MediaItem> = mutableListOf()
|
val mediaItems: MutableList<MediaBrowserCompat.MediaItem> = mutableListOf()
|
||||||
|
|
||||||
for (item in musicDirectory.getAllChild()) {
|
for (item in musicDirectory.getAllChild()) {
|
||||||
val entryBuilder: MediaDescriptionCompat.Builder =
|
val entryBuilder: MediaDescriptionCompat.Builder =
|
||||||
MediaDescriptionCompat.Builder()
|
MediaDescriptionCompat.Builder()
|
||||||
entryBuilder.setTitle(item.title).setMediaId(MEDIA_BROWSER_ALBUM_PREFIX + item.id)
|
entryBuilder.setTitle(item.title).setMediaId(MEDIA_BROWSER_ALBUM_PREFIX + item.id)
|
||||||
mediaItems.add(
|
mediaItems.add(
|
||||||
MediaBrowserCompat.MediaItem(
|
MediaBrowserCompat.MediaItem(
|
||||||
entryBuilder.build(),
|
entryBuilder.build(),
|
||||||
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE
|
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
result.sendResult(mediaItems)
|
result.sendResult(mediaItems)
|
||||||
|
@ -291,14 +295,14 @@ class AndroidAutoMediaBrowser(application: Application) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fetchTrackList(
|
private fun fetchTrackList(
|
||||||
id: String,
|
id: String,
|
||||||
result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>
|
result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>
|
||||||
) {
|
) {
|
||||||
executorService.execute {
|
executorService.execute {
|
||||||
val musicService = MusicServiceFactory.getMusicService()
|
val musicService = MusicServiceFactory.getMusicService()
|
||||||
|
|
||||||
val albumDirectory = musicService.getAlbum(
|
val albumDirectory = musicService.getAlbum(
|
||||||
id, "", false
|
id, "", false
|
||||||
)
|
)
|
||||||
|
|
||||||
// The idea here is that we want to attach the full album list to every song,
|
// The idea here is that we want to attach the full album list to every song,
|
||||||
|
@ -315,22 +319,22 @@ class AndroidAutoMediaBrowser(application: Application) {
|
||||||
val extras = Bundle()
|
val extras = Bundle()
|
||||||
|
|
||||||
extras.putByteArray(
|
extras.putByteArray(
|
||||||
MEDIA_BROWSER_EXTRA_ALBUM_LIST,
|
MEDIA_BROWSER_EXTRA_ALBUM_LIST,
|
||||||
songList
|
songList
|
||||||
)
|
)
|
||||||
extras.putString(
|
extras.putString(
|
||||||
MEDIA_BROWSER_EXTRA_MEDIA_ID,
|
MEDIA_BROWSER_EXTRA_MEDIA_ID,
|
||||||
item.id
|
item.id
|
||||||
)
|
)
|
||||||
|
|
||||||
val entryBuilder: MediaDescriptionCompat.Builder =
|
val entryBuilder: MediaDescriptionCompat.Builder =
|
||||||
MediaDescriptionCompat.Builder()
|
MediaDescriptionCompat.Builder()
|
||||||
entryBuilder.setTitle(item.title).setMediaId(item.id).setExtras(extras)
|
entryBuilder.setTitle(item.title).setMediaId(item.id).setExtras(extras)
|
||||||
mediaItems.add(
|
mediaItems.add(
|
||||||
MediaBrowserCompat.MediaItem(
|
MediaBrowserCompat.MediaItem(
|
||||||
entryBuilder.build(),
|
entryBuilder.build(),
|
||||||
MediaBrowserCompat.MediaItem.FLAG_PLAYABLE
|
MediaBrowserCompat.MediaItem.FLAG_PLAYABLE
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
result.sendResult(mediaItems)
|
result.sendResult(mediaItems)
|
|
@ -7,15 +7,13 @@
|
||||||
|
|
||||||
package org.moire.ultrasonic.service
|
package org.moire.ultrasonic.service
|
||||||
|
|
||||||
import android.app.Notification
|
import android.app.*
|
||||||
import android.app.NotificationChannel
|
|
||||||
import android.app.NotificationManager
|
|
||||||
import android.app.PendingIntent
|
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.os.IBinder
|
||||||
import android.support.v4.media.MediaBrowserCompat
|
import android.support.v4.media.MediaBrowserCompat
|
||||||
import android.support.v4.media.MediaMetadataCompat
|
import android.support.v4.media.MediaMetadataCompat
|
||||||
import android.support.v4.media.session.MediaSessionCompat
|
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.provider.UltrasonicAppWidgetProvider4X4
|
||||||
import org.moire.ultrasonic.receiver.MediaButtonIntentReceiver
|
import org.moire.ultrasonic.receiver.MediaButtonIntentReceiver
|
||||||
import org.moire.ultrasonic.service.MusicServiceFactory.getMusicService
|
import org.moire.ultrasonic.service.MusicServiceFactory.getMusicService
|
||||||
import org.moire.ultrasonic.util.AndroidAutoMediaBrowser
|
import org.moire.ultrasonic.util.*
|
||||||
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 timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -51,7 +45,8 @@ import timber.log.Timber
|
||||||
* while the rest of the Ultrasonic App is in the background.
|
* while the rest of the Ultrasonic App is in the background.
|
||||||
*/
|
*/
|
||||||
@Suppress("LargeClass")
|
@Suppress("LargeClass")
|
||||||
class MediaPlayerService : MediaBrowserServiceCompat() {
|
class MediaPlayerService : Service() {
|
||||||
|
private val binder: IBinder = SimpleServiceBinder(this)
|
||||||
private val scrobbler = Scrobbler()
|
private val scrobbler = Scrobbler()
|
||||||
|
|
||||||
private val jukeboxMediaPlayer by inject<JukeboxMediaPlayer>()
|
private val jukeboxMediaPlayer by inject<JukeboxMediaPlayer>()
|
||||||
|
@ -62,20 +57,21 @@ class MediaPlayerService : MediaBrowserServiceCompat() {
|
||||||
private val nowPlayingEventDistributor by inject<NowPlayingEventDistributor>()
|
private val nowPlayingEventDistributor by inject<NowPlayingEventDistributor>()
|
||||||
private val mediaPlayerLifecycleSupport by inject<MediaPlayerLifecycleSupport>()
|
private val mediaPlayerLifecycleSupport by inject<MediaPlayerLifecycleSupport>()
|
||||||
|
|
||||||
private var autoMediaBrowser: AndroidAutoMediaBrowser? = null
|
|
||||||
private var mediaSession: MediaSessionCompat? = null
|
private var mediaSession: MediaSessionCompat? = null
|
||||||
|
private var mediaSessionToken: MediaSessionCompat.Token? = null
|
||||||
private var isInForeground = false
|
private var isInForeground = false
|
||||||
private var notificationBuilder: NotificationCompat.Builder? = null
|
private var notificationBuilder: NotificationCompat.Builder? = null
|
||||||
|
|
||||||
private val repeatMode: RepeatMode
|
private val repeatMode: RepeatMode
|
||||||
get() = Util.getRepeatMode()
|
get() = Util.getRepeatMode()
|
||||||
|
|
||||||
|
override fun onBind(intent: Intent): IBinder {
|
||||||
|
return binder
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
|
|
||||||
autoMediaBrowser = AndroidAutoMediaBrowser(application)
|
|
||||||
updateMediaSession(null, PlayerState.IDLE)
|
|
||||||
|
|
||||||
downloader.onCreate()
|
downloader.onCreate()
|
||||||
shufflePlayBuffer.onCreate()
|
shufflePlayBuffer.onCreate()
|
||||||
localMediaPlayer.init()
|
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
|
@Synchronized
|
||||||
fun seekTo(position: Int) {
|
fun seekTo(position: Int) {
|
||||||
if (jukeboxMediaPlayer.isEnabled) {
|
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")
|
Timber.d("Updating the MediaSession")
|
||||||
|
|
||||||
if (mediaSession == null) initMediaSessions()
|
if (mediaSession == null) initMediaSessions()
|
||||||
|
@ -645,8 +626,8 @@ class MediaPlayerService : MediaBrowserServiceCompat() {
|
||||||
// Use the Media Style, to enable native Android support for playback notification
|
// Use the Media Style, to enable native Android support for playback notification
|
||||||
val style = androidx.media.app.NotificationCompat.MediaStyle()
|
val style = androidx.media.app.NotificationCompat.MediaStyle()
|
||||||
|
|
||||||
if (getSessionToken() != null) {
|
if (mediaSessionToken != null) {
|
||||||
style.setMediaSession(getSessionToken())
|
style.setMediaSession(mediaSessionToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear old actions
|
// Clear old actions
|
||||||
|
@ -813,7 +794,7 @@ class MediaPlayerService : MediaBrowserServiceCompat() {
|
||||||
Timber.w("Creating media session")
|
Timber.w("Creating media session")
|
||||||
|
|
||||||
mediaSession = MediaSessionCompat(applicationContext, "UltrasonicService")
|
mediaSession = MediaSessionCompat(applicationContext, "UltrasonicService")
|
||||||
setSessionToken(mediaSession!!.sessionToken)
|
mediaSessionToken = mediaSession!!.sessionToken
|
||||||
|
|
||||||
updateMediaButtonReceiver()
|
updateMediaButtonReceiver()
|
||||||
|
|
||||||
|
@ -829,7 +810,7 @@ class MediaPlayerService : MediaBrowserServiceCompat() {
|
||||||
|
|
||||||
Timber.v("Media Session Callback: onPlay")
|
Timber.v("Media Session Callback: onPlay")
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
override fun onPlayFromMediaId(mediaId: String?, extras: Bundle?) {
|
override fun onPlayFromMediaId(mediaId: String?, extras: Bundle?) {
|
||||||
super.onPlayFromMediaId(mediaId, extras)
|
super.onPlayFromMediaId(mediaId, extras)
|
||||||
|
|
||||||
|
@ -857,7 +838,7 @@ class MediaPlayerService : MediaBrowserServiceCompat() {
|
||||||
}
|
}
|
||||||
Timber.v("Media Session Callback: onPlayFromMediaId")
|
Timber.v("Media Session Callback: onPlayFromMediaId")
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
super.onPause()
|
super.onPause()
|
||||||
getPendingIntentForMediaAction(
|
getPendingIntentForMediaAction(
|
||||||
|
|
Loading…
Reference in New Issue