Skip to content

Inconsistent pausing between iOS and Android #40

Closed as not planned
Closed as not planned

Description

@AndreasLymalmMTM

Problem

The stream onTimebasedPlayerStateChanged emits different results depending on OS, when playing a publication in WebPubAudioOnly format:

  • When calling e.g. next() or previous():
    • Android: the state TimebasedState.loading is emitted.
    • iOS: the state TimebasedState.paused is emitted.
  • When audio files are switched (e.g. from 0001.mp3 to 0002.mp3):
    • Android: no new state (TimebasedState) is emitted.
    • iOS: the state TimebasedState.paused is emitted.

Expected Result

iOS behaves as Android and emits TimebasedState.loading or nothing.

If possible, do not emit TimebasedState.paused in these scenarios. We should be able to know that if TimebasedState.paused is set, it's an action from the user or OS.

Activity

  1. ddfreiling commented on Dec 9, 2025

    @ddfreiling
    Member

    Sorry for our MIA, lots of sickness going around the office these past weeks. The onTimebasedPlayerStateChanged didn't really reach a stage where it was tested very well across platforms. We will follow up on this as soon as possible.

  2. ddfreiling commented on Dec 11, 2025

    @ddfreiling
    Member

    If possible, do not emit TimebasedState.paused in these scenarios. We should be able to know that if TimebasedState.paused is set, it's an action from the user or OS.

    I would wish so, but right now it seems to be an artifact of how AVAudioPlayer behaves and is used in the swift-toolkit. See https://github.com/readium/swift-toolkit/blob/develop/Sources/Navigator/Audiobook/AudioNavigator.swift

    Maybe we should make a PR towards it, or alternatively map the state differently on our FlutterAudioNavigator.swift

    I will continue investigating the Android side.

  3. AndreasLymalmMTM commented on Dec 11, 2025

    @AndreasLymalmMTM
    ContributorAuthor

    The Android version works as we would expected already, in that the paused state only triggers when an actual pause of the book happens by the user, i.e. the user decided that the book should not continue playing anymore (by e.g. calling .pause() or pressing pause in control center).

    But the iOS version also triggers the paused state when it's swithcing mp3 files or jumps to another location (rewind/fast forward), which is not the user wanting to pause the book. It is this distinction of the paused state that would be good to keep (and hopefully make it happen in FlutterAudioNavigator.swift).

  4. ddfreiling commented on Dec 11, 2025

    @ddfreiling
    Member

    You can see the mapping in swift-toolkit here:
    https://github.com/readium/swift-toolkit/blob/develop/Sources/Navigator/Audiobook/AudioNavigator.swift#L516-L529

    This is the same enum that we forward in flutter_readium, do you have a suggestion on how to map or ignore this status change?

  5. AndreasLymalmMTM commented on Dec 11, 2025

    @AndreasLymalmMTM
    ContributorAuthor

    I assume swift-toolkit forward paused for control center pausing too? Because in that case we can't distinguish the actions based on the state alone.

  6. AndreasLymalmMTM commented on Dec 11, 2025

    @AndreasLymalmMTM
    ContributorAuthor

    The go function seems to be the culprit, by pausing everytime it moves location (be jumping or switching file): https://github.com/readium/swift-toolkit/blob/develop/Sources/Navigator/Audiobook/AudioNavigator.swift#L413-L452

  7. ddfreiling commented on Jan 23, 2026

    @ddfreiling
    Member

    The go function seems to be the culprit, by pausing everytime it moves location (be jumping or switching file): https://github.com/readium/swift-toolkit/blob/develop/Sources/Navigator/Audiobook/AudioNavigator.swift#L413-L452

    Yep that does seem to be the culprit. They should probably have disabled state-change emits while they pause there.

    For now when listening to the onTimebasedPlayerStateChanged, you should probably just use a debounceTime(50), so that minor erratic changes are skipped. This could solve the UI state representation, since the temporary pause state would be skipped when seeking.

  8. AndreasLymalmMTM commented on Jan 26, 2026

    @AndreasLymalmMTM
    ContributorAuthor

    Yes, that's how we decided to do it for now, and it works well enough.

  9. added
    upstream-issueThis issue is identified as being caused by upstream Readium toolkits
    on May 23, 2026
  10. AndreasLymalmMTM commented on Oct 15, 2026

    @AndreasLymalmMTM
    ContributorAuthor

    Android and/or iOS now behaves differently than was originally described, and the value that we wanted from it is now satified with #194.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    upstream-issueThis issue is identified as being caused by upstream Readium toolkits

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions