Hello! Welcome to my first ever post here (I will post here frequently when i got something interesting to discuss; I promise. But now, it is for the graduation event held by Github and Dev.to. Thanks, folks!).
So here is my final project during my undergrad final year, and i got to be honest... it was bad. And i will explain why.
Besides only as a developer, i am also a musician. And i need to find a way "How to make sure everyone in a small band stay in tempo without any complicated in-ear-monitoring setup?". Hence why this idea came to my mind.
I chose to use Nearby Connections API only because i have used it in my other project. And it also claimed that it is "high-bandwidth, low-latency, and fully encrypted to enable fast, secure data transfers.".
The idea is to create a simple metronome app that can connect to other devices that uses the same app using client-server approach. The server can play/pause/set tempo/configure the metronome, while other devices/clients that is joined to the server can only receives the server's command.
I decided to use MVVM approach to my app. There are only two
Fragments that serves as UI: the metronome page and the client-finding page. And there are only two
Services that will run in the background: the metronome, and the connection manager. Every changes is applied to the UI using Binding Adapters and every function calls (and returns) from the UI to the
Services has to go from the only global
As mentioned, there are two services;
MetronomeService is responsible to do all the metronome stuff, and the
ConnectionManagerService - as the name implies - manages all the connection stuff.
ConnectionManagerService is also the only instance that has all the Nearby Connection API implementations.
The whole idea turns out to be a huge mistake. I cannot even sync the metronome ticks while being played together! It somehow started all synced but gradually turned not synced when played with the exact same tempo. I also implemented naive latency compensation but turns out Nearby's latency was too spread out. Nearby mentioned that they used combination of Bluetooth and Wi-Fi and it turns out to be true. But when the switch from Bluetooth to Wi-Fi happens, the latency just spikes uncontrollably between devices in the same server.
The mistakes turns out to be on both Services. On
MetronomeService, there is a possibility that the low latency audio not consistently played throughout devices. And on
ConnectionManagerService, the lack of granular control in Nearby makes things just... uncontrollable.
I really want this project to be successful and help musicians to do gigs better. It wont be updated in near future but i have made a simple roadmap for this app:
- Complete UI/UX redesign. The current ones looks like a bunch of placeholders.
- Replace current metronome audio implementation with something better. Oboe came out to my mind when i am thinking about this but i didn't have much time to implement that.
- Replace Nearby with Native Wi-Fi API. I do not know if it's possible but i was thinking to make the device that acts as a server also acts as a Wi-Fi Router that only accepts connections from clients that uses the app. I know there will be security obstacles to tackle out of this idea but if you have insights about what to use/what to do, please let me know!
- More metronome features! Right now, it is only a metronome that plays a beep in constant beats per minute. I want to add more features such as subdivisions, more sounds, accentuations, etc.
I really want to thank all stakeholders who helped me in this project. It was really a learning process throughout the project. By the way, here's the repo!
Wesync: Synchronized Metronome application made using Native Android SDK (Kotlin) and Nearby Connections API.
And happy graduation to all of us!