expo-audio 58.0.9 → 58.0.10

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.
Files changed (55) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/android/build.gradle +2 -2
  3. package/android/src/main/java/expo/modules/audio/AudioRecords.kt +3 -1
  4. package/android/src/main/java/expo/modules/audio/service/AudioControlsService.kt +43 -12
  5. package/android/src/main/java/expo/modules/audio/service/SeekInterval.kt +9 -0
  6. package/build/AudioConstants.d.ts +24 -0
  7. package/build/AudioConstants.js.map +1 -1
  8. package/build/MediaSessionController.web.js +4 -4
  9. package/build/MediaSessionController.web.js.map +1 -1
  10. package/build/utils/lockScreenOptions.d.ts +2 -0
  11. package/build/utils/lockScreenOptions.js +17 -0
  12. package/build/utils/lockScreenOptions.js.map +1 -0
  13. package/ios/AudioRecords.swift +2 -0
  14. package/ios/MediaController.swift +21 -5
  15. package/local-maven-repo/expo/modules/audio/expo.modules.audio/{58.0.9/expo.modules.audio-58.0.9-sources.jar → 58.0.10/expo.modules.audio-58.0.10-sources.jar} +0 -0
  16. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.10/expo.modules.audio-58.0.10-sources.jar.md5 +1 -0
  17. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.10/expo.modules.audio-58.0.10-sources.jar.sha1 +1 -0
  18. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.10/expo.modules.audio-58.0.10-sources.jar.sha256 +1 -0
  19. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.10/expo.modules.audio-58.0.10-sources.jar.sha512 +1 -0
  20. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.10/expo.modules.audio-58.0.10.aar +0 -0
  21. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.10/expo.modules.audio-58.0.10.aar.md5 +1 -0
  22. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.10/expo.modules.audio-58.0.10.aar.sha1 +1 -0
  23. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.10/expo.modules.audio-58.0.10.aar.sha256 +1 -0
  24. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.10/expo.modules.audio-58.0.10.aar.sha512 +1 -0
  25. package/local-maven-repo/expo/modules/audio/expo.modules.audio/{58.0.9/expo.modules.audio-58.0.9.module → 58.0.10/expo.modules.audio-58.0.10.module} +22 -22
  26. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.10/expo.modules.audio-58.0.10.module.md5 +1 -0
  27. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.10/expo.modules.audio-58.0.10.module.sha1 +1 -0
  28. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.10/expo.modules.audio-58.0.10.module.sha256 +1 -0
  29. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.10/expo.modules.audio-58.0.10.module.sha512 +1 -0
  30. package/local-maven-repo/expo/modules/audio/expo.modules.audio/{58.0.9/expo.modules.audio-58.0.9.pom → 58.0.10/expo.modules.audio-58.0.10.pom} +1 -1
  31. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.10/expo.modules.audio-58.0.10.pom.md5 +1 -0
  32. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.10/expo.modules.audio-58.0.10.pom.sha1 +1 -0
  33. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.10/expo.modules.audio-58.0.10.pom.sha256 +1 -0
  34. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.10/expo.modules.audio-58.0.10.pom.sha512 +1 -0
  35. package/package.json +4 -4
  36. package/src/AudioConstants.ts +24 -0
  37. package/src/MediaSessionController.web.ts +4 -5
  38. package/src/utils/lockScreenOptions.ts +21 -0
  39. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.9/expo.modules.audio-58.0.9-sources.jar.md5 +0 -1
  40. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.9/expo.modules.audio-58.0.9-sources.jar.sha1 +0 -1
  41. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.9/expo.modules.audio-58.0.9-sources.jar.sha256 +0 -1
  42. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.9/expo.modules.audio-58.0.9-sources.jar.sha512 +0 -1
  43. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.9/expo.modules.audio-58.0.9.aar +0 -0
  44. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.9/expo.modules.audio-58.0.9.aar.md5 +0 -1
  45. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.9/expo.modules.audio-58.0.9.aar.sha1 +0 -1
  46. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.9/expo.modules.audio-58.0.9.aar.sha256 +0 -1
  47. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.9/expo.modules.audio-58.0.9.aar.sha512 +0 -1
  48. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.9/expo.modules.audio-58.0.9.module.md5 +0 -1
  49. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.9/expo.modules.audio-58.0.9.module.sha1 +0 -1
  50. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.9/expo.modules.audio-58.0.9.module.sha256 +0 -1
  51. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.9/expo.modules.audio-58.0.9.module.sha512 +0 -1
  52. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.9/expo.modules.audio-58.0.9.pom.md5 +0 -1
  53. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.9/expo.modules.audio-58.0.9.pom.sha1 +0 -1
  54. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.9/expo.modules.audio-58.0.9.pom.sha256 +0 -1
  55. package/local-maven-repo/expo/modules/audio/expo.modules.audio/58.0.9/expo.modules.audio-58.0.9.pom.sha512 +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 58.0.10
