一场「社死」引发的技术探索:Android 录音抢占逻辑处理
如今,直播应用如此火热,几乎每个人都有机会手握话筒,随时随地登上 “C 位”。
但即便是非常乐于分享自己生活的人,也会对分享边界有要求。
试想一下,当美食主播正在直播大秀厨艺之时,突然接通了来自母亲大人的微信电话,并且此时直播后台并没能自动静音,而是直接把隐私的聊天内容来了个“现场直播”,那将是怎样的一场“社死瞬间”……
其实,在语聊房类场景中也有同样的问题。
语聊房场景中,当出现以上情况时,一般要求产品能够自动静音,而非手动处理。按理说这是一个提高使用体验的合理需求,但在处理方法上,Android 系统面临着比较复杂的情况,使得问题更加棘手一些。
本文属于融云技术分享的“实践探索”系列,作者是融云音视频工具研发中心的 Andriod 研发工程师。围绕以上问题,他展开了一系列调研分析,一点一点向最终的解决方案探索。下文中,他将详细讲述这一过程,希望能够给开发者们带来一些新的启发。
看完全文,欢迎大家踊跃发言,看看有没有更好的解决方案哦 ~
背景
我以前在做语聊房应用时,曾经接到过这样的需求:主播进行直播时,手机通话和微信通话来电接通后,需要自动静音当前主播直播的声音,挂断后再恢复。
这个需求非常合理,能够省去主播自己点击静音/取消静音按钮的步骤,提升使用体验。
使用 Android 提供的手机通话的状态监听广播 ACTION_PHONE_STATE_CHANGED 可以实现上述需求,这个广播提供了接听挂断等来电相关信息的通知,能够非常简单地实现我们所说的需求。
但是,微信通话怎么办?
我当时在如何监听微信应用是否启动这个方向上调研未果,又由于工期紧张,与客户协商后将需求暂时搁置下来。
现在,我在 Android 音视频 SDK 开发工作中,经常遇到客户反馈录音文件没有声音的问题。经过排查,录音设备被占用导致 SDK 启动录音失败,是产生这类问题的主要原因之一。
为解决上述问题,我起初的方案是:SDK 发现录音失败后不断重启录音,直到用户手动结束占用录音的应用,SDK 启动录音成功后才停止重试。
经实验,我发现该方案存在两个严重问题:
1)Android 10 上并不可行,具体原因后文会说明;
2)失败的原因可能并不是录音设备被占用导致,如果是权限问题导致的 SDK 重试,开启录音也于事无补。
所以,能否像手机通话状态监听一样,来监听录音设备的占用情况呢?SDK 启动录音时发现录音设备已占用,随即提示用户结束其它录音应用,当监测到录音设备被释放时,再自动启动录音。
结合我以前做语聊房时未完成的需求,如果 SDK 可以监控到其它录音应用也启动了录音行为,那就可以通知用户做自定义的操作,比如语聊房的自动静音。
调研
带着这样的问题,我查阅了谷歌开发者文档,关键信息如下图所示)。
同时,我也参考了华为开发者文档,关键信息如下。
如此看来,使用 Android 原生提供的几个简单调用,就可以实现监测其它应用录音行为的功能。
微信这样的录音应用在 Android 10 上如果抢占了 SDK 的录音设备,SDK 的录音会自动被系统静音,虽然录音仍然处于 Recording 状态,但 Read 采集的都是真 0 的空数据。
这样一来,主动静音是否就不太必要了呢?事实并非如此。
这是因为:部分手机厂商会修改 Android 系统,使其支持多应用同时录音,以致谷歌官方描述不适用于该类机型,实现需求时也要考虑到这类机型的支持情况。
方案
综合以上调研结果,最终我在使用 AudioRecord 录音时,录音抢占逻辑流程实现如下。
若使用 OpenSL 录音,录音配置变更的回调依然会正常执行,但由于 OpenSL 获取不到当前录音的 SessionID,无法判断配置更改的录音持有者(参考了谷歌 bug 追踪网站),所有有关 OpenSL SessionID 的问题都是 Won’t Fix (Obsolete),所以无法兼容 OpenSL 录音方案。
另外,Android 在 Android 8 后提供了 AAudio NDK 录音库,该库虽然可以绑定 SessionID,但支持版本必须升级到 Android 8,如果要保证 SDK 兼容性强的话,不推荐使用该库。
#实践探索讨论征集贴#
作者的查证过程到这里基本就结束啦。那么关于这个问题,你有没有别的处理方式呢?或者你是否也同作者一样,有一些发现、探索并接近真理的小故事? 欢迎下方留言让我们知道!