简介: CSDN博客专家、《Android系统多媒体进阶实战》作者
博主新书推荐:《Android系统多媒体进阶实战》🚀
Android Audio工程师专栏地址:Audio工程师进阶系列【原创干货持续更新中...... 】🚀
Android多媒体专栏地址:多媒体系统工程师系列【原创干货持续更新中...... 】🚀
专题一 二:AAOS车载系统+AOSP14系统攻城狮入门视频实战课 🚀
专题三:Android14 Binder之HIDL与AIDL通信实战课 🚀
专题四:Android15快速自定义与集成音效实战课 🚀
专题五:Android15音频策略实战课 🚀
专题六:Android15音频性能实战课(无声/杂音/断音/爆音实战案例) 🚀
人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.
更多原创,欢迎关注:Android系统攻城狮

🍉🍉🍉文章目录🍉🍉🍉
-
-
- [🌻1. 前言](#🌻1. 前言)
- [🌻2. 用法与应用场景](#🌻2. 用法与应用场景)
- [🌻3. 调用流程剖析](#🌻3. 调用流程剖析)
-
- [3.1 核心步骤](#3.1 核心步骤)
- [3.2 涉及核心时序图](#3.2 涉及核心时序图)
- [🌻4. 实战应用案例](#🌻4. 实战应用案例)
- [🌻5. 用法总结](#🌻5. 用法总结)
-
🌻1. 前言
本篇目的:Android16音频深度解析之MediaPlayer.getAudioSessionId调用流程与实战。
要点概括:
- 核心功能 :
getAudioSessionId用于获取当前播放器分配的唯一音频会话 ID。 - 作用范围 :该 ID 是连接
MediaPlayer与音效组件(如Equalizer,Visualizer)的关键纽带。 - 调用时机:实例创建后即可获取,但通常在设置音效前调用。
- 系统机制 :ID 由底层
AudioFlinger分配,确保音频流在混音器(Mixer)中具备独立的可控身份。
🌻2. 用法与应用场景
MediaPlayer.getAudioSessionId 返回一个大于 0 的整数 ID。如果返回 0,通常表示获取失败或播放器未正确初始化。
- 用法说明 :在
MediaPlayer对象成功实例化后,调用此方法获取会话标识,并将其传递给音效类的构造函数。 - 应用场景:
- 均衡器(Equalizer):根据会话 ID 对特定音乐播放请求应用高低音调节。
- 可视化频谱(Visualizer):绑定会话 ID 获取当前播放音频的波形或频率数据,实现动态频谱图。
- 重低音/环绕音(BassBoost/Virtualizer):针对当前音频流开启特定的硬件加速音效。
- 音量均衡(LoudnessEnhancer):在不改变系统全局音量的情况下,提升特定媒体流的响度。
🌻3. 调用流程剖析
3.1 核心步骤
- Java 层触发 :应用调用
getAudioSessionId(),Java 层MediaPlayer对象通过 JNI 接口访问本地(Native)代码。 - Native 代理 :
MediaPlayer.cpp接收指令,通过 Binder 接口向远端的MediaPlayerService发起查询。 - Client 端映射 :在
MediaPlayerService中,每个播放器实例都对应一个Client。如果创建时未指定 ID,服务层会请求AudioFlinger生成一个新的全局唯一 ID。 - AudioFlinger 分配 :
AudioFlinger作为 Android 音频系统的核心,管理所有音频轨道(Tracks)。它会分配一个audio_session_t类型的标识符,并将其记录在AudioTrack实例中。 - 链路回传:该 ID 沿着 Binder -> JNI -> Java 的路径返回,最终由应用层持有用于后续音效绑定。
3.2 涉及核心时序图
AudioFlinger (Native) MediaPlayerService MediaPlayer Native MediaPlayer Java 应用代码层 AudioFlinger (Native) MediaPlayerService MediaPlayer Native MediaPlayer Java 应用代码层 若 ID 为空,则请求 AF 分配 调用 getAudioSessionId() 调用 native_getAudioSessionId 通过 Binder 获取 SessionId createAudioTrack (请求分配 Session) 返回分配的 audio_session_t 返回 SessionId 返回 int 值 获取成功 (e.g. 65)
🌻4. 实战应用案例
本案例展示了如何获取 AudioSessionId 并利用它初始化 Equalizer(均衡器)来实现音频处理。
java
public class AudioEffectManager {
private MediaPlayer mediaPlayer;
private Equalizer equalizer;
public void initPlayerWithEffect(Context context, Uri uri) {
mediaPlayer = new MediaPlayer();
try {
mediaPlayer.setDataSource(context, uri);
// 1. 获取当前播放器的音频会话 ID
int sessionId = mediaPlayer.getAudioSessionId();
System.out.println("当前音频会话 ID: " + sessionId);
// 2. 将会话 ID 绑定到音效组件
if (sessionId != AudioSystem.AUDIO_SESSION_ALLOCATE) {
initEqualizer(sessionId);
}
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(MediaPlayer::start);
} catch (Exception e) {
e.printStackTrace();
}
}
private void initEqualizer(int sessionId) {
// 优先级 0 意味着我们请求默认的控制权限
equalizer = new Equalizer(0, sessionId);
equalizer.setEnabled(true);
// 设置一个预设音效(如:流行乐 Pop)
short presets = equalizer.getNumberOfPresets();
if (presets > 0) {
equalizer.usePreset((short) 0);
System.out.println("已启用均衡器预设: " + equalizer.getPresetName((short) 0));
}
}
public void release() {
if (equalizer != null) {
equalizer.release();
}
if (mediaPlayer != null) {
mediaPlayer.release();
}
}
}
落地步骤总结:
- 实例化 :先创建
MediaPlayer实例,确保底层播放链路初步建立。 - 获取 ID :调用
getAudioSessionId()。注意,即使在prepare之前,此 ID 也是可用的。 - 绑定音效 :将获取的 ID 传入
Equalizer或Visualizer的构造函数中。 - 激活 :调用音效组件的
setEnabled(true)激活处理逻辑。 - 释放 :在销毁播放器时,务必先释放音效组件,再释放
MediaPlayer,防止内存泄漏。
🌻5. 用法总结
| 调用层级 | 核心职责 | 关键报错/结果 |
|---|---|---|
| 应用框架层 | 提供 Java API 入口,保存 ID 缓存 | 频繁调用无额外性能损耗 |
| 系统服务层 | 维护 Client 与 Session 的映射关系 | 确保跨进程 ID 的唯一性 |
| 音频引擎层 | AudioFlinger 负责 ID 的物理分配 |
决定了混音器(Mixer)的路由逻辑 |
| 音效框架层 | 利用 ID 拦截对应 Session 的数据流 | 若 ID 错误将无法应用任何效果 |
| 硬件驱动层 | 提供硬件级别的音效后处理(可选) | 依据 ID 在 DSP 中开启加速 |