โจ A native Android audio player that combines multi-source streaming, local control, rich lyrics, and self-hosted sync ๐ต
The project name and icon are inspired by "Kazamata Neri" from
"ๆ็ฉบ้้ใจใทใญใฎๆ
".
NeriPlayer is a native Android app for Android 9 (API 28) and above,
focused on multi-source exploration, online playback, local control, and
user-owned data.
๐ ๏ธ
Active development
> [!WARNING]
> This project is for learning and research purposes only. Do not use it for illegal purposes.
>
> This project and its maintainer do not accept any form of sponsorship, donation, or commercial funding.
---
> [!NOTE]
> NeriPlayer does not provide a public cloud music library or media distribution service.
> Online audio capabilities depend on your authorization on third-party platforms.
> VIP or restricted content still follows the original platform rules.
---
## Start here
If you only want to try the app, start with [Getting Started](#getting-started).
If you want to understand what makes the project different, read
[Why it stands out](#why-it-stands-out) and [Key Features](#key-features).
If you plan to contribute, read [CONTRIBUTING_EN.md](./CONTRIBUTING_EN.md).
If you want to self-host Listen Together, jump to
[Listen Together Deployment](#listen-together-deployment).
```text
NeriPlayer
โโโ Multi-source playback: NetEase / Bilibili / YouTube Music
โโโ Local-first data: cache, downloads, playlists, history, stats, settings
โโโ User-owned sync: GitHub / WebDAV metadata sync
โโโ Rich playback: Media3, lyrics, effects, fluid background, floating/status-bar lyrics
โโโ Recovery built in: safe mode, crash logs, ANR traces, debug probes
```
---
## About
NeriPlayer is a native Android audio player built with **Jetpack Compose + Media3**.
It does not build a public cloud service. Instead, it integrates online content
from **NetEase Cloud Music**, **Bilibili**, and **YouTube Music** when the user
has the corresponding third-party platform account capability. It also provides
local playback, downloads, caching, playlist management, and several sync/backup
options.
Current positioning:
- **Account as capability**: third-party platform authorization enables search,
playback, playlists, and favorites access.
- **Local-first**: playback cache, downloads, playlists, history, settings, and
auth data are stored locally on the device by default.
- **Optional sync**: playlists, favorites, recent plays, and playback stats can
be synced to your own GitHub repository (repositories created in-app default
to private) or a WebDAV remote file.
- **Privacy and account safety first**: sync is intentionally decentralized.
Data is written to GitHub/WebDAV storage that you control, not to a centralized
service operated by the project maintainer. The app is technically capable of
sending playback history back to third-party music platforms, but centralized
music clients often have risk-control and behavior-sampling systems. Uploading
local playback history directly may be interpreted as abnormal login or playback
behavior and could put an account at risk. To protect account safety,
NeriPlayer does not upload local playback history or playback stats back to
those platforms.
- **Single Activity + Compose**: `MainActivity` is the only external entry point.
The UI is organized by Compose `NavHost`, a dynamic bottom bar, Mini Player,
and the Now Playing overlay.
- **Startup and recovery flow**: the normal startup path is
`Loading -> Disclaimer -> Onboarding -> Main`. If the previous launch ended in
a crash or system ANR, the app enters `Safe Mode` first.
- **Test guardrails**: download storage, sync merging, YouTube playback,
Listen Together, lyrics, playback policies, config backup, and safe mode all
have focused unit or device tests.
---
## Why it stands out
- **Local-first, with real offline behavior**:
`NetworkStatusMonitor` follows Android's default direct network transport,
while `offlineCachedImageRequest` disables remote image requests in offline
mode and falls back to local caches. Home, Explore, Now Playing, Lyrics,
playlists, and downloads all receive `offlineMode`, so local files,
downloaded audio, playback cache, cached covers, and local playlists remain
usable without a network.
- **Multi-source playback is not just a list of entry points**:
`PlayerManager` owns stream resolution, queues, and failure recovery. When a
NetEase track is unavailable, has no playable URL, or only returns a preview,
the player first tries a lower quality, then
`PlayerManagerNeteaseAutoSourceSwitch` scores Bilibili candidates by title,
artist, and duration. Playback errors can also refresh the current URL before
falling back to skip/stop behavior.
- **YouTube resolution has layered fallbacks**:
valid signed-in identity cookies are preserved and rotated when needed, while
anonymous visitor sessions keep separate bootstrap and PoToken state. Verified
signature/n, `player.js`, and challenge results are cached and reused; stale
player code or a CDN-rejected direct URL falls through to EJS/HLS instead of
retrying the same unusable stream.
- **High-performance GLSL/AGSL fluid background**:
the Now Playing dynamic background is rendered frame-by-frame by
`BgEffectPainter`, `RuntimeShader`, and
`assets/shaders/hyper_background_effect.glsl`.
The shader combines cover-derived colors, animated color blobs, and lightweight
grain while reacting to `uMusicLevel / uBeat`; it is not just a Gaussian-blurred
cover. The RuntimeShader/audio-reactive path requires Android 13+. Cover blur
requires Android 12+, while advanced blur requires Android 13+; older versions
automatically use a compatible fallback without those effects.
- **Apple Music-style lyrics, backed by the playback pipeline**:
`SyncedLyricsView` and `AdvancedLyricsView` support word/character-timed
highlighting, translated lyrics, phonetic display, lyric offset, click-to-seek,
long-press sharing, depth blur, edge fade, and a full-screen Lyrics page.
`LyricShareSheet` can select lyric lines, copy text, share the song, or render
a 1080px lyric card. The Now Playing cover lyric view and bottom Dock can be
disabled independently; narrow or heavily scaled portrait layouts switch to a
compact control arrangement with stable touch slots. Long-press selection can
select a range from the first line to the target line. Floating lyrics, status-bar lyrics,
SuperLyric, Lyricon, Bluetooth lyrics, and lyric editing reuse the same
playback data path.
- **Complete local music management**:
`LocalAudioImportManager` supports external share/open imports, authorized
folder scanning, device media-library scanning, common audio formats, nearby
`lrc/txt` lyrics, and `cover/folder/front` cover files. Large scans can show
a quick preview first, then hydrate richer title/artist/album/cover metadata
in the background. `LocalPlaylistRepository` manages system local playlists,
user playlists, favorites, sorting, de-duplication, backup, and sync triggers.
- **Library browsing now has real categories**:
`Library` is no longer just a playlist list. Local content can switch between
playlists and artists, while `LocalArtistSummary` groups songs by display
artist, splits common collaboration artist text, and keeps stable identity
and cover selection. NetEase songs can open an artist page with songs, albums,
and follow state.
- **Large screens and daily controls are getting real polish**:
tablet/landscape Now Playing, Lyrics, Settings, and artist pages use steadier
width constraints and bottom control layouts. The `Mini Player` supports
horizontal swipe for previous/next without expanding the full player. Main
bottom tabs use interruptible directional page transitions that retain both
outgoing and incoming scenes, avoiding glass, scroll-state, and page-state
discontinuities during rapid switching. Long-pressing the Now Playing artwork
opens an immersive preview with pinch-to-zoom, panning, and a download action.
- **Sound controls are tied to the active audio session**:
`PlaybackEffectsController` applies speed, pitch, Android `Equalizer`, and
`LoudnessEnhancer` to the current Media3 audio session. Presets, manual bands,
loudness gain, per-track real-time normalization, fade/crossfade, pause on
Bluetooth disconnect, channel balance, 32-bit high-resolution system output,
USB exclusive playback, and audio-focus behavior are all available. Native USB
exclusive playback currently targets **UAC1.0** and compatible
**UAC2.0 Type I PCM** audio devices, so system sounds and other apps cannot
share the USB transport on that path. Device selection, sample-rate/bit-depth/
buffer policies, 32-bit PCM, software PCM-float conversion, background-playback
guidance, UAC2 clock-topology and explicit-feedback endpoint resolution,
startup watchdogs, foreground/background health audits, dynamic transfer
scaling, and automatic stall recovery are now part of the path. After a long
scheduling gap, the runtime reacquires the feedback clock instead of continuing
with a stale rate estimate. Foreground/background recovery chooses wake behavior
from the network or local source, and bit-perfect volume keeps software gain at
0 dB so the DAC controls the level. Settings report battery-optimization or
background-permission limits. While service playback is retained, a background
audio anchor selects silence or a zero-mean carrier for the actual output route;
MediaSession provides remote volume routing and the carrier is not user content.
- **Downloads have moved from "can save" to "can recover"**:
downloads do not use the system `DownloadManager`. They use the shared
`OkHttpClient`, configurable concurrency, staging files, and sidecar metadata.
Direct links, YouTube range chunks, and HLS each have a resume strategy.
Network-policy pauses can continue later, startup recovery restores unfinished
queues, and already-finalized local hits are settled directly. Manual
cancellation cleans up partial artifacts.
- **Storage usage is visible and cleanup has boundaries**:
`StorageUsageAnalyzer` groups audio cache, image cache, download staging,
share staging, platform playlist cache, downloaded content, logs, crash
reports, and core app data. Cache cleanup targets regenerable cache data and
does not treat user-saved downloads as disposable cache.
- **Self-owned sync plus playback stats**:
NeriPlayer does not provide a public cloud library or developer-hosted user
data service. GitHub/WebDAV sync stores playlists, favorites, recent plays,
and playback stats in the user's own remote. `PlaybackStatsRepository` records
play count, total listen time, first/last played time, and daily buckets by
stable track identity, then participates in sync merging. Remote sync snapshots
tolerate legacy or malformed missing-field payloads, filter records without
resolvable track identity, and keep songs with missing `addedAt` behind dated
songs in current display-order playlists. Playback and traffic statistics use
debounced batch writes, flush at important lifecycle points, and keep a bounded
number of daily buckets.
- **Traffic controls are built into the product, not bolted on later**:
`TrafficStatsRepository` tracks playback/download bytes, Wi-Fi/mobile/roaming
distribution, and cache-hit bytes. Download flows can also warn before high-risk
mobile or roaming transfers.
- **Highly personalized, beyond theme colors**:
`AutoSettingsSchema` covers dynamic colors, seed colors, palette style,
auto/light/dark mode, UI scaling, custom backgrounds, lyric font size,
lyric blur, two-level advanced blur, Coherent Feedback, the fluid Now Playing background,
Home card toggles, default start
destination, haptic feedback, and custom song title/artist/cover metadata.
Enhanced Advanced Blur and Coherent Feedback are off by default. With Coherent
Feedback off, playlist and related detail pages use a drawer-style transition.
Enhanced Advanced Blur is available only on Android 13+ while its parent blur
setting is enabled. It adds shared live-glass material to
screen-level top tabs, the bottom tab bar, and structural settings cards without
changing foreground content, layout, or touch targets. Its blur radius is adjustable
from `12-64 dp`.
- **ANR, crash logs, and safe mode form a diagnostics loop**:
`AnrWatchdog` reads Android `ApplicationExitInfo.REASON_ANR` and stores the
system ANR trace. `ExceptionHandler` and `NativeCrashHandler` record JVM and
native crashes. If the previous startup failed, `SafeModeManager` can skip full
app initialization and open safe mode for preview, copy, or export.
- **Listen Together syncs the room, not just a progress bar**:
the Android client and Cloudflare Worker maintain rooms, roles, queues,
playback state, repeat/shuffle modes, controller-offline recovery, member
control requests, optional stream-link sharing, version-gated updates, and
custom server URLs. Repeat/shuffle changes use `PLAYBACK_MODE` /
`REQUEST_PLAYBACK_MODE`, while member controls and asynchronous stream-link
results validate the target stable track key so they cannot affect a track
that has already changed. The client also estimates server clock offset, corrects
position drift by threshold, and reloads the authoritative stream after an
asynchronous shared link arrives so pending local startup cannot override
the room's pause/play command.
Invites must carry the room secret needed for a first join, while member secrets
are kept out of public room state. Local tracks cannot create or replace a room
track. When stream sharing is enabled, Durable Objects cache the controller's
current URLs so listeners can retrieve them without waiting for another controller
response. A current track keeps at most three validated candidates; listeners always
resolve with their own quality policy first and use those session-only candidates only
after local resolution fails, so they never enter song or offline caches. Reconnecting
with the same member credential does not trigger member-change auto-pause, and both
roles keep their WebSocket connection alive. Explicitly leaving a room removes the
member and broadcasts the departure, while a transport-only disconnect remains
reconnectable. Durable Objects persist room state while WebSocket keeps active
members in sync.
---
## Getting Started
### a. Download a Release build (recommended)
1. Go to [GitHub Releases](https://github.com/cwuom/NeriPlayer/releases).
2. Which APK should you choose?
- Most phones should use `arm64-v8a`.
- Older 32-bit devices should use `armeabi-v7a`.
- `x86` / `x86_64` are mainly for emulators, Intel devices, or Chromebooks.
> [!IMPORTANT]
> The Release channel is not a strict stable channel. Builds are usually pushed
> manually after a batch of features is completed and may still contain issues.
### b. Download a CI build
1. Go to [GitHub Actions](https://github.com/cwuom/NeriPlayer/actions), download
the Artifacts from the latest successful build, and extract them.
2. Or visit [NeriPlayer CI Builds](https://t.me/neriplayer_ci).
> The master CI artifact is `arm64-v8a` by default; the manual Release workflow
> builds multi-ABI APKs.
### c. Local build
1. Clone the repository and initialize submodules:
```bash
git clone --recursive https://github.com/cwuom/NeriPlayer.git
cd NeriPlayer
```
2. Open the project with the latest stable Android Studio and sync dependencies.
3. Build the Debug APK:
```bash
./gradlew :app:assembleDebug
```
4. Install the APK:
```bash
adb install -r app/build/outputs/apk/debug/app-debug.apk
```
5. On first launch, read the disclaimer and complete onboarding. Android 13+
devices will request notification permission.
6. For debugging tools, tap the **version number** 7 times in Settings. A
standalone `Debug` tab will appear in the bottom bar.
> Debug builds are for testing only. Their performance and size do not represent Release builds.
For release build and signing details, see
[CONTRIBUTING_EN.md](./CONTRIBUTING_EN.md#release-build).
---
## Key Features
- ๐ง **Multi-source exploration and playback**:
supports NetEase Cloud Music, Bilibili, YouTube Music, and local audio.
- ๐ **Home recommendations and continue listening**:
the Home page supports recently used playlists and recommendation cards.
International mode prioritizes YouTube Music home shelves.
- ๐๏ธ **Categorized Library browsing**:
`Library` includes Local, Favorites, NetEase, YouTube Music, and Bilibili areas.
YouTube can be fully disabled under Settings > General, which hides its entry
points and stops related background warmups.
Local content can switch between playlists/artists with search and artist
sorting; Favorites can switch between playlists/artists; NetEase can switch
between playlists/albums; Bilibili separates created favorites, subscribed
favorites, and collections.
- ๐ **Layered search**:
`Explore` searches NetEase / Bilibili / YouTube Music separately.
Playback metadata completion uses NetEase / QQ Music and integrates LRCLIB
as an external lyrics source.
- ๐ง **Media3 playback core**:
`PlayerManager` handles stream resolution, queue state, shuffle/repeat,
persistence, failure retry, playback URL refresh, YouTube prefetching, and
platform-specific request policies.
- YouTube playback preserves valid login cookies, supports cookie rotation and
anonymous resolution, reuses bootstrap/`player.js`/PoToken caches with priority
prefetching, and falls back to EJS/HLS after direct-link rejection.
- โฉ **Optional BilibiliSponsorBlock auto-skip**: disabled by default. When enabled,
the public API receives only a SHA-256 prefix of the current BV ID; matching
page, duration, and `intro`/`outro`/`sponsor`/`music_offtopic`/`filler`/`padding` segments are
skipped locally. No account data, playback history, or segment submissions are
uploaded, and the feature remains disabled during Listen Together to prevent room
state drift.
- ๐ **NetEase auto source switch**:
when a NetEase song is unavailable, has no playable URL, or only returns a
preview clip, the player first tries lower quality and can then match a
Bilibili fallback source by title, artist, and duration. When enabled, it can
also match a readable local audio file by stable metadata.
- ๐งฏ **Playback failure fallback**:
playback errors first try refreshing the active playback URL. Bilibili stream
resolution retries missing DASH audio and can fall back to html5/mp4 progressive
streams; repeated failures skip or stop playback to avoid getting stuck.
- ๐๏ธ **Playback sound controls**:
Now Playing includes speed, pitch, loudness enhancer, Android system equalizer
presets, and manual EQ bands. Playback settings also provide per-track
real-time loudness normalization, channel balance, and 32-bit high-resolution
system output. Loudness normalization is bypassed during USB exclusive playback;
high-resolution system output keeps the high-precision pipeline where possible
and bypasses loudness normalization, channel balance, audio visualization, and
in-app speed processing.
- ๐๏ธ **Fine-grained playback behavior**:
keep last playback progress, restore playback mode, fade-in/fade-out,
crossfade-next, pause on Bluetooth disconnect, USB exclusive playback,
mixed playback, and preemptive audio focus are configurable. Long-form progress
memory is enabled by default only for tracks at least 15 minutes long; positions
below 5 seconds are ignored, positions within 30 seconds of the end are cleared,
and an explicitly requested position wins over remembered progress. The value is
stored as `resumePositionMs` for local or optional sync and is not third-party
playback history.
- ๐ **USB exclusive playback**:
supports **UAC1.0** and compatible **UAC2.0 Type I PCM** USB DAC devices, with
device selection, sample-rate/bit-depth/buffer policies, compatibility toggles,
and background-playback guidance. It also handles 32-bit PCM and software
conversion from PCM float into the selected device format. When following the
track sample rate, native exclusive output tries the exact source rate against
USB descriptors first, then tries a reported compatible rate when the exact
format is unavailable and compatibility fallback is enabled. Compatible UAC2
asynchronous topologies resolve a clock chain and explicit feedback endpoint,
schedule packets from device feedback, and reacquire the feedback clock after
long scheduling gaps. If playback startup, native transfer backpressure, or
foreground/background transitions become unhealthy, the app tries in-place
reconfiguration, coordinated AudioSink recreation, dynamic transfer scaling,
and soft recovery before falling back to Android system output. Foreground/background
recovery chooses wake behavior for network or local playback, and bit-perfect volume
keeps software gain at 0 dB for DAC-side volume control. Settings report battery-
optimization and background-permission limits. A retained service playback uses a
route-aware background audio anchor that selects silence or a zero-mean carrier,
while MediaSession provides remote volume routing and the carrier remains inaudible
user content.
- ๐พ **Configurable streaming cache**:
audio cache uses `SimpleCache + LRU`, defaults to **1 GB**, and supports
cleanup for audio cache, image cache, download staging, share staging, and
platform playlist cache, with grouped storage usage details.
- ๐ฐ๏ธ **Offline mode**:
automatically detects network availability, disables online Explore and remote
Home refreshes while offline, and uses cached images only for remote artwork.
Local files, downloaded audio, playback cache, playlists, recent plays, and
playback stats remain available.
- โฌ๏ธ **In-app downloads and management**:
supports multi-platform audio downloads, task progress, cancel/retry, and
local management with lyrics, covers, metadata, and audio tags. Default
download concurrency is **6**, configurable up to **8**. Download queues are
persisted so unfinished work can recover after restart, while complete local
files can settle directly as finished. `googlevideo` direct links use chunked
Range requests and resume by offset; if post-download tag writing fails, the
finalized audio file is retained.
- ๐ **Migratable download directory**:
downloads default to the app-managed directory, but can be moved to a custom
SAF directory. Existing downloads are migrated when switching directories.
Custom filename templates are also supported. For performance, avoid moving
to SAF unless an external directory is actually needed.
- ๐ต **Local audio import and scanning**:
supports system `VIEW / SEND / SEND_MULTIPLE` for `audio/*`, device music
scanning, authorized-folder scanning, and nearby sidecar lyrics/covers.
Large scans can show a quick preview first, filter to tracks with existing metadata,
and then continue background metadata hydration; an empty SAF listing cannot
accidentally clear an existing directory index.
- ๐ค **Local artist grouping and detail pages**:
local songs are grouped by display artist automatically, including common
`feat.`, `with`, Chinese conjunction, punctuation, and slash-separated artist
forms. Local artist pages support play-all, multi-select, playlist export,
and batch downloads for online-source songs.
- ๐ฉท **Local playlists and favorites**:
built-in "My Favorite Music" and "Local Files" system playlists, plus user
playlists with create/rename/delete/reorder/add-song support. "My Favorite
Music" can sync recognizable songs to NetEase Liked Songs.
- ๐งโ๐ค **NetEase artist pages**:
NetEase songs can open artist pages with artist metadata, paged songs/albums,
and follow/unfollow support. Followed artists appear in the Library Favorites
artist category.
- ๐งบ **NetEase playlist detail cache**:
playlist detail pages cache headers and track lists. Reopening a playlist can
show local data first, and network or parse failures can fall back to the last
successful load.
- โ๏ธ **GitHub / WebDAV sync**:
optional sync for local playlists, favorite playlists, recent plays, playback
stats, and deletion records through `WorkManager`, stored in the user's own
remote.
- ๐ **Playback stats**:
records play count, accumulated listen time, first/last played time, and daily
stat buckets by stable track identity. Day/week/month/year/all-time views are
available, and stats can be synced through GitHub/WebDAV when configured. Writes are
debounced and flushed at important lifecycle points, with a retention bound on daily buckets.
- ๐ถ **Traffic stats and download risk prompts**:
tracks playback/download bytes, Wi-Fi/mobile/roaming distribution, and cache
hits, and can warn before downloads on mobile data or roaming.
- โป๏ธ **Backup and restore**:
playlist JSON import/export, plus full config import/export for settings,
language, platform auth, GitHub/WebDAV config, and Listen Together settings.
- ๐ง **Listen Together**:
create or join rooms, sync playback state over WebSocket, support host/listener
permissions, member-control toggles, optional auto-pause when a new member joins
(not when the same member reconnects),
repeat/shuffle mode sync, optional sharing of controller-resolved stream URLs,
invite links, deep links, custom server URLs, and host-offline detection. A first join
requires the invite secret and member reconnects use member secrets. Controllers can copy the
complete invite or its secret separately; tapping Join reads a valid invite from the clipboard
and does not enter a room when none is present. Local tracks cannot create a room or replace
its current track. When sharing is enabled, the Worker caches and exposes only the current
controller URL; disabling sharing clears that cache. The Worker keeps at most three
deduplicated HTTP(S) candidates for the current track; listeners resolve their own quality
policy first and use candidates only as a session-scoped fallback after local resolution fails.
Candidates are never written to normal song or offline caches. Room position is projected from
track duration, and single-track repeat wraps it by that duration. Outdated client control events
are filtered, and `REQUEST_SET_TRACK` can only choose a song already in the current queue.
- ๐ **Personalization and themes**:
auto/light/dark mode, dynamic color, seed colors, theme styles, UI scaling,
custom background image, haptic feedback, lyric font size, lyric blur,
default start destination, and Home card toggles. Android 13+ can optionally
enable Enhanced Advanced Blur for top/bottom tabs and structural settings cards;
its radius is adjustable from `12-64 dp`, and disabling the parent preserves the
child choice and radius while removing enhanced drawing.
- โจ **Now Playing visuals and lyrics**:
`RuntimeShader` / GLSL fluid background, audio-reactive dynamic background,
cover blur background, Apple Music-style lyrics, advanced lyrics, word-timed
lyrics, translated lyrics, lyric offset, phonetic display, long-press lyric
sharing, lyric card generation, lyric editing, font scaling, lyric-aware
haptics, and a full Lyrics page. RuntimeShader animation is enabled on Android
13+; cover blur requires Android 12+, while advanced blur requires Android 13+.
- ๐ **Mini Player gestures**:
the bottom Mini Player supports horizontal swipe for previous/next while
keeping tap-to-expand and play/pause controls.
- ๐ช **Floating and status-bar lyrics**:
system overlay lyrics with customizable color, outline, font size, position,
alignment, and translation display, plus Meizu status-bar lyrics for select
devices, SuperLyric output, and auto-hide while the app is foregrounded.
- ๐ **External lyrics/device integration**:
Lyricon integration, SuperLyric, external Bluetooth lyrics, pause on Bluetooth
disconnect, and USB exclusive playback toggles. The external lyrics path
receives the current song, playback state, position, word-level lyrics,
and translations.
- ๐ ๏ธ **Developer mode and debug tools**:
tap the version number **7 times** to reveal the `Debug` tab, including
YouTube / Bili / NetEase / Search / Listen Together probes, log viewer, and
crash log viewer.
- ๐งพ **Friendlier sign-in and logging**:
NetEase and Bilibili support QR login with web-login fallback. Persistent file
logging can also be enabled outside developer mode for hard-to-reproduce bugs.
- ๐ **Safe mode and crash logs**:
if the previous startup hit a JVM/native crash or system ANR, the app can boot
directly into safe mode so you can inspect or export the log and selectively
clear settings or auth data.
---
## Platform Status
- **NetEase Cloud Music**:
login, song search, curated playlists, albums, playlist/album list search,
playback, downloads, lyrics, playback metadata completion, auto source switching
for restricted playback, syncing local favorites to NetEase Liked Songs,
artist pages, paged artist songs/albums, and artist follow support.
- **Bilibili**:
web login, QR login, video search, created favorites, subscribed favorites,
collections, favorite/collection list search, multi-part video-to-audio
playback, and downloads.
It is not a full video discovery or comments client.
- **YouTube Music**:
login, home/library playlist browsing, playlist details, search, playback,
downloads, PoToken, and JS Challenge support.
- **QQ Music**:
currently used only for playback metadata and lyrics completion. Login,
playback, and library data are not implemented.
- **Local audio**:
external share/open import, device scanning, authorized-folder scanning,
local file playback, local artist grouping, sharing, and local playlist management.
---
## Implementation Notes
### Build and versions
- `compileSdk = 37`
- `targetSdk = 36`
- `minSdk = 28`
- Java 17 / Kotlin JVM 17
- NDK `27.0.12077973`
- CMake `3.28.0+`
- Version name format: `