问题描述
我正在创建一个有声读物播放器,我正在使用与 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,openUI,PendingIntent.FLAG_UPDATE_CURRENT
)
}
这是我的 MediabrowserService 处理媒体会话,我在其中注册了回调。 bookplayer 是用 Koin 构建和注入的。 :
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
}
}
然后服务从主activity启动
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.
什么也没发生... 我已经搜索了整个互联网,但我完全一无所知,但这肯定很简单。有人能帮我吗 ?预先非常感谢您
解决方法
回调有效......只是不是预期的方式。原来是播放动作按钮在调用
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.ENCODING_PCM_16BIT),AudioTrack.MODE_STREAM);
at.play();
// a little sleep
at.stop();
at.release();
https://stackoverflow.com/a/50678833/9891730 - 这是我之前的回答