Commit graph

1128 commits

Author SHA1 Message Date
Stypox
56f79fac13
Merge branch 'release-0.28.0' into dev 2025-07-30 11:42:06 +02:00
litetex
893a1cb699
Encapsulate Formatters in PlayerHelper
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)
2025-07-28 15:11:27 +02:00
litetex
ebd5e1a318
Remove unused method 2025-07-28 15:11:27 +02:00
litetex
859555e129
Use regions 2025-07-28 15:11:27 +02:00
Michael Zh
50caba6606 Fix compile
Co-Authored-By: Isira Seneviratne <31027858+Isira-Seneviratne@users.noreply.github.com>
2025-07-23 18:49:28 -04:00
Michael Zh
26443f9f14 WIP: Fix compile 2025-07-23 18:45:30 -04:00
Michael Zh
04ef608f7a Specify RECEIVER_EXPORTED/RECEIVER_NOT_EXPORTED for sdk34 2025-07-23 18:45:30 -04:00
Kouki Badr
a4bd82be8a
fix: handle nullable nextPage behavior when searching albums #12401 (#12408)
* 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>
2025-07-22 08:58:56 +05:30
Isira Seneviratne
893a227ab1 Enable per-app language preferences for Android < 13 2025-07-20 04:50:49 +05:30
Stypox
4ddc0648ef
Merge pull request #12412 from Stypox/fix-ghost-notifications 2025-07-14 21:56:22 +02:00
Stypox
f3c20d43be
Merge pull request #12410 from Stypox/fix-android-auto-thumbnails 2025-07-08 11:42:20 +02:00
Stypox
79084568f2
Fix fullscreen eliciting "clear queue" prompt 2025-07-07 15:07:46 +02:00
Stypox
705b5e5580
Fix ghost notifications on Android 10
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 .
2025-07-07 01:06:59 +02:00
Stypox
a4d457b2b2
Use Kotlin's .toUri() instead of Uri.parse() 2025-07-06 15:05:30 +02:00
Stypox
834c93f22a
Fix thumbnails appearing on Android Auto even if disabled 2025-07-06 14:49:09 +02:00
Stypox
49b71942ad
Fix style and add comment about null player 2025-02-24 14:21:05 +01:00
Stypox
a7a7dc5363
Handle player and player service separately
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.
2025-02-18 19:27:46 +01:00
Stypox
6558794d26
Try to bind to PlayerService when MainActivity starts
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".
2025-02-18 17:49:38 +01:00
Stypox
1d98518bfa
Fix loading remote playlists in media browser 2025-02-16 21:44:50 +01:00
Stypox
e5458bcb14
Properly handle item errors during media browser loading
Non-item errors, i.e. critical parsing errors of the page, are still handled properly.
2025-02-16 21:44:50 +01:00
Stypox
dc62d211f5
Properly stop PlayerService
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.
2025-02-16 21:44:49 +01:00
Stypox
ec6612dd71
Call exoPlayer.prepare() on PlaybackPreparer.onPrepare()
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();
      }
    }
```
2025-02-16 21:44:49 +01:00
Stypox
064e1d39c7
Use the media browser implementation in PlayerService
Now the media browser queries are replied to by MediaBrowserImpl

Co-authored-by: Haggai Eran <haggai.eran@gmail.com>
2025-02-16 21:44:05 +01:00
Stypox
4c88a193bd
Add MediaBrowserImpl
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>
2025-02-16 21:43:46 +01:00
Stypox
3fcac10e7f
Add MediaBrowserPlaybackPreparer
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>
2025-02-16 21:43:35 +01:00
Stypox
690b40d0c4
Allow creating PlayQueue from ListInfo and index 2025-02-16 21:40:47 +01:00
Stypox
1e08cc8c8f
Add MediaBrowserCommon with info item's and pages' IDs
Co-authored-by: Haggai Eran <haggai.eran@gmail.com>
2025-02-16 21:40:29 +01:00
Stypox
7d17468266
Instantiate media session and connector in PlayerService
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)
2025-02-16 21:40:13 +01:00
Stypox
5819546ea9
Have PlayerService implement MediaBrowserServiceCompat
Co-authored-by: Haggai Eran <haggai.eran@gmail.com>
2025-02-16 21:36:59 +01:00
Stypox
b764ad33c4
Drop some assumptions on how PlayerService is started and reused
Read the comments in the lines changed to understand more
2025-02-15 17:48:19 +01:00
AudricV
b8e050f6c4
Adapt YoutubeHttpDataSource to extractor changes and improve requests
Always use POST requests and the same body that official HTML5 clients
use for a while.
2025-01-31 22:50:10 +01:00
Thompson3142
86203d6800 MainPlayer/PopupPlayer: Use system settings for subtitle size
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.
2025-01-21 17:23:08 +01:00
Thompson3142
f9711a3402 Removed call to setRecovery() entirely 2024-11-24 22:12:25 +01:00
Thompson3142
16c79c8219 Fixed player resuming from start when clicking on a timestamp 2024-11-21 22:42:42 +01:00
Thompson3142
23961548c0 Formatting changes (back to original) 2024-10-27 14:38:25 +01:00
Thompson3142
ba1e9c8e1b Update comment
Co-authored-by: Tobi <TobiGr@users.noreply.github.com>
2024-10-27 14:17:32 +01:00
litetex
2e96b65fda
Replaced `Icepick with Bridge and Android-State`
* 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
2024-10-23 21:28:07 +02:00
Thompson3142
eb9f300e60
Fix seekbar preview crashes (#11584)
Fixed crashes from recycled bitmaps by creating real copies of bitmaps if necessary + some minor refactoring
2024-10-10 10:32:06 +02:00
Stypox
72e9f7f9cf
Merge branch 'master' into dev 2024-07-15 10:17:27 +02:00
Stypox
9f766ebf78
Fix NPE in MediaSessionPlayerUi while destroying player 2024-07-11 09:41:33 +02:00
Stypox
f4fb960c62
Migrate to non-transitive R classes 2024-03-29 00:17:13 +01:00
Stypox
4b1824e8c1
Allow play/pausing from notification when buffering
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.
2023-12-29 16:18:26 +01:00
Stypox
17e88f1749
Do not update notification actions if nothing changed
This should avoid costly updates of the media session.
2023-12-29 16:16:45 +01:00
Stypox
5edafca05a
Implement notification actions via MediaSessionConnector on Android 13+ 2023-12-29 15:54:15 +01:00
Stypox
2c4c283099
Extract NotificationActionData from NotificationUtil 2023-12-29 15:54:15 +01:00
Stypox
9fb8125655
Allow each notification slot to contain any possible action 2023-12-29 15:54:15 +01:00
Isira Seneviratne
f3b458c803
Bump compileSdk to 34 2023-12-23 11:38:32 +01:00
TobiGr
e6965622bd
Fix crash with disabled thumbnails when trying to play a stream 2023-12-10 15:12:38 +01:00
Stypox
3dc593fe88
Merge pull request #10577 from AudricV/fix-npe-play-queue-audio-track-menu
Fix crash when building the play queue audio track menu if the player is null
2023-11-16 09:01:11 +01:00
AudricV
84d50da009
Restore player service start handling before player UI separation
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.
2023-11-15 23:21:20 +01:00