From f930ba1941428fe438b72d6968a8c43b7b5ee9a8 Mon Sep 17 00:00:00 2001 From: advplyr Date: Thu, 26 May 2022 19:10:29 -0500 Subject: [PATCH] Update:Send android device info when opening playback sessions --- .../audiobookshelf/app/data/DeviceClasses.kt | 17 ++++++++++++++ .../audiobookshelf/app/media/MediaManager.kt | 4 ++-- .../app/player/MediaSessionCallback.kt | 6 ++--- .../player/MediaSessionPlaybackPreparer.kt | 6 ++--- .../app/player/PlayerNotificationService.kt | 23 ++++++++++++++++--- .../app/plugins/AbsAudioPlayer.kt | 4 ++-- .../audiobookshelf/app/server/ApiHandler.kt | 9 ++------ 7 files changed, 49 insertions(+), 20 deletions(-) diff --git a/android/app/src/main/java/com/audiobookshelf/app/data/DeviceClasses.kt b/android/app/src/main/java/com/audiobookshelf/app/data/DeviceClasses.kt index 1958382c..917f6013 100644 --- a/android/app/src/main/java/com/audiobookshelf/app/data/DeviceClasses.kt +++ b/android/app/src/main/java/com/audiobookshelf/app/data/DeviceClasses.kt @@ -66,3 +66,20 @@ data class LocalFolder( JsonSubTypes.Type(LocalLibraryItem::class) ) open class LibraryItemWrapper() + +@JsonIgnoreProperties(ignoreUnknown = true) +data class DeviceInfo( + var manufacturer:String, + var model:String, + var brand:String, + var sdkVersion:Int, + var clientVersion: String +) + +@JsonIgnoreProperties(ignoreUnknown = true) +data class PlayItemRequestPayload( + var mediaPlayer:String, + var forceDirectPlay:Boolean, + var forceTranscode:Boolean, + var deviceInfo:DeviceInfo +) diff --git a/android/app/src/main/java/com/audiobookshelf/app/media/MediaManager.kt b/android/app/src/main/java/com/audiobookshelf/app/media/MediaManager.kt index 80bc92cb..2398c610 100644 --- a/android/app/src/main/java/com/audiobookshelf/app/media/MediaManager.kt +++ b/android/app/src/main/java/com/audiobookshelf/app/media/MediaManager.kt @@ -213,13 +213,13 @@ class MediaManager(var apiHandler: ApiHandler, var ctx: Context) { } } - fun play(libraryItemWrapper:LibraryItemWrapper, episode:PodcastEpisode?, mediaPlayer:String, cb: (PlaybackSession) -> Unit) { + fun play(libraryItemWrapper:LibraryItemWrapper, episode:PodcastEpisode?, playItemRequestPayload:PlayItemRequestPayload, cb: (PlaybackSession) -> Unit) { if (libraryItemWrapper is LocalLibraryItem) { val localLibraryItem = libraryItemWrapper as LocalLibraryItem cb(localLibraryItem.getPlaybackSession(episode)) } else { val libraryItem = libraryItemWrapper as LibraryItem - apiHandler.playLibraryItem(libraryItem.id,episode?.id ?: "",false, mediaPlayer) { + apiHandler.playLibraryItem(libraryItem.id,episode?.id ?: "",playItemRequestPayload) { cb(it) } } diff --git a/android/app/src/main/java/com/audiobookshelf/app/player/MediaSessionCallback.kt b/android/app/src/main/java/com/audiobookshelf/app/player/MediaSessionCallback.kt index c3609e38..e86f4ed2 100644 --- a/android/app/src/main/java/com/audiobookshelf/app/player/MediaSessionCallback.kt +++ b/android/app/src/main/java/com/audiobookshelf/app/player/MediaSessionCallback.kt @@ -28,7 +28,7 @@ class MediaSessionCallback(var playerNotificationService:PlayerNotificationServi override fun onPrepare() { Log.d(tag, "ON PREPARE MEDIA SESSION COMPAT") playerNotificationService.mediaManager.getFirstItem()?.let { li -> - playerNotificationService.mediaManager.play(li, null, playerNotificationService.getMediaPlayer()) { + playerNotificationService.mediaManager.play(li, null, playerNotificationService.getPlayItemRequestPayload(false)) { Log.d(tag, "About to prepare player with ${it.displayTitle}") Handler(Looper.getMainLooper()).post() { playerNotificationService.preparePlayer(it,true,null) @@ -50,7 +50,7 @@ class MediaSessionCallback(var playerNotificationService:PlayerNotificationServi override fun onPlayFromSearch(query: String?, extras: Bundle?) { Log.d(tag, "ON PLAY FROM SEARCH $query") playerNotificationService.mediaManager.getFromSearch(query)?.let { li -> - playerNotificationService.mediaManager.play(li, null, playerNotificationService.getMediaPlayer()) { + playerNotificationService.mediaManager.play(li, null, playerNotificationService.getPlayItemRequestPayload(false)) { Log.d(tag, "About to prepare player with ${it.displayTitle}") Handler(Looper.getMainLooper()).post() { playerNotificationService.preparePlayer(it,true,null) @@ -104,7 +104,7 @@ class MediaSessionCallback(var playerNotificationService:PlayerNotificationServi } libraryItemWrapper?.let { li -> - playerNotificationService.mediaManager.play(li, podcastEpisode, playerNotificationService.getMediaPlayer()) { + playerNotificationService.mediaManager.play(li, podcastEpisode, playerNotificationService.getPlayItemRequestPayload(false)) { Log.d(tag, "About to prepare player with ${it.displayTitle}") Handler(Looper.getMainLooper()).post() { playerNotificationService.preparePlayer(it,true,null) diff --git a/android/app/src/main/java/com/audiobookshelf/app/player/MediaSessionPlaybackPreparer.kt b/android/app/src/main/java/com/audiobookshelf/app/player/MediaSessionPlaybackPreparer.kt index 7c37f2c5..8c7a6984 100644 --- a/android/app/src/main/java/com/audiobookshelf/app/player/MediaSessionPlaybackPreparer.kt +++ b/android/app/src/main/java/com/audiobookshelf/app/player/MediaSessionPlaybackPreparer.kt @@ -30,7 +30,7 @@ class MediaSessionPlaybackPreparer(var playerNotificationService:PlayerNotificat override fun onPrepare(playWhenReady: Boolean) { Log.d(tag, "ON PREPARE $playWhenReady") playerNotificationService.mediaManager.getFirstItem()?.let { li -> - playerNotificationService.mediaManager.play(li, null, playerNotificationService.getMediaPlayer()) { + playerNotificationService.mediaManager.play(li, null, playerNotificationService.getPlayItemRequestPayload(false)) { Handler(Looper.getMainLooper()).post() { playerNotificationService.preparePlayer(it,playWhenReady,null) } @@ -53,7 +53,7 @@ class MediaSessionPlaybackPreparer(var playerNotificationService:PlayerNotificat } libraryItemWrapper?.let { li -> - playerNotificationService.mediaManager.play(li, podcastEpisode, playerNotificationService.getMediaPlayer()) { + playerNotificationService.mediaManager.play(li, podcastEpisode, playerNotificationService.getPlayItemRequestPayload(false)) { Log.d(tag, "About to prepare player with ${it.displayTitle}") Handler(Looper.getMainLooper()).post() { playerNotificationService.preparePlayer(it,playWhenReady,null) @@ -65,7 +65,7 @@ class MediaSessionPlaybackPreparer(var playerNotificationService:PlayerNotificat override fun onPrepareFromSearch(query: String, playWhenReady: Boolean, extras: Bundle?) { Log.d(tag, "ON PREPARE FROM SEARCH $query") playerNotificationService.mediaManager.getFromSearch(query)?.let { li -> - playerNotificationService.mediaManager.play(li, null, playerNotificationService.getMediaPlayer()) { + playerNotificationService.mediaManager.play(li, null, playerNotificationService.getPlayItemRequestPayload(false)) { Log.d(tag, "About to prepare player with ${it.displayTitle}") Handler(Looper.getMainLooper()).post() { playerNotificationService.preparePlayer(it,playWhenReady,null) diff --git a/android/app/src/main/java/com/audiobookshelf/app/player/PlayerNotificationService.kt b/android/app/src/main/java/com/audiobookshelf/app/player/PlayerNotificationService.kt index b4fa95b4..e960f4f3 100644 --- a/android/app/src/main/java/com/audiobookshelf/app/player/PlayerNotificationService.kt +++ b/android/app/src/main/java/com/audiobookshelf/app/player/PlayerNotificationService.kt @@ -17,7 +17,9 @@ import androidx.annotation.RequiresApi import androidx.core.app.NotificationCompat import androidx.media.MediaBrowserServiceCompat import androidx.media.utils.MediaConstants +import com.audiobookshelf.app.BuildConfig import com.audiobookshelf.app.data.* +import com.audiobookshelf.app.data.DeviceInfo import com.audiobookshelf.app.device.DeviceManager import com.audiobookshelf.app.media.MediaManager import com.audiobookshelf.app.server.ApiHandler @@ -373,12 +375,12 @@ class PlayerNotificationService : MediaBrowserServiceCompat() { // On error and was attempting to direct play - fallback to transcode currentPlaybackSession?.let { playbackSession -> if (playbackSession.isDirectPlay) { - val mediaPlayer = getMediaPlayer() - Log.d(tag, "Fallback to transcode $mediaPlayer") + val playItemRequestPayload = getPlayItemRequestPayload(true) + Log.d(tag, "Fallback to transcode $playItemRequestPayload.mediaPlayer") val libraryItemId = playbackSession.libraryItemId ?: "" // Must be true since direct play val episodeId = playbackSession.episodeId - apiHandler.playLibraryItem(libraryItemId, episodeId, true, mediaPlayer) { + apiHandler.playLibraryItem(libraryItemId, episodeId, playItemRequestPayload) { Handler(Looper.getMainLooper()).post { preparePlayer(it, true, null) } @@ -549,6 +551,21 @@ class PlayerNotificationService : MediaBrowserServiceCompat() { return if(currentPlayer == castPlayer) "cast-player" else "exo-player" } + fun getDeviceInfo(): DeviceInfo { + /* EXAMPLE + manufacturer: Google + model: Pixel 6 + brand: google + sdkVersion: 32 + appVersion: 0.9.46-beta + */ + return DeviceInfo(Build.MANUFACTURER, Build.MODEL, Build.BRAND, Build.VERSION.SDK_INT, BuildConfig.VERSION_NAME) + } + + fun getPlayItemRequestPayload(forceTranscode:Boolean):PlayItemRequestPayload { + return PlayItemRequestPayload(getMediaPlayer(), getDeviceInfo(), !forceTranscode, forceTranscode) + } + fun getContext():Context { return ctx } diff --git a/android/app/src/main/java/com/audiobookshelf/app/plugins/AbsAudioPlayer.kt b/android/app/src/main/java/com/audiobookshelf/app/plugins/AbsAudioPlayer.kt index 0dec5b59..807bfe9e 100644 --- a/android/app/src/main/java/com/audiobookshelf/app/plugins/AbsAudioPlayer.kt +++ b/android/app/src/main/java/com/audiobookshelf/app/plugins/AbsAudioPlayer.kt @@ -191,9 +191,9 @@ class AbsAudioPlayer : Plugin() { return call.resolve(JSObject()) } } else { // Play library item from server - val mediaPlayer = playerNotificationService.getMediaPlayer() + val playItemRequestPayload = playerNotificationService.getPlayItemRequestPayload(false) - apiHandler.playLibraryItem(libraryItemId, episodeId, false, mediaPlayer) { + apiHandler.playLibraryItem(libraryItemId, episodeId, playItemRequestPayload) { Handler(Looper.getMainLooper()).post { Log.d(tag, "Preparing Player TEST ${jacksonMapper.writeValueAsString(it)}") diff --git a/android/app/src/main/java/com/audiobookshelf/app/server/ApiHandler.kt b/android/app/src/main/java/com/audiobookshelf/app/server/ApiHandler.kt index 674e6c39..01cd165b 100644 --- a/android/app/src/main/java/com/audiobookshelf/app/server/ApiHandler.kt +++ b/android/app/src/main/java/com/audiobookshelf/app/server/ApiHandler.kt @@ -172,13 +172,8 @@ class ApiHandler(var ctx:Context) { } } - fun playLibraryItem(libraryItemId:String, episodeId:String?, forceTranscode:Boolean, mediaPlayer:String, cb: (PlaybackSession) -> Unit) { - val payload = JSObject() - payload.put("mediaPlayer", mediaPlayer) - - // Only if direct play fails do we force transcode - if (!forceTranscode) payload.put("forceDirectPlay", true) - else payload.put("forceTranscode", true) + fun playLibraryItem(libraryItemId:String, episodeId:String?, playItemRequestPayload:PlayItemRequestPayload, cb: (PlaybackSession) -> Unit) { + val payload = JSObject(jacksonMapper.writeValueAsString(playItemRequestPayload)) val endpoint = if (episodeId.isNullOrEmpty()) "/api/items/$libraryItemId/play" else "/api/items/$libraryItemId/play/$episodeId" postRequest(endpoint, payload) {