and reset them when the language is changed/changing.
This way they will be re-initialized on the next call.
Also Remove a bunch of outdated/non-thread safe code (STRING_FORMATTER)
* fix: handle nullable nextPage behavior when searching albums #12401
* feat: add nullable annotation to newPage attribute in SearchFragment
* Updated more usages of InfoItemsPage#getNextPage. Nullability is already handled in these areas so no other changes needed
---------
Co-authored-by: Siddhesh Naik <siddheshnaik20@protonmail.com>
Fixes#12400, see there for explanation. Citing from there:
So apparently the problem is onGetRoot always returning a BrowserRoot instance. Making it return null solved the issue (but again, breaks Android Auto compatibility). It turns out (see https://stackoverflow.com/q/63818988/) that onGetRoot is also used for media resumption https://developer.android.com/media/implement/surfaces/mobile#mediabrowserservice_implementation, which causes a new notification to pop up (in this case a useless notification because our onGetRoot does not return something that can be used for resumption). So what needs to be done is to check if rootHints?.getBoolean(EXTRA_RECENT) == true and if that's the case not return anything (as EXTRA_RECENT is used by the system for resumption).
The PackageValidator file is taken from 329a21b63c/common/src/main/java/com/example/android/uamp/media/PackageValidator.kt .
This is, again, a consequence of the commit "Drop some assumptions on how PlayerService is started and reused".
This commit notified VideoDetailFragment of player starting and stopping independently of the player.
Read the comments in the code changes for more information.
Fixes mini-player not appearing on app start if the player service is already playing something.
The PlayerService (and the player) may be started from an external intent that does not involve the MainActivity (e.g. RouterActivity or Android Auto's media browser interface).
This PR tries to bind to the PlayerService as soon as the MainActivity starts, but only does so in a passive way, i.e. if the service is not already running it is not started.
Once the connection between PlayerHolder and PlayerService is setup, the ACTION_PLAYER_STARTED broadcast is sent to MainActivity so that it can setup the bottom mini-player.
Another important thing this commit does is to check whether the player is open before actually adding the mini-player view, since the PlayerService could be bound even without a running player (e.g. Android Auto's media browser is being used). This is a consequence of commit "Drop some assumptions on how PlayerService is started and reused".
This commit is a consequence of the commit "Drop some assumptions on how PlayerService is started and reused". Since the assumptions on how the PlayerService is started and reused have changed, we also need to adapt the way it is stopped. This means allowing the service to remain alive even after the player is destroyed, in case the system is still accessing PlayerService e.g. through the media browser interface. The foreground service needs to be stopped and the notification removed in any case.
If a playbackPreparer is set, then instead of calling `player.prepare()`, the MediaSessionConnector will call `playbackPreparer.onPrepare(true)` instead, as seen below.
This commit makes it so that playbackPreparer.onPrepare(true) restores the original behavior of just calling player.prepare().
From MediaSessionConnector -> MediaSessionCompat.Callback implementation:
```java
@Override
public void onPlay() {
if (canDispatchPlaybackAction(PlaybackStateCompat.ACTION_PLAY)) {
if (player.getPlaybackState() == Player.STATE_IDLE) {
if (playbackPreparer != null) {
playbackPreparer.onPrepare(/* playWhenReady= */ true);
} else {
player.prepare();
}
} else if (player.getPlaybackState() == Player.STATE_ENDED) {
seekTo(player, player.getCurrentMediaItemIndex(), C.TIME_UNSET);
}
Assertions.checkNotNull(player).play();
}
}
```
This class implements the media browser service interface as a standalone class for clearer separation of concerns (otherwise everything would need to go in PlayerService, since PlayerService overrides MediaBrowserServiceCompat)
Co-authored-by: Haggai Eran <haggai.eran@gmail.com>
Co-authored-by: Profpatsch <mail@profpatsch.de>
This class will receive the media URLs generated by [MediaBrowserImpl] and will start playback of the corresponding streams or playlists.
Co-authored-by: Haggai Eran <haggai.eran@gmail.com>
Co-authored-by: Profpatsch <mail@profpatsch.de>
This changes significantly how the MediaSessionCompat and MediaSessionConnector objects are used:
- now they are tied to the service and not to the player, and so they might be reused with multiple players (which should be allowed)
- now they can exist even if there is no player (which is fundamental to be able to answer media browser queries)
This will use the exact subtitle sizes the user requested, both for
the main and the popup player. They will always be the same fraction
of the video, even if the popup player is resized.
* IcePick fails on Java 21 (default in Android Studio 2024.2)
* Bridge is the most modern alternative that is currently available. It is backed by ``Android-State`` and can be configured with various frameworks
* In the long term this should be replaced with something better
This change is in line with a recent change in how the play/pause button behaves in the player ui: if the buffering indicator is shown, it's still possible to toggle play/pause, to allow e.g. pausing videos before they even start.
This change was needed because on Android 13+ notification actions can't be null, and thus the buffering hourglass action wasn't shown.
This behavior was present before 0.24.0 and the player UI separation and
avoided crashes for which their exception contained
"Context.startForegroundService() did not then call Service.startForeground()".
Some player nullability checks have been also added, and the player service is
now stopped when it has been started from a media button and there is nothing
to play.