我在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();
}
}
答案 0 :(得分:1)
应用程序挂起的原因是Android具有UI线程的概念:简而言之,一个呈现UI,负责用户输入等的线程。 为确保您的应用不会变慢,您需要能够在每16ms窗口中以60fps的速度进行渲染。因此,如果您超载UI线程(例如在大循环/ IO中)-系统将无法渲染UI,请及时响应事件,因此应用程序将冻结。
为避免这种情况,您需要使数据异步。最好的选择是放入服务。 GitHub上有很多示例,这是一个很好的示例: