MediaSessionService: define foregroundServiceType

PiperOrigin-RevId: 447467287
This commit is contained in:
christosts 2022-05-09 15:47:30 +01:00 committed by Ian Baker
parent 54d8b5bc7c
commit 7a631f4050
4 changed files with 49 additions and 6 deletions

View File

@ -45,6 +45,7 @@
<service
android:name=".PlaybackService"
android:foregroundServiceType="mediaPlayback"
android:exported="true">
<intent-filter>
<action android:name="androidx.media3.session.MediaSessionService"/>

View File

@ -19,13 +19,17 @@ import static androidx.media3.common.util.Assertions.checkStateNotNull;
import android.app.Notification;
import android.content.Intent;
import android.content.pm.ServiceInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import androidx.annotation.DoNotInline;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationManagerCompat;
import androidx.core.content.ContextCompat;
import androidx.media3.common.Player;
import androidx.media3.common.util.Log;
import androidx.media3.common.util.Util;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
@ -44,6 +48,8 @@ import java.util.concurrent.TimeoutException;
*/
/* package */ final class MediaNotificationManager {
private static final String TAG = "MediaNtfMng";
private final MediaSessionService mediaSessionService;
private final MediaNotification.Provider mediaNotificationProvider;
private final MediaNotification.ActionFactory actionFactory;
@ -170,8 +176,12 @@ import java.util.concurrent.TimeoutException;
Player player = session.getPlayer();
if (player.getPlayWhenReady() && canStartPlayback(player)) {
ContextCompat.startForegroundService(mediaSessionService, startSelfIntent);
if (Util.SDK_INT >= 29) {
Api29.startForeground(mediaSessionService, mediaNotification);
} else {
mediaSessionService.startForeground(
mediaNotification.notificationId, mediaNotification.notification);
}
} else {
maybeStopForegroundService(/* removeNotifications= */ false);
notificationManagerCompat.notify(
@ -251,4 +261,29 @@ import java.util.concurrent.TimeoutException;
mediaSessionService.onUpdateNotification(session);
}
}
@RequiresApi(29)
private static class Api29 {
@DoNotInline
public static void startForeground(
MediaSessionService mediaSessionService, MediaNotification mediaNotification) {
try {
// startForeground() will throw if the service's foregroundServiceType is not defined in the
// manifest to include mediaPlayback.
mediaSessionService.startForeground(
mediaNotification.notificationId,
mediaNotification.notification,
ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK);
} catch (RuntimeException e) {
Log.e(
TAG,
"The service must be declared with a foregroundServiceType that includes "
+ " mediaPlayback");
throw e;
}
}
private Api29() {}
}
}

View File

@ -60,7 +60,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
* <p>To extend this class, declare the intent filter in your {@code AndroidManifest.xml}:
*
* <pre>{@code
* <service android:name="NameOfYourService">
* <service
* android:name="NameOfYourService"
* android:foregroundServiceType="mediaPlayback">
* <intent-filter>
* <action android:name="androidx.media3.session.MediaSessionService"/>
* </intent-filter>
@ -85,9 +87,11 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
*
* <h2 id="ServiceLifecycle">Service Lifecycle</h2>
*
* <p>A media session service is a bound service. When a {@link MediaController} is created for the
* service, the controller binds to the service. {@link #onGetSession(ControllerInfo)} will be
* called from {@link #onBind(Intent)}.
* <p>A media session service is a bound service and its <a
* href="https://developer.android.com/guide/topics/manifest/service-element#foregroundservicetype">foreground
* service type</a> must include <em>mediaPlayback</em>. When a {@link MediaController} is created
* for the service, the controller binds to the service. {@link #onGetSession(ControllerInfo)} will
* be called from {@link #onBind(Intent)}.
*
* <p>After binding, the session's {@link MediaSession.SessionCallback#onConnect(MediaSession,
* MediaSession.ControllerInfo)} will be called to accept or reject the connection request from the

View File

@ -81,6 +81,7 @@
</service>
<service android:name="androidx.media3.session.MockMediaSessionService"
android:foregroundServiceType="mediaPlayback"
android:exported="true"
android:process=":remote">
<intent-filter>
@ -89,6 +90,7 @@
</service>
<service android:name="androidx.media3.session.LocalMockMediaSessionService"
android:foregroundServiceType="mediaPlayback"
android:exported="true">
<intent-filter>
<action android:name="androidx.media3.session.MediaSessionService" />
@ -96,6 +98,7 @@
</service>
<service android:name="androidx.media3.session.MockMediaLibraryService"
android:foregroundServiceType="mediaPlayback"
android:exported="true"
android:process=":remote">
<intent-filter>