docs: refresh README with screenshots, full feature list, and build guide
Add AI disclaimer, 4 emulator screenshots, expanded feature sections (Android Auto, SomaFM, per-station quality, tabs, Media3 notification, now-playing logging, blurred art background), build.sh documentation, inline architecture diagram, and tech stack table. Made-with: Cursor
This commit is contained in:
143
README.md
143
README.md
@@ -1,36 +1,149 @@
|
||||
# 24/7 Radio
|
||||
|
||||
Personal-use Android app for 24/7 internet radio streaming.
|
||||
Android app for 24/7 internet radio streaming with minimum latency, aggressive reconnection, and full Icecast/Shoutcast metadata support.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> This project was built with the assistance of [Cursor](https://cursor.com) (Claude Opus/Sonnet 4.6).
|
||||
|
||||
---
|
||||
|
||||
## Screenshots
|
||||
|
||||
| Station List | Now Playing | Mini-Player | Station Art Fallback |
|
||||
|:---:|:---:|:---:|:---:|
|
||||
|  |  |  |  |
|
||||
|
||||
---
|
||||
|
||||
## Features
|
||||
|
||||
- **Custom Raw Audio Pipeline** — OkHttp → IcyParser → Mp3FrameSync → MediaCodec → AudioTrack for absolute minimum latency (~26ms per MP3 frame)
|
||||
- **Stay Connected Mode** — Aggressive reconnection with exponential backoff, never gives up
|
||||
- **Dual Timers** — Session elapsed time and connection elapsed time
|
||||
- **Latency Indicator** — Estimated stream-to-speaker latency
|
||||
- **Icecast/Shoutcast Metadata** — Track title, artist extraction from ICY protocol
|
||||
- **Album Art** — MusicBrainz/Cover Art Archive lookup with fallback chain
|
||||
- **Playlist Management** — PLS/M3U import/export with #EXTIMG support
|
||||
- **Station Organization** — Playlists, starring/favoriting, manual reorder
|
||||
### Playback
|
||||
- **Custom raw audio pipeline** — OkHttp → IcyParser → Mp3FrameSync → MediaCodec → AudioTrack for minimum latency (~26ms per MP3 frame)
|
||||
- **Stay Connected mode** — aggressive reconnection with exponential backoff; never gives up until you say stop
|
||||
- **Configurable buffer** — 0–500ms slider; 0ms keeps you as live as possible, higher values smooth out spotty connections
|
||||
- **Icecast/Shoutcast metadata** — ICY protocol track title and artist extraction
|
||||
- **Album art** — MusicBrainz/Cover Art Archive lookup with a fallback chain (ICY stream URL → station default art → station logo → placeholder)
|
||||
|
||||
### Station Management
|
||||
- **SomaFM built-in** — full SomaFM catalog pre-loaded, sorted by listener count
|
||||
- **Per-station stream quality** — choose 128/256 kbps and SSL/non-SSL per station, or set a global preference order
|
||||
- **PLS/M3U import/export** — with `#EXTIMG` support for station artwork URLs
|
||||
- **Tabs (playlists)** — pin/unpin, rename, and drag-to-reorder tabs and stations within them
|
||||
- **Starring/favoriting** — starred stations sort to the top of their tab
|
||||
|
||||
### Now Playing Screen
|
||||
- **Blurred album art background** — art fills the screen behind the player controls
|
||||
- **Session timer** — total elapsed time since you hit play, not reset on reconnect
|
||||
- **Connection timer** — elapsed time for the current TCP connection, resets on each reconnect
|
||||
- **Latency indicator** — estimated stream-to-speaker latency in ms
|
||||
- **Track history** — every track change is logged to the database with station and timestamp
|
||||
- **Now Playing file logging** — optionally write track history to CSV, JSON Lines, or plain text
|
||||
|
||||
### System Integration
|
||||
- **Media3 notification** — system media notification with album art, transport controls (play/stop + seek-to-live), lockscreen and Bluetooth headset support
|
||||
- **Android Auto** — app registers as a media source; browse your playlists and stations from the car display
|
||||
|
||||
### Build Tooling
|
||||
- **`build.sh`** — interactive menu: release APK (signed), debug APK, keystore management, and clean
|
||||
|
||||
---
|
||||
|
||||
## Requirements
|
||||
|
||||
- Android 9.0+ (API 28)
|
||||
- Internet connection
|
||||
|
||||
---
|
||||
|
||||
## Build
|
||||
|
||||
The recommended path is the interactive build script:
|
||||
|
||||
```bash
|
||||
./gradlew assembleDebug
|
||||
./build.sh
|
||||
```
|
||||
|
||||
## Import Stations
|
||||
Menu options:
|
||||
1. **Build Release APK** — signed, ready to sideload
|
||||
2. **Build Debug APK** — quick, for testing
|
||||
3. **Manage Keystore** — create or inspect the signing key
|
||||
4. **Clean** — remove build artifacts
|
||||
|
||||
On first run, choose option 3 to create a keystore before building a release APK. Output lands in `dist/`.
|
||||
|
||||
Alternatively, build directly with Gradle:
|
||||
|
||||
```bash
|
||||
./gradlew assembleDebug # debug
|
||||
./gradlew assembleRelease # release (requires keystore configured in build.gradle.kts)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Importing Stations
|
||||
|
||||
1. Open the app
|
||||
2. Tap the import icon in the top bar
|
||||
3. Select a .m3u or .pls file
|
||||
4. Stations are added to your list
|
||||
2. Tap the settings gear → Import
|
||||
3. Select a `.m3u` or `.pls` file
|
||||
4. Stations are added to your library
|
||||
|
||||
Exported files include `#EXTIMG` tags for stations that have a default artwork URL set.
|
||||
|
||||
---
|
||||
|
||||
## SomaFM
|
||||
|
||||
The SomaFM catalog is pre-loaded on first launch — no import needed. Stations are sorted by current listener count (refreshable with the sync button). You can set a global stream quality preference (256 kbps SSL recommended) or override it per station via long-press → Quality.
|
||||
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
See [Design Document](docs/plans/2026-03-09-android-247-radio-design.md) and [Implementation Plan](docs/plans/2026-03-09-android-247-radio-implementation.md).
|
||||
Four layers:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ UI Layer │
|
||||
│ Compose screens, ViewModel, StateFlow │
|
||||
├─────────────────────────────────────────┤
|
||||
│ Service Layer │
|
||||
│ RadioPlaybackService (MediaLibrary │
|
||||
│ Service), RadioPlayerAdapter (Media3 │
|
||||
│ Player facade), wake + wifi locks │
|
||||
├─────────────────────────────────────────┤
|
||||
│ Audio Engine │
|
||||
│ StreamConnection → IcyParser → │
|
||||
│ Mp3FrameSync → MediaCodec → AudioTrack │
|
||||
├─────────────────────────────────────────┤
|
||||
│ Data Layer │
|
||||
│ Room DB, PLS/M3U import/export, │
|
||||
│ DataStore preferences │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
The audio engine is a standalone component with no Android framework dependencies. The service owns reconnection policy, Android Auto browse tree, and the Media3 session. The UI observes state via `StateFlow` and never touches the engine directly.
|
||||
|
||||
For full detail see the [design document](docs/plans/2026-03-09-android-247-radio-design.md) and [Media3/Android Auto design](docs/plans/2026-03-18-media3-android-auto-design.md).
|
||||
|
||||
---
|
||||
|
||||
## Tech Stack
|
||||
|
||||
| Layer | Library |
|
||||
|---|---|
|
||||
| Language | Kotlin |
|
||||
| UI | Jetpack Compose, Material Design 3 |
|
||||
| Media session / Auto | AndroidX Media3 (media3-session, media3-common) |
|
||||
| HTTP streaming | OkHttp |
|
||||
| Audio decoding | MediaCodec (hardware-accelerated) |
|
||||
| Audio output | AudioTrack |
|
||||
| Database | Room |
|
||||
| Preferences | DataStore |
|
||||
| Image loading | Coil |
|
||||
| Album art lookup | MusicBrainz / Cover Art Archive (no API key required) |
|
||||
|
||||
---
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE)
|
||||
|
||||
BIN
docs/screenshots/01-station-list.jpg
Normal file
BIN
docs/screenshots/01-station-list.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 275 KiB |
BIN
docs/screenshots/02-now-playing-art.jpg
Normal file
BIN
docs/screenshots/02-now-playing-art.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 256 KiB |
BIN
docs/screenshots/03-station-list-miniplayer.jpg
Normal file
BIN
docs/screenshots/03-station-list-miniplayer.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 277 KiB |
BIN
docs/screenshots/04-now-playing-station-art.jpg
Normal file
BIN
docs/screenshots/04-now-playing-station-art.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 195 KiB |
Reference in New Issue
Block a user