【Android适配问题集锦-音频类】当Android手机插入耳机后仍为外放的尴尬

  • 1、Android耳机插拔检测原理
  • 2、Android耳机插拔检测具体实现
  • 3、真机上的适配问题

澳大利亚悉尼市新南威尔士大学的一名男生在课堂上看色情片,不料耳机没有插好,变成了现场直播。
这里写图片描述
如果在手机上看电影时,当你插上耳机,音乐却从扬声器里响了起来,这未免会更加尴尬了。

1、Android耳机插拔检测原理
Android系统在耳机插入和拔出的时候会发送广播,通过
Broadcast Receiver 监听“android.intent.action.HEADSET_PLUG” 这个Intent来判断耳机是否插拔。

Intent值 说明
state 0代表拔出,1代表插入
name 字符串,代表headset的类型
microphone 1代表这个headset有麦克风,0则没有

2、Android耳机插拔检测具体实现
在Android4.0以上的版本,耳机插拔检测的源文件位于frameworks/base/services/java/com/android/server/WiredAccessoryObserver.java;(4.1及以上是WiredAccessoryManager.java;在android4.0以前是HeadsetObserver.java)顾名思义,它主要是用来检测有线的设备连接状态。

  • Android耳机插拔检测流程图

这里写图片描述
我们重点来看一下WiredAccessoryObserver。
WiredAccessoryObserver继承自UEventObserver(Android耳机插拔可以有两个机制实现:InputEvent和UEvent),从该文件的路径可以得知,这个类位于service目录,应该是在android系统服务初始化的时候实例化的,在这个类的构造方法中,注册了一个广播接收器用来接收系统启动完毕的广播。
这里写图片描述

  • WiredAccessoryObserver工作流程图

这里写图片描述
在收到这个广播之后:先执行init()函数,在这个函数中判断要检测的设备是否已经处于连接状态(比如开机之前就已经插上),如果已经连接上就调用updateState立即向系统上报。然后调用startObserving函数监测文件节点路径是否有状态变化,这个函数位于他的父类UEventObserver.java中。在之前建立好的监测中,如果kernel层有uevent事件发送上来则会去匹配这个路径字符串,如果匹配成功会调用在WiredAccessoryObserver重载的onUEvent函数,从event string中解析出devPath, name和state的值,然后继续调用updateState进行处理,在updateState中会对设备的类型进行进一步的分析之后调用update上报,在update中,会往handler中发送一个消息,将耳机的状态报告给Audio系统。之后由AudioService在sendDeviceConnectionIntent函数中向系统广播耳机已经插入的ACTION_HEADSET_PLUG广播,同时会通知AudioPolicy做audio通路切换的工作。

3、真机上的适配问题
(1)在HuaWei T8833上播放音乐,在插入耳机之后耳机和扬声器都会有声音;
updateState中需要进行update操作。
这里写图片描述
通过反编译HuaWei T8833 Framework层WiredAccessoryObserver,我们发现了问题的原因;
这里写图片描述
HDMI状态改变时未进行update操作,也就是没有向系统进行设备连接状态的通知,导致了在插入耳机之后耳机和扬声器都会有声音。

(2)在小米 2S上如果想实现PTT语音消息的功能,播放语音时你可能这样做:
这里写图片描述
使用Audio进行扬声器播放的时候,当插入耳机时声音并未按预期的由耳机输出,而依旧使用的扬声器进行播放。如果您也是这样做的,那么我们建议您在这台机型上将MODE_IN_CALL与STREAM_MUSIC配对或者将SpeakerphoneOn设置为false,从而让程序具有兼容性。

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页