GuessTheSongYear ๐ŸŽต

A music quiz party game for Android โ€” watch a music video, guess its release year, compete with friends on the same device or over LAN.

No accounts. No ads. No tracking. Just music and guessing.

๐Ÿ›ก๏ธ Development environment security verified: 2026-07-28 โ€” build machine hardened (UFW, fail2ban, tirith, key-only auth pending final step)


๐ŸŽฎ How the Game Works

  1. Pick a difficulty โ€” Easy (1980โ€“2010, with hints), Medium (1970โ€“2024), or Hard (1960โ€“2025). Harder = more points.
  2. Watch the video โ€” A YouTube music video plays and you listen (and watch, unless you toggle listen-only mode).
  3. Guess the year โ€” Type a year or scroll through the year picker. The closer you are, the more points you get.
  4. See the results โ€” After everyone guesses, the host reveals the answer with a leaderboard.

Exact guess: 50 pts + streak bonus ยท Off by 1: 30 pts ยท Off by โ‰ค3: 20 pts ยท Off by โ‰ค5: 10 pts ยท Off by โ‰ค10: 5 pts ยท Way off: 0 pts, but the right answer stares you in the face.


๐Ÿ‘ฅ Multiplayer

Play solo or host a LAN party โ€” everyone on the same WiFi can join:

ModeHow it works
HostPress "Vert" (Host). The app shows your IP + a QR code. Friends scan or type it in.
JoinPress "Bli med" (Join). It scans your network automatically for active hosts โ€” no manual typing needed.
QR scanPress the QR button to scan the host's code directly with your camera.

Discovery is automatic. As soon as someone opens the Join tab, the app probes 192.168.x.2โ€“254 looking for hosts with a HELLO/ACK handshake. Usually it finds the host before you notice.

Connection Types

  • WiFi (TCP on port 8888) โ€” the default, requires same LAN
  • TLS (TCP on port 8889) โ€” encrypted channel with SPKI certificate pinning, activated when the joiner scans the host's QR code
  • Bluetooth RFCOMM โ€” close-range fallback, no WiFi needed

Messages exchanged between host and joiners are HMAC-SHA256 signed using a per-session random key distributed at join time. Older unsigned clients are still accepted (backward-compatible).


๐Ÿ“ฑ Features

  • ๐ŸŽต YouTube video via official Iframe Player API โ€” zero ToS violations, no API keys, no user login
  • ๐ŸŽต ~40 music videos spanning decades โ€” from 80s classics to modern hits
  • ๐ŸŽฏ Three difficulty levels with different year ranges and score multipliers
  • ๐Ÿ“Š Streak system โ€” correct guesses build a streak for bonus points, wrong guesses reset it
  • ๐Ÿ•น๏ธ Classic and Arcade local multiplayer โ€” either everyone guesses together or players rotate one turn at a time
  • ๐Ÿ‘ฅ Remembered party setup โ€” two to eight named players persist between games
  • ๐ŸŽš๏ธ Configurable song distribution โ€” choose pure random, modern-prioritized, or custom decade weights
  • ๐Ÿ“ˆ Persistent player statistics โ€” review guesses, exact answers, and points from the toolbar
  • ๐Ÿ“ Responsive game surfaces โ€” 16:9 playback and adaptive spacing scale from phones to tablets
  • ๐Ÿ”Š Listen-only mode โ€” the video overlay with the video opens and manages YouTube externally
  • ๐ŸŒ“ Dark theme with amber accent, Material3 design
  • ๐Ÿ”ค Norwegian โ†โ†’ English UI โ€” switch language from the toolbar
  • ๐Ÿšซ Duplicate prevention โ€” songs you've already seen are avoided
  • โญ๏ธ Auto-skip โ€” embed-disabled videos skip silently to the next one
  • ๐Ÿ“ฑ Min SDK 24 (Android 7.0) through target SDK 37 (Android 15)

๐Ÿ—๏ธ Architecture

GuessTheSongYear
โ”œโ”€โ”€ MainActivity.kt                Entry point, toolbar, difficulty & language switching
โ”œโ”€โ”€ VideoPlayerFragment.kt         Core game: WebView YouTube Iframe API, guess engine, scoring
โ”œโ”€โ”€ ScoreManager.kt                Points calculation, streaks, accuracy
โ”œโ”€โ”€ Difficulty.kt                  Easy/Medium/Hard config (year ranges + multipliers)
โ”œโ”€โ”€ GameSessionManager.kt          Session state for multiplayer
โ”œโ”€โ”€ HostGameFragment.kt            Host UI: IP/QGSR display, player list
โ”œโ”€โ”€ JoinGameFragment.kt            Join UI: LAN scan results, QR scanning, manual IP entry
โ”œโ”€โ”€ Protocol.kt                    TCP message JSON protocol (10 message types)
โ”œโ”€โ”€ HostGameService.kt             TCP server on port 8888 + TLS on 8889, HMAC signing
โ”œโ”€โ”€ JoinGameService.kt             TCP client, LAN scanner, SPKI pinning, HMAC verify
โ”œโ”€โ”€ SecureChannelManager.kt        TLS infrastructure: ephemeral RSA keys, self-signed certs
โ””โ”€โ”€ ... (layouts, resources, tests)

Security Features

LayerApproach
TransportOptional TLS (TLSv1.3) with ephemeral RSA 2048 keys + self-signed X.509 cert per session
Certificate pinningSPKI hash shown on host screen โ€” clients verify it during TLS join
Message signingHMAC-SHA256 on every message body, key shared in JOIN_ACK
FallbackPlain TCP still available for backwards compatibility; unsigned messages still accepted from old clients
CIcontents: write permission scoped to release job only, not workflow level

๐Ÿงฑ Tech Stack

LayerTechnology
LanguageKotlin
BuildGradle + Android Gradle Plugain 9.3.0 + Kotlin 2.4.10
UIAndroid ViewBinding + Material3
Video playerYouTube Iframe Player API (WebView embeddings)
YouTube API librarycom.pierfrancescosoffritti.androidyoutubeplayer:core 12.1.2
QR codeZXing Core 3.5.3 + ZXing Embedded 4.3.0
Crypto (TLS)BouncyCastle bcpkix-jdk18on 1.84 + standard javax.net.ssl
Crypto (signing)HMAC-SHA256 via javax.crypto.Mac
CI/CDGitHub Actions (build + test + release on push to master)

๐Ÿ“„ License & Privacy

GuessTheSongYear is open source. The name "GuessTheSongYear", the game loop concept, and all source code in this repository are open source. Contributions are welcome.

Privacy: No accounts. No ads. No tracking. The app uses YouTube Iframe Player API with zero API keys and no user login. Multiplayer traffic stays on your local LAN. Personal data is not collected.

For a detailed security audit, see SECURITY.md in the repository.


๐Ÿ“ฆ Releases

Every push to master auto-builds a new APK through CI, bumps version numbers, and creates a GitHub Release. Find the latest one and side-load it onto your Android device โ€” the project isn't on the Play Store (it was a weekend side-project).

Repository: https://github.com/turbolego/GuessTheSongYear