You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 23:19:52