Fix some JavaDoc in the Media3 session module
#minor-release PiperOrigin-RevId: 513501046 (cherry picked from commit 6042bec18a4b30449a20d1e858bac799cc6d18c3)
This commit is contained in:
parent
67fd41a49d
commit
d47675f017
@ -67,14 +67,16 @@ import java.util.List;
|
|||||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A session that allows a media app to expose its transport controls and playback information in a
|
* A session that allows a media app to expose its player functionality, information of the playlist
|
||||||
* process to other processes including the Android framework and other apps. The common use cases
|
* and the media item currently being played to other processes including the Android framework and
|
||||||
* are as follows:
|
* other apps. The common use cases are as follows:
|
||||||
*
|
*
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>Bluetooth/wired headset key events support
|
* <li>Receiving and dispatching media key events (for instance Bluetooth/wired headset and remote
|
||||||
* <li>Android Auto/Wearable support
|
* control devices).
|
||||||
* <li>Separating UI process and playback process
|
* <li>Publish media playback information and player commands to SystemUI (media notification) and
|
||||||
|
* Android Auto/Wear OS.
|
||||||
|
* <li>Separating UI process and playback process.
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* <p>A session should be created when an app wants to publish media playback information or handle
|
* <p>A session should be created when an app wants to publish media playback information or handle
|
||||||
@ -82,9 +84,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
* sessions can be created to provide finer grain controls of media. See <a
|
* sessions can be created to provide finer grain controls of media. See <a
|
||||||
* href="#MultipleSessions">Supporting Multiple Sessions</a> for details.
|
* href="#MultipleSessions">Supporting Multiple Sessions</a> for details.
|
||||||
*
|
*
|
||||||
* <p>If you want to support background playback, {@link MediaSessionService} is preferred. With the
|
* <p>If an app wants to support playback when in the background, using a {@link
|
||||||
* service, your playback can be revived even after playback is finished. See {@link
|
* MediaSessionService} is the preferred approach. See {@link MediaSessionService} for details.
|
||||||
* MediaSessionService} for details.
|
|
||||||
*
|
*
|
||||||
* <p>Topics covered here:
|
* <p>Topics covered here:
|
||||||
*
|
*
|
||||||
@ -103,7 +104,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
* #getToken() session token} to other processes to allow them to create a {@link MediaController}
|
* #getToken() session token} to other processes to allow them to create a {@link MediaController}
|
||||||
* to interact with the session.
|
* to interact with the session.
|
||||||
*
|
*
|
||||||
* <p>When a session receives transport control commands, the session sends the commands directly to
|
* <p>When a session receives playback commands, the session calls corresponding methods directly on
|
||||||
* the underlying player set by {@link Builder#Builder(Context, Player)} or {@link
|
* the underlying player set by {@link Builder#Builder(Context, Player)} or {@link
|
||||||
* #setPlayer(Player)}.
|
* #setPlayer(Player)}.
|
||||||
*
|
*
|
||||||
@ -113,15 +114,15 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
*
|
*
|
||||||
* <h2 id="ThreadingModel">Threading Model</h2>
|
* <h2 id="ThreadingModel">Threading Model</h2>
|
||||||
*
|
*
|
||||||
* <p>The instances are thread safe, but should be used on the thread with a looper.
|
* <p>The instances are thread safe, but must be used on a thread with a looper.
|
||||||
*
|
*
|
||||||
* <p>{@link Callback} methods will be called from the application thread associated with the {@link
|
* <p>{@link Callback} methods will be called on the application thread associated with the {@link
|
||||||
* Player#getApplicationLooper() application looper} of the underlying player. When a new player is
|
* Player#getApplicationLooper() application looper} of the underlying player. When a new player is
|
||||||
* set by {@link #setPlayer}, the player should use the same application looper as the previous one.
|
* set by {@link #setPlayer}, the player must use the same application looper as the previous one.
|
||||||
*
|
*
|
||||||
* <p>The session listens to events from the underlying player via {@link Player.Listener} and
|
* <p>The session listens to player events via {@link Player.Listener} and expects the callback
|
||||||
* expects the callback methods to be called from the application thread. If the player violates the
|
* methods to be called on the application thread. If the player violates the threading contract, an
|
||||||
* threading contract, {@link IllegalStateException} will be thrown.
|
* {@link IllegalStateException} will be thrown.
|
||||||
*
|
*
|
||||||
* <h2 id="KeyEvents">Media Key Events Mapping</h2>
|
* <h2 id="KeyEvents">Media Key Events Mapping</h2>
|
||||||
*
|
*
|
||||||
@ -160,7 +161,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
* </li>
|
* </li>
|
||||||
* <li>{@link Player#play()} otherwise</li>
|
* <li>{@link Player#play()} otherwise</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* <li>For a double tap, {@link Player#seekToNext()}</li>
|
* <li>In case the media key events are coming from another package ID than the package ID of
|
||||||
|
* the media app (events coming for instance from Bluetooth), a double tap generating two
|
||||||
|
* key events within a brief amount of time, is converted to {@link Player#seekToNext()}
|
||||||
|
* </li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* </td>
|
* </td>
|
||||||
* </tr>
|
* </tr>
|
||||||
@ -193,16 +197,15 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
* media or remote playback, since the <a
|
* media or remote playback, since the <a
|
||||||
* href="https://developer.android.com/guide/topics/media-apps/audio-focus">audio focus policy</a>
|
* href="https://developer.android.com/guide/topics/media-apps/audio-focus">audio focus policy</a>
|
||||||
* recommends not playing multiple audio content at the same time. Also, keep in mind that multiple
|
* recommends not playing multiple audio content at the same time. Also, keep in mind that multiple
|
||||||
* media sessions would make Android Auto and Bluetooth device with display to show your apps
|
* media sessions would make Android Auto and Bluetooth devices with display to show your app
|
||||||
* multiple times, because they list up media sessions, not media apps.
|
* multiple times, because they list up media sessions, not media apps.
|
||||||
*
|
*
|
||||||
* <h2 id="BackwardCompatibility">Backward Compatibility with Legacy Session APIs</h2>
|
* <h2 id="BackwardCompatibility">Backward Compatibility with Legacy Session APIs</h2>
|
||||||
*
|
*
|
||||||
* <p>An active {@link MediaSessionCompat} is internally created with the session for the backward
|
* <p>An active {@link MediaSessionCompat} is internally created with the session for backwards
|
||||||
* compatibility. It's used to handle incoming connection and commands from {@link
|
* compatibility. It's used to handle incoming connections and commands from {@link
|
||||||
* MediaControllerCompat}, and helps to utilize existing APIs that are built with legacy media
|
* MediaControllerCompat} instances, and helps to utilize existing APIs that are built with legacy
|
||||||
* session APIs. Use {@link #getSessionCompatToken} to get the legacy token of {@link
|
* media session APIs.
|
||||||
* MediaSessionCompat}.
|
|
||||||
*
|
*
|
||||||
* <h2 id="CompatibilityController">Backward Compatibility with Legacy Controller APIs</h2>
|
* <h2 id="CompatibilityController">Backward Compatibility with Legacy Controller APIs</h2>
|
||||||
*
|
*
|
||||||
@ -211,10 +214,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
* {@linkplain MediaControllerCompat AndroidX controller compat}. However, {@link ControllerInfo}
|
* {@linkplain MediaControllerCompat AndroidX controller compat}. However, {@link ControllerInfo}
|
||||||
* may not be precise for legacy controllers. See {@link ControllerInfo} for the details.
|
* may not be precise for legacy controllers. See {@link ControllerInfo} for the details.
|
||||||
*
|
*
|
||||||
* <p>Unknown package name nor UID doesn't mean that you should disallow connection nor commands.
|
* <p>Neither an unknown package name nor an unknown UID mean that you should disallow a connection
|
||||||
* For SDK levels where such issues happen, session tokens could only be obtained by trusted
|
* or commands per se. For SDK levels where such issues happen, session tokens can only be obtained
|
||||||
* controllers (e.g. Bluetooth, Auto, ...), so it may be better for you to allow them as you did
|
* by trusted controllers (e.g. Bluetooth, Auto, ...). This means only trusted controllers can
|
||||||
* with legacy sessions.
|
* connect and an app can accept such controllers in the same way as with legacy sessions.
|
||||||
*/
|
*/
|
||||||
public class MediaSession {
|
public class MediaSession {
|
||||||
|
|
||||||
@ -242,7 +245,7 @@ public class MediaSession {
|
|||||||
* Creates a builder for {@link MediaSession}.
|
* Creates a builder for {@link MediaSession}.
|
||||||
*
|
*
|
||||||
* @param context The context.
|
* @param context The context.
|
||||||
* @param player The underlying player to perform playback and handle transport controls.
|
* @param player The underlying player to perform playback and handle player commands.
|
||||||
* @throws IllegalArgumentException if {@link Player#canAdvertiseSession()} returns false.
|
* @throws IllegalArgumentException if {@link Player#canAdvertiseSession()} returns false.
|
||||||
*/
|
*/
|
||||||
public Builder(Context context, Player player) {
|
public Builder(Context context, Player player) {
|
||||||
@ -253,13 +256,13 @@ public class MediaSession {
|
|||||||
* Sets a {@link PendingIntent} to launch an {@link android.app.Activity} for the {@link
|
* Sets a {@link PendingIntent} to launch an {@link android.app.Activity} for the {@link
|
||||||
* MediaSession}. This can be used as a quick link to an ongoing media screen.
|
* MediaSession}. This can be used as a quick link to an ongoing media screen.
|
||||||
*
|
*
|
||||||
* <p>A client can use this pending intent to start an activity belonging to this session. When
|
* <p>A client can use this pending intent to start an activity belonging to this session. On
|
||||||
* this pending intent is for instance included in the notification {@linkplain
|
* API levels below 33 the pending intent can be used {@linkplain
|
||||||
* NotificationCompat.Builder#setContentIntent(PendingIntent) as the content intent}, tapping
|
* NotificationCompat.Builder#setContentIntent(PendingIntent) as the content intent}. Tapping
|
||||||
* the notification will open this activity.
|
* the notification will then send that pending intent and open the activity (see <a
|
||||||
*
|
* href="https://developer.android.com/training/notify-user/navigation">'Start an Activity from
|
||||||
* <p>See <a href="https://developer.android.com/training/notify-user/navigation">'Start an
|
* a Notification'</a>). For API levels starting with 33, the media notification reads the
|
||||||
* Activity from a Notification'</a> also.
|
* pending intent directly from the session.
|
||||||
*
|
*
|
||||||
* @param pendingIntent The pending intent.
|
* @param pendingIntent The pending intent.
|
||||||
* @return The builder to allow chaining.
|
* @return The builder to allow chaining.
|
||||||
@ -290,6 +293,13 @@ public class MediaSession {
|
|||||||
* Sets a callback for the {@link MediaSession} to handle incoming requests from {link
|
* Sets a callback for the {@link MediaSession} to handle incoming requests from {link
|
||||||
* MediaController}.
|
* MediaController}.
|
||||||
*
|
*
|
||||||
|
* <p>Apps that want to allow controllers to {@linkplain MediaController#setMediaItems(List)
|
||||||
|
* set} or {@linkplain MediaController#addMediaItems(List) add} media items to the playlist,
|
||||||
|
* must use a callback and override its {@link
|
||||||
|
* MediaSession.Callback#onSetMediaItems(MediaSession, ControllerInfo, List, int, long)} or
|
||||||
|
* {@link MediaSession.Callback#onSetMediaItems(MediaSession, ControllerInfo, List, int, long)}
|
||||||
|
* methods.
|
||||||
|
*
|
||||||
* @param callback The callback.
|
* @param callback The callback.
|
||||||
* @return The builder to allow chaining.
|
* @return The builder to allow chaining.
|
||||||
*/
|
*/
|
||||||
@ -371,7 +381,8 @@ public class MediaSession {
|
|||||||
* @param remoteUserInfo The remote user info.
|
* @param remoteUserInfo The remote user info.
|
||||||
* @param trusted {@code true} if trusted, {@code false} otherwise.
|
* @param trusted {@code true} if trusted, {@code false} otherwise.
|
||||||
* @param cb ControllerCb. Can be {@code null} only when a MediaBrowserCompat connects to
|
* @param cb ControllerCb. Can be {@code null} only when a MediaBrowserCompat connects to
|
||||||
* MediaSessionService and ControllerInfo is needed for {@code SessionCallback#onConnect()}.
|
* MediaSessionService and ControllerInfo is needed for {@link
|
||||||
|
* MediaSession.Callback#onConnect(MediaSession, ControllerInfo)}.
|
||||||
* @param connectionHints A session-specific argument sent from the controller for the
|
* @param connectionHints A session-specific argument sent from the controller for the
|
||||||
* connection. The contents of this bundle may affect the connection result.
|
* connection. The contents of this bundle may affect the connection result.
|
||||||
*/
|
*/
|
||||||
|
@ -447,7 +447,7 @@ import org.checkerframework.checker.initialization.qual.Initialized;
|
|||||||
|
|
||||||
public MediaSession.ConnectionResult onConnectOnHandler(ControllerInfo controller) {
|
public MediaSession.ConnectionResult onConnectOnHandler(ControllerInfo controller) {
|
||||||
return checkNotNull(
|
return checkNotNull(
|
||||||
callback.onConnect(instance, controller), "onConntext must return non-null future");
|
callback.onConnect(instance, controller), "onConnect must return non-null future");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onPostConnectOnHandler(ControllerInfo controller) {
|
public void onPostConnectOnHandler(ControllerInfo controller) {
|
||||||
|
@ -57,26 +57,27 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
/**
|
/**
|
||||||
* Superclass to be extended by services hosting {@link MediaSession media sessions}.
|
* Superclass to be extended by services hosting {@link MediaSession media sessions}.
|
||||||
*
|
*
|
||||||
* <p>It's highly recommended for an app to use this class if they want to keep media playback in
|
* <p>It's highly recommended for an app to use this class if media playback should continue while
|
||||||
* the background. The service allows other apps to know that your app supports {@link MediaSession}
|
* in the background. The service allows other apps to know that your app supports {@link
|
||||||
* even when your app isn't running. For example, a user voice command may start your app to play
|
* MediaSession} even when your app isn't running. This way, a user voice command may be able start
|
||||||
* media.
|
* your app to play media.
|
||||||
*
|
*
|
||||||
* <p>To extend this class, declare the intent filter in your {@code AndroidManifest.xml}:
|
* <p>To extend this class, declare the intent filter in your {@code AndroidManifest.xml}:
|
||||||
*
|
*
|
||||||
* <pre>{@code
|
* <pre>{@code
|
||||||
* <service
|
* <service
|
||||||
* android:name="NameOfYourService"
|
* android:name="NameOfYourService"
|
||||||
* android:foregroundServiceType="mediaPlayback">
|
* android:foregroundServiceType="mediaPlayback"
|
||||||
|
* android:exported="true">
|
||||||
* <intent-filter>
|
* <intent-filter>
|
||||||
* <action android:name="androidx.media3.session.MediaSessionService"/>
|
* <action android:name="androidx.media3.session.MediaSessionService"/>
|
||||||
* </intent-filter>
|
* </intent-filter>
|
||||||
* </service>
|
* </service>
|
||||||
* }</pre>
|
* }</pre>
|
||||||
*
|
*
|
||||||
* <p>You may also declare {@code android.media.browse.MediaBrowserService} for compatibility with
|
* <p>You may also declare the action {@code android.media.browse.MediaBrowserService} for
|
||||||
* {@link android.support.v4.media.MediaBrowserCompat}. This service can handle the case
|
* compatibility with {@link android.support.v4.media.MediaBrowserCompat}. This service can handle
|
||||||
* automatically.
|
* the case automatically.
|
||||||
*
|
*
|
||||||
* <p>It's recommended for an app to have a single service declared in the manifest. Otherwise, your
|
* <p>It's recommended for an app to have a single service declared in the manifest. Otherwise, your
|
||||||
* app might be shown twice in the list of the controller apps, or another app might fail to pick
|
* app might be shown twice in the list of the controller apps, or another app might fail to pick
|
||||||
@ -93,10 +94,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
* <h2 id="ServiceLifecycle">Service Lifecycle</h2>
|
* <h2 id="ServiceLifecycle">Service Lifecycle</h2>
|
||||||
*
|
*
|
||||||
* <p>A media session service is a bound service and its <a
|
* <p>A media session service is a bound service and its <a
|
||||||
* href="https://developer.android.com/guide/topics/manifest/service-element#foregroundservicetype">foreground
|
* href="https://developer.android.com/guide/topics/manifest/service-element#foregroundservicetype">
|
||||||
* service type</a> must include <em>mediaPlayback</em>. When a {@link MediaController} is created
|
* foreground service type</a> must include <em>mediaPlayback</em>. When a {@link MediaController}
|
||||||
* for the service, the controller binds to the service. {@link #onGetSession(ControllerInfo)} will
|
* is created for the service, the controller binds to the service. {@link
|
||||||
* be called from {@link #onBind(Intent)}.
|
* #onGetSession(ControllerInfo)} will be called from {@link #onBind(Intent)}.
|
||||||
*
|
*
|
||||||
* <p>After binding, the session's {@link MediaSession.Callback#onConnect(MediaSession,
|
* <p>After binding, the session's {@link MediaSession.Callback#onConnect(MediaSession,
|
||||||
* MediaSession.ControllerInfo)} will be called to accept or reject the connection request from the
|
* MediaSession.ControllerInfo)} will be called to accept or reject the connection request from the
|
||||||
@ -115,8 +116,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
* #onUpdateNotification(MediaSession)}. In this case, you must also start or stop the service from
|
* #onUpdateNotification(MediaSession)}. In this case, you must also start or stop the service from
|
||||||
* the foreground, when playback starts or stops respectively.
|
* the foreground, when playback starts or stops respectively.
|
||||||
*
|
*
|
||||||
* <p>The service will be destroyed when all sessions are closed, or no controller is binding to the
|
* <p>The service will be destroyed when all sessions are {@linkplain MediaController#release()
|
||||||
* service while the service is in the background.
|
* released}, or no controller is binding to the service while the service is in the background.
|
||||||
*
|
*
|
||||||
* <h2 id="MultipleSessions">Supporting Multiple Sessions</h2>
|
* <h2 id="MultipleSessions">Supporting Multiple Sessions</h2>
|
||||||
*
|
*
|
||||||
@ -247,7 +248,8 @@ public abstract class MediaSessionService extends Service {
|
|||||||
* Adds a {@link MediaSession} to this service. This is not necessary for most media apps. See <a
|
* Adds a {@link MediaSession} to this service. This is not necessary for most media apps. See <a
|
||||||
* href="#MultipleSessions">Supporting Multiple Sessions</a> for details.
|
* href="#MultipleSessions">Supporting Multiple Sessions</a> for details.
|
||||||
*
|
*
|
||||||
* <p>The added session will be removed automatically when it's closed.
|
* <p>The added session will be removed automatically {@linkplain MediaSession#release() when the
|
||||||
|
* session is released}.
|
||||||
*
|
*
|
||||||
* @param session A session to be added.
|
* @param session A session to be added.
|
||||||
* @see #removeSession(MediaSession)
|
* @see #removeSession(MediaSession)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user