音频应用的MediaSession冲突
前提条件
-
系统级应用,使用了sharedUserId
- 应用在AndroidManifest.xml中声明了系统级UID:
android:sharedUserId="android.uid.system"
- 该配置使应用具有系统级权限,可以访问系统级API和资源
- 应用在AndroidManifest.xml中声明了系统级UID:
-
使用MediaSession框架
- 应用通过MediaSession框架实现音频播放控制
- 使用MediaSessionCompat类创建会话
- 实现了播放、暂停、下一首等标准媒体控制功能
问题描述
在测试过程中发现一个严重问题:
- 当应用通过MediaSession控制音频输出时, 实际获取到的音源与预期不符,系统返回了另一个应用的音源, 导致音频控制功能完全失效。
尝试定位问题
-
初步排查
- 检查MediaSession的初始化代码
- 验证MediaSession的UID是否正确
- 确认MediaController的连接状态
-
深入分析
- 组长进行源码分析, 重点排查了MediaSessionService相关代码
-
问题定位
- 经过近一周的排查,发现问题根源:
- 我们的应用和讯飞的语音应用都使用了相同的sharedUserId
- Android系统中,MediaSession是通过UID进行分组的
- 当多个应用使用相同的sharedUserId时,会导致MediaSession分组冲突
- 系统无法正确区分不同应用的MediaSession
- 经过近一周的排查,发现问题根源:
解决问题
-
解决方案
- 组长通过修改系统源码实现以下改进:
- 在MediaSession分组逻辑中忽略UID冲突时的容错逻辑
- 修改MediaSessionService的会话管理逻辑
- 确保即使使用相同的sharedUserId,不会错误的分配MediaSession
- 组长通过修改系统源码实现以下改进:
-
验证结果
- 重新编译系统镜像
- 部署到测试设备
- 验证音频控制功能恢复正常
- 确认不再出现音源混淆问题
总结
-
技术要点
- Android系统中,MediaSession默认按照UID进行分组
- 使用sharedUserId的应用需要特别注意MediaSession的隔离问题
- 系统级应用在实现音频控制时需要额外考虑兼容性问题
-
最佳实践
- 尽量避免在多个应用中使用相同的sharedUserId
- 如果必须使用sharedUserId,需要确保MediaSession的唯一性
- 可以通过修改系统源码或使用自定义标识来解决冲突问题
-
经验教训
- 系统级应用的开发需要深入理解Android框架机制
- 音频相关的功能实现需要全面考虑系统层面的影响
- 遇到复杂问题时,源码分析是最有效的解决手段之一
-
后续改进
- 在应用设计阶段就考虑MediaSession的隔离问题
- 建立更完善的测试用例,覆盖多应用场景
- 将解决方案文档化,供后续开发参考