Теперь я разрабатываю приложение для воспроизведения музыки с помощью библиотеки Media3. Теперь в классе службы я добавил пользовательские действия (воспроизводитесь, воспроизводитесь предыдущим), и он работает отлично, как показано в коде ниже. >
class PlayerService : MediaSessionService(){
private var mediaSession : MediaSession? = null
private val stopCommand = SessionCommand("Stop" , Bundle.EMPTY)
private val nextMediaItemCommand = SessionCommand("Next" , Bundle.EMPTY)
private val previousMediaItemCommand = SessionCommand("Previous" , Bundle.EMPTY)
@OptIn(UnstableApi::class)
override fun onCreate() {
super.onCreate()
val player = ExoPlayer.Builder(this).build()
player.repeatMode = Player.REPEAT_MODE_ALL
mediaSession = MediaSession.Builder(this , player)
.setCallback(MyCallback())
.setCustomLayout(setCustomLayout())
.build()
notificationService()
}
@OptIn(UnstableApi::class)
private fun notificationService() {
NotificationCompat
.Builder(this , "SERVICE")
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setStyle(MediaStyleNotificationHelper.MediaStyle(mediaSession!!))
.setContentTitle("Service")
.setContentText("Service is running")
.build()
}
override fun onGetSession(controllerInfo : MediaSession.ControllerInfo) : MediaSession? = mediaSession
override fun onDestroy() {
super.onDestroy()
mediaSession?.run {
release()
player.release()
mediaSession = null
}
}
private fun setCustomLayout() : ImmutableList{
val previous = CommandButton.Builder()
.setDisplayName("Skip to Previous")
.setIconResId(R.drawable.skip_previous)
.setSessionCommand(previousMediaItemCommand)
.build()
val next = CommandButton.Builder()
.setDisplayName("Skip to Next")
.setIconResId(R.drawable.skip_next)
.setSessionCommand(nextMediaItemCommand)
.build()
val stop = CommandButton.Builder()
.setDisplayName("Stop Playing")
.setIconResId(R.drawable.baseline_close_24)
.setSessionCommand(stopCommand)
.build()
return ImmutableList.of(previous , next , stop)
}
private inner class MyCallback : MediaSession.Callback{
@OptIn(UnstableApi::class)
override fun onConnect(
session : MediaSession ,
controller : MediaSession.ControllerInfo
) : ConnectionResult {
return AcceptedResultBuilder(session)
.setAvailablePlayerCommands(
ConnectionResult.DEFAULT_PLAYER_COMMANDS.buildUpon()
.remove(Player.COMMAND_SEEK_TO_NEXT)
.remove(Player.COMMAND_SEEK_TO_PREVIOUS)
.remove(Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM)
.remove(Player.COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM)
.build()
)
.setAvailableSessionCommands(
ConnectionResult.DEFAULT_SESSION_COMMANDS.buildUpon()
.add(stopCommand)
.add(nextMediaItemCommand)
.add(previousMediaItemCommand)
.build()
)
.build()
}
override fun onCustomCommand(
session : MediaSession ,
controller : MediaSession.ControllerInfo ,
customCommand : SessionCommand ,
args : Bundle
) : ListenableFuture {
if (customCommand.customAction == "Stop") {
onDestroy()
} else if (customCommand.customAction == "Next") {
session.player.seekToNextMediaItem()
} else if (customCommand.customAction == "Previous") {
session.player.seekToPreviousMediaItem()
}
return super.onCustomCommand(session , controller , customCommand , args)
}
override fun onAddMediaItems(
mediaSession : MediaSession ,
controller : MediaSession.ControllerInfo ,
mediaItems : MutableList
) : ListenableFuture {
Log.d("add" , "yes")
val _mediaItems = mediaItems.map {musicItem ->
musicItem.buildUpon()
.setUri(musicItem.mediaId)
.build()
}.toMutableList()
return Futures.immediateFuture(_mediaItems)
}
}
}
< /code>
note < /strong>
Я добавил медиаитемы в пользовательский интерфейс Player < /p>
Проблема в том, что при нажатии одного из них Кнопки обновляют текущий медиайтем, такие как добавление MediaMetadata
Для этой цели я использую следующий код в действие Custom Command в классе MyCallback: < /p>
session.player.replaceMediaItem(
session.player.currentMediaItemIndex ,
MediaItem.Builder()
.setMediaId(session.player.currentMediaItem?.mediaId!!)
.setMediaMetadata(MediaMetadata.Builder().setArtworkUri(//setartworkUri)
.build())
.build()
)
< /code>
Когда я запускаю приложение, оно вылетает, и я получаю следующее исключение: < /p>
Process: com.example.aplayer, PID: 2 5 3 0 8 < b r / > java.lang.NullPointerException
at androidx.media3.common.util.Assertions.checkNotNull(Assertions.java:155)
at androidx.media3.exoplayer.source.DefaultMediaSourceFactory.createMediaSource(DefaultMediaSourceFactory.java:457)
at androidx.media3.exoplayer.ExoPlayerImpl.createMediaSources(ExoPlayerImpl.java:1971)
at androidx.media3.exoplayer.ExoPlayerImpl.replaceMediaItems(ExoPlayerImpl.java:767)
at androidx.media3.common.BasePlayer.replaceMediaItem(BasePlayer.java:83)
at com.example.aplayer.data.PlayerService$MyCallback.onCustomCommand(PlayerService.kt:128)
at androidx.media3.session.MediaSessionImpl.onCustomCommandOnHandler(MediaSessionImpl.java:735)
at androidx.media3.session.MediaSessionLegacyStub.lambda$onCustomAction$1$androidx-media3-session-MediaSessionLegacyStub(MediaSessionLegacyStub.java:310)
at androidx.media3.session.MediaSessionLegacyStub$$ExternalSyntheticLambda6.run(D8$$SyntheticClass:0)
at androidx.media3.session.MediaSessionLegacyStub.lambda$dispatchSessionTaskWithSessionCommandInternal$22$androidx-media3-session-MediaSessionLegacyStub(MediaSessionLegacyStub.java:760)
at androidx.media3.session.MediaSessionLegacyStub$$ExternalSyntheticLambda3.run(D8$$SyntheticClass:0)
at androidx.media3.common.util.Util.postOrRun(Util.java:794)
at androidx.media3.session.MediaSessionLegacyStub.dispatchSessionTaskWithSessionCommandInternal(MediaSessionLegacyStub.java:729)
at androidx.media3.session.MediaSessionLegacyStub.dispatchSessionTaskWithSessionCommand(MediaSessionLegacyStub.java:713)
at androidx.media3.session.MediaSessionLegacyStub.onCustomAction(MediaSessionLegacyStub.java:306)
at androidx.media3.session.legacy.MediaSessionCompat$Callback$MediaSessionCallbackApi21.onCustomAction(MediaSessionCompat.java:1656)
at android.media.session.MediaSession$CallbackMessageHandler.handleMessage(MediaSession.java:1656)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:230)
at android.os.Looper.loop(Looper.java:319)
at android.app.ActivityThread.main(ActivityThread.java:8919)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:578)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103)
Есть ли какое -либо решение этой проблемы или инструкции по обновлению MediaItem в классе MediaSessionsers
Теперь я разрабатываю приложение для воспроизведения музыки с помощью библиотеки Media3. Теперь в классе службы я добавил пользовательские действия (воспроизводитесь, воспроизводитесь предыдущим), и он работает отлично, как показано в коде ниже. >[code]class PlayerService : MediaSessionService(){
private var mediaSession : MediaSession? = null private val stopCommand = SessionCommand("Stop" , Bundle.EMPTY) private val nextMediaItemCommand = SessionCommand("Next" , Bundle.EMPTY) private val previousMediaItemCommand = SessionCommand("Previous" , Bundle.EMPTY)
@OptIn(UnstableApi::class) override fun onCreate() { super.onCreate()
val player = ExoPlayer.Builder(this).build() player.repeatMode = Player.REPEAT_MODE_ALL mediaSession = MediaSession.Builder(this , player) .setCallback(MyCallback()) .setCustomLayout(setCustomLayout()) .build()
notificationService()
} @OptIn(UnstableApi::class) private fun notificationService() {
private fun setCustomLayout() : ImmutableList{ val previous = CommandButton.Builder() .setDisplayName("Skip to Previous") .setIconResId(R.drawable.skip_previous) .setSessionCommand(previousMediaItemCommand) .build() val next = CommandButton.Builder() .setDisplayName("Skip to Next") .setIconResId(R.drawable.skip_next) .setSessionCommand(nextMediaItemCommand) .build() val stop = CommandButton.Builder() .setDisplayName("Stop Playing") .setIconResId(R.drawable.baseline_close_24) .setSessionCommand(stopCommand) .build()
return ImmutableList.of(previous , next , stop) }
private inner class MyCallback : MediaSession.Callback{
override fun onAddMediaItems( mediaSession : MediaSession , controller : MediaSession.ControllerInfo , mediaItems : MutableList ) : ListenableFuture { Log.d("add" , "yes") val _mediaItems = mediaItems.map {musicItem -> musicItem.buildUpon() .setUri(musicItem.mediaId) .build() }.toMutableList() return Futures.immediateFuture(_mediaItems) } } } < /code> note < /strong> Я добавил медиаитемы в пользовательский интерфейс Player < /p> Проблема в том, что при нажатии одного из них Кнопки обновляют текущий медиайтем, такие как добавление MediaMetadata Для этой цели я использую следующий код в действие Custom Command в классе MyCallback: < /p> session.player.replaceMediaItem( session.player.currentMediaItemIndex , MediaItem.Builder() .setMediaId(session.player.currentMediaItem?.mediaId!!) .setMediaMetadata(MediaMetadata.Builder().setArtworkUri(//setartworkUri) .build()) .build() ) < /code> Когда я запускаю приложение, оно вылетает, и я получаю следующее исключение: < /p> Process: com.example.aplayer, PID: 2 5 3 0 8 < b r / > java.lang.NullPointerException at androidx.media3.common.util.Assertions.checkNotNull(Assertions.java:155) at androidx.media3.exoplayer.source.DefaultMediaSourceFactory.createMediaSource(DefaultMediaSourceFactory.java:457) at androidx.media3.exoplayer.ExoPlayerImpl.createMediaSources(ExoPlayerImpl.java:1971) at androidx.media3.exoplayer.ExoPlayerImpl.replaceMediaItems(ExoPlayerImpl.java:767) at androidx.media3.common.BasePlayer.replaceMediaItem(BasePlayer.java:83) at com.example.aplayer.data.PlayerService$MyCallback.onCustomCommand(PlayerService.kt:128) at androidx.media3.session.MediaSessionImpl.onCustomCommandOnHandler(MediaSessionImpl.java:735) at androidx.media3.session.MediaSessionLegacyStub.lambda$onCustomAction$1$androidx-media3-session-MediaSessionLegacyStub(MediaSessionLegacyStub.java:310) at androidx.media3.session.MediaSessionLegacyStub$$ExternalSyntheticLambda6.run(D8$$SyntheticClass:0) at androidx.media3.session.MediaSessionLegacyStub.lambda$dispatchSessionTaskWithSessionCommandInternal$22$androidx-media3-session-MediaSessionLegacyStub(MediaSessionLegacyStub.java:760) at androidx.media3.session.MediaSessionLegacyStub$$ExternalSyntheticLambda3.run(D8$$SyntheticClass:0) at androidx.media3.common.util.Util.postOrRun(Util.java:794) at androidx.media3.session.MediaSessionLegacyStub.dispatchSessionTaskWithSessionCommandInternal(MediaSessionLegacyStub.java:729) at androidx.media3.session.MediaSessionLegacyStub.dispatchSessionTaskWithSessionCommand(MediaSessionLegacyStub.java:713) at androidx.media3.session.MediaSessionLegacyStub.onCustomAction(MediaSessionLegacyStub.java:306) at androidx.media3.session.legacy.MediaSessionCompat$Callback$MediaSessionCallbackApi21.onCustomAction(MediaSessionCompat.java:1656) at android.media.session.MediaSession$CallbackMessageHandler.handleMessage(MediaSession.java:1656) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:230) at android.os.Looper.loop(Looper.java:319) at android.app.ActivityThread.main(ActivityThread.java:8919) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:578) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103) [/code] Есть ли какое -либо решение этой проблемы или инструкции по обновлению MediaItem в классе MediaSessionsers
Теперь я разрабатываю приложение для воспроизведения музыки с помощью библиотеки Media3. Теперь в классе службы я добавил пользовательские действия (воспроизводитесь, воспроизводитесь предыдущим), и он работает отлично, как показано в коде ниже. >...
Я использую Media3, и я хочу заменить загрузчик изображения по умолчанию, используемый в уведомлении в стиле медиа с помощью Glide, в основном, чтобы изображения были загружены из кэша, когда они доступны, вместо того, чтобы быть снова извлеченными....
Может быть, это только я, но в разделе Media3 Create a MediaController в документации по Android мне просто не хватает последней части, которая заключается в получении «плеера» и использовании его в компонуемом объекте.
Мне также нужен сеанс для...