Обратные вызовы Android MediaSessionCompat не запускаются
Я создаю проигрыватель аудиокниг и использую классы, связанные с MediaSessionCompat, для обработки уведомлений. Мой код в значительной степени вдохновлен образцами android-MediaBrowserService ( https://github.com/googlearchive/android-MediaBrowserService ), и я пока не совсем понимаю все это (особенно createContentIntent)
Вот мой простой класс, отвечающий за создание уведомлений от bookPlayer, предоставляющих метаданные и данные состояния воспроизведения.
class PlayerNotificationManager(val playerService: PlayerService) {
val CHANNEL_ID = "pylvain.gamma"
val NOTIFICATION_ID = 412
private val REQUEST_CODE = 501
val notificationManager =
playerService.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
private val playAction: NotificationCompat.Action =
NotificationCompat.Action (
android.R.drawable.ic_media_pause,
"PAUSE",
buildMediaButtonPendingIntent(
playerService,
PlaybackStateCompat.ACTION_PAUSE
)
)
fun getNotification(bookPlayer: BookPlayer): Notification {
if (isAndroidOOrHigher()) createChannel()
val style = androidx.media.app.NotificationCompat.MediaStyle()
.setMediaSession(playerService.sessionToken)
.setShowCancelButton(true)
.setShowActionsInCompactView(0)
.setCancelButtonIntent(
buildMediaButtonPendingIntent(
playerService,
PlaybackStateCompat.ACTION_STOP
)
)
val builder = NotificationCompat.Builder(playerService, CHANNEL_ID)
.addAction(playAction)
.setStyle(style)
.setSmallIcon(R.drawable.ic_music_rest_quarter)
.setContentIntent(createContentIntent())
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
return builder.build()
}
private fun createContentIntent(): PendingIntent { //TODO: Understand that
Timber.i("Creating Intent")
val openUI = Intent(playerService, MainActivity::class.java)
openUI.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
return PendingIntent.getActivity(
playerService, 0, openUI, PendingIntent.FLAG_UPDATE_CURRENT
)
}
Уведомление отлично отображается с метаданными
Вот моя служба MediaBrowserService, обрабатывающая сеанс мультимедиа, где я зарегистрировал обратные вызовы. Bookplayer построен и внедрен с помощью коина. :
class PlayerService : MediaBrowserServiceCompat() {
private lateinit var playerNotificationManager: PlayerNotificationManager
lateinit var session: MediaSessionCompat
private val bookPlayer: BookPlayer by inject()
override fun onCreate() {
super.onCreate()
session = MediaSessionCompat(this, "MusicService")
session.apply {
setFlags(
MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS or
MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS
)
setPlaybackState(bookPlayer.playbackState)
setMetadata(bookPlayer.getMetadata())
setCallback(callbacks)
setActive(true)
}
setSessionToken(session.sessionToken)
playerNotificationManager = PlayerNotificationManager(this)
val notification = playerNotificationManager.getNotification(bookPlayer)
startForeground(playerNotificationManager.NOTIFICATION_ID, notification)
}
override fun onTaskRemoved(rootIntent: Intent?) { //TODO
super.onTaskRemoved(rootIntent)
stopSelf()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
return super.onStartCommand(intent, flags, startId)
}
override fun onGetRoot(
clientPackageName: String,
clientUid: Int,
rootHints: Bundle?
): BrowserRoot? {
return BrowserRoot("root", null)
}
override fun onLoadChildren(
parentId: String, result: Result<MutableList<MediaBrowserCompat.MediaItem>>
) {
result.sendResult(null);
}
override fun onDestroy() {
session.release()
}
val callbacks = object : MediaSessionCompat.Callback() {
override fun onCommand(command: String?, extras: Bundle?, cb: ResultReceiver?) {
Timber.i("Test")
super.onCommand(command, extras, cb)
}
override fun onPrepare() {
Timber.i("Preparing")
}
override fun onPlay() {
Timber.i("Playing")
bookPlayer.pause()
}
override fun onPause() {
Timber.i("Pausing")
bookPlayer.pause()
}
override fun onSkipToNext() {}
override fun onSkipToPrevious() {}
override fun onStop() {}
override fun onSeekTo(pos: Long) {}
override fun onMediaButtonEvent(mediaButtonIntent: Intent): Boolean = true
}
}
Затем служба запускается из основного действия с
startService(Intent(mainContext, PlayerService::class.java))
Я также добавил это в свой манифест Android
<service android:name=".playerservice.PlayerService">
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService" />
</intent-filter>
</service>
<receiver android:name="androidx.media.session.MediaButtonReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
Ни один из обратных вызовов не вызывается всякий раз, когда я нажимаю кнопку. когда я это сделаю, приложение записывает следующий текст:
D/MediaBrowserCompat: Connecting to a MediaBrowserService.
и ничего не происходит ... Я обыскал весь Интернет и совершенно не понимаю, но это определенно что-то простое. Кто-нибудь может мне помочь ? Заранее большое спасибо <3
2 ответа
Обратный вызов сработал ... Просто не так, как предполагалось. Оказывается, кнопка действия воспроизведения вызывала
override fun onMediaButtonEvent(mediaButtonIntent: Intent): Boolean = true
Я удалил функцию, и ... Работает ...
Спасибо за Ваше внимание !
Если вы хотите получить кнопку мультимедиа, вы должны во что-то сыграть. Попробуйте воспроизвести фиктивный звук, когда ваш сервис запущен
// play dummy audio
AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, 48000, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT,
AudioTrack.getMinBufferSize(48000, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT), AudioTrack.MODE_STREAM);
at.play();
// a little sleep
at.stop();
at.release();
/questions/37196938/kak-zaregistrirovat-broadcast-receiver-dlya-media-knopki-v-oreo/37196949#37196949 - это мой ответ раньше