Android Studio:While循环冻结应用程序

时间:2019-01-19 04:40:30

标签: java android android-studio audiorecord

我在Android Studio中的一个应用程序上的代码由一个开始/停止按钮组成,该按钮用于使用AudioRecord录制音频,然后将该音频数据输出到文本视图,一次完成效果很好。如果我反复单击该按钮,它也可以工作。但是,如果我将其置于while循环中,则该应用程序将冻结(仅该应用程序将冻结;在仿真器和真正的智能手机上结果相同)。我相信我发现它与AudioRecord没有任何关系,也没有将循环放入按钮侦听器中,或者将其放入从侦听器调用的方法中,或者与被调用的方法相反,开始和停止了录音。侦听器,甚至lambda表达式或其他任何内容。没有while循环,它会正常工作;它冻结了。但是我需要连续获取音频数据。非常感谢您的帮助。我的缩写代码:

public class MainActivity extends AppCompatActivity {

    public static final int SAMPLE_RATE = 16000;

    private AudioRecord recorder;
    private Button btn;
    private TextView txtView;
    private boolean isRecording = false;
    private short[] buffer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btn = (Button) findViewById(R.id.btn);
        txtView = (TextView) findViewById(R.id.TextView);

        initializeRecorder();

        btn.setOnClickListener(e -> {
            if (!isRecording) {
                btn.setText("Stop");
                isRecording = true;
                recorder.startRecording();
                record();
            }
            else {
                btn.setText("Start");
                isRecording = false;
                recorder.stop();
            }
        });
    }

    private void initializeRecorder() {
        int bufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE, 
                AudioFormat.CHANNEL_IN_MONO,
                AudioFormat.ENCODING_PCM_16BIT);
        buffer = new short[bufferSize];
        recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 
                SAMPLE_RATE,
                AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, 
                bufferSize);
    }

    private void record() {
        int readSize;

        while (isRecording) { // This is the loop causing trouble

            readSize = recorder.read(buffer, 0, buffer.length);
            // Perform calculations on this data and output to txtView, 
            // like:

            txtView.setText(Integer.toString(readSize));

            // BTW, I know I'm not saving this audio to a file; that's on 
            // purpose. I just need this data.
        }
    }

    @Override
    public void onDestroy() {
        recorder.release();
        super.onDestroy();
    }
}

1 个答案:

答案 0 :(得分:1)

应用程序挂起的原因是Android具有UI线程的概念:简而言之,一个呈现UI,负责用户输入等的线程。 为确保您的应用不会变慢,您需要能够在每16ms窗口中以60fps的速度进行渲染。因此,如果您超载UI线程(例如在大循环/ IO中)-系统将无法渲染UI,请及时响应事件,因此应用程序将冻结。

为避免这种情况,您需要使数据异步。最好的选择是放入服务。 GitHub上有很多示例,这是一个很好的示例:

https://github.com/dkim0419/SoundRecorder

RecordingService example