Kotlin开发中如何实现点击通知时停止正在播放的音频
核心问题分析
- 你写的
stopSelf()位置完全错误,它在通知刚构建完成还没展示时就直接销毁了当前Service,但你的音频是通过单例MediaPlayerManager播放的,Service销毁不会影响单例持有的MediaPlayer状态,音频自然会持续播放。 setAutoCancel(true)的作用仅为点击通知后将通知从通知栏移除,不会自动触发任何停止音频的逻辑,和你要实现的效果无关。- 你当前给通知设置的
contentIntent是跳转FullAzan页面的PendingIntent,没有绑定任何停止音频的逻辑,点击后只会触发页面跳转,不会修改MediaPlayer的播放状态。
修复方案
第一步 给通知点击事件增加停止音频逻辑
你可以根据需求选择以下任意一种方案实现:
方案1:跳转Activity同时停止音频
修改PendingIntent配置,给跳转Intent加参数标识:
val notificationIntent = Intent(this, FullAzan::class.java).apply { putExtra("STOP_AZAN_AUDIO", true) flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP } // Android 12+要求必须指定PendingIntent可变性,这里使用FLAG_IMMUTABLE即可 val pendingIntent = PendingIntent.getActivity( this, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT )
在FullAzan的onCreate方法中补充停止逻辑:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 原有初始化逻辑 if (intent.getBooleanExtra("STOP_AZAN_AUDIO", false)) { MediaPlayerManager.getInstance(applicationContext).stopAzan() } }
方案2:复用现有停止广播逻辑
如果需要和通知栏的停止按钮共用逻辑,可以直接把点击事件绑定到广播,需要跳转页面的话在广播接收器中补充跳转逻辑即可:
val clickIntent = Intent(this, StopAlarm::class.java).apply { putExtra("NEED_JUMP_TO_FULL_AZAN", true) } // requestCode要和停止按钮的不同,避免PendingIntent被覆盖 val pendingIntent = PendingIntent.getBroadcast( this, 1, clickIntent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT )
在StopAlarm广播接收器的onReceive方法中补充逻辑:
override fun onReceive(context: Context?, intent: Intent?) { // 原有停止音频的逻辑 MediaPlayerManager.getInstance(context?.applicationContext).stopAzan() // 需要跳转页面的话保留以下代码,不需要可以删掉 if (intent?.getBooleanExtra("NEED_JUMP_TO_FULL_AZAN", false) == true) { val jumpIntent = Intent(context, FullAzan::class.java).apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP } context?.startActivity(jumpIntent) } }
第二步 调整stopSelf()的调用位置
删除你现在写在通知构建阶段的stopSelf(),如果需要在音频播放完成后自动销毁Service,可以给MediaPlayer增加OnCompletionListener,在音频播放结束的回调中调用stopSelf()。
第三步 补充MediaPlayer停止接口
确认你的MediaPlayerManager中存在合法的停止方法,参考逻辑如下:
fun stopAzan() { if (mediaPlayer?.isPlaying == true) { mediaPlayer?.stop() mediaPlayer?.reset() mediaPlayer?.release() mediaPlayer = null } }
内容的提问来源于stack exchange,提问作者Enigma
相关产品推荐
相关产品推荐

