尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证Yoin Android music client
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗A native Android music client for your own server (Subsonic / OpenSubsonic), Spotify and Apple Music, built with Jetpack Compose and Material 3 Expressive for phones, foldables and tablets.
Score tracks and albums down to 0.1, follow line-by-line synced lyrics, pin notes to the exact second, and look back through album Memories. Local-first by design, with optional sync through hidden files in your own Google Drive or to NeoDB.
One navigation bar that adapts to the window. The same bar becomes a bottom bar on a phone,
a centered bar on a tablet, and a bar that spans two columns when a detail page opens beside the
library. Each slot's width comes from one pure function, so no frame shows a gap.
YoinButtonGroup.kt,
FloatingBottomBar.kt,
WindowAdaptiveRuntime.kt,
docs/adaptive-principles.md
Predictive back built from AOSP's own numbers. Outside the two-column layout, detail pages are separate Activities. Their back
gesture is a port of the platform's cross-activity animation, constant for constant, so leaving a page
feels like the system did it. The navigation bar stays put while the page underneath moves.
BackMotionTokens.kt,
DetailPredictiveBackCollapse.kt,
DetailBackEntering.kt
A covered window that kept drawing. A Perfetto trace showed that the window behind a detail page
still rendered every frame. Pausing its frame clock, plus a few smaller cuts, brought expanded lyrics
on a Pixel Tablet from about 80% CPU to about 20%.
CoveredWindowAnimationGate.kt,
commit ec1dc15f
Versions are taken from gradle/libs.versions.toml.
MediaSession playback serviceStateFlow, manual dependency injectionflowchart TD
UI["Compose screens"] --> VM["ViewModels (StateFlow)"]
VM --> Repo["YoinRepository"]
Repo --> PM["ProfileManager<br/>(active account)"]
PM --> Sub["SubsonicMusicSource"]
PM --> Spo["SpotifyMusicSource"]
PM --> App["AppleMusicSource"]
Repo --> Room[("Room")]
VM --> Play["PlaybackManager"]
Play --> Media3["Media3 / MediaSession"]
Play --> Remote["Spotify App Remote"]
Play --> MusicKit["Apple MusicKit player"]
Every provider implements the same MusicSource interface and uses the same neutral models. A provider
declares which capabilities it supports, and the UI hides what a provider can't do.
See MusicSource.kt.
Most of the implementation code was written by AI coding agents. I made the product and design
decisions, tested on real devices, and set the direction when something broke. The rules the agents
follow are in AGENTS.md, docs/ and the unit tests.
Yoin 0.5 is in a closed test on Google Play for Android 8.0 and later. See yoin.gojyuplus.com for how to join and the user docs.
You need JDK 17 or newer (Android Studio's bundled JBR works) and the Android SDK for API 36.
The project does not build without these:
musickitauth-release-1.1.2.aar and
mediaplayback-release-1.1.1.aar in app/libs/. See
app/libs/README-apple-music.md.../yoin-symbols), or pass -PyoinSymbolsDir=<path>.Each music service also needs your own credentials:
-PspotifyClientId=<id>.services/apple-music-token/. Enter its URL in Settings../gradlew assembleDebug # debug APK
./gradlew test # unit tests
./gradlew ktlintCheck # lint
See CONTRIBUTING.md for the pull request flow and docs/ci-cd.md
for CI and release setup.
Apache-2.0. Third-party notices are in NOTICE.