audiorecorder read总是返回0分析

本文探讨了一个在应用中遇到的录音问题,即首次录音成功,但后续录音失败的情况。通过深入分析发现,问题源于录音引擎未被正确释放。文章详细解释了问题现象、可能的原因(涉及C层代码、硬件资源占用),并最终定位到UI逻辑层的错误,即录音引擎在使用完毕后未执行release操作。解决方法在于确保在使用录音引擎后执行正确的资源释放。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

项目用到录音功能  在写时发现这个问题 在应用进行第一次录音是ok,但录完后进行再次录音时录不上

后经追踪发现 是audiorecorder的read抓不到数据 总是返回0

这个问题很奇怪 因为重新创建recoder时可以重新创建,且所有状态均正确,但就是在read时抓不到数据

后经各种蛋疼的调试后 发现ui逻辑层 做用完录音引擎后没有对引擎做release操作 导致上次的recorder的对象没有release

原因是这个原因 但是为什么上次的recorder没有release,这次重新new的理应与上次没关系 没有release也没关系 如果从纯java层来考虑是没有问题的

这样出问题的原因

目前猜测是

是audiorecorder 是调用c层代码实现的 而c则是通过操作硬件实现的 但是硬件只有一个 上次没有release 就会导致硬件被占用

这只是猜测,具体的等以后有时间了,撸下源码会确定,撸完源码 再把具体的原因写下

<think>嗯,用户遇到了MediaRecorder.getMaxAmplitude()总是返回0的问题,需要找出原因和解决方案。首先,我得回忆一下之前看到的引用内容。根据引用[1]和[2],这个方法正常情况下应该返回0到32767之间的值,但有些设备可能表现不同。用户提到返回0的情况,可能涉及权限问题或者设备兼容性。 首先,权限问题。应用需要录音权限,如果用户没有授予,可能无法获取有效的音频数据,导致返回0。这时候应该检查权限是否已经正确申请,并且用户是否允许了。引用[1]里提到,即使没有权限,也可能返回0,所以不能仅靠是否为0来判断权限,但权限确实是前提条件。 其次,设备兼容性。不同厂商的设备可能有不同的实现,导致getMaxAmplitude()的行为不一致。比如有些设备可能在初始化过程中返回0,或者需要更长时间才能开始捕获声音。这时候可能需要延迟获取数据的时间,或者在开始录音后等待一段时间再开始采样。 另外,硬件问题也有可能,比如麦克风被其他应用占用,或者物理损坏。需要确保麦克风正常工作,没有被其他程序占用。比如用户可能在测试时,周围环境过于安静,导致振幅过小,但返回0的话可能还是有问题,可以考虑模拟一些声音输入,比如拍手或说话,来测试是否有变化。 还有代码逻辑的问题。比如是否正确调用了prepare()和start()方法,状态是否正确转换。根据引用[3],MediaRecorder的状态机需要按照Initial -> Initialized -> Prepared -> Recording的顺序进行。如果状态转换不正确,比如没有调用prepare()就直接start(),可能导致方法调用失败,进而返回0。 用户可能在开始录音后立即调用getMaxAmplitude(),这时候音频数据还没准备好,导致返回0。应该在开始录音后等待一段时间,比如100毫秒,再开始采样。引用[2]中提到前1秒取10次数据判断,可能也是类似的思路,多次采样排除初始化的延迟。 另外,可以考虑使用AudioRecord代替MediaRecorder,因为AudioRecord提供更底层的控制,但代码复杂度更高。不过根据引用[3],用户可能已经在考虑这个问题,所以可以作为一个备选方案。 总结下来,可能的解决步骤是:检查权限、确保设备麦克风正常、正确管理MediaRecorder的生命周期、延迟采样时间、多次采样取平均值或最大值,以及处理设备兼容性问题,比如调整除数或者动态计算最大值。如果问题依旧存在,可能需要改用AudioRecord或者检查硬件问题。</think>针对Android开发中$MediaRecorder.getMaxAmplitude()$始终返回0的问题,结合技术资料和开发经验,以下是分步排查与解决方案: --- ### **一、核心原因分析** 1. **权限未正常获取** - 缺少$android.permission.RECORD_AUDIO$权限时,麦克风输入被阻断[^3] - 部分厂商系统会返回0值而非抛出异常[^1] 2. **录音状态异常** - 未正确执行状态转换:$Initial \rightarrow Initialized \rightarrow Prepared \rightarrow Recording$[^3] - 过早调用方法(如未调用$start()$就获取振幅) 3. **硬件/环境问题** - 麦克风被其他应用占用 - 物理麦克风损坏或静音环境 --- ### **二、解决方案步骤** #### **步骤1:权限验证** ```xml <!-- AndroidManifest.xml --> <uses-permission android:name="android.permission.RECORD_AUDIO"/> ``` - 动态权限请求需在录音前完成 - 使用$ContextCompat.checkSelfPermission()$二次验证 #### **步骤2:状态机控制** ```java MediaRecorder recorder = new MediaRecorder(); recorder.setAudioSource(MediaRecorder.AudioSource.MIC); // Initialized状态 recorder.setOutputFormat(...); recorder.setAudioEncoder(...); recorder.setOutputFile(...); recorder.prepare(); // Prepared状态 recorder.start(); // Recording状态 // 延迟100ms后开始采样 new Handler().postDelayed(() -> { int amplitude = recorder.getMaxAmplitude(); }, 100); ``` 需严格按照状态转换顺序操作[^3] #### **步骤3:数据采样优化** ```java // 连续采样10次判断(如引用[2]方案) int validCount = 0; for(int i=0; i<10; i++){ int amp = recorder.getMaxAmplitude(); if(amp > 0) validCount++; Thread.sleep(100); } if(validCount < 3) throw new AudioException(); ``` #### **步骤4:设备兼容处理** - 动态计算最大振幅基准值: ```java int baseAmplitude = 32768; // 默认值 if(Build.MANUFACTURER.equals("Xiaomi")) baseAmplitude = 65536; ``` --- ### **三、替代方案** 若问题仍未解决,可改用$AudioRecord$类: ```java AudioRecord record = new AudioRecord( MediaRecorder.AudioSource.MIC, 44100, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, AudioRecord.getMinBufferSize(...) ); byte[] buffer = new byte[bufferSize]; record.read(buffer, 0, bufferSize); // 直接读取原始音频数据 ``` ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值