词幕Lyricon Provider开发教程:从零为你的播放器插件接入状态栏歌词
词幕Lyricon Provider开发教程:从零为你的播放器插件接入状态栏歌词
词幕(Lyricon) 是一款为 Android 状态栏扩展歌词显示功能的增强工具,能把你正在播放的歌曲歌词实时渲染到系统状态栏。本教程面向插件与播放器开发者,带你从零开始,用官方 Provider 模块完成接入:添加依赖、配置 Manifest、注册中心服务,再发送歌曲、逐字歌词、翻译与播放进度,让状态栏跟着音乐同步滚动。
🎯 词幕 Provider 是什么?
词幕采用「中心服务 + 插件端」的架构:
- 中心服务:运行在 System UI(System UI 进程)中,负责把歌词渲染到状态栏。
- Provider(歌词提供端):运行在你的播放器 / 歌词插件里,负责把歌曲、歌词、播放状态、显示配置推送给中心服务。
你作为开发者要做的,就是让自己的应用成为一个合法的 Provider。整个接入流程如下:
- 添加 Provider 依赖
- 配置
AndroidManifest.xml元数据 - 创建
LyriconProvider - 调用
register()注册 - 通过
provider.player发送数据 - 不再使用时调用
unregister()/destroy()
📌 想深入了解整体设计,可阅读官方 Provider 文档入口。
📋 开发前准备
| 项目 | 要求 |
|---|---|
| 运行环境 | Android 8.1(API 27)及以上 |
| 语言 | 建议使用 Kotlin(Java 调用未经完整验证) |
| 核心依赖 | io.github.proify.lyricon:provider |
⚠️ 注意:Android 8.1 以下系统会返回空实现(不报错但不生效),接入时可留意设备版本。
🧩 第一步:添加 Provider 依赖
在你的应用模块 build.gradle.kts 中引入 Provider 库:
implementation("io.github.proify.lyricon:provider:0.1.70")
这个依赖就是整个插件端的「入口」,核心工厂类 LyriconFactory.kt 会负责创建 Provider 实例,并在低版本系统上安全降级。
⚙️ 第二步:配置 AndroidManifest.xml 元数据
为了让词幕识别你的应用是一个合法的歌词提供端,需要在 <application> 节点声明模块元数据:
<application>
<meta-data android:name="lyricon_module" android:value="true" />
<meta-data android:name="lyricon_module_author" android:value="your name" />
<meta-data android:name="lyricon_module_description" android:value="my player module" />
</application>
| 字段 | 说明 |
|---|---|
lyricon_module |
必填,标记当前应用为词幕模块 |
lyricon_module_author |
模块作者名称 |
lyricon_module_description |
模块说明(面向用户的可读文本) |
💡 还能通过 lyricon_module_tags 声明能力标签,如 $syllable(逐字/动态歌词)、$translation(翻译歌词)。这些标签仅用于展示,不会自动开启对应功能。详细字段见 Manifest 配置。
🚀 第三步:创建并注册 Provider
创建实例
val provider = LyriconFactory.createProvider(context)
如需自定义注册信息(包名、图标、元数据),可传入更多参数:
val provider = LyriconFactory.createProvider(
context = context,
providerPackageName = context.packageName,
playerPackageName = context.packageName,
logo = null,
metadata = null
)
监听连接状态
建议添加连接监听,方便调试与状态提示:
provider.service.addConnectionListener {
onConnected { } // 首次连接成功
onReconnected { } // 断线后重连成功
onDisconnected { } // 连接断开
onConnectTimeout { } // 连接中心服务超时
}
注册
provider.register()
注册成功后,词幕中心服务即可开始接收你的推送数据。register() 返回值只代表请求是否成功发出,并不代表歌词已经被显示。更多生命周期说明见 连接生命周期。
📝 第四步:发送歌词
拿到 provider.player 后,就有两种发送方式。
方式一:纯文本 sendText()
适合没有时间轴的简单展示(注意:调用后会清除之前设置的歌曲信息):
val player = provider.player
player.setPlaybackState(true)
player.sendText("我无法只是普通朋友")
方式二:结构化歌曲 setSong()
支持行级歌词、逐字歌词、翻译等,是推荐的主路径:
player.setSong(
Song(
id = "song-id",
name = "普通朋友",
artist = "陶喆",
duration = 2000,
lyrics = listOf(
RichLyricLine(begin = 0, end = 1000, text = "我无法只是普通朋友"),
RichLyricLine(begin = 1000, end = 2000, text = "不想做普通朋友")
)
)
)
player.setPosition(100)
歌词数据结构速览
Song:歌曲基础信息,id/name/artist/duration/lyrics,时间单位统一为毫秒。RichLyricLine:单行歌词,含begin/end/text,还可携带secondary(次要歌词)、translation(翻译)。LyricWord:逐字歌词,描述每个词/字的时间范围,需填在所在行的时间范围内。
逐字歌词示例(RichLyricLine.words):
RichLyricLine(
begin = 0, end = 1000, text = "我无法只是普通朋友",
words = listOf(
LyricWord(text = "我", begin = 0, end = 200),
LyricWord(text = "无法", begin = 200, end = 400)
// ...
)
)
完整字段说明见 歌词数据结构。
⏱️ 播放器控制 API 速查
所有播放控制都通过 provider.player(接口定义见 RemotePlayer.kt):
| 方法 | 用途 |
|---|---|
setSong(song) |
设置当前歌曲与结构化歌词;null 表示清空 |
sendText(text) |
发送无时间轴文本,会清除歌曲信息 |
setPlaybackState(playing) |
同步播放 / 暂停状态 |
setPosition(ms) |
持续同步当前播放位置(毫秒) |
seekTo(ms) |
主动跳转(拖进度条、切歌恢复) |
setDisplayTranslation(true) |
开启翻译显示 |
setDisplayRoma(true) |
开启罗马音显示 |
📌 setPosition() 用于正常播放时定期更新进度;seekTo() 用于用户主动跳转。推荐调用顺序见 播放器控制。
🧪 第五步:本地测试(LocalCentralService)
正式环境需要在 LSPosed / Xposed 中激活词幕中心服务。若你的设备暂时没有 LSPosed,可用 LocalCentralService 做基础联调:
- 安装 LocalCentralService 并打开、激活服务
- 授予其悬浮窗权限
- 创建 Provider 时指定本地中心服务包名
- 调用
register(),再推送播放状态与歌词,检查显示效果
val provider = LyriconFactory.createProvider(
context,
centralPackageName = "io.github.lyricon.localcentralapp"
)
⚠️ 发布前务必删除
centralPackageName这一行测试配置,改用默认中心服务包名。测试建议先用sendText()验证连接,再用setSong()验证结构化歌词。详见 本地测试。
🚨 常见问题排查
| 现象 | 可能原因与解决 |
|---|---|
| 注册后不显示歌词 | 中心服务未运行 / LSPosed 作用域未勾选 / 未调 register() / 只注册没发数据 |
| 翻译不显示 | 需同时满足:歌词含 translation、调了 setDisplayTranslation(true)、展示端允许显示 |
| 罗马音不显示 | 同上,需数据 + setDisplayRoma(true) + 展示端允许 |
| LocalCentralService 连不上 | 确认服务已启动并已授予悬浮窗权限 |
更多排查项见 常见问题 FAQ。
✅ 发布前检查清单
- [ ] 已删除 LocalCentralService 的
centralPackageName测试配置 - [ ]
AndroidManifest.xml已声明lyricon_module等模块元数据 - [ ] 模块标签(tags)与实际能力一致
- [ ] 连接断开、应用退出时正确调用
unregister()/destroy()释放资源
恭喜!完成以上步骤,你的播放器就成功接入了词幕,用户切歌时状态栏会实时滚动显示歌词、逐字高亮与翻译。🎉 如需继续扩展,可参考仓库 Provider 模块源码 与 官方开发文档。