I am building a metronome in android with sound and a visual blink and of course both things need to be in sync. The problem is that the audio processing happens inside a background thread and as we all very well know "only the thread that created the thread hierarchy can change it's views" therefore I needed a way to get the UI thread to change the veiew. So how can I update the ui thread in sync with the beat I am producing? Both things don't seem synchronized. Is there a better way to achieve this than the method I depict below?
This is the current code I have:
public class MetronomeService extends Service implements Runnable
{
//Thread
private HandlerThread handlerThread;
private Handler backgroundHandler;
private Handler uiHandler
//Interface to the Fragment that owns the views
@Setter
private Listener listener;
//Colour view
private ColourViewManager colour = null;
@Override
public void onCreate()
{
handlerThread = new HandlerThread("PlayerHandlerThread", Process.THREAD_PRIORITY_AUDIO);
handlerThread.start();
//For packages of work in the background
this.backgroundHandler = new Handler(handlerThread.getLooper());
//To send messages to the UI
this.uiHandler = new Handler(Looper.getMainLooper())
{
@Override
public void handleMessage(@NonNull Message msg)
{
switch (msg.what)
{
case 0:
{
listener.resetState();
break;
}
case 1:
{
colour = listener.blink();
break;
}
}
}
};
super.onCreate();
}
@Override
public void run()
{
uiHandler.sendEmptyMessage(0);
audioGenerator.playTrack(bpm);
while (playingState.get() == TimerState.PLAYING)
{
uiHandler.sendEmptyMessage(1);
if (colour == PulsingColourToggleButton.PulsingColour.YELLOW)
{
audioGenerator.writeSound(AudioGenerator.TICKING);
} else if (colour == PulsingColourToggleButton.PulsingColour.RED)
{
audioGenerator.writeSound(AudioGenerator.TOCKING);
}
audioGenerator.writeSound(AudioGenerator.SILENCE);
}
audioGenerator.destroy();
colour = null;
}
public void start()
{
backgroundHandler.post(this);
}
}
Then on the Fragment class I call the service with a simple
service.start()
I don't know what you are doing exactly but to change the view from service you need to use LocalBroadcast so check this
In your service create the LocalBradcastManager
And in your view
This is an example of the logic you have to do