Fix chapter buttons in new playback service (#8488)

### Description

Fix chapter buttons in new playback service. They still tried to use the
old service controls.
Closes #8483

### Checklist
<!-- 
To help us keep the issue tracker clean and work as efficient as
possible,
  please make sure that you have done all of the following.
You can tick the boxes below by placing an x inside the brackets like
this: [x]
-->
- [x] I have read the contribution guidelines:
https://github.com/AntennaPod/AntennaPod/blob/develop/CONTRIBUTING.md#submit-a-pull-request
- [x] I have performed a self-review of my code, going through my
changes line by line and carefully considering why this line change is
necessary
- [x] I have run the automated code checks using `./gradlew checkstyle
lint`
- [x] My code follows the style guidelines of the AntennaPod project:
https://antennapod.org/contribute/develop/app/code-style
- [x] I have mentioned the corresponding issue and the relevant keyword
(e.g., "Closes: #xy") in the description (see
https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue)
- [x] If it is a core feature, I have added automated tests
This commit is contained in:
Hans-Peter Lehmann
2026-05-28 10:58:21 +02:00
committed by GitHub
parent f5184b68c7
commit 269d6b7ef1
5 changed files with 24 additions and 20 deletions

View File

@ -11,6 +11,8 @@ AntennaPod uses a highly modularized Gradle architecture with modules organized
Each module is stored in a folder of the same name (for example `:net:discovery` in `./net/discovery`)
and contains a `README.md` file with a brief explanation of the module's purpose and internal structure.
Before looking at code in a module, always read its `README.md` first.
When you discover something broadly useful about a module, such as the correct API to use, or a pattern all callers should follow, update that module's `README.md` proactively.
Only add information that is long-term stable and generic (patterns, APIs, conventions), not task-specific details or things already obvious from reading the code.
Several functional areas follow a service-interface/service split: the interface module is depended on by consumers, and the implementation is registered at app startup via `ClientConfigurator`.
- `:app` - Main application module that integrates all features
- `:event` - EventBus events used for cross-component communication throughout the app

View File

@ -24,7 +24,6 @@ import de.danoeh.antennapod.event.playback.PlaybackPositionEvent;
import de.danoeh.antennapod.model.feed.Chapter;
import de.danoeh.antennapod.model.feed.FeedMedia;
import de.danoeh.antennapod.model.playback.Playable;
import de.danoeh.antennapod.playback.base.PlayerStatus;
import de.danoeh.antennapod.playback.service.PlaybackController;
import de.danoeh.antennapod.storage.database.DBReader;
import de.danoeh.antennapod.storage.preferences.PlaybackPreferences;
@ -79,11 +78,11 @@ public class ChaptersFragment extends AppCompatDialogFragment {
adapter = new ChaptersListAdapter(getActivity(), pos -> {
Chapter chapter = adapter.getItem(pos);
PlaybackController.bindToService(getActivity(), playbackService -> {
if (playbackService.getStatus() != PlayerStatus.PLAYING) {
playbackService.resume();
PlaybackController.bindToMedia3Service(getActivity(), controller -> {
if (!controller.isPlaying()) {
controller.play();
}
playbackService.seekTo((int) chapter.getStart());
controller.seekTo(chapter.getStart());
});
updateChapterSelection(pos, true);
});

View File

@ -30,7 +30,6 @@ import de.danoeh.antennapod.model.feed.FeedMedia;
import de.danoeh.antennapod.model.feed.Transcript;
import de.danoeh.antennapod.model.feed.TranscriptSegment;
import de.danoeh.antennapod.model.playback.Playable;
import de.danoeh.antennapod.playback.base.PlayerStatus;
import de.danoeh.antennapod.playback.service.PlaybackController;
import de.danoeh.antennapod.storage.database.DBReader;
import de.danoeh.antennapod.storage.preferences.PlaybackPreferences;
@ -126,14 +125,14 @@ public class TranscriptDialogFragment extends DialogFragment
long endTime = segment.getEndTime();
scrollToPosition(pos);
PlaybackController.bindToService(getActivity(), playbackService -> {
if (!(playbackService.getCurrentPosition() >= startTime
&& playbackService.getCurrentPosition() <= endTime)) {
playbackService.seekTo((int) startTime);
} else if (playbackService.getStatus() == PlayerStatus.PLAYING) {
playbackService.pause(false, false);
PlaybackController.bindToMedia3Service(getActivity(), controller -> {
if (!(controller.getCurrentPosition() >= startTime
&& controller.getCurrentPosition() <= endTime)) {
controller.seekTo(startTime);
} else if (controller.isPlaying()) {
controller.pause();
} else {
playbackService.resume();
controller.play();
}
});
adapter.notifyItemChanged(pos);

View File

@ -237,15 +237,15 @@ public class CoverFragment extends Fragment {
return;
}
PlaybackController.bindToService(getActivity(), playbackService -> {
PlaybackController.bindToMedia3Service(getActivity(), controller -> {
if (displayedChapterIndex < 1) {
playbackService.seekTo(0);
} else if ((playbackService.getCurrentPosition() - 10000 * playbackService.getCurrentPlaybackSpeed())
controller.seekTo(0);
} else if ((controller.getCurrentPosition() - 10000 * controller.getPlaybackParameters().speed)
< curr.getStart()) {
refreshChapterData(displayedChapterIndex - 1);
playbackService.seekTo((int) media.getChapters().get(displayedChapterIndex).getStart());
controller.seekTo(media.getChapters().get(displayedChapterIndex).getStart());
} else {
playbackService.seekTo((int) curr.getStart());
controller.seekTo(curr.getStart());
}
});
}
@ -257,8 +257,8 @@ public class CoverFragment extends Fragment {
}
refreshChapterData(displayedChapterIndex + 1);
PlaybackController.bindToService(getActivity(), playbackService ->
playbackService.seekTo((int) media.getChapters().get(displayedChapterIndex).getStart()));
PlaybackController.bindToMedia3Service(getActivity(), controller ->
controller.seekTo(media.getChapters().get(displayedChapterIndex).getStart()));
}
@Override

View File

@ -7,3 +7,7 @@ The main service doing media playback.
External callers should interact with the service through `PlaybackController`, which provides a
`bindToMedia3Service()` helper that connects a `MediaController` and runs a callback on it.
The `MediaController` exposes the standard Media3 `Player` interface: `seekTo(positionMs)`,
`play()`, `pause()`, `getCurrentPosition()`, `getPlaybackParameters()`, etc.
Each call to `bindToMedia3Service()` creates a short-lived connection that is released after the
callback returns.