更新记录
1.0.1(2026-01-16)
增加通知栏使用方法
1.0.0(2026-01-16)
新增功能
- ✨ 首次发布
- ✨ 支持实时监听音频设备状态变化
- ✨ 支持检测扬声器、听筒、有线耳机、蓝牙设备
- ✨ 提供开始监听、停止监听、获取当前状态三个核心API
- ✨ 支持 Android 平台(通过广播接收器监听)
- ✨ 支持 iOS 平台(通过 AVAudioSession 监听)
- ✨ 完善的错误码和错误处理机制
- ✨ 详细的使用文档和示例代码
平台兼容性
uni-app(4.85)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-vue插件版本 | app-nvue | app-nvue插件版本 | Android | Android插件版本 | iOS | iOS插件版本 | 鸿蒙 | 鸿蒙插件版本 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| × | × | × | × | √ | 1.0.0 | √ | 1.0.0 | 4.4 | 1.0.0 | 12 | 1.0.0 | 21 | 1.0.0 |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|
| × | × | × | × | × | × | × | × | × | × | × |
uni-app x(4.85)
| Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|
| - | - | - | - | - | - |
miko-audioListener
音频监听器插件 - 实时监听扬声器/耳机状态变化 & 通知栏播放控制
功能说明
🎧 音频设备状态监听
本插件提供了音频设备状态监听功能,可以实时检测以下设备状态变化:
- 📢 扬声器 - 检测是否使用扬声器播放
- 📞 听筒 - 检测是否使用听筒播放
- 🎧 有线耳机 - 检测耳机的插入和拔出
- 🔊 蓝牙设备 - 检测蓝牙音频设备的连接和断开
🎵 通知栏播放控制
插件还提供了完整的通知栏播放控制功能:
- 🎛️ 播放控制按钮 - 播放/暂停、上一曲、下一曲
- 📊 播放信息显示 - 歌曲标题、艺术家、封面图片
- 🔄 状态同步 - 实时更新播放状态
- 📱 跨平台支持 - Android & iOS 统一API
平台支持
- ✅ Android
- ✅ iOS
使用方法
1. 开始监听音频设备状态
在需要监听音频设备状态的页面中,调用 startAudioListener 方法:
import { startAudioListener } from "@/uni_modules/miko-audioListener"
export default {
onLoad() {
startAudioListener({
// 状态变化回调(必填)
onChange: (status) => {
console.log("音频设备状态变化:", status)
console.log("输出类型:", status.outputType) // "speaker" | "earpiece" | "wiredHeadset" | "bluetooth" | "unknown"
console.log("是否使用扬声器:", status.isSpeaker) // true/false
console.log("是否连接耳机:", status.isHeadsetConnected) // true/false
console.log("是否连接蓝牙:", status.isBluetoothConnected) // true/false
console.log("设备描述:", status.description) // "扬声器" | "听筒" | "有线耳机" | "蓝牙设备"
// 根据状态做相应处理
if (status.outputType === 'wiredHeadset') {
console.log('用户插入了耳机')
} else if (status.outputType === 'speaker') {
console.log('当前使用扬声器播放')
}
},
// 成功回调(可选)
success: (res) => {
console.log("开始监听成功", res)
console.log("当前设备状态:", res.currentStatus)
},
// 失败回调(可选)
fail: (err) => {
console.error("开始监听失败", err.errCode, err.errMsg)
},
// 完成回调(可选)
complete: (res) => {
console.log("监听器启动完成", res)
}
})
}
}
2. 停止监听音频设备状态
在页面卸载或不需要监听时,调用 stopAudioListener 方法:
import { stopAudioListener } from "@/uni_modules/miko-audioListener"
export default {
onUnload() {
stopAudioListener({
success: (res) => {
console.log("停止监听成功", res)
},
fail: (err) => {
console.error("停止监听失败", err.errCode, err.errMsg)
}
})
}
}
3. 获取当前音频设备状态
可以随时查询当前的音频设备状态:
import { getCurrentAudioStatus } from "@/uni_modules/miko-audioListener"
getCurrentAudioStatus({
success: (res) => {
console.log("获取状态成功", res)
const status = res.status
console.log("当前输出设备:", status.outputType)
console.log("是否使用扬声器:", status.isSpeaker)
console.log("是否连接耳机:", status.isHeadsetConnected)
console.log("是否连接蓝牙:", status.isBluetoothConnected)
},
fail: (err) => {
console.error("获取状态失败", err.errCode, err.errMsg)
}
})
通知栏播放控制
插件还提供了通知栏播放控制功能,可以在通知栏显示媒体播放控制按钮。
4. 初始化通知栏控制器
在使用通知栏功能前需要先初始化控制器:
import { initializeNotificationController } from "@/uni_modules/miko-audioListener"
initializeNotificationController({
success: (res) => {
console.log("通知栏控制器初始化成功", res)
},
fail: (err) => {
console.error("通知栏控制器初始化失败", err.errCode, err.errMsg)
}
})
5. 显示通知栏播放控制
初始化后可以显示通知栏:
import { showNotification } from "@/uni_modules/miko-audioListener"
showNotification({
success: (res) => {
console.log("通知栏显示成功", res)
},
fail: (err) => {
console.error("通知栏显示失败", err.errCode, err.errMsg)
}
})
6. 隐藏通知栏播放控制
不需要显示时可以隐藏通知栏:
import { hideNotification } from "@/uni_modules/miko-audioListener"
hideNotification({
success: (res) => {
console.log("通知栏隐藏成功", res)
},
fail: (err) => {
console.error("通知栏隐藏失败", err.errCode, err.errMsg)
}
})
7. 更新通知栏播放信息
更新通知栏中显示的歌曲信息:
import { updateNotificationInfo } from "@/uni_modules/miko-audioListener"
updateNotificationInfo({
title: "歌曲名称",
artist: "艺术家",
coverUrl: "https://example.com/cover.jpg"
}, {
success: (res) => {
console.log("通知栏信息更新成功", res)
},
fail: (err) => {
console.error("通知栏信息更新失败", err.errCode, err.errMsg)
}
})
8. 更新通知栏播放状态
更新通知栏中的播放状态(播放/暂停):
import { updateNotificationState } from "@/uni_modules/miko-audioListener"
updateNotificationState({
isPlaying: true // true: 播放状态, false: 暂停状态
}, {
success: (res) => {
console.log("通知栏状态更新成功", res)
},
fail: (err) => {
console.error("通知栏状态更新失败", err.errCode, err.errMsg)
}
})
9. 设置通知栏按钮回调监听器
设置持续监听通知栏按钮点击事件的回调:
import { onNotificationCallbacks } from "@/uni_modules/miko-audioListener"
// 设置监听器,持续监听按钮点击事件
onNotificationCallbacks((callbackData) => {
console.log("通知栏按钮被点击:", callbackData.action)
switch (callbackData.action) {
case 'playPause':
// 处理播放/暂停按钮点击
console.log('播放/暂停按钮被点击')
break
case 'previous':
// 处理上一曲按钮点击
console.log('上一曲按钮被点击')
break
case 'next':
// 处理下一曲按钮点击
console.log('下一曲按钮被点击')
break
default:
console.log('未知按钮被点击:', callbackData.action)
}
})
10. 停止通知栏按钮回调监听
停止监听通知栏按钮点击事件:
import { stopNotificationCallbacks } from "@/uni_modules/miko-audioListener"
stopNotificationCallbacks({
success: (res) => {
console.log("停止通知栏回调监听成功", res)
},
fail: (err) => {
console.error("停止通知栏回调监听失败", err.errCode, err.errMsg)
}
})
11. 释放通知栏控制器
在应用退出或不需要使用通知栏功能时释放资源:
import { releaseNotificationController } from "@/uni_modules/miko-audioListener"
releaseNotificationController()
完整示例
<template>
<view class="container">
<text class="title">音频设备监听器</text>
<view class="status-card">
<text class="status-label">当前设备:</text>
<text class="status-value">{{ deviceStatus.description }}</text>
</view>
<view class="status-card">
<text class="status-label">输出类型:</text>
<text class="status-value">{{ deviceStatus.outputType }}</text>
</view>
<view class="status-card">
<text class="status-label">是否扬声器:</text>
<text class="status-value">{{ deviceStatus.isSpeaker ? '是' : '否' }}</text>
</view>
<view class="status-card">
<text class="status-label">耳机连接:</text>
<text class="status-value">{{ deviceStatus.isHeadsetConnected ? '已连接' : '未连接' }}</text>
</view>
<view class="status-card">
<text class="status-label">蓝牙连接:</text>
<text class="status-value">{{ deviceStatus.isBluetoothConnected ? '已连接' : '未连接' }}</text>
</view>
<button @click="startListening" :disabled="isListening">开始监听</button>
<button @click="stopListening" :disabled="!isListening">停止监听</button>
<button @click="checkStatus">查询当前状态</button>
<!-- 通知栏控制区域 -->
<view class="section-title">通知栏播放控制</view>
<button @click="initNotification" :disabled="notificationInitialized">初始化通知栏</button>
<button @click="showNotificationBar" :disabled="!notificationInitialized">显示通知栏</button>
<button @click="hideNotificationBar" :disabled="!notificationInitialized">隐藏通知栏</button>
<view class="input-group">
<text class="input-label">歌曲标题:</text>
<input v-model="songTitle" placeholder="输入歌曲标题" />
</view>
<view class="input-group">
<text class="input-label">艺术家:</text>
<input v-model="songArtist" placeholder="输入艺术家" />
</view>
<button @click="updateNotificationInfo" :disabled="!notificationInitialized">更新通知栏信息</button>
<view class="toggle-group">
<text class="toggle-label">播放状态:</text>
<switch :checked="isNotificationPlaying" @change="toggleNotificationPlay" :disabled="!notificationInitialized" />
<text>{{ isNotificationPlaying ? '播放中' : '已暂停' }}</text>
</view>
</view>
</template>
<script>
import {
startAudioListener,
stopAudioListener,
getCurrentAudioStatus,
initializeNotificationController,
showNotification,
hideNotification,
updateNotificationInfo,
updateNotificationState,
onNotificationCallbacks,
stopNotificationCallbacks,
releaseNotificationController
} from "@/uni_modules/miko-audioListener"
export default {
data() {
return {
isListening: false,
deviceStatus: {
outputType: 'unknown',
isSpeaker: false,
isHeadsetConnected: false,
isBluetoothConnected: false,
description: '未知'
},
// 通知栏相关数据
notificationInitialized: false,
songTitle: '示例歌曲',
songArtist: '示例艺术家',
isNotificationPlaying: false
}
},
methods: {
// 开始监听
startListening() {
startAudioListener({
onChange: (status) => {
console.log('设备状态变化:', status)
this.deviceStatus = status
// 可以根据状态做相应处理
if (status.outputType === 'wiredHeadset') {
uni.showToast({ title: '检测到耳机插入', icon: 'none' })
} else if (status.outputType === 'speaker') {
uni.showToast({ title: '当前使用扬声器', icon: 'none' })
}
},
success: (res) => {
console.log('开始监听成功:', res)
this.isListening = true
this.deviceStatus = res.currentStatus
uni.showToast({ title: '开始监听成功', icon: 'success' })
},
fail: (err) => {
console.error('开始监听失败:', err)
uni.showToast({ title: err.errMsg, icon: 'none' })
}
})
},
// 停止监听
stopListening() {
stopAudioListener({
success: (res) => {
console.log('停止监听成功:', res)
this.isListening = false
uni.showToast({ title: '停止监听成功', icon: 'success' })
},
fail: (err) => {
console.error('停止监听失败:', err)
uni.showToast({ title: err.errMsg, icon: 'none' })
}
})
},
// 查询当前状态
checkStatus() {
getCurrentAudioStatus({
success: (res) => {
console.log('获取状态成功:', res)
this.deviceStatus = res.status
uni.showToast({
title: `当前设备: ${res.status.description}`,
icon: 'none'
})
},
fail: (err) => {
console.error('获取状态失败:', err)
uni.showToast({ title: err.errMsg, icon: 'none' })
}
})
},
// 初始化通知栏
initNotification() {
initializeNotificationController({
success: (res) => {
console.log('通知栏初始化成功:', res)
this.notificationInitialized = true
uni.showToast({ title: '通知栏初始化成功', icon: 'success' })
// 设置通知栏回调监听器
this.setupNotificationCallbacks()
},
fail: (err) => {
console.error('通知栏初始化失败:', err)
uni.showToast({ title: err.errMsg, icon: 'none' })
}
})
},
// 设置通知栏回调监听器
setupNotificationCallbacks() {
onNotificationCallbacks((callbackData) => {
console.log('通知栏按钮点击:', callbackData.action)
switch (callbackData.action) {
case 'playPause':
this.handleNotificationPlayPause()
break
case 'previous':
this.handleNotificationPrevious()
break
case 'next':
this.handleNotificationNext()
break
}
})
},
// 处理通知栏播放/暂停
handleNotificationPlayPause() {
this.isNotificationPlaying = !this.isNotificationPlaying
this.updateNotificationState()
uni.showToast({
title: this.isNotificationPlaying ? '播放' : '暂停',
icon: 'none'
})
},
// 处理通知栏上一曲
handleNotificationPrevious() {
uni.showToast({ title: '上一曲', icon: 'none' })
},
// 处理通知栏下一曲
handleNotificationNext() {
uni.showToast({ title: '下一曲', icon: 'none' })
},
// 显示通知栏
showNotificationBar() {
showNotification({
success: (res) => {
console.log('显示通知栏成功:', res)
uni.showToast({ title: '通知栏已显示', icon: 'success' })
},
fail: (err) => {
console.error('显示通知栏失败:', err)
uni.showToast({ title: err.errMsg, icon: 'none' })
}
})
},
// 隐藏通知栏
hideNotificationBar() {
hideNotification({
success: (res) => {
console.log('隐藏通知栏成功:', res)
uni.showToast({ title: '通知栏已隐藏', icon: 'success' })
},
fail: (err) => {
console.error('隐藏通知栏失败:', err)
uni.showToast({ title: err.errMsg, icon: 'none' })
}
})
},
// 更新通知栏信息
updateNotificationInfo() {
updateNotificationInfo({
title: this.songTitle,
artist: this.songArtist,
coverUrl: 'https://example.com/cover.jpg'
}, {
success: (res) => {
console.log('更新通知栏信息成功:', res)
uni.showToast({ title: '通知栏信息已更新', icon: 'success' })
},
fail: (err) => {
console.error('更新通知栏信息失败:', err)
uni.showToast({ title: err.errMsg, icon: 'none' })
}
})
},
// 更新通知栏播放状态
updateNotificationState() {
updateNotificationState({
isPlaying: this.isNotificationPlaying
}, {
success: (res) => {
console.log('更新通知栏状态成功:', res)
},
fail: (err) => {
console.error('更新通知栏状态失败:', err)
}
})
},
// 切换通知栏播放状态
toggleNotificationPlay() {
this.isNotificationPlaying = !this.isNotificationPlaying
this.updateNotificationState()
}
},
onUnload() {
// 页面卸载时停止监听
if (this.isListening) {
this.stopListening()
}
// 停止通知栏回调监听
if (this.notificationInitialized) {
stopNotificationCallbacks({
success: (res) => {
console.log('停止通知栏回调监听成功:', res)
},
fail: (err) => {
console.error('停止通知栏回调监听失败:', err)
}
})
// 释放通知栏控制器
releaseNotificationController()
}
}
}
</script>
<style>
.container {
padding: 40rpx;
}
.title {
font-size: 36rpx;
font-weight: bold;
text-align: center;
margin-bottom: 40rpx;
}
.status-card {
display: flex;
justify-content: space-between;
padding: 20rpx;
margin-bottom: 20rpx;
background-color: #f5f5f5;
border-radius: 10rpx;
}
.status-label {
font-size: 28rpx;
color: #666;
}
.status-value {
font-size: 28rpx;
color: #333;
font-weight: bold;
}
button {
margin-top: 20rpx;
}
.section-title {
font-size: 32rpx;
font-weight: bold;
margin: 40rpx 0 20rpx 0;
color: #333;
}
.input-group {
display: flex;
align-items: center;
margin-bottom: 20rpx;
padding: 20rpx;
background-color: #f9f9f9;
border-radius: 10rpx;
}
.input-label {
font-size: 28rpx;
color: #666;
width: 160rpx;
flex-shrink: 0;
}
input {
flex: 1;
padding: 10rpx;
border: 1rpx solid #ddd;
border-radius: 6rpx;
font-size: 28rpx;
}
.toggle-group {
display: flex;
align-items: center;
padding: 20rpx;
margin-bottom: 20rpx;
background-color: #f9f9f9;
border-radius: 10rpx;
}
.toggle-label {
font-size: 28rpx;
color: #666;
margin-right: 20rpx;
}
switch {
margin-right: 20rpx;
}
</style>
API说明
startAudioListener(options)
开始监听音频设备状态
参数说明:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| onChange | Function | 是 | 状态变化回调,参数为 AudioDeviceStatus |
| success | Function | 否 | 成功回调 |
| fail | Function | 否 | 失败回调 |
| complete | Function | 否 | 完成回调(成功或失败都会执行) |
AudioDeviceStatus 对象说明:
| 字段 | 类型 | 说明 |
|---|---|---|
| outputType | String | 输出设备类型:"speaker"(扬声器) / "earpiece"(听筒) / "wiredHeadset"(有线耳机) / "bluetooth"(蓝牙设备) / "unknown"(未知) |
| isSpeaker | Boolean | 是否使用扬声器 |
| isHeadsetConnected | Boolean | 是否连接耳机 |
| isBluetoothConnected | Boolean | 是否连接蓝牙 |
| description | String | 设备描述 |
stopAudioListener(options)
停止监听音频设备状态
参数说明:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| success | Function | 否 | 成功回调 |
| fail | Function | 否 | 失败回调 |
| complete | Function | 否 | 完成回调(成功或失败都会执行) |
getCurrentAudioStatus(options)
获取当前音频设备状态
参数说明:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| success | Function | 否 | 成功回调,参数包含 status 字段 |
| fail | Function | 否 | 失败回调 |
| complete | Function | 否 | 完成回调(成功或失败都会执行) |
initializeNotificationController(options)
初始化通知栏控制器
参数说明:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| success | Function | 否 | 成功回调 |
| fail | Function | 否 | 失败回调 |
| complete | Function | 否 | 完成回调(成功或失败都会执行) |
showNotification(options)
显示通知栏播放控制
参数说明:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| success | Function | 否 | 成功回调 |
| fail | Function | 否 | 失败回调 |
| complete | Function | 否 | 完成回调(成功或失败都会执行) |
hideNotification(options)
隐藏通知栏播放控制
参数说明:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| success | Function | 否 | 成功回调 |
| fail | Function | 否 | 失败回调 |
| complete | Function | 否 | 完成回调(成功或失败都会执行) |
updateNotificationInfo(info, options)
更新通知栏播放信息
参数说明:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| info | Object | 是 | 播放信息对象 |
| info.title | String | 否 | 歌曲标题 |
| info.artist | String | 否 | 艺术家 |
| info.coverUrl | String | 否 | 封面图片URL |
| success | Function | 否 | 成功回调 |
| fail | Function | 否 | 失败回调 |
| complete | Function | 否 | 完成回调(成功或失败都会执行) |
updateNotificationState(state, options)
更新通知栏播放状态
参数说明:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| state | Object | 是 | 播放状态对象 |
| state.isPlaying | Boolean | 是 | 是否正在播放 |
| success | Function | 否 | 成功回调 |
| fail | Function | 否 | 失败回调 |
| complete | Function | 否 | 完成回调(成功或失败都会执行) |
onNotificationCallbacks(callback)
设置通知栏按钮回调监听器(持续监听模式)
参数说明:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| callback | Function | 否 | 按钮点击回调函数,参数为包含action的对象 |
回调数据格式:
{
action: "playPause" | "previous" | "next", // 按钮动作
type: "playPause" | "previous" | "next" // 动作类型(兼容字段)
}
stopNotificationCallbacks(options)
停止通知栏按钮回调监听
参数说明:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| success | Function | 否 | 成功回调 |
| fail | Function | 否 | 失败回调 |
| complete | Function | 否 | 完成回调(成功或失败都会执行) |
releaseNotificationController()
释放通知栏控制器资源
参数说明: 无
错误码说明
音频监听器错误码
| 错误码 | 说明 |
|---|---|
| 9030001 | 监听器未启动 |
| 9030002 | 监听器已经在运行 |
| 9030003 | 启动监听器失败 |
| 9030004 | 停止监听器失败 |
| 9030005 | 获取音频状态失败 |
通知栏错误码
| 错误码 | 说明 |
|---|---|
| 9040001 | 获取应用上下文失败 |
| 9040002 | 通知栏控制器初始化异常 |
| 9040003 | 显示通知栏异常 |
| 9040004 | 隐藏通知栏异常 |
| 9040005 | 更新通知栏信息异常 |
| 9040006 | 更新通知栏状态异常 |
| 9040007 | 通知栏控制器未初始化 |
| 9040008 | 设置通知栏回调监听器异常 |
注意事项
- 及时停止监听:在不需要监听时(如页面卸载),务必调用
stopAudioListener停止监听,避免内存泄漏 - 权限要求:插件会自动处理所需权限,无需额外配置
- 重复启动:如果监听器已经在运行,再次调用
startAudioListener会返回错误码 9030002 - Android 特性:Android 端通过广播接收器监听设备变化,响应迅速
- iOS 特性:iOS 端通过 AVAudioSession 监听路由变化,兼容性良好
使用场景
音频设备监听
- 🎵 音乐/视频播放器:检测耳机拔出自动暂停播放
- 📞 通话应用:检测音频输出设备切换
- 🎮 游戏应用:根据设备类型调整音量
- 📱 社交应用:语音/视频通话时的设备管理
通知栏播放控制
- 🎵 音乐播放器App:在通知栏显示播放控制按钮
- 🎬 视频播放器App:后台播放时保持控制界面
- 📻 音频直播App:实时控制播放状态
- 🏃♂️ 运动健身App:边运动边控制音乐播放
开发文档
更新日志
详见 changelog.md
问题反馈
如有问题或建议,请提交 Issue 或 Pull Request。
微信:cnshaoyu(170 33333 111)
License
MIT

收藏人数:
购买普通授权版(
试用
使用 HBuilderX 导入示例项目
赞赏(0)
下载 42
赞赏 0
下载 13365919
赞赏 1845
赞赏
京公网安备:11010802035340号