From 69d22f6c45deda4d0cfcada6d9207158993a7dc4 Mon Sep 17 00:00:00 2001 From: plksharma30 Date: Thu, 3 Aug 2023 10:31:52 +0530 Subject: [PATCH 1/3] Added custom actions to support on wear devices --- .../android/uamp/media/MusicService.kt | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/com/example/android/uamp/media/MusicService.kt b/common/src/main/java/com/example/android/uamp/media/MusicService.kt index 9007d0e1..5fad3d47 100644 --- a/common/src/main/java/com/example/android/uamp/media/MusicService.kt +++ b/common/src/main/java/com/example/android/uamp/media/MusicService.kt @@ -42,6 +42,7 @@ import androidx.media3.common.Player.Listener import androidx.media3.common.util.UnstableApi import androidx.media3.exoplayer.ExoPlayer import androidx.media3.exoplayer.util.EventLogger +import androidx.media3.session.CommandButton import androidx.media3.session.LibraryResult import androidx.media3.session.MediaLibraryService import androidx.media3.session.MediaSession @@ -206,6 +207,15 @@ open class MusicService : MediaLibraryService() { } build() } + val customActionButton = + CommandButton.Builder() + .setEnabled(true) + .setSessionCommand(customSessionCommand) + .setDisplayName("Custom command") + .setIconResId(android.R.drawable.ic_dialog_info) + .build() + + mediaSession.setCustomLayout(listOf(customActionButton)) // adds custom actions in media session // The media library is built from a remote JSON file. We start loading asynchronously here. // Use [callWhenMusicSourceReady] to execute code that needs the source load being @@ -326,6 +336,7 @@ open class MusicService : MediaLibraryService() { .buildUpon() // Add custom commands .add(SessionCommand(ACTION_TOGGLE_SPATIALIZATION, Bundle())) + .add(customSessionCommand) .build() return MediaSession.ConnectionResult.accept( sessionCommands, connectionResult.availablePlayerCommands @@ -470,6 +481,12 @@ open class MusicService : MediaLibraryService() { return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS)) } + + if(customCommand.customAction== CUSTOM_SESSION_COMMAND){ + Log.i(TAG, "Custom session command received") + return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS)) + } + return Futures.immediateFuture(SessionResult(SessionResult.RESULT_ERROR_NOT_SUPPORTED)) } } @@ -525,7 +542,9 @@ open class MusicService : MediaLibraryService() { } } + /** Content styling constants */ +private const val EXTRA_CUSTOM_ACTION_SHOW_ON_WEAR = "android.support.wearable.media.extra.CUSTOM_ACTION_SHOW_ON_WEAR" // Flag to display custom actions on wear private const val CONTENT_STYLE_BROWSABLE_HINT = "android.media.browse.CONTENT_STYLE_BROWSABLE_HINT" private const val CONTENT_STYLE_PLAYABLE_HINT = "android.media.browse.CONTENT_STYLE_PLAYABLE_HINT" private const val CONTENT_STYLE_SUPPORTED = "android.media.browse.CONTENT_STYLE_SUPPORTED" @@ -534,7 +553,11 @@ private const val CONTENT_STYLE_GRID = 2 const val ACTION_TOGGLE_SPATIALIZATION = "com.example.android.uamp.ACTION_TOGGLE_SPATIALIZATION" const val EXTRAS_TOGGLE_SPATIALIZATION = "com.example.android.uamp.EXTRAS_TOGGLE_SPATIALIZATION" +const val CUSTOM_SESSION_COMMAND = "com.example.android.uamp.CUSTOM_SESSION_COMMAND" +val customSessionCommand = SessionCommand(CUSTOM_SESSION_COMMAND, + Bundle().apply { + putBoolean(EXTRA_CUSTOM_ACTION_SHOW_ON_WEAR, true) + }) const val MEDIA_DESCRIPTION_EXTRAS_START_PLAYBACK_POSITION_MS = "playback_start_position_ms" - private const val TAG = "MusicService" From 266fbb3664d9ef0d535761408ae375072e310fd1 Mon Sep 17 00:00:00 2001 From: plksharma30 Date: Sat, 12 Aug 2023 20:19:18 +0530 Subject: [PATCH 2/3] Added seek forward and seek back custom actions --- .../android/uamp/media/MusicService.kt | 53 ++++++++++++------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/common/src/main/java/com/example/android/uamp/media/MusicService.kt b/common/src/main/java/com/example/android/uamp/media/MusicService.kt index 5fad3d47..514b76e4 100644 --- a/common/src/main/java/com/example/android/uamp/media/MusicService.kt +++ b/common/src/main/java/com/example/android/uamp/media/MusicService.kt @@ -207,15 +207,6 @@ open class MusicService : MediaLibraryService() { } build() } - val customActionButton = - CommandButton.Builder() - .setEnabled(true) - .setSessionCommand(customSessionCommand) - .setDisplayName("Custom command") - .setIconResId(android.R.drawable.ic_dialog_info) - .build() - - mediaSession.setCustomLayout(listOf(customActionButton)) // adds custom actions in media session // The media library is built from a remote JSON file. We start loading asynchronously here. // Use [callWhenMusicSourceReady] to execute code that needs the source load being @@ -336,13 +327,37 @@ open class MusicService : MediaLibraryService() { .buildUpon() // Add custom commands .add(SessionCommand(ACTION_TOGGLE_SPATIALIZATION, Bundle())) - .add(customSessionCommand) + .add(SessionCommand(SEEK_BACK,Bundle())) + .add(SessionCommand(SEEK_FORWARD,Bundle())) .build() return MediaSession.ConnectionResult.accept( sessionCommands, connectionResult.availablePlayerCommands ) } + override fun onPostConnect( + session: MediaSession, + controller: MediaSession.ControllerInfo + ) { + // Display a button for seek back action + val seekBackButton = CommandButton.Builder() + .setDisplayName("Seek Back") + .setIconResId(R.drawable.media3_notification_seek_back) + .setSessionCommand(SessionCommand(SEEK_BACK,Bundle())) + .build() + session.setCustomLayout(listOf(seekBackButton)) + + // Display a button for seek forward action + val seekForwardButton = CommandButton.Builder() + .setDisplayName("Seek Forward") + .setIconResId(R.drawable.media3_notification_seek_forward) + .setSessionCommand(SessionCommand(SEEK_FORWARD,Bundle())) + .build() + session.setCustomLayout(listOf(seekBackButton,seekForwardButton)) + + super.onPostConnect(session, controller) + } + override fun onGetLibraryRoot( session: MediaLibrarySession, browser: MediaSession.ControllerInfo, @@ -482,11 +497,15 @@ open class MusicService : MediaLibraryService() { return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS)) } - if(customCommand.customAction== CUSTOM_SESSION_COMMAND){ - Log.i(TAG, "Custom session command received") + if (customCommand.customAction == SEEK_BACK) { + exoPlayer.seekBack() return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS)) } + if (customCommand.customAction == SEEK_FORWARD) { + exoPlayer.seekForward() + return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS)) + } return Futures.immediateFuture(SessionResult(SessionResult.RESULT_ERROR_NOT_SUPPORTED)) } } @@ -542,9 +561,7 @@ open class MusicService : MediaLibraryService() { } } - /** Content styling constants */ -private const val EXTRA_CUSTOM_ACTION_SHOW_ON_WEAR = "android.support.wearable.media.extra.CUSTOM_ACTION_SHOW_ON_WEAR" // Flag to display custom actions on wear private const val CONTENT_STYLE_BROWSABLE_HINT = "android.media.browse.CONTENT_STYLE_BROWSABLE_HINT" private const val CONTENT_STYLE_PLAYABLE_HINT = "android.media.browse.CONTENT_STYLE_PLAYABLE_HINT" private const val CONTENT_STYLE_SUPPORTED = "android.media.browse.CONTENT_STYLE_SUPPORTED" @@ -553,11 +570,9 @@ private const val CONTENT_STYLE_GRID = 2 const val ACTION_TOGGLE_SPATIALIZATION = "com.example.android.uamp.ACTION_TOGGLE_SPATIALIZATION" const val EXTRAS_TOGGLE_SPATIALIZATION = "com.example.android.uamp.EXTRAS_TOGGLE_SPATIALIZATION" -const val CUSTOM_SESSION_COMMAND = "com.example.android.uamp.CUSTOM_SESSION_COMMAND" -val customSessionCommand = SessionCommand(CUSTOM_SESSION_COMMAND, - Bundle().apply { - putBoolean(EXTRA_CUSTOM_ACTION_SHOW_ON_WEAR, true) - }) +const val SEEK_FORWARD = "com.example.android.uamp.SEEK_FORWARD" +const val SEEK_BACK = "com.example.android.uamp.SEEK_BACK" const val MEDIA_DESCRIPTION_EXTRAS_START_PLAYBACK_POSITION_MS = "playback_start_position_ms" + private const val TAG = "MusicService" From 9a87812427970cdd13476b6a5ccda740d725ab6a Mon Sep 17 00:00:00 2001 From: plksharma30 Date: Sat, 12 Aug 2023 20:29:03 +0530 Subject: [PATCH 3/3] Added custom actions using setCustomLayout --- .../main/java/com/example/android/uamp/media/MusicService.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/common/src/main/java/com/example/android/uamp/media/MusicService.kt b/common/src/main/java/com/example/android/uamp/media/MusicService.kt index 514b76e4..6552e94f 100644 --- a/common/src/main/java/com/example/android/uamp/media/MusicService.kt +++ b/common/src/main/java/com/example/android/uamp/media/MusicService.kt @@ -345,7 +345,6 @@ open class MusicService : MediaLibraryService() { .setIconResId(R.drawable.media3_notification_seek_back) .setSessionCommand(SessionCommand(SEEK_BACK,Bundle())) .build() - session.setCustomLayout(listOf(seekBackButton)) // Display a button for seek forward action val seekForwardButton = CommandButton.Builder() @@ -574,5 +573,4 @@ const val SEEK_FORWARD = "com.example.android.uamp.SEEK_FORWARD" const val SEEK_BACK = "com.example.android.uamp.SEEK_BACK" const val MEDIA_DESCRIPTION_EXTRAS_START_PLAYBACK_POSITION_MS = "playback_start_position_ms" - private const val TAG = "MusicService"