问题
My code on an app in Android Studio, consisting of a start/stop button for recording audio using AudioRecord and then outputting that audio data to a text view, works great when done once. If I repeatedly click the button, it works too. However, if I put it in a while loop, the app freezes (only the app freezes; same result on an emulator and a real smartphone). I believe I've found that it doesn't have anything to do with AudioRecord, or putting the loop in the button listener or putting it in the method called from the listener, or starting and stopping recording in the called method as opposed to the listener, or even lambda expressions or anything. Without the while loop it works fine; with it, it freezes. But I need to get the audio data continuously. Help is much appreciated. My abbreviated code:
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:
The reason the application hangs is that Android has this concept of UI Thread: In short a thread that renders UI, responsible for user input, etc To make sure that your app doesn't feel slow you need to be able to render in every 16ms windows for 60fps. Thus, if you overload UI thread (like in a big loop / IO) - the system won't be able to render UI, respond to the events in time, so the app will freeze.
To avoid that you need to get data async. The best option will be to put into a Service. There are many example on the GitHub, here is a good one:
https://github.com/dkim0419/SoundRecorder
RecordingService example
来源:https://stackoverflow.com/questions/54264125/android-studio-while-loop-freezing-application