@roitium/expo-orpheus 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/android/build.gradle +1 -0
- package/android/src/main/AndroidManifest.xml +1 -0
- package/android/src/main/java/expo/modules/orpheus/OrpheusHeadlessTaskService.kt +23 -0
- package/android/src/main/java/expo/modules/orpheus/OrpheusMusicService.kt +22 -0
- package/bilibili--BV1DL4y1V7xH--584235509.json +1 -0
- package/build/index.d.ts +7 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +5 -0
- package/build/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +17 -0
package/README.md
CHANGED
|
@@ -30,6 +30,12 @@ Orpheus 集成了 Media3 的 DownloadManager,抛弃了原先 BBPlayer 中繁
|
|
|
30
30
|
相信聪明的你去看一下公开方法名就知道怎么使用了!
|
|
31
31
|
(需要注意的是,在切歌时,会自动清空当前的歌词)
|
|
32
32
|
|
|
33
|
+
## 注意事项
|
|
34
|
+
|
|
35
|
+
该库一些修改比较随意,我怕后续我自己都忘了,所以在这里进行一下记录。
|
|
36
|
+
|
|
37
|
+
1. `onTrackStarted` 事件在 v0.9.0 版本后不再存在。需要使用 `registerOrpheusHeadlessTask` 注册事件并自行判断事件是否为 `onTrackStarted`
|
|
38
|
+
|
|
33
39
|
## 使用
|
|
34
40
|
|
|
35
41
|
虽然该包是公开的,但仍然主要供 BBPlayer 内部使用。可能不会有完整的文档覆盖。我们欢迎你 fork 后自行修改使用。
|
package/android/build.gradle
CHANGED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
package expo.modules.orpheus
|
|
2
|
+
|
|
3
|
+
import android.content.Intent
|
|
4
|
+
import com.facebook.react.HeadlessJsTaskService
|
|
5
|
+
import com.facebook.react.bridge.Arguments
|
|
6
|
+
import com.facebook.react.jstasks.HeadlessJsTaskConfig
|
|
7
|
+
|
|
8
|
+
class OrpheusHeadlessTaskService : HeadlessJsTaskService() {
|
|
9
|
+
|
|
10
|
+
override fun getTaskConfig(intent: Intent?): HeadlessJsTaskConfig? {
|
|
11
|
+
val extras = intent?.extras
|
|
12
|
+
return if (extras != null) {
|
|
13
|
+
HeadlessJsTaskConfig(
|
|
14
|
+
"OrpheusHeadlessTask",
|
|
15
|
+
Arguments.fromBundle(extras),
|
|
16
|
+
5000, // timeout for the task
|
|
17
|
+
true // allowed in foreground
|
|
18
|
+
)
|
|
19
|
+
} else {
|
|
20
|
+
null
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -220,6 +220,26 @@ class OrpheusMusicService : MediaLibraryService() {
|
|
|
220
220
|
|
|
221
221
|
player.playWhenReady = GeneralStorage.isAutoplayOnStartEnabled()
|
|
222
222
|
player.prepare()
|
|
223
|
+
|
|
224
|
+
// 软件冷启动时,恢复的歌曲并不会触发 onMediaTransition 事件,我们需要手动补发一个
|
|
225
|
+
if (player.currentMediaItem != null) {
|
|
226
|
+
sendTrackStartEvent(player.currentMediaItem, Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED)
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
@OptIn(UnstableApi::class)
|
|
232
|
+
private fun sendTrackStartEvent(mediaItem: androidx.media3.common.MediaItem?, reason: Int) {
|
|
233
|
+
if (mediaItem == null) return
|
|
234
|
+
|
|
235
|
+
try {
|
|
236
|
+
val intent = Intent(this, OrpheusHeadlessTaskService::class.java)
|
|
237
|
+
intent.putExtra("eventName", "onTrackStarted")
|
|
238
|
+
intent.putExtra("trackId", mediaItem.mediaId)
|
|
239
|
+
intent.putExtra("reason", reason)
|
|
240
|
+
startService(intent)
|
|
241
|
+
} catch (e: Exception) {
|
|
242
|
+
e.printStackTrace()
|
|
223
243
|
}
|
|
224
244
|
}
|
|
225
245
|
|
|
@@ -239,6 +259,8 @@ class OrpheusMusicService : MediaLibraryService() {
|
|
|
239
259
|
mediaItem: androidx.media3.common.MediaItem?,
|
|
240
260
|
reason: Int
|
|
241
261
|
) {
|
|
262
|
+
sendTrackStartEvent(mediaItem, reason)
|
|
263
|
+
|
|
242
264
|
floatingLyricsManager.setLyrics(emptyList())
|
|
243
265
|
saveCurrentQueue()
|
|
244
266
|
val uri = mediaItem?.localConfiguration?.uri?.toString() ?: return
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"tags":{"00":"51.81","01":"47.24","02":"53.70","03":"39.62"},"lyrics":[{"timestamp":0,"text":"作词 : えびかれー伯爵/知代/くりーむぱい太郎"},{"timestamp":1,"text":"作曲 : えびかれー伯爵"},{"timestamp":7.66,"text":"I can't be a superstar","translation":"我成为不了超级明星"},{"timestamp":10.66,"text":"Not happy like in the silver screen","translation":"无法像银幕里那样幸福美满"},{"timestamp":15.05,"text":"But we can get everything here","translation":"但在这里,我们能获得想要的一切"},{"timestamp":37.18,"text":"It's kinda fiction","translation":"这是一篇小说"},{"timestamp":38.56,"text":"It's a made up story","translation":"是虚构的故事"},{"timestamp":40.18,"text":"That would be too good for me, sometimes","translation":"虽然它有时也对我太过友好"},{"timestamp":44.6,"text":"But the beginning is from that point","translation":"但一切都要从那里说起"},{"timestamp":52.07,"text":"Perfect story is waiting on me who failure","translation":"完美的故事正等着失败的我书写"},{"timestamp":59.51,"text":"Even though I'm not honest man","translation":"我并非诚实之人,但也无妨"},{"timestamp":66.7,"text":"It's a breeze","translation":"这事小菜一碟"},{"timestamp":70.4,"text":"I can't be a superstar","translation":"我成为不了超级明星"},{"timestamp":73.43,"text":"Not happy like in the silver screen","translation":"无法像银幕里那样幸福美满"},{"timestamp":77.77,"text":"But we can get everything here","translation":"但在这里,我们能获得想要的一切"},{"timestamp":92.58,"text":"It's Low-key life","translation":"这是低调生活"},{"timestamp":93.94,"text":"It's so small role","translation":"属于边缘配角"},{"timestamp":95.59,"text":"Cursed this terrible doom fades me away","translation":"尽管被诅咒的可怕厄运企图将我扼杀"},{"timestamp":99.92,"text":"But it's a chance to change the life brand new","translation":"但同时它也是令生活焕然一新的良机"},{"timestamp":107.52,"text":"Perfect story is waiting on me who failure","translation":"完美的故事正等着失败的我书写"},{"timestamp":114.92,"text":"Even though I'm not honest man","translation":"我并非诚实之人,但也无妨"},{"timestamp":122.13,"text":"It's a breeze","translation":"这事小菜一碟"},{"timestamp":125.78,"text":"I can't be a superstar","translation":"我成为不了超级明星"},{"timestamp":128.76,"text":"Not happy like in the silver screen","translation":"无法像银幕里那样幸福美满"},{"timestamp":133.18,"text":"But we can get everything here","translation":"但在这里,我们能获得想要的一切"},{"timestamp":155.51,"text":"It's kinda fiction","translation":"这是一篇小说"},{"timestamp":157.39,"text":"It's a made up story","translation":"是虚构的故事"},{"timestamp":159.27,"text":"That would be too good for me, sometimes","translation":"虽然它有时也对我太过友好"},{"timestamp":162.96,"text":"But the beginning is from that point","translation":"但一切都要从那里说起"},{"timestamp":170.01,"text":"It's a breeze","translation":"这事小菜一碟"},{"timestamp":173.8,"text":"I can't be a superstar","translation":"我成为不了超级明星"},{"timestamp":176.75,"text":"Not happy like in the silver screen","translation":"无法像银幕里那样幸福美满"},{"timestamp":181.16,"text":"But we can get everything here","translation":"但在这里,我们能获得想要的一切"},{"timestamp":189.55,"text":"I can't be a superstar","translation":"我成为不了超级明星"},{"timestamp":192.45,"text":"Not happy like in the silver screen","translation":"无法像银幕里那样幸福美满"},{"timestamp":196.89,"text":"But we can get everything here","translation":"但在这里,我们能获得想要的一切"},{"timestamp":211.65,"text":"But we can get everything here","translation":"但在这里,我们能获得想要的一切"}],"rawOriginalLyrics":"[00:00.00] 作词 : えびかれー伯爵/知代/くりーむぱい太郎\n[00:01.00] 作曲 : えびかれー伯爵\n[00:07.66]I can't be a superstar\n[00:10.66]Not happy like in the silver screen\n[00:15.05]But we can get everything here\n[00:22.44]\n[00:37.18]It's kinda fiction\n[00:38.56]It's a made up story\n[00:40.18]That would be too good for me, sometimes\n[00:44.60]But the beginning is from that point\n[00:51.81]\n[00:52.07]Perfect story is waiting on me who failure\n[00:59.51]Even though I'm not honest man\n[01:06.70]It's a breeze\n[01:10.30]\n[01:10.40]I can't be a superstar\n[01:13.43]Not happy like in the silver screen\n[01:17.77]But we can get everything here\n[01:28.93]\n[01:32.58]It's Low-key life\n[01:33.94]It's so small role\n[01:35.59]Cursed this terrible doom fades me away\n[01:39.92]But it's a chance to change the life brand new\n[01:47.24]\n[01:47.52]Perfect story is waiting on me who failure\n[01:54.92]Even though I'm not honest man\n[02:02.13]It's a breeze\n[02:05.68]\n[02:05.78]I can't be a superstar\n[02:08.76]Not happy like in the silver screen\n[02:13.18]But we can get everything here\n[02:24.30]\n[02:35.51]It's kinda fiction\n[02:37.39]It's a made up story\n[02:39.27]That would be too good for me, sometimes\n[02:42.96]But the beginning is from that point\n[02:48.99]\n[02:50.01]It's a breeze\n[02:53.70]\n[02:53.80]I can't be a superstar\n[02:56.75]Not happy like in the silver screen\n[03:01.16]But we can get everything here\n[03:08.61]\n[03:09.55]I can't be a superstar\n[03:12.45]Not happy like in the silver screen\n[03:16.89]But we can get everything here\n[03:28.02]\n[03:31.65]But we can get everything here\n[03:39.62]\n","rawTranslatedLyrics":"\n[00:07.66]我成为不了超级明星\n[00:10.66]无法像银幕里那样幸福美满\n[00:15.05]但在这里,我们能获得想要的一切\n[00:22.44]\n[00:37.18]这是一篇小说\n[00:38.56]是虚构的故事\n[00:40.18]虽然它有时也对我太过友好\n[00:44.60]但一切都要从那里说起\n[00:51.81]\n[00:52.07]完美的故事正等着失败的我书写\n[00:59.51]我并非诚实之人,但也无妨\n[01:06.70]这事小菜一碟\n[01:10.30]\n[01:10.40]我成为不了超级明星\n[01:13.43]无法像银幕里那样幸福美满\n[01:17.77]但在这里,我们能获得想要的一切\n[01:28.93]\n[01:32.58]这是低调生活\n[01:33.94]属于边缘配角\n[01:35.59]尽管被诅咒的可怕厄运企图将我扼杀\n[01:39.92]但同时它也是令生活焕然一新的良机\n[01:47.24]\n[01:47.52]完美的故事正等着失败的我书写\n[01:54.92]我并非诚实之人,但也无妨\n[02:02.13]这事小菜一碟\n[02:05.68]\n[02:05.78]我成为不了超级明星\n[02:08.76]无法像银幕里那样幸福美满\n[02:13.18]但在这里,我们能获得想要的一切\n[02:24.30]\n[02:35.51]这是一篇小说\n[02:37.39]是虚构的故事\n[02:39.27]虽然它有时也对我太过友好\n[02:42.96]但一切都要从那里说起\n[02:48.99]\n[02:50.01]这事小菜一碟\n[02:53.70]\n[02:53.80]我成为不了超级明星\n[02:56.75]无法像银幕里那样幸福美满\n[03:01.16]但在这里,我们能获得想要的一切\n[03:08.61]\n[03:09.55]我成为不了超级明星\n[03:12.45]无法像银幕里那样幸福美满\n[03:16.89]但在这里,我们能获得想要的一切\n[03:28.02]\n[03:31.65]但在这里,我们能获得想要的一切\n[03:39.62]"}
|
package/build/index.d.ts
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
1
|
export * from "./ExpoOrpheusModule";
|
|
2
2
|
export * from "./hooks";
|
|
3
|
+
export type OrpheusHeadlessTrackStartedEvent = {
|
|
4
|
+
eventName: "onTrackStarted";
|
|
5
|
+
trackId: string;
|
|
6
|
+
reason: number;
|
|
7
|
+
};
|
|
8
|
+
export type OrpheusHeadlessEvent = OrpheusHeadlessTrackStartedEvent;
|
|
9
|
+
export declare function registerOrpheusHeadlessTask(task: (event: OrpheusHeadlessEvent) => Promise<void>): void;
|
|
3
10
|
//# sourceMappingURL=index.d.ts.map
|
package/build/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,qBAAqB,CAAC;AACpC,cAAc,SAAS,CAAC;AAIxB,MAAM,MAAM,gCAAgC,GAAG;IAC7C,SAAS,EAAE,gBAAgB,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,gCAAgC,CAAC;AAEpE,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,OAAO,CAAC,IAAI,CAAC,QAGrD"}
|
package/build/index.js
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import { AppRegistry } from "react-native";
|
|
1
2
|
export * from "./ExpoOrpheusModule";
|
|
2
3
|
export * from "./hooks";
|
|
4
|
+
const ORPHEUS_HEADLESS_TASK = "OrpheusHeadlessTask";
|
|
5
|
+
export function registerOrpheusHeadlessTask(task) {
|
|
6
|
+
AppRegistry.registerHeadlessTask(ORPHEUS_HEADLESS_TASK, () => task);
|
|
7
|
+
}
|
|
3
8
|
//# sourceMappingURL=index.js.map
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,SAAS,CAAC","sourcesContent":["
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,cAAc,qBAAqB,CAAC;AACpC,cAAc,SAAS,CAAC;AAExB,MAAM,qBAAqB,GAAG,qBAAqB,CAAC;AAUpD,MAAM,UAAU,2BAA2B,CACzC,IAAoD;IAEpD,WAAW,CAAC,oBAAoB,CAAC,qBAAqB,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;AACtE,CAAC","sourcesContent":["import { AppRegistry } from \"react-native\";\nexport * from \"./ExpoOrpheusModule\";\nexport * from \"./hooks\";\n\nconst ORPHEUS_HEADLESS_TASK = \"OrpheusHeadlessTask\";\n\nexport type OrpheusHeadlessTrackStartedEvent = {\n eventName: \"onTrackStarted\";\n trackId: string;\n reason: number;\n};\n\nexport type OrpheusHeadlessEvent = OrpheusHeadlessTrackStartedEvent;\n\nexport function registerOrpheusHeadlessTask(\n task: (event: OrpheusHeadlessEvent) => Promise<void>\n) {\n AppRegistry.registerHeadlessTask(ORPHEUS_HEADLESS_TASK, () => task);\n}\n"]}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,2 +1,19 @@
|
|
|
1
|
+
import { AppRegistry } from "react-native";
|
|
1
2
|
export * from "./ExpoOrpheusModule";
|
|
2
3
|
export * from "./hooks";
|
|
4
|
+
|
|
5
|
+
const ORPHEUS_HEADLESS_TASK = "OrpheusHeadlessTask";
|
|
6
|
+
|
|
7
|
+
export type OrpheusHeadlessTrackStartedEvent = {
|
|
8
|
+
eventName: "onTrackStarted";
|
|
9
|
+
trackId: string;
|
|
10
|
+
reason: number;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export type OrpheusHeadlessEvent = OrpheusHeadlessTrackStartedEvent;
|
|
14
|
+
|
|
15
|
+
export function registerOrpheusHeadlessTask(
|
|
16
|
+
task: (event: OrpheusHeadlessEvent) => Promise<void>
|
|
17
|
+
) {
|
|
18
|
+
AppRegistry.registerHeadlessTask(ORPHEUS_HEADLESS_TASK, () => task);
|
|
19
|
+
}
|