Android蓝牙设备连接时通知音无法停止问题
蓝牙连接下闹钟通知音无法停止的解决方案
问题核心分析
你遇到的问题主要源于三个关键点:
- 通知标志位用法错误,导致通知常驻且无法正确触发音频停止逻辑;
- 依赖系统通知的默认音频播放,未手动管理音频生命周期;
- 蓝牙连接时音频焦点与资源未正确释放,即使应用被销毁仍在后台播放。
代码修正与解决方案
1. 修复通知标志位的错误用法
原代码中setDefaults(Notification.FLAG_ONGOING_EVENT)是错误的:setDefaults用于设置默认的声音、震动等行为,而FLAG_ONGOING_EVENT是通知的常驻标志,应使用setOngoing()方法设置。如果不需要通知常驻,直接设为false即可,这样关闭通知时能触发系统的音频停止逻辑。
修正后的通知构建代码:
val builder = NotificationCompat.Builder(context, channelId) .setSmallIcon(R.drawable.ic_notification) .setOngoing(false) // 替换错误的setDefaults用法 .setCategory(NotificationCompat.CATEGORY_ALARM) .setContentTitle(alarm.getNotificationTitle(context)) .setContentText(alarm.getNotificationDescription(context)) .setPriority(NotificationCompat.PRIORITY_MAX) .setFullScreenIntent(pendingIntent, true) .setForegroundServiceBehavior(NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE)
2. 手动管理音频播放与资源释放
不要依赖通知的默认声音播放,改用MediaPlayer手动控制音频,这样能确保在任意场景下都能主动停止播放:
// 初始化并播放闹钟音频 val mediaPlayer = MediaPlayer.create(context, R.raw.your_alarm_sound) mediaPlayer.setAudioAttributes(AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_ALARM) // 标记为闹钟用途,确保系统优先级 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) .build()) mediaPlayer.start() // 在通知清除、闹钟取消或应用销毁时调用以下代码停止并释放资源 if (mediaPlayer.isPlaying) { mediaPlayer.stop() } mediaPlayer.release()
3. 处理音频焦点,适配蓝牙场景
通过AudioManager获取音频焦点,当失去焦点(比如用户切换音频输出、关闭应用)时自动停止播放:
val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager val audioFocusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT) .setAudioAttributes(AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_ALARM) .build()) .setOnAudioFocusChangeListener { focusChange -> if (focusChange == AudioManager.AUDIOFOCUS_LOSS) { // 失去焦点时立即停止音频 mediaPlayer?.let { if (it.isPlaying) it.stop() it.release() } } } .build() // 请求焦点成功后再播放音频 if (audioManager.requestAudioFocus(audioFocusRequest) == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { mediaPlayer.start() }
4. 确保前台服务正确销毁
如果使用了前台服务承载闹钟,在闹钟结束时必须主动停止前台服务并清理资源:
// 在Service中停止前台服务并销毁自身 stopForeground(true) // true表示同时移除通知 stopSelf() // 同步停止音频播放 mediaPlayer?.let { if (it.isPlaying) it.stop() it.release() }
5. 监听应用销毁事件,兜底释放资源
在Service的onDestroy()方法中添加资源释放逻辑,确保应用被杀死时音频能停止:
override fun onDestroy() { super.onDestroy() mediaPlayer?.let { if (it.isPlaying) it.stop() it.release() } }
内容的提问来源于stack exchange,提问作者Abanoub Samaan
相关产品推荐
相关产品推荐

