Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ enum class CustomCommandButton(
),
PREVIOUS(
customAction = "PREVIOUS",
capability = Capability.SKIP_TO_NEXT,
capability = Capability.SKIP_TO_PREVIOUS,
commandButton = CommandButton.Builder()
.setDisplayName("Previous")
.setSessionCommand(SessionCommand("PREVIOUS", Bundle()))
Expand All @@ -39,7 +39,7 @@ enum class CustomCommandButton(
),
NEXT(
customAction = "NEXT",
capability = Capability.SKIP_TO_PREVIOUS,
capability = Capability.SKIP_TO_NEXT,
commandButton = CommandButton.Builder()
.setDisplayName("Next")
.setSessionCommand(SessionCommand("NEXT", Bundle()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,14 @@ abstract class BaseAudioPlayer internal constructor(
playerEventHolder.updateOnPlayerActionTriggeredExternally(MediaSessionCallback.PAUSE)
}

override fun setPlayWhenReady(playWhenReady: Boolean) {
if (playWhenReady) {
playerEventHolder.updateOnPlayerActionTriggeredExternally(MediaSessionCallback.PLAY)
} else {
playerEventHolder.updateOnPlayerActionTriggeredExternally(MediaSessionCallback.PAUSE)
}
}

override fun seekToNext() {
playerEventHolder.updateOnPlayerActionTriggeredExternally(MediaSessionCallback.NEXT)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,38 @@ class MusicService : HeadlessJsMediaService() {
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
onStartCommandIntentValid = intent != null
Timber.d("onStartCommand: ${intent?.action}, ${intent?.`package`}")

// Handle custom notification button clicks (NEXT, PREVIOUS, JUMP_FORWARD, JUMP_BACKWARD)
// from Media3's notification UI. This works on all Android versions.
if (intent?.action == ACTION_CUSTOM_NOTIFICATION_ACTION) {
val customAction = intent.getStringExtra(EXTRAS_KEY_CUSTOM_NOTIFICATION_ACTION)

if (customAction != null && ::player.isInitialized) {
player.forwardingPlayer.let {
when (customAction) {
CustomCommandButton.JUMP_BACKWARD.customAction -> {
it.seekBack()
}
CustomCommandButton.JUMP_FORWARD.customAction -> {
it.seekForward()
}
CustomCommandButton.NEXT.customAction -> {
it.seekToNext()
}
CustomCommandButton.PREVIOUS.customAction -> {
it.seekToPrevious()
}
else -> {
Timber.d("Unknown custom action: $customAction")
}
}
}
}
}

// Handle hardware media buttons (Bluetooth, car stereo, etc.) on Android < 13
// On Android 13+, these are handled via onMediaButtonEvent callback instead
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
// HACK: this is not supposed to be here. I definitely screwed up. but Why?
onMediaKeyEvent(intent)
}
// HACK: Why is onPlay triggering onStartCommand??
Expand Down Expand Up @@ -812,7 +842,15 @@ class MusicService : HeadlessJsMediaService() {
if (keyEvent?.action == KeyEvent.ACTION_DOWN) {
return when (keyEvent.keyCode) {
KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE -> {
emit(MusicEvents.BUTTON_PLAY_PAUSE)
if (::player.isInitialized) {
if (player.isPlaying) {
emit(MusicEvents.BUTTON_PAUSE)
} else {
emit(MusicEvents.BUTTON_PLAY)
}
} else {
emit(MusicEvents.BUTTON_PLAY_PAUSE)
}
true
}

Expand Down Expand Up @@ -933,10 +971,19 @@ class MusicService : HeadlessJsMediaService() {
): ListenableFuture<SessionResult> {
player.forwardingPlayer.let {
when (command.customAction) {
CustomCommandButton.JUMP_BACKWARD.customAction -> { it.seekBack() }
CustomCommandButton.JUMP_FORWARD.customAction -> { it.seekForward() }
CustomCommandButton.NEXT.customAction -> { it.seekToNext() }
CustomCommandButton.PREVIOUS.customAction -> { it.seekToPrevious() }
CustomCommandButton.JUMP_BACKWARD.customAction -> {
it.seekBack()
}
CustomCommandButton.JUMP_FORWARD.customAction -> {
it.seekForward()
}
CustomCommandButton.NEXT.customAction -> {
it.seekToNext()
}
CustomCommandButton.PREVIOUS.customAction -> {
it.seekToPrevious()
}
else -> {}
}
}
return super.onCustomCommand(session, controller, command, args)
Expand Down Expand Up @@ -994,6 +1041,10 @@ class MusicService : HeadlessJsMediaService() {
const val DURATION_KEY = "duration"
const val BUFFERED_POSITION_KEY = "buffered"

// Media3 custom notification action constants
const val ACTION_CUSTOM_NOTIFICATION_ACTION = "androidx.media3.session.CUSTOM_NOTIFICATION_ACTION"
const val EXTRAS_KEY_CUSTOM_NOTIFICATION_ACTION = "androidx.media3.session.EXTRAS_KEY_CUSTOM_NOTIFICATION_ACTION"

const val TASK_KEY = "TrackPlayer"

const val MIN_BUFFER_KEY = "minBuffer"
Expand Down
2 changes: 2 additions & 0 deletions example/.ruby-version
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
3.3.6

5 changes: 4 additions & 1 deletion example/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ source 'https://rubygems.org'
# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
ruby ">= 2.6.10"

# Load kconv compatibility patch for Ruby 3.4
require_relative 'kconv_patch'

# Exclude problematic versions of cocoapods and activesupport that causes build failures.
gem 'cocoapods', '>= 1.13', '!= 1.15.0', '!= 1.15.1'
gem 'cocoapods', '>= 1.13', '!= 1.15.0', '!= 1.15.1', '< 1.17.0'
gem 'activesupport', '>= 6.1.7.5', '!= 7.1.0'
gem 'xcodeproj', '< 1.26.0'
gem 'concurrent-ruby', '< 1.3.4'
Expand Down
51 changes: 29 additions & 22 deletions example/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.7)
CFPropertyList (3.0.8)
activesupport (7.2.3)
base64
nkf
rexml
activesupport (6.1.7.10)
concurrent-ruby (~> 1.0, >= 1.0.2)
benchmark (>= 0.3)
bigdecimal
concurrent-ruby (~> 1.0, >= 1.3.1)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
logger (>= 1.4.2)
minitest (>= 5.1)
tzinfo (~> 2.0)
zeitwerk (~> 2.3)
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
securerandom (>= 0.3)
tzinfo (~> 2.0, >= 2.0.5)
addressable (2.8.8)
public_suffix (>= 2.0.2, < 8.0)
algoliasearch (1.27.5)
httpclient (~> 2.8, >= 2.8.3)
json (>= 1.5.1)
atomos (0.1.3)
base64 (0.3.0)
benchmark (0.4.1)
bigdecimal (3.2.2)
benchmark (0.5.0)
bigdecimal (4.0.1)
claide (1.1.0)
cocoapods (1.15.2)
addressable (~> 2.8)
Expand Down Expand Up @@ -60,29 +63,34 @@ GEM
cocoapods-try (1.2.0)
colored2 (3.1.2)
concurrent-ruby (1.3.3)
connection_pool (3.0.2)
drb (2.2.3)
escape (0.0.4)
ethon (0.16.0)
ethon (0.18.0)
ffi (>= 1.15.0)
ffi (1.17.2)
logger
ffi (1.17.3)
fourflusher (2.3.1)
fuzzy_match (2.0.4)
gh_inspector (1.1.3)
httpclient (2.9.0)
mutex_m
i18n (1.14.7)
i18n (1.14.8)
concurrent-ruby (~> 1.0)
json (2.7.6)
json (2.18.0)
logger (1.7.0)
minitest (5.25.4)
minitest (6.0.1)
prism (~> 1.5)
molinillo (0.8.0)
mutex_m (0.3.0)
nanaimo (0.3.0)
nap (1.1.0)
netrc (0.11.0)
nkf (0.2.0)
prism (1.7.0)
public_suffix (4.0.7)
rexml (3.4.1)
rexml (3.4.4)
ruby-macho (2.5.1)
securerandom (0.4.1)
typhoeus (1.4.1)
ethon (>= 0.9.0)
tzinfo (2.0.6)
Expand All @@ -94,7 +102,6 @@ GEM
colored2 (~> 3.1)
nanaimo (~> 0.3.0)
rexml (>= 3.3.6, < 4.0)
zeitwerk (2.6.18)

PLATFORMS
ruby
Expand All @@ -103,14 +110,14 @@ DEPENDENCIES
activesupport (>= 6.1.7.5, != 7.1.0)
benchmark
bigdecimal
cocoapods (>= 1.13, != 1.15.1, != 1.15.0)
cocoapods (>= 1.13, < 1.17.0, != 1.15.1, != 1.15.0)
concurrent-ruby (< 1.3.4)
logger
mutex_m
xcodeproj (< 1.26.0)

RUBY VERSION
ruby 2.6.10p210
ruby 2.6.10p210

BUNDLED WITH
1.17.2
4.0.3
120 changes: 60 additions & 60 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2743,81 +2743,81 @@ SPEC CHECKSUMS:
fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd
glog: 5683914934d5b6e4240e497e0f4a3b42d1854183
hermes-engine: bbc1152da7d2d40f9e59c28acc6576fcf5d28e2a
RCT-Folly: 59ec0ac1f2f39672a0c6e6cecdd39383b764646f
RCT-Folly: 846fda9475e61ec7bcbf8a3fe81edfcaeb090669
RCTDeprecation: 300c5eb91114d4339b0bb39505d0f4824d7299b7
RCTRequired: e0446b01093475b7082fbeee5d1ef4ad1fe20ac4
RCTTypeSafety: cb974efcdc6695deedf7bf1eb942f2a0603a063f
React: e7a4655b09d0e17e54be188cc34c2f3e2087318a
React-callinvoker: 62192daaa2f30c3321fc531e4f776f7b09cf892b
React-Core: c400b068fdb6172177f3b3fae00c10d1077244d7
React-CoreModules: 8e911a5a504b45824374eec240a78de7a6db8ca2
React-cxxreact: 06a91f55ac5f842219d6ca47e0f77187a5b5f4ac
React-Core: b23cdaaa9d76389d958c06af3c57aa6ad611c542
React-CoreModules: 8e0f562e5695991e455abbebe1e968af71d52553
React-cxxreact: 6ccbe0cc2c652b29409b14b23cfb3cd74e084691
React-debug: 1834225a63b420b16e9b8b01ba5870aee96d0610
React-defaultsnativemodule: 260aa990a9617c58df46c00321f396ad6ea7cc7f
React-domnativemodule: 9b3456a614c325da986867f27ca0eb34cb86828c
React-Fabric: fc7bcbac28989e6025ca6ae0988bff61bb78e5d3
React-FabricComponents: ae4a9c82bedf7c95bace1b215caf8685bcb32e23
React-FabricImage: c9cd4786180c150bb2a3841d65d360fd52be9ef8
React-featureflags: 534cd678e05848fbfc8c7288d4b14bcd8894b696
React-featureflagsnativemodule: bf7419f4d81226a3c4dd792445a03a6d703ce9a4
React-graphics: 18296c3559d54a42baaf7f2ae9c137a2e0fe9d51
React-hermes: b6e33fcd21aa7523dc76e62acd7a547e68c28a5b
React-idlecallbacksnativemodule: da8696a714ab16adb56bbfc9e0dfb4de7a713340
React-ImageManager: 052ccce122e4fd4e09c5d4f30e56381704dac439
React-jserrorhandler: 4c037384a32f57332abfa64181aeea915f9e0f0d
React-jsi: 3fde19aaf675c0607a0824c4d6002a4943820fd9
React-jsiexecutor: 4f898228240cf261a02568e985dfa7e1d7ad1dfb
React-jsinspector: 4ad0cdfa25a45d1362e2ddd06c78727d7964b34f
React-jsinspectorcdp: a649cc98a448e0fd8d54ac2a9e3e53177a1d8bd3
React-jsinspectornetwork: 2d701b6b152be202342f8269223046ec664c7d47
React-jsinspectortracing: cd898b3d7ea89f3e0ae10020fe3504bb4b327dd8
React-jsitooling: feca163583c69ba642cebb6b8ccd2f5e6732fed8
React-jsitracing: 1965307a468987b20d2a020f8fe782efa591ded7
React-logger: ea80169d826e0cd112fa4d68f58b2b3b968f1ecb
React-Mapbuffer: a5d550d1add940ed2bc65b20dc1413407bf1a63f
React-microtasksnativemodule: 5d00fefc19f0bc9a6432e5533683d6fc9c3da4e1
react-native-safe-area-context: 31fa8b0bb05496c4005aa5560283f5015e809b91
react-native-segmented-control: 44d14c6899ee12de3384517f4fa1cf4a66ae105c
react-native-slider: 83d77040942794b3994a8c3e116258463326cee5
react-native-track-player: 9dd1e9b14654320f2c7db15522bfd58b5be22820
React-defaultsnativemodule: dd88d445d542d58ab61a8a29a7c1d2272dfed577
React-domnativemodule: fc3c24f4d3bb92770727ea48b4133dab77ded7f7
React-Fabric: 00fe76339e568da0d0497cc72daeeb01e463871a
React-FabricComponents: 7bb179ee55db68f88c007800b0ac62c930115a85
React-FabricImage: 21e01118011dd1e4ff3cdab20dbf57839cff52ee
React-featureflags: 6e67f2e252bc8ebb1d538c2ae8c14df432fe5fc0
React-featureflagsnativemodule: eff5216a5cde5df5d09243d15db1bc401474deef
React-graphics: 8539372da8754118a565251ed08a88fc70f69340
React-hermes: cc8c77acee1406c258622cd8abbee9049f6b5761
React-idlecallbacksnativemodule: 7349675d1ccbec876c29b0e206ac08c762baaa36
React-ImageManager: 4089d8ad52c86a8ae1d7591282fff1665ff5518b
React-jserrorhandler: 89a7a5fa8d04791e729119d1db03bf0ee85a9e29
React-jsi: ea5c640ea63c127080f158dac7f4f393d13d415c
React-jsiexecutor: cf7920f82e46fe9a484c15c9f31e67d7179aa826
React-jsinspector: 69e974b6313dbbb635ba503f2f4f2c389b30edbf
React-jsinspectorcdp: 231ddd5b7164c37589dcde3b8b6960136c891d6d
React-jsinspectornetwork: ff74911f79cf0a407a7f0ad0eeb0be64687ed815
React-jsinspectortracing: df2aa2d944bb3fa280d9c920b9a06664bca8a7e8
React-jsitooling: 77849c27e374a028ed8106e434a35267f6c6600b
React-jsitracing: 0dc6978e5b38c6e5e01e6aed484e4aec3f5f581b
React-logger: 7cfc7b1ae1f8e5fe5097f9c746137cc3a8fad4ce
React-Mapbuffer: 7018c5b7da5b13ed22fe55dae51d50187a00b2d7
React-microtasksnativemodule: 8ff9cb220a8efa625b5885996bd69e69db9edf02
react-native-safe-area-context: 3bae4f8474c13ab141c40ed6c5c33f6177778d71
react-native-segmented-control: bf6e0032726727498e18dd437ae88afcdbc18e99
react-native-slider: c434f7094c9500dfa1176931f48e5957872818f8
react-native-track-player: 293b007093d0aca7145613d5e7ac9eaac8d80fad
react-native-vector-icons-fontawesome6: 624a5578d701e52b18fb7f35b56556395a4249c0
React-NativeModulesApple: b22e6abb44d78270dfdfc7d85efe29e35e0333a7
React-NativeModulesApple: 37c08c3c54db55854de816b0df0f3683832be35a
React-oscompat: 56d6de59f9ae95cd006a1c40be2cde83bc06a4e1
React-perflogger: 0633844e495d8b34798c9bf0cb32ce315f1d5c9f
React-performancetimeline: a04dae9154c32eda1891fcfa51cb2680a0421b3e
React-perflogger: 4008bd05a8b6c157b06608c0ea0b8bd5d9c5e6c9
React-performancetimeline: 9321ba7605abcfb3a2b497fd7cbaf5cfd8c7cf67
React-RCTActionSheet: 49138012280ec3bbb35193d8d09adb8bc61c982e
React-RCTAnimation: c7ed4a9d5a4e43c9b10f68bb43cd238c4a2e7e89
React-RCTAppDelegate: ea2ab6f4aef1489f72025b7128d8ab645b40eafb
React-RCTBlob: c052799460b245e1fffe3d1dddea36fa88e998a0
React-RCTFabric: e7acf005f8ed58d09f755b980ff83703b3af9fcf
React-RCTFBReactNativeSpec: ffb22c3ee3d359ae9245ca94af203845da9371ec
React-RCTImage: 59fc2571f4f109a77139924f5babee8f9cd639c9
React-RCTLinking: a045cb58c08188dce6c6f4621de105114b1b16ce
React-RCTNetwork: fc7115a2f5e15ae0aa05e9a9be726817feefb482
React-RCTRuntime: a7bca9be4f571586b2a9d4b57cf605421ffb6335
React-RCTSettings: 30d7dd7eae66290467a1e72bf42d927fa78c3884
React-RCTText: 755d59284e66c7d33bb4f0ccc428fe69110c3e74
React-RCTVibration: ffe019e588815df226f6f8ccdc65979f8b2bc440
React-RCTAnimation: ebfe7c62016d4c17b56b2cab3a221908ae46288d
React-RCTAppDelegate: 0108657ba9a19f6a1cd62dcd19c2c0485b3fc251
React-RCTBlob: 6cc309d1623f3c2679125a04a7425685b7219e6b
React-RCTFabric: 0a9ff5c9d1e1d7fc026bda6671180cbf56861c15
React-RCTFBReactNativeSpec: ff3e37e2456afc04211334e86d07bf20488df0ae
React-RCTImage: bb98a59aeed953a48be3f917b9b745b213b340ab
React-RCTLinking: d6e9795d4d75d154c1dd821fd0746cc3e05d6670
React-RCTNetwork: 5c8a7a2dd26728323189362f149e788548ac72bc
React-RCTRuntime: 96808e8fdce300a26c82d8c24174e33ba5210a7c
React-RCTSettings: b6a02d545ce10dd936b39914b32674db6e865307
React-RCTText: c7d9232da0e9b5082a99a617483d9164a9cd46e9
React-RCTVibration: fe636c985c1bf25e4a5b5b4d9315a3b882468a72
React-rendererconsistency: d20fcb77173861cc7d8356239823e3b36966fc31
React-renderercss: 63c720c32aaabd4788ac4136a071d49a052d8002
React-rendererdebug: a25ddddc73cabf50d814d8dfbc60d257b3d854c4
React-renderercss: 56461d1e18db6a325048fdd04a51d68bd7ddb5a8
React-rendererdebug: fcd44d3eb8a02d74beee778bb142e724016c7375
React-rncore: bafb76fc01b78757a9592e92dbc227f9260bf0ac
React-RuntimeApple: 45f8ef1b220a91b4fa4a79820b81990bffd95aa5
React-RuntimeCore: a0e095493b22ee3f6c639df4258cc5185674f0b8
React-RuntimeApple: 01e3ad08793efaa54cf85276457fa4a1f103d5b4
React-RuntimeCore: 5c4bec5bf402a99b134e55972f2f4e676c70b9ab
React-runtimeexecutor: b35de9cb7f5d19c66ea9b067235f95b947697ba5
React-RuntimeHermes: 5b8126fffd1531475861dc0294a10b5f9793271a
React-runtimescheduler: 44fa97351d105afd0ffaecc4ed11cadad562deb6
React-RuntimeHermes: ba549a5834a6592d243b9a605530ecd7b6f5e79c
React-runtimescheduler: 9a9914d58caec7976aaae381cd2d997408f2260f
React-timing: 4f97958cc918f0af9444f93e4a7083415e6f5daf
React-utils: 3c4b0b7788e4dc132d1bf918bc0615e2b21f36b3
ReactAppDependencyProvider: 6c9197c1f6643633012ab646d2bfedd1b0d25989
ReactCodegen: 9ea66ee246511816b72e9d6e380f884b7b3b99d7
ReactCommon: 7aca047f2f453a7d7f0adeccb63810d61829235a
RNGestureHandler: 9d04ec6e1379b595222c2467f5e8d1c44157fcc9
RNReanimated: 2010262133feb53009f16faaa404042eed7da018
React-utils: f491e2726eb8ced8af13893e1f77317f0fa9a954
ReactAppDependencyProvider: 8df342c127fd0c1e30e8b9f71ff814c22414a7c0
ReactCodegen: 439c427ccc115d71d16cc84256e5fbdc7fcef57a
ReactCommon: 592ef441605638b95e533653259254b4bd35ff4f
RNGestureHandler: eeb622199ef1fb3a076243131095df1c797072f0
RNReanimated: bc1ddb7a5352648bcf0d592256069833bf935a46
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
SwiftAudioEx: f6aa653770f3a0d3851edaf8d834a30aee4a7646
Yoga: 1c52fbd270869e556504def7e94fffbf67f53f7b
Yoga: a742cc68e8366fcfc681808162492bc0aa7a9498

PODFILE CHECKSUM: 3b4ec20947e91756d94116d805d6728ccbf46a37

COCOAPODS: 1.16.2
COCOAPODS: 1.15.2
Loading