4
+
5
+ ### Patch Changes
6
+
7
+ - Add `seekForwardIntervalSeconds` and `seekBackwardIntervalSeconds` to `AudioLockScreenOptions` to customize the lock screen skip intervals. Both default to 10 seconds and are clamped to at least 0.1 seconds. ([#44804](https://github.com/expo/expo/pull/44804) by [@radko93](https://github.com/radko93))
8
+
3
9
  ## 58.0.9
4
10
 
5
11
  ### Patch Changes
@@ -4,13 +4,13 @@ plugins {
4
4
  }
5
5
 
6
6
  group = 'expo.modules.audio'
7
- version = '58.0.9'
7
+ version = '58.0.10'
8
8
 
9
9
  android {
10
10
  namespace "expo.modules.audio"
11
11
  defaultConfig {
12
12
  versionCode 1
13
- versionName "58.0.9"
13
+ versionName "58.0.10"
14
14
  }
15
15
 
16
16
  compileOptions {
@@ -114,7 +114,9 @@ class AudioLockScreenOptions(
114
114
  @Field val showSeekBackward: Boolean,
115
115
  @Field val showNextTrack: Boolean = false,
116
116
  @Field val showPreviousTrack: Boolean = false,
117
- @Field val isLiveStream: Boolean? = null
117
+ @Field val isLiveStream: Boolean? = null,
118
+ @Field val seekForwardIntervalSeconds: Double = 10.0,
119
+ @Field val seekBackwardIntervalSeconds: Double = 10.0
118
120
  ) : Record
119
121
 
120
122
  enum class InterruptionMode(val value: String) : Enumerable {
@@ -269,6 +269,22 @@ class AudioControlsService : MediaSessionService() {
269
269
  return builder.build()
270
270
  }
271
271
 
272
+ private fun skipBackIcon(seconds: Double): Int = when (seconds) {
273
+ 5.0 -> CommandButton.ICON_SKIP_BACK_5
274
+ 10.0 -> CommandButton.ICON_SKIP_BACK_10
275
+ 15.0 -> CommandButton.ICON_SKIP_BACK_15
276
+ 30.0 -> CommandButton.ICON_SKIP_BACK_30
277
+ else -> CommandButton.ICON_SKIP_BACK
278
+ }
279
+
280
+ private fun skipForwardIcon(seconds: Double): Int = when (seconds) {
281
+ 5.0 -> CommandButton.ICON_SKIP_FORWARD_5
282
+ 10.0 -> CommandButton.ICON_SKIP_FORWARD_10
283
+ 15.0 -> CommandButton.ICON_SKIP_FORWARD_15
284
+ 30.0 -> CommandButton.ICON_SKIP_FORWARD_30
285
+ else -> CommandButton.ICON_SKIP_FORWARD
286
+ }
287
+
272
288
  private fun updateSessionCustomLayout(isPlaying: Boolean) {
273
289
  val session = mediaSession ?: return
274
290
  val mediaButtons = mutableListOf<CommandButton>()
@@ -285,8 +301,9 @@ class AudioControlsService : MediaSessionService() {
285
301
  .build()
286
302
  )
287
303
  } else if (currentOptions?.showSeekBackward == true) {
304
+ val backwardSeconds = seekIntervalMs(currentOptions?.seekBackwardIntervalSeconds) / 1000.0
288
305
  mediaButtons.add(
289
- CommandButton.Builder(CommandButton.ICON_SKIP_BACK_10)
306
+ CommandButton.Builder(skipBackIcon(backwardSeconds))
290
307
  .setDisplayName("Seek Backward")
291
308
  .setEnabled(true)
292
309
  .setSessionCommand(SessionCommand(ACTION_SEEK_BACKWARD, Bundle.EMPTY))
@@ -326,8 +343,9 @@ class AudioControlsService : MediaSessionService() {
326
343
  .build()
327
344
  )
328
345
  } else if (currentOptions?.showSeekForward == true) {
346
+ val forwardSeconds = seekIntervalMs(currentOptions?.seekForwardIntervalSeconds) / 1000.0
329
347
  mediaButtons.add(
330
- CommandButton.Builder(CommandButton.ICON_SKIP_FORWARD_10)
348
+ CommandButton.Builder(skipForwardIcon(forwardSeconds))
331
349
  .setDisplayName("Seek Forward")
332
350
  .setEnabled(true)
333
351
  .setSessionCommand(SessionCommand(ACTION_SEEK_FORWARD, Bundle.EMPTY))
@@ -385,15 +403,28 @@ class AudioControlsService : MediaSessionService() {
385
403
  private fun resolveSessionPlayer(playable: LockScreenPlayable, options: AudioLockScreenOptions?): Player {
386
404
  val player = PlayRequestingPlayer(playable.player) { playable.requestPlay() }
387
405
  val isLive = options?.isLiveStream ?: playable.isLive
388
- if (!isLive) {
389
- return player
390
- }
406
+ val forwardMs = seekIntervalMs(options?.seekForwardIntervalSeconds)
407
+ val backwardMs = seekIntervalMs(options?.seekBackwardIntervalSeconds)
391
408
 
392
409
  return object : ForwardingPlayer(player) {
410
+ override fun getSeekForwardIncrement(): Long = forwardMs
411
+
412
+ override fun getSeekBackIncrement(): Long = backwardMs
413
+
414
+ override fun seekForward() {
415
+ seekTo(currentPosition + forwardMs)
416
+ }
417
+
418
+ override fun seekBack() {
419
+ seekTo((currentPosition - backwardMs).coerceAtLeast(0))
420
+ }
421
+
393
422
  override fun getAvailableCommands(): Player.Commands {
394
- return super.getAvailableCommands().buildUpon()
395
- .remove(Player.COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM)
396
- .build()
423
+ val commands = super.getAvailableCommands().buildUpon()
424
+ if (isLive) {
425
+ commands.remove(Player.COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM)
426
+ }
427
+ return commands.build()
397
428
  }
398
429
  }
399
430
  }
@@ -532,13 +563,15 @@ class AudioControlsService : MediaSessionService() {
532
563
 
533
564
  fun seekForward() {
534
565
  currentPlayable?.player?.let { player ->
535
- player.seekTo(player.currentPosition + SEEK_INTERVAL_MS)
566
+ val intervalMs = seekIntervalMs(currentOptions?.seekForwardIntervalSeconds)
567
+ player.seekTo(player.currentPosition + intervalMs)
536
568
  }
537
569
  }
538
570
 
539
571
  fun seekBackward() {
540
572
  currentPlayable?.player?.let { player ->
541
- player.seekTo(player.currentPosition - SEEK_INTERVAL_MS)
573
+ val intervalMs = seekIntervalMs(currentOptions?.seekBackwardIntervalSeconds)
574
+ player.seekTo((player.currentPosition - intervalMs).coerceAtLeast(0))
542
575
  }
543
576
  }
544
577
 
@@ -660,7 +693,5 @@ class AudioControlsService : MediaSessionService() {
660
693
  const val ACTION_SEEK_BACKWARD = "expo.modules.audio.action.SEEK_BACKWARD"
661
694
  const val ACTION_NEXT_TRACK = "expo.modules.audio.action.NEXT_TRACK"
662
695
  const val ACTION_PREVIOUS_TRACK = "expo.modules.audio.action.PREVIOUS_TRACK"
663
-
664
- const val SEEK_INTERVAL_MS = 10000L
665
696
  }
666
697
  }
@@ -0,0 +1,9 @@
1
+ package expo.modules.audio.service
2
+
3
+ private const val DEFAULT_SEEK_INTERVAL_SECONDS = 10.0
4
+ private const val MIN_SEEK_INTERVAL_MS = 100L
5
+
6
+ internal fun seekIntervalMs(seconds: Double?): Long {
7
+ val resolved = seconds?.takeIf { it.isFinite() } ?: DEFAULT_SEEK_INTERVAL_SECONDS
8
+ return (resolved * 1000).toLong().coerceAtLeast(MIN_SEEK_INTERVAL_MS)
9
+ }
@@ -23,4 +23,28 @@ export type AudioLockScreenOptions = {
23
23
  * and scrub bar, and disable seek controls.
24
24
  */
25
25
  isLiveStream?: boolean;
26
+ /**
27
+ * How far, in seconds, the lock screen seek forward button jumps ahead.
28
+ * Values below `0.1` are clamped up to `0.1` so that the button always moves playback.
29
+ *
30
+ * On Android, the whole-second values `5`, `10`, `15`, and `30` render a matching numbered skip
31
+ * icon, and every other value renders a generic skip icon. On iOS, the number is drawn into the
32
+ * glyph for any value, because it is passed through as the skip command's preferred interval.
33
+ * On web, the browser decides which control it shows and which offset it sends, so this value is
34
+ * only used as a fallback when the browser omits an offset of its own.
35
+ * @default 10
36
+ */
37
+ seekForwardIntervalSeconds?: number;
38
+ /**
39
+ * How far, in seconds, the lock screen seek backward button jumps back.
40
+ * Values below `0.1` are clamped up to `0.1` so that the button always moves playback.
41
+ *
42
+ * On Android, the whole-second values `5`, `10`, `15`, and `30` render a matching numbered skip
43
+ * icon, and every other value renders a generic skip icon. On iOS, the number is drawn into the
44
+ * glyph for any value, because it is passed through as the skip command's preferred interval.
45
+ * On web, the browser decides which control it shows and which offset it sends, so this value is
46
+ * only used as a fallback when the browser omits an offset of its own.
47
+ * @default 10
48
+ */
49
+ seekBackwardIntervalSeconds?: number;
26
50
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["AudioConstants.ts"],"sourcesContent":[null],"names":[],"mappings":"AAAA,cAAc;AACd;;CAEC,GACD,WAsBE"}
1
+ {"version":3,"sources":["AudioConstants.ts"],"sourcesContent":[null],"names":[],"mappings":"AAAA,cAAc;AACd;;CAEC,GACD,WA8CE"}
@@ -1,4 +1,4 @@
1
- const SKIP_SECONDS = 10;
1
+ import { normalizeLockScreenOptions } from './utils/lockScreenOptions';
2
2
  class MediaSessionController {
3
3
  activePlayer = null;
4
4
  metadata = null;
@@ -10,7 +10,7 @@ class MediaSessionController {
10
10
  }
11
11
  this.activePlayer = player;
12
12
  this.metadata = metadata ?? null;
13
- this.options = options ?? null;
13
+ this.options = normalizeLockScreenOptions(options);
14
14
  this._applyMetadata();
15
15
  this._applyActionHandlers();
16
16
  this.updatePlaybackState(player);
@@ -115,13 +115,13 @@ class MediaSessionController {
115
115
  }
116
116
  });
117
117
  const seekForward = (details)=>{
118
- const skipTime = details.seekOffset ?? SKIP_SECONDS;
118
+ const skipTime = details.seekOffset ?? this.options?.seekForwardIntervalSeconds ?? 10;
119
119
  const newTime = Math.min(player.currentTime + skipTime, player.duration || 0);
120
120
  player.seekTo(newTime);
121
121
  this.updatePositionState(player);
122
122
  };
123
123
  const seekBackward = (details)=>{
124
- const skipTime = details.seekOffset ?? SKIP_SECONDS;
124
+ const skipTime = details.seekOffset ?? this.options?.seekBackwardIntervalSeconds ?? 10;
125
125
  const newTime = Math.max(player.currentTime - skipTime, 0);
126
126
  player.seekTo(newTime);
127
127
  this.updatePositionState(player);
@@ -1 +1 @@
1
- {"version":3,"sources":["MediaSessionController.web.ts"],"sourcesContent":[null],"names":["SKIP_SECONDS","MediaSessionController","activePlayer","metadata","options","setActivePlayer","player","navigator","mediaSession","clear","_applyMetadata","_applyActionHandlers","updatePlaybackState","updatePositionState","updateMetadata","playbackState","actions","action","_setHandler","setPositionState","playing","duration","Number","isFinite","position","Math","min","max","currentTime","playbackRate","isActive","getActiveState","title","artist","albumTitle","artworkUrl","artwork","src","MediaMetadata","album","handler","setActionHandler","play","pause","details","seekTime","seekTo","seekForward","skipTime","seekOffset","newTime","seekBackward","showSeekForward","showSeekBackward","showNextTrack","next","showPreviousTrack","previous","mediaSessionController"],"mappings":"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"}
1
+ {"version":3,"sources":["MediaSessionController.web.ts"],"sourcesContent":[null],"names":["normalizeLockScreenOptions","MediaSessionController","activePlayer","metadata","options","setActivePlayer","player","navigator","mediaSession","clear","_applyMetadata","_applyActionHandlers","updatePlaybackState","updatePositionState","updateMetadata","playbackState","actions","action","_setHandler","setPositionState","playing","duration","Number","isFinite","position","Math","min","max","currentTime","playbackRate","isActive","getActiveState","title","artist","albumTitle","artworkUrl","artwork","src","MediaMetadata","album","handler","setActionHandler","play","pause","details","seekTime","seekTo","seekForward","skipTime","seekOffset","seekForwardIntervalSeconds","newTime","seekBackward","seekBackwardIntervalSeconds","showSeekForward","showSeekBackward","showNextTrack","next","showPreviousTrack","previous","mediaSessionController"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { AudioLockScreenOptions } from '../AudioConstants';
2
+ export declare function normalizeLockScreenOptions(options: AudioLockScreenOptions | undefined): AudioLockScreenOptions;
@@ -0,0 +1,17 @@
1
+ const DEFAULT_SEEK_INTERVAL_SECONDS = 10;
2
+ const MIN_SEEK_INTERVAL_SECONDS = 0.1;
3
+ function normalizeInterval(seconds) {
4
+ if (seconds === undefined || !Number.isFinite(seconds)) {
5
+ return DEFAULT_SEEK_INTERVAL_SECONDS;
6
+ }
7
+ return Math.max(seconds, MIN_SEEK_INTERVAL_SECONDS);
8
+ }
9
+ export function normalizeLockScreenOptions(options) {
10
+ return {
11
+ ...options,
12
+ seekForwardIntervalSeconds: normalizeInterval(options?.seekForwardIntervalSeconds),
13
+ seekBackwardIntervalSeconds: normalizeInterval(options?.seekBackwardIntervalSeconds)
14
+ };
15
+ }
16
+
17
+ //# sourceMappingURL=lockScreenOptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["utils/lockScreenOptions.ts"],"sourcesContent":[null],"names":["DEFAULT_SEEK_INTERVAL_SECONDS","MIN_SEEK_INTERVAL_SECONDS","normalizeInterval","seconds","undefined","Number","isFinite","Math","max","normalizeLockScreenOptions","options","seekForwardIntervalSeconds","seekBackwardIntervalSeconds"],"mappings":"AAEA,MAAMA,gCAAgC;AACtC,MAAMC,4BAA4B;AAElC,SAASC,kBAAkBC,OAA2B;IACpD,IAAIA,YAAYC,aAAa,CAACC,OAAOC,QAAQ,CAACH,UAAU;QACtD,OAAOH;IACT;IACA,OAAOO,KAAKC,GAAG,CAACL,SAASF;AAC3B;AAEA,OAAO,SAASQ,2BACdC,OAA2C;IAE3C,OAAO;QACL,GAAGA,OAAO;QACVC,4BAA4BT,kBAAkBQ,SAASC;QACvDC,6BAA6BV,kBAAkBQ,SAASE;IAC1D;AACF"}
@@ -82,6 +82,8 @@ struct LockScreenOptions: Record {
82
82
  @Field var showNextTrack: Bool = false
83
83
  @Field var showPreviousTrack: Bool = false
84
84
  @Field var isLiveStream: Bool? = false
85
+ @Field var seekForwardIntervalSeconds: Double = 10.0
86
+ @Field var seekBackwardIntervalSeconds: Double = 10.0
85
87
  }
86
88
 
87
89
  enum BitRateStrategy: String, Enumerable {
@@ -279,6 +279,20 @@ class MediaController {
279
279
  .resume()
280
280
  }
281
281
 
282
+ static func cmTime(seconds: Double) -> CMTime {
283
+ return CMTime(seconds: seconds, preferredTimescale: CMTimeScale(NSEC_PER_SEC))
284
+ }
285
+
286
+ static func normalizedSkipInterval(_ seconds: Double?) -> Double {
287
+ guard let seconds, seconds.isFinite else {
288
+ return defaultSkipIntervalSeconds
289
+ }
290
+ return max(seconds, minSkipIntervalSeconds)
291
+ }
292
+
293
+ private static let defaultSkipIntervalSeconds = 10.0
294
+ private static let minSkipIntervalSeconds = 0.1
295
+
282
296
  private func enableRemoteCommands(options: LockScreenOptions?) {
283
297
  removeRemoteCommandTargets()
284
298
 
@@ -322,14 +336,15 @@ class MediaController {
322
336
  return .commandFailed
323
337
  }
324
338
 
325
- let seekTime = CMTime(seconds: event.positionTime, preferredTimescale: 1)
339
+ let seekTime = MediaController.cmTime(seconds: event.positionTime)
326
340
  playable.lockScreenPlayer.seek(to: seekTime)
327
341
 
328
342
  return .success
329
343
  }
330
344
  remoteCommandTargets.append((remoteCommandCenter.changePlaybackPositionCommand, changePlaybackPositionTarget))
331
345
 
332
- remoteCommandCenter.skipForwardCommand.preferredIntervals = [10.0]
346
+ let forwardInterval = MediaController.normalizedSkipInterval(options?.seekForwardIntervalSeconds)
347
+ remoteCommandCenter.skipForwardCommand.preferredIntervals = [NSNumber(value: forwardInterval)]
333
348
  let skipForwardTarget = remoteCommandCenter.skipForwardCommand.addTarget { [weak self] event in
334
349
  guard let playable = self?.activePlayable,
335
350
  let event = event as? MPSkipIntervalCommandEvent else {
@@ -337,14 +352,15 @@ class MediaController {
337
352
  }
338
353
 
339
354
  let currentTime = playable.lockScreenPlayer.currentTime()
340
- let seekTime = currentTime + CMTime(seconds: event.interval, preferredTimescale: 1)
355
+ let seekTime = currentTime + MediaController.cmTime(seconds: event.interval)
341
356
  playable.lockScreenPlayer.seek(to: seekTime, toleranceBefore: .zero, toleranceAfter: .zero)
342
357
 
343
358
  return .success
344
359
  }
345
360
  remoteCommandTargets.append((remoteCommandCenter.skipForwardCommand, skipForwardTarget))
346
361
 
347
- remoteCommandCenter.skipBackwardCommand.preferredIntervals = [10.0]
362
+ let backwardInterval = MediaController.normalizedSkipInterval(options?.seekBackwardIntervalSeconds)
363
+ remoteCommandCenter.skipBackwardCommand.preferredIntervals = [NSNumber(value: backwardInterval)]
348
364
  let skipBackwardTarget = remoteCommandCenter.skipBackwardCommand.addTarget { [weak self] event in
349
365
  guard let playable = self?.activePlayable,
350
366
  let event = event as? MPSkipIntervalCommandEvent else {
@@ -352,7 +368,7 @@ class MediaController {
352
368
  }
353
369
 
354
370
  let currentTime = playable.lockScreenPlayer.currentTime()
355
- let seekTime = currentTime - CMTime(seconds: event.interval, preferredTimescale: 1)
371
+ let seekTime = currentTime - MediaController.cmTime(seconds: event.interval)
356
372
  playable.lockScreenPlayer.seek(to: seekTime, toleranceBefore: .zero, toleranceAfter: .zero)
357
373
 
358
374
  return .success
@@ -0,0 +1 @@
1
+ e7035fa3aa4c45a8f1c77d9472b35851ffb8e75bed9e68db92e2fd37244af937
@@ -0,0 +1 @@
1
+ b649370f9eddc880f23c87efa10c0c2945fe4cff8305a53ab9c4daf2709130c8fe2cac5704709d502934cc0715442b81bd04295ea089e9ea7d1d2b7c778a5b45
@@ -0,0 +1 @@
1
+ ad896a65fac8e318f5c60bed4af93679a59f13e14e2d0efc403172de490e5651
@@ -0,0 +1 @@
1
+ 07c509104e22b83b36e7e8b4b41d3b991945b3840e88136de912c13b7cb99527471248df5804f37d1ab675ca1e5d013110ec6e4e0f3df39328514ec182a3b5cb
@@ -3,7 +3,7 @@
3
3
  "component": {
4
4
  "group": "expo.modules.audio",
5
5
  "module": "expo.modules.audio",
6
- "version": "58.0.9",
6
+ "version": "58.0.10",
7
7
  "attributes": {
8
8
  "org.gradle.status": "release"
9
9
  }
@@ -24,13 +24,13 @@
24
24
  },
25
25
  "files": [
26
26
  {
27
- "name": "expo.modules.audio-58.0.9.aar",
28
- "url": "expo.modules.audio-58.0.9.aar",
29
- "size": 562788,
30
- "sha512": "4251e28214a66fe78e625507dc58ff5a7f4547ce00a7ac7fd93171043547fd383168a0fff1936654259ebb916e4ac392770afd96be55a8ec7e7185fac49f7d2f",
31
- "sha256": "148a8d932e5afc93e3a3cf4ea35d969d7f3329ac3127cc9da9fea428144321c9",
32
- "sha1": "bc24348a398e64ff880dc00571befaff11fcdd7c",
33
- "md5": "9bd94c9bb03c7d84ae5536946035f450"
27
+ "name": "expo.modules.audio-58.0.10.aar",
28
+ "url": "expo.modules.audio-58.0.10.aar",
29
+ "size": 565381,
30
+ "sha512": "07c509104e22b83b36e7e8b4b41d3b991945b3840e88136de912c13b7cb99527471248df5804f37d1ab675ca1e5d013110ec6e4e0f3df39328514ec182a3b5cb",
31
+ "sha256": "ad896a65fac8e318f5c60bed4af93679a59f13e14e2d0efc403172de490e5651",
32
+ "sha1": "e68c21381c292fb846dfbf1e5d1100a8121ac714",
33
+ "md5": "20a4382720f542aa2ff96be772e74dd8"
34
34
  }
35
35
  ]
36
36
  },
@@ -137,13 +137,13 @@
137
137
  ],
138
138
  "files": [
139
139
  {
140
- "name": "expo.modules.audio-58.0.9.aar",
141
- "url": "expo.modules.audio-58.0.9.aar",
142
- "size": 562788,
143
- "sha512": "4251e28214a66fe78e625507dc58ff5a7f4547ce00a7ac7fd93171043547fd383168a0fff1936654259ebb916e4ac392770afd96be55a8ec7e7185fac49f7d2f",
144
- "sha256": "148a8d932e5afc93e3a3cf4ea35d969d7f3329ac3127cc9da9fea428144321c9",
145
- "sha1": "bc24348a398e64ff880dc00571befaff11fcdd7c",
146
- "md5": "9bd94c9bb03c7d84ae5536946035f450"
140
+ "name": "expo.modules.audio-58.0.10.aar",
141
+ "url": "expo.modules.audio-58.0.10.aar",
142
+ "size": 565381,
143
+ "sha512": "07c509104e22b83b36e7e8b4b41d3b991945b3840e88136de912c13b7cb99527471248df5804f37d1ab675ca1e5d013110ec6e4e0f3df39328514ec182a3b5cb",
144
+ "sha256": "ad896a65fac8e318f5c60bed4af93679a59f13e14e2d0efc403172de490e5651",
145
+ "sha1": "e68c21381c292fb846dfbf1e5d1100a8121ac714",
146
+ "md5": "20a4382720f542aa2ff96be772e74dd8"
147
147
  }
148
148
  ]
149
149
  },
@@ -157,13 +157,13 @@
157
157
  },
158
158
  "files": [
159
159
  {
160
- "name": "expo.modules.audio-58.0.9-sources.jar",
161
- "url": "expo.modules.audio-58.0.9-sources.jar",
162
- "size": 44166,
163
- "sha512": "ec4911e9008b292a0785c1496a40432c56b611dc2f19ecb0dc71020d4b439fed146d7bb18337a96bf6b77da28cb0fe71e6e8c7bd17b37649e554e4de43fb9d37",
164
- "sha256": "0f11527368066bf18f182fb39f3c1d69696aa59ddaec4b7ee16ec48183e25e23",
165
- "sha1": "cbab8824e92895ba7865770ec62e4875325bd42a",
166
- "md5": "a514205fbda56545f5396a0990b9f4f9"
160
+ "name": "expo.modules.audio-58.0.10-sources.jar",
161
+ "url": "expo.modules.audio-58.0.10-sources.jar",
162
+ "size": 44839,
163
+ "sha512": "b649370f9eddc880f23c87efa10c0c2945fe4cff8305a53ab9c4daf2709130c8fe2cac5704709d502934cc0715442b81bd04295ea089e9ea7d1d2b7c778a5b45",
164
+ "sha256": "e7035fa3aa4c45a8f1c77d9472b35851ffb8e75bed9e68db92e2fd37244af937",
165
+ "sha1": "1089c59b7c8b6286130e48fa84cdbd683184f842",
166
+ "md5": "7f6fb27d35bc920588fa9100a7fd63ac"
167
167
  }
168
168
  ]
169
169
  }
@@ -0,0 +1 @@
1
+ 0b7117f23a0d5366f3cefc72504b605109b54030cd2ad58c80002f0c26b137d7
@@ -0,0 +1 @@
1
+ 1fa307765b9ee64dea9bf2ad272bf9e725549e6e146239d854658255170cc0471e248e62fd37f49fff2e1d2007b8be09f1d348f390ed62d68d59b3b35e19555d
@@ -9,7 +9,7 @@
9
9
  <modelVersion>4.0.0</modelVersion>
10
10
  <groupId>expo.modules.audio</groupId>
11
11
  <artifactId>expo.modules.audio</artifactId>
12
- <version>58.0.9</version>
12
+ <version>58.0.10</version>
13
13
  <packaging>aar</packaging>
14
14
  <name>expo.modules.audio</name>
15
15
  <url>https://github.com/expo/expo</url>
@@ -0,0 +1 @@
1
+ 6d976674b65585be9eac9979969db121c77c3a2123914e62a6d4b7dd3daa6225
@@ -0,0 +1 @@
1
+ 7a3baec32e592adc2a07e478a8f25d0d6716a307de5835408687a5f16be0d5e02328c0b2a2ad0c5753767cc9d91d0178fddbb79da90aa90f12967eb4a0424cbf
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-audio",
3
- "version": "58.0.9",
3
+ "version": "58.0.10",
4
4
  "description": "A cross-platform audio library for React Native and Expo apps.",
5
5
  "keywords": [
6
6
  "android",
@@ -22,12 +22,12 @@
22
22
  "main": "build/index.js",
23
23
  "types": "build/index.d.ts",
24
24
  "devDependencies": {
25
- "@expo/internal-scripts": "58.0.1",
25
+ "@expo/internal-scripts": "58.0.4",
26
26
  "@types/jest": "^30.0.0",
27
27
  "@types/node": "^22.14.0",
28
28
  "@types/react": "~19.3.0",
29
- "expo": "58.0.8",
30
- "expo-asset": "58.0.14"
29
+ "expo": "58.0.17",
30
+ "expo-asset": "58.0.18"
31
31
  },
32
32
  "peerDependencies": {
33
33
  "expo": "*",
@@ -24,4 +24,28 @@ export type AudioLockScreenOptions = {
24
24
  * and scrub bar, and disable seek controls.
25
25
  */
26
26
  isLiveStream?: boolean;
27
+ /**
28
+ * How far, in seconds, the lock screen seek forward button jumps ahead.
29
+ * Values below `0.1` are clamped up to `0.1` so that the button always moves playback.
30
+ *
31
+ * On Android, the whole-second values `5`, `10`, `15`, and `30` render a matching numbered skip
32
+ * icon, and every other value renders a generic skip icon. On iOS, the number is drawn into the
33
+ * glyph for any value, because it is passed through as the skip command's preferred interval.
34
+ * On web, the browser decides which control it shows and which offset it sends, so this value is
35
+ * only used as a fallback when the browser omits an offset of its own.
36
+ * @default 10
37
+ */
38
+ seekForwardIntervalSeconds?: number;
39
+ /**
40
+ * How far, in seconds, the lock screen seek backward button jumps back.
41
+ * Values below `0.1` are clamped up to `0.1` so that the button always moves playback.
42
+ *
43
+ * On Android, the whole-second values `5`, `10`, `15`, and `30` render a matching numbered skip
44
+ * icon, and every other value renders a generic skip icon. On iOS, the number is drawn into the
45
+ * glyph for any value, because it is passed through as the skip command's preferred interval.
46
+ * On web, the browser decides which control it shows and which offset it sends, so this value is
47
+ * only used as a fallback when the browser omits an offset of its own.
48
+ * @default 10
49
+ */
50
+ seekBackwardIntervalSeconds?: number;
27
51
  };
@@ -1,5 +1,6 @@
1
1
  import type { AudioMetadata } from './Audio.types';
2
2
  import type { AudioLockScreenOptions } from './AudioConstants';
3
+ import { normalizeLockScreenOptions } from './utils/lockScreenOptions';
3
4
 
4
5
  interface MediaSessionPlayer {
5
6
  play(): void;
@@ -13,8 +14,6 @@ interface MediaSessionPlayer {
13
14
  readonly playbackRate: number;
14
15
  }
15
16
 
16
- const SKIP_SECONDS = 10;
17
-
18
17
  class MediaSessionController {
19
18
  private activePlayer: MediaSessionPlayer | null = null;
20
19
  private metadata: AudioMetadata | null = null;
@@ -33,7 +32,7 @@ class MediaSessionController {
33
32
 
34
33
  this.activePlayer = player;
35
34
  this.metadata = metadata ?? null;
36
- this.options = options ?? null;
35
+ this.options = normalizeLockScreenOptions(options);
37
36
 
38
37
  this._applyMetadata();
39
38
  this._applyActionHandlers();
@@ -159,14 +158,14 @@ class MediaSessionController {
159
158
  });
160
159
 
161
160
  const seekForward = (details: MediaSessionActionDetails) => {
162
- const skipTime = details.seekOffset ?? SKIP_SECONDS;
161
+ const skipTime = details.seekOffset ?? this.options?.seekForwardIntervalSeconds ?? 10;
163
162
  const newTime = Math.min(player.currentTime + skipTime, player.duration || 0);
164
163
  player.seekTo(newTime);
165
164
  this.updatePositionState(player);
166
165
  };
167
166
 
168
167
  const seekBackward = (details: MediaSessionActionDetails) => {
169
- const skipTime = details.seekOffset ?? SKIP_SECONDS;
168
+ const skipTime = details.seekOffset ?? this.options?.seekBackwardIntervalSeconds ?? 10;
170
169
  const newTime = Math.max(player.currentTime - skipTime, 0);
171
170
  player.seekTo(newTime);
172
171
  this.updatePositionState(player);
@@ -0,0 +1,21 @@
1
+ import type { AudioLockScreenOptions } from '../AudioConstants';
2
+
3
+ const DEFAULT_SEEK_INTERVAL_SECONDS = 10;
4
+ const MIN_SEEK_INTERVAL_SECONDS = 0.1;
5
+
6
+ function normalizeInterval(seconds: number | undefined): number {
7
+ if (seconds === undefined || !Number.isFinite(seconds)) {
8
+ return DEFAULT_SEEK_INTERVAL_SECONDS;
9
+ }
10
+ return Math.max(seconds, MIN_SEEK_INTERVAL_SECONDS);
11
+ }
12
+
13
+ export function normalizeLockScreenOptions(
14
+ options: AudioLockScreenOptions | undefined
15
+ ): AudioLockScreenOptions {
16
+ return {
17
+ ...options,
18
+ seekForwardIntervalSeconds: normalizeInterval(options?.seekForwardIntervalSeconds),
19
+ seekBackwardIntervalSeconds: normalizeInterval(options?.seekBackwardIntervalSeconds),
20
+ };
21
+ }
@@ -1 +0,0 @@
1
- 0f11527368066bf18f182fb39f3c1d69696aa59ddaec4b7ee16ec48183e25e23
@@ -1 +0,0 @@
1
- ec4911e9008b292a0785c1496a40432c56b611dc2f19ecb0dc71020d4b439fed146d7bb18337a96bf6b77da28cb0fe71e6e8c7bd17b37649e554e4de43fb9d37
@@ -1 +0,0 @@
1
- bc24348a398e64ff880dc00571befaff11fcdd7c
@@ -1 +0,0 @@
1
- 148a8d932e5afc93e3a3cf4ea35d969d7f3329ac3127cc9da9fea428144321c9
@@ -1 +0,0 @@
1
- 4251e28214a66fe78e625507dc58ff5a7f4547ce00a7ac7fd93171043547fd383168a0fff1936654259ebb916e4ac392770afd96be55a8ec7e7185fac49f7d2f
@@ -1 +0,0 @@
1
- fc5b401e0b74ce952248f6326f1886e58c5782af8ba4be045499ce3d6662a248
@@ -1 +0,0 @@
1
- 0bf6874fcb8ebe25db4034cff6ff6f76dedfb0f0640dc04f825d50a321801a66598c09c5eb4b8daaa0a27bd64b2208e53ed19aa4632674de03d125b1ae50c6f1
@@ -1 +0,0 @@
1
- 0753d2a03dadccd6ec89f924f7d7a530003a397b
@@ -1 +0,0 @@
1
- b7cd8f79f5f7e4914206b6912eeb50edd852a485299c7c3e430306db626ce63b
@@ -1 +0,0 @@
1
- 641646b9c31bd16aa30a7bf6cac11ad642525e2812a41ca135edcfbddece5e8038816658ff8906941ef5e3343f87b870dd8774790484c339997f15558f6f4b5b