RadioCheck is an Android application built with Kotlin and Jetpack Compose, using Firebase Realtime Database for data synchronization and WebRTC for peer-to-peer audio communication between Formula 1 team members.
- Language: Kotlin
- UI: Jetpack Compose
- Architecture: MVVM
- Backend: Firebase Realtime Database
- Real-time Communication: WebRTC (STUN/TURN)
- Build System: Gradle (KTS)
git clone https://github.com/<your-username>/RadioCheck.git
cd RadioCheckYou must provide your own Firebase configuration file:
- Go to Firebase Console.
- Create a new project.
- Add a new Android app.
- Download the
google-services.jsonfile. - Place it inside the project at:
app/google-services.json
⚠️ This file is excluded from version control using.gitignorefor security reasons.
- Go to Build → Realtime Database → Create Database.
- Set your database mode to Test for development purposes.
- Add the following data structure to your Firebase:
{
"Teams": {
"Alpine": {
"callers": {
"Bruno Famin": {
"detail": "Team Principal",
"name": "Bruno Famin",
"userImage": ""
},
"Franco Colapinto": {
"detail": "Driver 1",
"name": "Esteban Ocon",
"userImage": ""
},
"Karel Loos": {
"detail": "Race Engineer",
"name": "Karel Loos",
"userImage": ""
},
"Pierre Gasly": {
"detail": "Driver 2",
"name": "Pierre Gasly",
"userImage": ""
}
},
"color": "#0090FF",
"img1": "https://res.cloudinary.com/dsyz7epcb/image/upload/v1752751220/alpine_wc3u5s.png",
"img2": "https://res.cloudinary.com/dsyz7epcb/image/upload/v1752751219/alpine_f1_team-logo_brandlogos.net_4ny0w_kd4rwb.png",
"name": "Alpine",
"officialName": "BWT Alpine F1 Team"
}
}
}(The full JSON with all teams should be included as needed.)
WebRTC handles the peer-to-peer communication layer of the app. Configuration is managed in Kotlin with a STUN and TURN server setup similar to this:
val iceServers = listOf(
PeerConnection.IceServer.builder("stun:stun.l.google.com:19302").createIceServer(),
PeerConnection.IceServer.builder("turn:YOUR_TURN_SERVER")
.setUsername("USERNAME")
.setPassword("PASSWORD")
.createIceServer()
)During connection events, you can log the state transitions:
peerConnection?.let {
it.onConnectionChange = { newState ->
Log.d("WebRTC", "Connection state changed: $newState")
}
}If you see WebRTCConnection State: FAILED, ensure:
- Both peers have valid internet connectivity.
- You are using a TURN server when connecting devices behind NAT (like mobile hotspots).
Main components:
MainActivity.kt: Entry point and permission handling.TeamListScreen.kt: Displays all available teams from Firebase.CallScreen.kt: Handles WebRTC setup and live audio streams.FirebaseRepository.kt: Reads and updates Realtime Database.WebRTCClient.kt: Manages peer connections, ICE candidates, and media streams.
This project demonstrates:
- Integrating Firebase Realtime Database with Jetpack Compose.
- Building WebRTC connections in Kotlin.
- Handling real-time peer signaling.
- Structuring scalable Compose-based apps with MVVM.
- Never commit
google-services.jsonor API keys to VCS. - Use test mode for development only; configure security rules for production.
- All peer-to-peer audio is handled via WebRTC with end-to-end encryption.
This project is licensed under the MIT License. See LICENSE for details.