Headphone remote control - enable next and previous navigation option on Android #676

Open
opened 2026-04-24 23:33:47 +02:00 by adam · 7 comments
Owner

Originally created by @sandreas on GitHub (Aug 27, 2023).

I'm not sure this is documented anywhere, but I think currently, it is not possible to enable the ability of navigating to next or previous via headphone remote control on android.

pause and play rewinds 10 seconds by default, which is sane, but I'm missing the other player functions (next, previous, fast forward, rewind) via headphone remote.

So there are multiple different implementations / tap codings, where some share common ground (e.g. toggle play is almost everywhere a single tap. For android there actually is an expected behaviour: https://source.android.com/docs/core/interaction/accessories/headset/expected-behavior

I would love to see this at least partly configurable. I use a Samsung EG920 EO-EG920BW headset with three buttons (for reference, let's call them vol+, vol-, toggle):

  |
┌───┐
│   │
│ + │    -> vol+
│   │ 
│   │ 
│ - │    -> vol-
│   │
│   │
│   │
│ > │    -> toggle
│   │
└───┘
  |

so my personal preference would be:

  • play / pause: single tap toggle
  • next: double tap toggle
  • previous: triple tap toggle (alternative: single tap and hold toggle)
  • fast forward: double tap and hold toggle
  • rewind: triple tap and hold toggle

This would be the way iPods EarPod remotes work. But I would accept any other implementation as long as the other features are working somehow.

Possible code reference: https://github.com/advplyr/audiobookshelf-app/blob/394479bea0ec68ca73fc17914577b67676aa2698/android/app/src/main/java/com/audiobookshelf/app/player/PlayerNotificationService.kt#L264

Originally created by @sandreas on GitHub (Aug 27, 2023). I'm not sure this is documented anywhere, but I think currently, it is not possible to enable the ability of navigating to `next` or `previous` via headphone remote control on android. `pause` and `play` rewinds 10 seconds by default, which is sane, but I'm missing the other player functions (**next**, **previous**, **fast forward**, **rewind**) via headphone remote. So there are multiple different implementations / tap codings, where some share common ground (e.g. `toggle play` is almost everywhere a single tap. For android there actually is an *expected behaviour*: https://source.android.com/docs/core/interaction/accessories/headset/expected-behavior I would love to see this at least partly configurable. I use a Samsung EG920 EO-EG920BW headset with three buttons (for reference, let's call them `vol+`, `vol-`, `toggle`): ``` | ┌───┐ │ │ │ + │ -> vol+ │ │ │ │ │ - │ -> vol- │ │ │ │ │ │ │ > │ -> toggle │ │ └───┘ | ``` so my personal preference would be: - **play** / **pause**: single tap `toggle` - **next**: double tap `toggle` - **previous**: triple tap `toggle` (alternative: single tap and hold `toggle`) - **fast forward**: double tap and hold `toggle` - **rewind**: triple tap and hold `toggle` This would be the way iPods EarPod remotes work. But I would accept any other implementation as long as the other features are working somehow. Possible code reference: https://github.com/advplyr/audiobookshelf-app/blob/394479bea0ec68ca73fc17914577b67676aa2698/android/app/src/main/java/com/audiobookshelf/app/player/PlayerNotificationService.kt#L264
Author
Owner

@advplyr commented on GitHub (Sep 10, 2023):

What do you expect to happen when you use a next/prev action?

@advplyr commented on GitHub (Sep 10, 2023): What do you expect to happen when you use a next/prev action?
Author
Owner

@sandreas commented on GitHub (Sep 11, 2023):

What do you expect to happen when you use a next/prev action?

Depends on the content / personal preferences.

Music / audio books with multiple files:

  • Next: Next track, if available, stop when no more tracks available
  • Prev: If within the first 3 seconds of a track, skip to previous, otherwise skip to the beginning of a track

Files with chapters (audio books, podcasts):

  • Next: Next chapter, if available, stop when no more chapters available
  • Prev: If within the first 3 seconds of a chapter, skip to previous, otherwise skip to the beginning of a chapter

However, there are some minor tweaks I would love to see in the settings, although they would take a lot of effort to implement:

  • Instead of next / prev track or chapter, I would configure next/prev to fast forward / rewind 5 minutes on files with chapters
    • Reason: Chapters are unpredictable - some books have 3 minute chapters, some have 15 minute chapters

For play/pause i would like to see an increasing amount of rewind seconds, that resets after 3 seconds of no action, example:

  • First Pause: Rewind 10 seconds and pause
  • Play again
  • Pause again (within 3 seconds): Rewind 20 seconds and pause
  • Play again
  • Pause again (within 3 seconds): Rewind 30 seconds and pause
  • Play again
  • Pause again (within 3 seconds): Rewind 60 seconds and pause
  • Play again (more than 3 seconds) => reset the increasing timer
  • Pause again: rewind 10 seconds

Same of course applies to step back and step forward on the player and lockscreen controls. You could also increase that to 2 times per time step (increase timer after 2 rounds of rewinding). I think in most cases you pause multiple times you want to rewind the book just a few seconds, because you missed something. But the more you do it the more you want to go back.

So possible settings could be:

  • Play / Pause: Rewind [ ] seconds where
    • A single value would be a fixed one
    • A comma separated value would behave like described above (10,10,20,20,30,30,60,60)
  • Next/Prev: Default behaviour / Skip fixed amount of time: [ ] seconds
    • Default behaviour: Next or Previous
    • Fixed amount of time: Just fast forward or rewind.
@sandreas commented on GitHub (Sep 11, 2023): > What do you expect to happen when you use a next/prev action? Depends on the content / personal preferences. Music / audio books with multiple files: - Next: Next track, if available, stop when no more tracks available - Prev: If within the first 3 seconds of a track, skip to previous, otherwise skip to the beginning of a track Files with chapters (audio books, podcasts): - Next: Next chapter, if available, stop when no more chapters available - Prev: If within the first 3 seconds of a chapter, skip to previous, otherwise skip to the beginning of a chapter However, there are some minor tweaks I would love to see in the settings, although they would take a lot of effort to implement: - Instead of next / prev track or chapter, I would configure next/prev to fast forward / rewind 5 minutes on files with chapters - Reason: Chapters are unpredictable - some books have 3 minute chapters, some have 15 minute chapters For play/pause i would like to see an increasing amount of rewind seconds, that resets after 3 seconds of no action, example: - First Pause: Rewind 10 seconds and pause - Play again - Pause again (within 3 seconds): Rewind 20 seconds and pause - Play again - Pause again (within 3 seconds): Rewind 30 seconds and pause - Play again - Pause again (within 3 seconds): Rewind 60 seconds and pause - Play again (more than 3 seconds) => reset the increasing timer - Pause again: rewind 10 seconds Same of course applies to step back and step forward on the player and lockscreen controls. You could also increase that to 2 times per time step (increase timer after 2 rounds of rewinding). I think in most cases you pause multiple times you want to rewind the book just a few seconds, because you missed something. But the more you do it the more you want to go back. So possible settings could be: - Play / Pause: Rewind `[ ]` seconds where - A single value would be a fixed one - A comma separated value would behave like described above (`10,10,20,20,30,30,60,60`) - Next/Prev: Default behaviour / Skip fixed amount of time: `[ ]` seconds - Default behaviour: Next or Previous - Fixed amount of time: Just fast forward or rewind.
Author
Owner

@gazpachoking commented on GitHub (Sep 18, 2023):

Just weighing in on how I use headphone buttons: I'd never want my headphone buttons to do next or previous track/chapter. That's way too long in an audio book, and way too easy to mess up with no way to get back to where you just were. The only button I would personally use from my headphones is a short rewind 30-60s. When I'm out running or walking, sometimes I need to skip back because I got distracted and missed something.

@gazpachoking commented on GitHub (Sep 18, 2023): Just weighing in on how I use headphone buttons: I'd _never_ want my headphone buttons to do next or previous track/chapter. That's way too long in an audio book, and way too easy to mess up with no way to get back to where you just were. The only button I would personally use from my headphones is a short rewind 30-60s. When I'm out running or walking, sometimes I need to skip back because I got distracted and missed something.
Author
Owner

@sandreas commented on GitHub (May 22, 2024):

Ok, I played around with the click handler in a fork and think I found a pretty neat solution for the click detection. Unfortunately I'm not a kotlin native and can't get it translate to the player actions - so I could use some help.

So here is the diff:
https://github.com/advplyr/audiobookshelf-app/compare/master...sandreas:audiobookshelf-app:master

how does this work:

  • every keyDown and keyUp triggers a scheduled handler (!)
  • the handler takes clickCount:int and clickPressed:bool (if held down)
  • another keyDown or keyUp cancels the active scheduled handler and re-triggers it
  • keyCodes increase the number of clicks (PlayPause+=1, Next+=2, Prev+=3)
  • depending on the number of clicks, the playerNotificationService handles the configured action

problems:

  • the logs show pretty accurate click / hold detection, but it does not really translate well in the player
  • since the trigger is scheduled, it does run in a different thread
  • this leads to strange behaviour - probably easy to fix, but I'm no kotlin native (Coroutines)
  • probably after some actions the thread of the player is no longer accessible...

missing things:

  • FastForward and Rewind are not implemented in the player
  • Next (Chapter) and Previous (Chapter) are not implemented either

@advplyr
What do you think of this? Would you be able to help me a little bit? ;)

@sandreas commented on GitHub (May 22, 2024): Ok, I played around with the click handler in a fork and think I found a pretty neat solution for the click detection. Unfortunately I'm not a kotlin native and can't get it translate to the player actions - so I could use some help. So here is the diff: https://github.com/advplyr/audiobookshelf-app/compare/master...sandreas:audiobookshelf-app:master **how does this work:** - every keyDown and keyUp triggers a *scheduled* handler (!) - the handler takes clickCount:int and clickPressed:bool (if held down) - another keyDown or keyUp cancels the active scheduled handler and re-triggers it - keyCodes increase the number of clicks (PlayPause+=1, Next+=2, Prev+=3) - depending on the number of clicks, the playerNotificationService handles the configured action **problems:** - the logs show pretty accurate click / hold detection, but it does not really translate well in the player - since the trigger is scheduled, it does run in a different thread - this leads to strange behaviour - probably easy to fix, but I'm no kotlin native (Coroutines) - probably after some actions the thread of the player is no longer accessible... **missing things:** - FastForward and Rewind are not implemented in the player - Next (Chapter) and Previous (Chapter) are not implemented either @advplyr What do you think of this? Would you be able to help me a little bit? ;)
Author
Owner

@sandreas commented on GitHub (May 23, 2024):

@advplyr
As said in matrix chat, I would suggest the following settings and actions as default:

click sequence selected action
click play / pause
double click next chapter / track
triple click previous chapter / track
hold jump backwards
click + hold jump forward
============ ============
double click + hold rewind
quadruple click - none / ignore -

whereas the second column is a select box with the following options:

selected action
- none / ignore -
play / pause
next chapter / track
previous chapter / track
jump backwards
jump backwards (2min)
jump backwards (5min)
jump forward
jump forward (2min)
jump forward (5min)
reset sleep timer
==============
fast forward
rewind
increase speed
decrease speed
time announcement
metadata announcement
  • increase / decrease speed refers to playback speed
  • reset sleep timer refers to the auto sleep timer
  • time announcement would try to synthesize speech to read the current time over headphones
  • metadata announcement would try to synthesize speech to read the current track name over headphones

Additionally, the click-timeout could be a setting:

  • Click timeout: 600 ms

Since some of the actions would need additional implementation steps, the items below the ======== are just ideas for future improvements. Starting with the existing actions would be totally fine.

@sandreas commented on GitHub (May 23, 2024): @advplyr As said in matrix chat, I would suggest the following settings and actions as default: | click sequence | selected action | |---------------------|--------------------------| | click | play / pause | | double click | next chapter / track | | triple click | previous chapter / track | | hold | jump backwards | | click + hold | jump forward | | ============ | ============ | | double click + hold | rewind | | quadruple click | - none / ignore - | whereas the second column is a select box with the following options: | selected action | |--------------------------| | - none / ignore - | | play / pause | | next chapter / track | | previous chapter / track | | jump backwards | | jump backwards (2min) | | jump backwards (5min) | | jump forward | | jump forward (2min) | | jump forward (5min) | | reset sleep timer | | ============== | | fast forward | | rewind | | increase speed | | decrease speed | | time announcement | | metadata announcement | - increase / decrease speed refers to playback speed - reset sleep timer refers to the auto sleep timer - time announcement would try to synthesize speech to read the current time over headphones - metadata announcement would try to synthesize speech to read the current track name over headphones Additionally, the click-timeout could be a setting: - Click timeout: `600` ms Since some of the actions would need additional implementation steps, the items below the `========` are just ideas for future improvements. Starting with the existing actions would be totally fine.
Author
Owner

@sandreas commented on GitHub (May 23, 2024):

@advplyr
UPDATE: I think I got it working with Coroutines. It works flawlessly on my testing device, but I did not have the time to check for side effects (regression issues with other player features).

I think this would be a GREAT addition to Audiobookshelf, maybe we should start with a configuration less default setting (like described above).

I think the most important part missing is the fastForward, rewind, next, previous steps in the player notification service.

@sandreas commented on GitHub (May 23, 2024): @advplyr UPDATE: I think I got it working with Coroutines. It works flawlessly on my testing device, but I did not have the time to check for side effects (regression issues with other player features). I think this would be a GREAT addition to Audiobookshelf, maybe we should start with a configuration less default setting (like described above). I think the most important part missing is the fastForward, rewind, next, previous steps in the player notification service.
Author
Owner

@sandreas commented on GitHub (May 26, 2024):

UPDATE: Setting enableExperimentalHeadsetControls is now integrated. It is not persisted yet, but you CAN test the behaviour, if you start a track and let it play, then go to the settings and enable the setting.

Using a headset now uses the following experimental click-codes by default:

click sequence selected action
click play / pause
double click jump forward 5 min
triple click jump backwards 5 min
hold jump backwards
click + hold fast forward (new implementation)
double click + hold rewind (new implementation)

I would love to get some feedback on this. Fastest way to check it out is probably cloning my repo and just build it:

git clone https://github.com/sandreas/audiobookshelf-app.git
cd audiobookshelf-app
npm install
npm run generate
npx cap sync
npx cap open android

Then start the Android session of your liking

@sandreas commented on GitHub (May 26, 2024): UPDATE: Setting `enableExperimentalHeadsetControls` is now integrated. It is not persisted yet, but you CAN test the behaviour, if you start a track and let it play, then go to the settings and enable the setting. Using a headset now uses the following experimental click-codes by default: | click sequence | selected action | |---------------------|--------------------------| | click | play / pause | | double click | jump forward 5 min | | triple click | jump backwards 5 min | | hold | jump backwards | | click + hold | fast forward ([new implementation](https://github.com/sandreas/audiobookshelf-app/blob/dc8d0cff56edea1791b373de4511e6c26956ffd6/android/app/src/main/java/com/audiobookshelf/app/player/PlayerNotificationService.kt#L983)) | | double click + hold | rewind ([new implementation](https://github.com/sandreas/audiobookshelf-app/blob/dc8d0cff56edea1791b373de4511e6c26956ffd6/android/app/src/main/java/com/audiobookshelf/app/player/PlayerNotificationService.kt#L997)) | I would love to get some feedback on this. Fastest way to check it out is probably cloning my repo and just build it: ```bash git clone https://github.com/sandreas/audiobookshelf-app.git cd audiobookshelf-app npm install npm run generate npx cap sync npx cap open android ``` Then start the Android session of your liking
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/audiobookshelf-app#676