1
0
mirror of https://github.com/TeamNewPipe/NewPipe synced 2025-08-07 14:35:13 +00:00

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>
This commit is contained in:
Stypox 2025-02-16 09:14:19 +01:00
parent 4c88a193bd
commit 064e1d39c7
No known key found for this signature in database
GPG Key ID: 4BDF1B40A49FDD23

View File

@ -37,6 +37,8 @@ import androidx.media.MediaBrowserServiceCompat;
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector; import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector;
import org.schabi.newpipe.ktx.BundleKt; import org.schabi.newpipe.ktx.BundleKt;
import org.schabi.newpipe.player.mediabrowser.MediaBrowserImpl;
import org.schabi.newpipe.player.mediabrowser.MediaBrowserPlaybackPreparer;
import org.schabi.newpipe.player.mediasession.MediaSessionPlayerUi; import org.schabi.newpipe.player.mediasession.MediaSessionPlayerUi;
import org.schabi.newpipe.player.notification.NotificationPlayerUi; import org.schabi.newpipe.player.notification.NotificationPlayerUi;
import org.schabi.newpipe.util.ThemeHelper; import org.schabi.newpipe.util.ThemeHelper;
@ -55,6 +57,12 @@ public final class PlayerService extends MediaBrowserServiceCompat {
public static final String SHOULD_START_FOREGROUND_EXTRA = "should_start_foreground_extra"; public static final String SHOULD_START_FOREGROUND_EXTRA = "should_start_foreground_extra";
public static final String BIND_PLAYER_HOLDER_ACTION = "bind_player_holder_action"; public static final String BIND_PLAYER_HOLDER_ACTION = "bind_player_holder_action";
// These objects are used to cleanly separate the Service implementation (in this file) and the
// media browser and playback preparer implementations. At the moment the playback preparer is
// only used in conjunction with the media browser.
private MediaBrowserImpl mediaBrowserImpl;
private MediaBrowserPlaybackPreparer mediaBrowserPlaybackPreparer;
// these are instantiated in onCreate() as per // these are instantiated in onCreate() as per
// https://developer.android.com/training/cars/media#browser_workflow // https://developer.android.com/training/cars/media#browser_workflow
private MediaSessionCompat mediaSession; private MediaSessionCompat mediaSession;
@ -66,10 +74,7 @@ public final class PlayerService extends MediaBrowserServiceCompat {
private final IBinder mBinder = new PlayerService.LocalBinder(this); private final IBinder mBinder = new PlayerService.LocalBinder(this);
/*////////////////////////////////////////////////////////////////////////// //region Service lifecycle
// Service's LifeCycle
//////////////////////////////////////////////////////////////////////////*/
@Override @Override
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
@ -80,12 +85,21 @@ public final class PlayerService extends MediaBrowserServiceCompat {
assureCorrectAppLanguage(this); assureCorrectAppLanguage(this);
ThemeHelper.setTheme(this); ThemeHelper.setTheme(this);
mediaBrowserImpl = new MediaBrowserImpl(this, this::notifyChildrenChanged);
// see https://developer.android.com/training/cars/media#browser_workflow // see https://developer.android.com/training/cars/media#browser_workflow
mediaSession = new MediaSessionCompat(this, "MediaSessionPlayerServ"); mediaSession = new MediaSessionCompat(this, "MediaSessionPlayerServ");
setSessionToken(mediaSession.getSessionToken()); setSessionToken(mediaSession.getSessionToken());
sessionConnector = new MediaSessionConnector(mediaSession); sessionConnector = new MediaSessionConnector(mediaSession);
sessionConnector.setMetadataDeduplicationEnabled(true); sessionConnector.setMetadataDeduplicationEnabled(true);
mediaBrowserPlaybackPreparer = new MediaBrowserPlaybackPreparer(
this,
sessionConnector::setCustomErrorMessage,
() -> sessionConnector.setCustomErrorMessage(null)
);
sessionConnector.setPlaybackPreparer(mediaBrowserPlaybackPreparer);
// Note: you might be tempted to create the player instance and call startForeground here, // Note: you might be tempted to create the player instance and call startForeground here,
// but be aware that the Android system might start the service just to perform media // but be aware that the Android system might start the service just to perform media
// queries. In those cases creating a player instance is a waste of resources, and calling // queries. In those cases creating a player instance is a waste of resources, and calling
@ -177,8 +191,10 @@ public final class PlayerService extends MediaBrowserServiceCompat {
cleanup(); cleanup();
mediaBrowserPlaybackPreparer.dispose();
mediaSession.setActive(false); mediaSession.setActive(false);
mediaSession.release(); mediaSession.release();
mediaBrowserImpl.dispose();
} }
private void cleanup() { private void cleanup() {
@ -197,7 +213,9 @@ public final class PlayerService extends MediaBrowserServiceCompat {
protected void attachBaseContext(final Context base) { protected void attachBaseContext(final Context base) {
super.attachBaseContext(AudioServiceLeakFix.preventLeakOf(base)); super.attachBaseContext(AudioServiceLeakFix.preventLeakOf(base));
} }
//endregion
//region Bind
@Override @Override
public IBinder onBind(final Intent intent) { public IBinder onBind(final Intent intent) {
if (DEBUG) { if (DEBUG) {
@ -236,18 +254,28 @@ public final class PlayerService extends MediaBrowserServiceCompat {
return playerService.get().player; return playerService.get().player;
} }
} }
//endregion
@Nullable //region Media browser
@Override @Override
public BrowserRoot onGetRoot(@NonNull final String clientPackageName, public BrowserRoot onGetRoot(@NonNull final String clientPackageName,
final int clientUid, final int clientUid,
@Nullable final Bundle rootHints) { @Nullable final Bundle rootHints) {
return null; // TODO check if the accessing package has permission to view data
return mediaBrowserImpl.onGetRoot(clientPackageName, clientUid, rootHints);
} }
@Override @Override
public void onLoadChildren(@NonNull final String parentId, public void onLoadChildren(@NonNull final String parentId,
@NonNull final Result<List<MediaBrowserCompat.MediaItem>> result) { @NonNull final Result<List<MediaBrowserCompat.MediaItem>> result) {
mediaBrowserImpl.onLoadChildren(parentId, result);
} }
@Override
public void onSearch(@NonNull final String query,
final Bundle extras,
@NonNull final Result<List<MediaBrowserCompat.MediaItem>> result) {
mediaBrowserImpl.onSearch(query, result);
}
//endregion
} }