把心爱的邦邦角色放在手机桌面上,随时戳一戳 ✨
Bandori Pet 是一个 Android 桌面宠物 / 动态壁纸应用,使用 Live2D 模型驱动 BanG Dream! 系列角色的动态演出。基于 Compose + OpenGL ES 2.0 + LuaJIT 构建,支持 MOC2 和 MOC3 格式模型。
- 📱 桌面宠物模式 —— 角色在你的屏幕上自由活动,戳她会触发动作反馈
- 🖼️ 动态壁纸模式 —— 把角色设为系统动态壁纸,解锁屏幕就能看到她们
- 🎭 多角色多服装 —— 覆盖 10 个乐队、45+ 角色,每人多套服装随意切换
- ⚙️ 帧率可调 —— 15~120 FPS,开启垂直同步,性能与流畅度自己拿捏
- 🎨 Material 3 设计 —— 粉紫色调主题,浅色 / 深色自动适配
| 工具 | 版本 / 说明 |
|---|---|
| Android Studio | 2024+ 推荐(自带了 Gradle 和 SDK) |
| Android SDK | compileSdk 35, minSdk 26 |
| Android NDK | 27+(用于编译 Rust JNI 库和 LuaJIT) |
| Rust | 1.85+ stable,需安装 aarch64-linux-android target |
| cargo-ndk | 当前稳定版,由 Gradle 调用 |
| JDK | 17 |
| Gradle | 由项目 wrapper 管理,无需单独安装 |
注意:本项目默认只构建
arm64-v8a架构。模拟器请使用 arm64 镜像,真机没问题。
Bandori-Pet-Android/
├── app/ # Android 应用模块
│ ├── build.gradle.kts # 应用构建配置
│ └── src/main/
│ ├── AndroidManifest.xml
│ ├── rust/ # Rust JNI:EGL + LuaJIT + 渲染循环
│ │ ├── Cargo.toml
│ │ └── src/
│ ├── java/com/bandori/pet/ # Kotlin 源码
│ └── res/ # 资源文件
├── band.json # 乐队 & 角色定义
├── outfit.json # 角色服装映射
├── band_logo/ # 乐队 Logo 图片
├── icon.png # 应用图标
├── docs/ # 补充文档
├── third_party/ # [需自行提供] Live2D Lua 运行时
├── models/ # [需自行提供] 角色模型文件
└── jniLibs/ # [需自行提供] 预编译 .so 文件
third_party/、models/、jniLibs/ 均被 .gitignore 排除,需要自行准备。
核心思路:手动准备第三方运行库,项目自身的 libbandoripet.so 由 Gradle 调用 Cargo 自动构建并打包。
rustup target add aarch64-linux-android
cargo install cargo-ndkcargo-ndk 会自动查找 Android Studio 安装的 NDK。项目固定输出 arm64-v8a,并以 Android API 26 作为最低原生平台版本。
应用通过 dlopen 动态加载 LuaJIT,因此需要一个 Android arm64 版本的 libluajit.so。
# 克隆 LuaJIT
git clone https://github.com/LuaJIT/LuaJIT.git
cd LuaJIT
# 设置 NDK 路径(按你的实际路径修改)
NDK=$HOME/Android/sdk/ndk/27.0.12077973
TOOL=$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin
# 编译
make clean
make -j$(nproc) \
HOST_CC="gcc" \
CROSS="$TOOL/aarch64-linux-android23-" \
TARGET_SYS=Linux \
XCFLAGS="-DLUAJIT_ENABLE_GC64"
# 复制产物
cp src/libluajit.so <项目根目录>/app/src/main/jniLibs/arm64-v8a/libluajit.so注意:必须开启
-DLUAJIT_ENABLE_GC64,64 位 Android 设备上否则luaL_newstate()会返回 null。千万不要加-DLUAJIT_USE_SYSMALLOC,会导致初始化失败。
Windows 用户:建议在 WSL2 或远程 Linux 机器上编译,然后把 .so 拉回 Windows。
Kotlin 层的 Zstd 解压依赖 com.github.luben:zstd-jni,但其 JAR 不含 Android 原生库,需手动从 AAR 提取。
# 下载 AAR
curl -sL "https://repo1.maven.org/maven2/com/github/luben/zstd-jni/1.5.6-9/zstd-jni-1.5.6-9.aar" \
-o zstd-jni-1.5.6-9.aar
# 解压获取 .so
unzip -o zstd-jni-1.5.6-9.aar -d zstd-aar-extract
cp zstd-aar-extract/jni/arm64-v8a/libzstd-jni-1.5.6-9.so \
<项目根目录>/app/src/main/jniLibs/arm64-v8a/
# 清理
rm -rf zstd-jni-1.5.6-9.aar zstd-aar-extract这个由 Cargo 在 Gradle 构建时自动编译,无需手动复制。只要 Rust Android target、cargo-ndk 和 NDK 已安装即可。
Debug/Release 构建分别输出到 app/build/generated/rustJniLibs/,Cargo 中间产物保存在 app/build/rust-target/,两者都会随 gradlew clean 清理。
app/src/main/jniLibs/arm64-v8a/
├── libluajit.so # LuaJIT 运行时
├── libzstd-jni-1.5.6-9.so # Zstd 解压
└── (libbandoripet.so 由 Cargo/Gradle 自动生成,不放在此目录)
注意:本项目未使用 Live2D 官方 Cubism Core SDK,而是基于社区维护的 EasyLive2D/Live2D-v2-Lua 开源 Lua 运行时。这是一个纯 Lua 实现的 Live2D 解析与渲染引擎,支持 MOC2 / MOC3 模型格式,无需依赖官方原生库。
该运行时负责模型解析和 OpenGL 绘制,需要放到项目根目录下的 third_party/Live2D-v2-Lua/。
Gradle sync 任务会自动将其复制到 APK assets 中(排除 .git、venv、*.md、*.png、测试文件等)。
角色模型以 Zstd 压缩 tar 归档(.zst 文件)形式存储。放置方式二选一:
- 打包进 APK:放到
models/<characterId>.zst,Gradle 会自动打包进 assets - 运行时下载:不打包,应用启动后自动从 ModelScope CDN 下载到本地(需要网络权限)
模型归档内结构示例:
<characterId>.zst
└── <costumeId>/
├── character.png
├── <name>.model.json # MOC2 模型配置
├── <name>.model3.json # MOC3 模型配置
├── <name>.moc / <name>.moc3 # 二进制模型
├── textures/
├── motions/
├── expressions/
└── sounds/
# 在项目根目录执行
./gradlew assembleDebug产物路径:app/build/outputs/apk/debug/app-debug.apk
如果是 Windows:
.\gradlew.bat assembleDebug发布签名不再写入仓库。需要签名的 Release APK 时,请在用户级 gradle.properties 中配置
BANDORI_RELEASE_STORE_FILE、BANDORI_RELEASE_STORE_PASSWORD、
BANDORI_RELEASE_KEY_ALIAS 和 BANDORI_RELEASE_KEY_PASSWORD;未配置时仍可生成未签名的 Release APK。
- 用 Android Studio 打开项目根目录
- 等待 Sync 完成(首次需下载依赖,喝杯茶等一等 🍵)
- Build → Make Project 或直接点 Run
Gradle 构建时会自动:
- 将
band.json、outfit.json、band_logo/、models/、third_party/Live2D-v2-Lua/复制到生成 assets 目录 - 将
icon.png复制为应用图标 - 然后通过
cargo-ndk编译并打包 Rustlibbandoripet.so
# 通过 adb 安装
adb install app/build/outputs/apk/debug/app-debug.apk
# 或者 Android Studio 里直接 Run(⌘R / Ctrl+R)- NDK 编译需要 Linux 交叉工具链,建议在 WSL2 或远程 Linux 上编译 LuaJIT
- 编译好的
libluajit.so拉回 Windows 放对应目录即可 - Gradle 调用
cargo-ndk使用 NDK 交叉编译 Rust JNI 库,这个在 Windows 上没问题 dlopen/dlsym等 POSIX API 由 Android NDK 提供,编译时不需要额外配置
本项目基于 GNU General Public License v3 发布。详见 LICENSE 文件。
- EasyLive2D/Live2D-v2-Lua —— 社区 Live2D Lua 运行时(非官方 Core)
- Live2D Cubism —— 赋予角色灵魂的 Live2D 技术
- LuaJIT —— 极速 Lua 运行时
- BanG Dream! —— 闪闪发光心动不已!
- 所有为 Bandori Live2D 模型整理做出贡献的社区成员
キラキラドキドキ!