SoundScope 是一个 Android 端的蓝牙耳机音频使用分析工具。当你的蓝牙耳机(A2DP)连接时,它会自动统计各个音频 App(音乐、视频、播客……)真正在播放的时间,并绘制这段时间内的音量变化曲线,帮你了解:
- 今天/最近 7 天/30 天里,哪些 App 在耳机里占用了你的耳朵,各用了多久
- 某个 App 播放时的音量习惯是怎样的(平均音量比例、随时间的变化)
- 一次耳机连接期间,每个 App 实际播放了多少
为什么是"真实播放"而不是"应用前台时长"? SoundScope 通过
PlaybackState.STATE_PLAYING判断是否在出声——App 挂着媒体通知但已暂停的时间不计入,所以数据反映的是你真正在听的时间。
- 🎧 仅统计蓝牙耳机期间:自动检测 A2DP 耳机连接/断开,连接时才开始记录
- 🎵 精确到播放状态:基于 MediaSession 的 PlaybackState,暂停/缓冲不计时长
- 🔈 音量曲线:播放期间周期采样(每 15 秒)+ 音量变化即时采样,绘制完整曲线
- 📊 可视化:
- 总览页:今日各 App 时长柱状图、实时连接状态、正在播放的 App
- 详情页:音量随时间变化曲线(折线)、累计时长、平均音量比例、按耳机连接聚合的播放记录
- ⏱ 可切换时间区间:今天 / 最近 7 天 / 最近 30 天 / 全部
- 🔄 开机自启 + 断线重连自动恢复
- 🎨 Material3 + 动态取色,Jetpack Compose 原生 UI
| 总览页 | 详情页-音量曲线 |
|---|---|
| 待补充 | 待补充 |
[A2DP 耳机连接] → 开启 BluetoothSession
↓
[某 App 进入 STATE_PLAYING] → 记录该 App 的 AudioSession 开始(出声才计时)
↓
[系统媒体音量变化 / 每 15 秒] → 采样 VolumeSample(音量比例)
↓
[App 暂停或停止播放] → AudioSession 结束
↓
[A2DP 耳机断开] → BluetoothSession 结束
核心组件:
BluetoothHeadsetService:前台服务,监听 A2DP 蓝牙耳机的连接/断开AudioNotificationListener:NotificationListenerService,通过 MediaSession 订阅 PlaybackState,判断"真正在播放"VolumeObserver:播放期间周期采样系统媒体音量SessionRegistry:进程内单例,协调三个服务的实时状态并供 UI 读取
| 领域 | 方案 |
|---|---|
| 语言 | Kotlin 2.0 |
| UI | Jetpack Compose + Material3 |
| 音频追踪 | NotificationListenerService + MediaSession |
| 蓝牙监听 | A2DP profile |
| 存储 | Room |
| 图表 | MPAndroidChart(详情页音量曲线)+ Compose 原生柱状图 |
| 依赖注入 | Hilt |
| 异步 | Coroutines + Flow |
| 构建 | Gradle Kotlin DSL + Version Catalog |
- JDK 17(推荐用 mise 管理,见
.mise.toml) - Android SDK:platform-tools + platforms;android-34 + build-tools;34.0.0
:: 1. 安装 JDK 17(项目已锁定在 .mise.toml)
mise install java@temurin-17
:: 2. 信任配置
mise trustAndroid SDK 需自行安装(指向
ANDROID_HOME)。可用sdkmanager安装所需组件:sdkmanager "platform-tools" "platforms;android-34" "build-tools;34.0.0"
:: 生成 Gradle Wrapper(仅首次需要,需本机有 gradle 或通过 mise 安装)
gradle wrapper --gradle-version 8.9 --distribution-type bin
:: 构建 Debug APK
.\gradlew.bat assembleDebug产物:app\build\outputs\apk\debug\app-debug.apk
"%ANDROID_HOME%\platform-tools\adb.exe" install -r app\build\outputs\apk\debug\app-debug.apk- 安装并打开 SoundScope
- 授权通知监听权限(关键):首次进入会看到红色横幅提示,点击 → 系统设置里开启「音频使用监听」
- 允许「蓝牙连接」「通知」运行时权限
- 连接蓝牙耳机
- 正常用音乐/视频 App 播放——总览页柱状图会实时出现该 App,时长持续增长
- 点击柱状图条目进入详情页,查看该 App 的音量变化曲线和历史记录
- 仅在蓝牙耳机(A2DP)连接期间记录,未连接耳机时不统计(手机外放/有线耳机不计入)
- 时长基于 PlaybackState 的 STATE_PLAYING,暂停的时间不计
- 音量曲线横轴可切换「今天/7天/30天/全部」,长区间会自动降采样保证流畅
- 无法捕获完全没有 MediaSession 通知的 App(极少数播放器)
- LE Audio-only 设备(
DEVICE_TYPE_LE)和非音频蓝牙外设会被过滤 - 通知监听权限必须用户手动授权,App 无法自动开启(系统限制)
欢迎提交 Issue 和 PR!
- Fork 本仓库
- 创建特性分支:
git checkout -b feature/your-feature - 提交更改:
git commit -m 'Add some feature' - 推送:
git push origin feature/your-feature - 提交 Pull Request
请阅读 AGENTS.md 了解项目架构与代码约定(AI 协作者同样适用)。