Android 录音在1-2小时后停止录制

Android 录音在1-2小时后停止录制,android,audiorecord,android-audiorecord,Android,Audiorecord,Android Audiorecord,我收到W/AudioRecord(17145):录制1-2小时后,获取缓冲区超时(CPU是否已锁定?)用户=11b7f820,服务器=11b7f820。显然,由于AudioRecord的read()读取了0字节,因此录制停止。我为此挣扎了两个多星期,还没有找到解决办法。下面是初始化audioRecord对象的方法: private void initPCMRecorder() throws Exception { Log.d(getClass().getName(), "Init

我收到
W/AudioRecord(17145):录制1-2小时后,获取缓冲区超时(CPU是否已锁定?)用户=11b7f820,服务器=11b7f820
。显然,由于AudioRecord的read()读取了0字节,因此录制停止。我为此挣扎了两个多星期,还没有找到解决办法。下面是初始化audioRecord对象的方法:

private void initPCMRecorder() throws Exception {
        Log.d(getClass().getName(), "Initializing AudioRecord...");
        int channelConfig = nChannels == 1 ? AudioFormat.CHANNEL_IN_MONO: AudioFormat.CHANNEL_IN_STEREO;  
        bufferSize = AudioRecord.getMinBufferSize(sRate, channelConfig, aFormat);
        if (bufferSize == AudioRecord.ERROR_BAD_VALUE)
            Log.e(getClass().getName(), "Bad encoding value, see logcat");                  
        else if (bufferSize == AudioRecord.ERROR)
            Log.e(getClass().getName(), "Error creating buffer size");

        bufferSize *= 3;
        buffer = new byte[bufferSize];

        //check if is not yet released
        if(aRecorder != null){
            try {
                aRecorder.release();    
            } catch (Exception e) {
                Log.e(getClass().getName(), e.getMessage(), e);
            }           
        }

        System.out.println("Source="+aSource+"; sampRate="+sRate+"; format="+aFormat+"; bufSize="+bufferSize);
        aRecorder = new AudioRecord(aSource, sRate, channelConfig, aFormat, bufferSize);
        if (aRecorder.getState() != AudioRecord.STATE_INITIALIZED) {
            throw new Exception("" + ErrorCodes.ERROR_CODE_0);
        }
        Log.d(getClass().getName(), "AudioRecord Initialized");
        state = State.INITIALIZING;
    }
我读了第二篇文章。请注意,我尝试使用positionNotificationListener,但结果相同

public void run() {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);

    while (!stopped) {
        while (!suspend) {
            int result = aRecorder.read(buffer, 0, buffer.length);
            if(result == AudioRecord.ERROR_INVALID_OPERATION){
                Log.e(getClass().getName(), "aRecorder.read() returns ERROR_INVALID_OPERATION !!!");
                continue;
            }else if(result == AudioRecord.ERROR_BAD_VALUE){
                Log.e(getClass().getName(), "aRecorder.read() returns ERROR_BAD_VALUE !!!");
                continue;
            }else if(result == 0){
                Log.w(getClass().getName(), "SKIP audio block.");
                continue;
            }

            payloadSize += buffer.length;

            //data processing/writing is done in another thread 
            WAVData audioData = new WAVData(buffer);
            audioData.setGain(rGain);
            audioData.setBitsPerSamples(bitsPerSample);
            audioData.setNrChannels(nChannels);
            if(writersArray.size()>=1)
                writersArray.get(writersArray.size() - 1).add(audioData);
        }
        // lock here
        synchronized (lock) {
            try {
                lock.wait();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return;
            }
        }
    }
}
编辑(从控制台添加错误-
com.audioRec.android.recorder
是我的应用程序):

08-02 12:30:38.162:D/dalvikvm(1451):GC_并发释放7867K,36%释放18889K/29447K,暂停17ms+8ms,总计151ms
8-02 12:30:38.953:D/dalvikvm(1451):释放36K的所有物质的GC_,36%释放18892K/29447K,暂停46ms,总计47ms

8-02 12:30:39.063:D/dalvikvm(1451):GC_-CONCURRENT-freed已知音频API在某些特定设备上被破坏

我的建议是:

a。默认情况下执行正常行为(只需保持录制,直到需要正常停止)。 我假设这个问题只出现在特定的模型上,所以默认行为将在大多数用户的设备上工作

b。通过
Build.MODEL
识别设备类型,并创建需要解决方法的设备模型字符串数组。例如,将您自己的设备型号添加到列表中,并从用户报告(如果您有)扩展它

c。在您的逻辑中,检查您是否在需要解决方法的设备上运行—如果是,请执行您的启发式方法来识别问题—从AudioRecord中顺序读取0字节—然后重新启动它


我发现最好在依赖于设备模型查询的特殊条件下隔离类似的变通方法,以防止“正常”代码变脏。

这在两个不同的设备中是一致的吗?因为如果这是一个制造商的差异,那么这可能是一个更大问题的迹象。我在我的Xperia Z上注意到了。我今天将尝试使用Galaxy mini来查看结果。我怀疑my Z的耐力模式是“有罪的”,因为当使用商店的另一个录音应用程序时,我收到一个通知:“Recordin应用程序正在阻止耐力模式以节省电池…”该应用程序能够使手机保持虚弱,但我的应用程序不能。今天我将用另一部手机测试,让你知道Galaxy mini的工作正常。测试了2:30小时,录音没有停止。谢谢你的回答。我已经在做了:如果两次连续读取返回0,重新启动录音,强制屏幕打开(变暗)(如果用户没有从设置中取消选中该属性),然后继续录音。但正如你所建议的,我的代码变脏了,因此你的方法更加优雅,2有2种读取/处理录音的方法。问题是,我必须等到用户抱怨录音被停止一段时间后,再将他们的手机添加到列表中。如果有太多设备出现相同问题,你也可以作为默认行为来解决(假设它不会破坏正常设备上的应用程序)。
08-02 12:30:38.162: D/dalvikvm(1451): GC_CONCURRENT freed 7867K, 36% free 18889K/29447K, paused 17ms+8ms, total 151ms
08-02 12:30:38.953: D/dalvikvm(1451): GC_FOR_ALLOC freed 36K, 36% free 18892K/29447K, paused 46ms, total 47ms
08-02 12:30:39.063: D/dalvikvm(1451): GC_CONCURRENT freed <1K, 29% free 21196K/29447K, paused 18ms+6ms, total 108ms
08-02 12:30:59.004: W/AudioRecord(703): obtainBuffer timed out (is the CPU pegged?) user=00f49160, server=00f49160
08-02 12:30:59.515: W/AudioRecord(703): obtainBuffer timed out (is the CPU pegged?) user=00f49160, server=00f49160
08-02 12:31:00.035: W/AudioRecord(703): obtainBuffer timed out (is the CPU pegged?) user=00f49160, server=00f49160
08-02 12:31:00.526: W/com.audioRec.android.recorder.AudioRecorder$RecorderThread(703): SKIP audio block.
08-02 12:31:00.766: W/AudioRecord(703): obtainBuffer timed out (is the CPU pegged?) user=00f49160, server=00f49160
08-02 12:31:01.297: W/AudioRecord(703): obtainBuffer timed out (is the CPU pegged?) user=00f49160, server=00f49160
08-02 12:31:01.797: W/AudioRecord(703): obtainBuffer timed out (is the CPU pegged?) user=00f49160, server=00f49160
08-02 12:31:02.308: W/AudioRecord(703): obtainBuffer timed out (is the CPU pegged?) user=00f49160, server=00f49160
08-02 12:31:02.558: W/com.audioRec.android.recorder.AudioRecorder$RecorderThread(703): SKIP audio block.
08-02 12:31:02.558: D/com.audioRec.android.recorder.AudioRecorder$RecorderThread(703): MUST RESET AUDIORECORD....obtainBuffer timed out ?
08-02 12:31:02.568: D/com.audioRec.android.recorder.AudioRecorder$AudioRecordCalibrator(703): Calibrating AudioRecord object...
08-02 12:31:08.494: E/alsa_pcm(257): Arec: error5
08-02 12:31:08.494: W/AudioStreamInALSA(257): pcm_read() returned error n -5, Recovering from error
08-02 12:31:08.615: E/ALSADevice(257): standby handle h 0x4234f358
08-02 12:31:08.645: D/alsa_ucm(257): snd_use_case_set(): uc_mgr 0x42e24fb8 identifier _dismod value Capture Music
08-02 12:31:08.645: D/alsa_ucm(257): Set mixer controls for Capture Music enable 0
08-02 12:31:08.655: D/alsa_ucm(257): Setting mixer control: MultiMedia1 Mixer SLIM_0_TX, value: 0
08-02 12:31:08.655: E/ALSADevice(257): Number of modifiers 0
08-02 12:31:08.655: E/ALSADevice(257): usecase_type is 0