如何在ExoPlayer播放时添加Android通知栏控制?
实现ExoPlayer通知栏控制步骤
1. 配置通知渠道(Android 8.0+必备)
在MediaPlayerService启动时先创建通知渠道,否则8.0以上系统无法显示通知:
private fun createNotificationChannel() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel( "AUDIO_PLAYER_CHANNEL", "音频播放控制", NotificationManager.IMPORTANCE_LOW ).apply { description = "用于音频播放的通知栏控制" } val notificationManager = getSystemService(NotificationManager::class.java) notificationManager.createNotificationChannel(channel) } }
2. 构建MediaStyle通知与控制按钮
编写通知构建方法,使用MediaStyle适配媒体播放场景,添加播放/暂停、关闭按钮:
// 先定义Action常量,放在Service类顶部 const val ACTION_PLAY_PAUSE = "com.your.package.action.PLAY_PAUSE" const val ACTION_STOP = "com.your.package.action.STOP" private fun buildPlayerNotification(): Notification { // 播放/暂停按钮的PendingIntent val playPauseIntent = Intent(this, MediaPlayerService::class.java).apply { action = ACTION_PLAY_PAUSE } val playPausePendingIntent = PendingIntent.getService( this, 0, playPauseIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) // 关闭按钮的PendingIntent val stopIntent = Intent(this, MediaPlayerService::class.java).apply { action = ACTION_STOP } val stopPendingIntent = PendingIntent.getService( this, 1, stopIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) // 根据当前播放状态切换按钮图标 val playPauseIcon = if (exoPlayer.isPlaying) R.drawable.ic_pause else R.drawable.ic_play val playPauseText = if (exoPlayer.isPlaying) "暂停" else "播放" // 构建通知 return NotificationCompat.Builder(this, "AUDIO_PLAYER_CHANNEL") .setSmallIcon(R.drawable.ic_audio_player) .setContentTitle("当前播放音频") .setContentText("音频名称") .setStyle( androidx.media.app.NotificationCompat.MediaStyle() .setShowActionsInCompactView(0, 1) // 紧凑模式下显示前两个按钮 ) .addAction(playPauseIcon, playPauseText, playPausePendingIntent) .addAction(R.drawable.ic_stop, "停止", stopPendingIntent) .setPriority(NotificationCompat.PRIORITY_LOW) .build() }
3. 处理通知按钮的Action逻辑
在MediaPlayerService的onStartCommand中响应按钮点击:
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { intent?.action?.let { action -> when (action) { ACTION_PLAY_PAUSE -> { if (exoPlayer.isPlaying) exoPlayer.pause() else exoPlayer.play() updateNotification() } ACTION_STOP -> { exoPlayer.stop() stopForeground(STOP_FOREGROUND_REMOVE) stopSelf() } } } return START_STICKY } private fun updateNotification() { val notification = buildPlayerNotification() startForeground(1, notification) }
4. 监听ExoPlayer状态自动更新通知
给ExoPlayer添加状态监听器,播放状态变化时自动刷新通知:
private fun setupPlayerListener() { exoPlayer.addListener(object : Player.Listener { override fun onPlaybackStateChanged(playbackState: Int) { super.onPlaybackStateChanged(playbackState) updateNotification() } override fun onIsPlayingChanged(isPlaying: Boolean) { super.onIsPlayingChanged(isPlaying) updateNotification() } }) }
5. 启动前台服务
在初始化ExoPlayer并开始播放时,启动前台服务:
fun startPlaying(audioUri: Uri) { // 初始化ExoPlayer逻辑 exoPlayer.setMediaItem(MediaItem.fromUri(audioUri)) exoPlayer.prepare() exoPlayer.play() // 创建渠道+启动前台服务 createNotificationChannel() startForeground(1, buildPlayerNotification()) setupPlayerListener() }
关键注意事项
- 必须将
MediaPlayerService设为前台服务,Android 8.0+后台服务无法显示通知,必须调用startForeground - PendingIntent的
FLAG_IMMUTABLE需适配API 31+,低于该版本可使用FLAG_UPDATE_CURRENT - 替换代码中的图标资源为你项目里的播放、暂停、停止图标
- 若要显示当前音频的标题、歌手信息,可从
MediaItem的mediaMetadata中提取后设置到通知的setContentTitle/setContentText中
内容的提问来源于stack exchange,提问作者Andongwisye Mwamengo
相关产品推荐
相关产品推荐

