Handler stuck UI when cycling through runnable tasks [android]
I’m going to repeat – – – … Wait a minute.
When its energy reaches a certain threshold and is played, the recording (for a few seconds) stops. After playback, start a new recording. So I have to use the buffer to monitor the energy and start a new recording after the playback time is calculated. My pseudocode (in its simplest form) looks like this:
…
public class MainActivity extends Activity {
private Handler myHandler = new Handler();
....
private Runnable timedTask = new Runnable() {
public void run() {
audiorecorder = new AudioRecord(... initializes
audiorecorder.startRecording();
isRecording = true;
ElapsedTime = 0.0;
while(true) {
ReadByte = audiorecorder.read(buffer, 0, buffersize);
Write ReadByte onto file (temp.pcm)
EnergyBuffer = <some averaged energy over a period (1 sec or so)>
if(EnergyBuffer > Threshold)
break;
ElapsedTime = ...
}
audiorecorder.release, stop, and null
play temp.pcm using AudioTrack
myHandler.postDelayed(timedTask, Elapsedtime);
};
}
This is triggered by the start and stop buttons, as shown below
StartButton.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
myHandler.post(timedTask);
}
});
StopButton.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
myHandler.removeCallbacks(timedTask);
}
});
The problem is that when recording or playing audio, no button works, I have to wait until it finishes recording. How do I prevent stuck recording? Is it just because of the whileloop? Please help..!
If I run it as follows, no error is reported.
Thread t = new Thread(timedTask);
t.start();
This is just ok once, but then it also gets stuck in the UI when the handler is delayed.
Solution
The handler posts the runnable task to a looper in a thread. It does not create a new thread on its own to run the runnable asynchronously.
When you create a handler by calling the constructor new Handler(),
the handler gets the looper for the current thread that calls the constructor by default. Because you called new Handler()
on the UI thread, any runnable objects provided for the handler’s post command are added to the UI thread.
You need to create a new thread and get its looper by doing the following
HandlerThread readThread = new HandlerThread("");
readThread.start();
myHandler = new Handler(readThread.getLooper());
A handlerThread is a thread that automatically sets up a looper for you to use.
Of course, you also need to quit the thread when you don’t need it
readThread.quit();