Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
SDK
/
exoplayer
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
6042bec1
authored
Mar 02, 2023
by
bachinger
Committed by
tonihei
Mar 02, 2023
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Fix some JavaDoc in the Media3 session module
#minor-release PiperOrigin-RevId: 513501046
parent
cd753bd7
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
65 additions
and
52 deletions
libraries/session/src/main/java/androidx/media3/session/MediaSession.java
libraries/session/src/main/java/androidx/media3/session/MediaSessionImpl.java
libraries/session/src/main/java/androidx/media3/session/MediaSessionService.java
libraries/session/src/main/java/androidx/media3/session/MediaSession.java
View file @
6042bec1
...
...
@@ -68,14 +68,16 @@ import java.util.List;
import
org.checkerframework.checker.nullness.qual.MonotonicNonNull
;
/**
* A session that allows a media app to expose its
transport controls and playback information in a
*
process to other processes including the Android framework and other apps. The common use cases
* are as follows:
* A session that allows a media app to expose its
player functionality, information of the playlist
*
and the media item currently being played to other processes including the Android framework and
*
other apps. The common use cases
are as follows:
*
* <ul>
* <li>Bluetooth/wired headset key events support
* <li>Android Auto/Wearable support
* <li>Separating UI process and playback process
* <li>Receiving and dispatching media key events (for instance Bluetooth/wired headset and remote
* control devices).
* <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>
*
* <p>A session should be created when an app wants to publish media playback information or handle
...
...
@@ -83,9 +85,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
* sessions can be created to provide finer grain controls of media. See <a
* href="#MultipleSessions">Supporting Multiple Sessions</a> for details.
*
* <p>If you want to support background playback, {@link MediaSessionService} is preferred. With the
* service, your playback can be revived even after playback is finished. See {@link
* MediaSessionService} for details.
* <p>If an app wants to support playback when in the background, using a {@link
* MediaSessionService} is the preferred approach. See {@link MediaSessionService} for details.
*
* <p>Topics covered here:
*
...
...
@@ -104,7 +105,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
* #getToken() session token} to other processes to allow them to create a {@link MediaController}
* 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
* #setPlayer(Player)}.
*
...
...
@@ -114,15 +115,15 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
*
* <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
* 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
*
expects the callback methods to be called from the application thread. If the player violates the
*
threading contract,
{@link IllegalStateException} will be thrown.
* <p>The session listens to
player events via {@link Player.Listener} and expects the callback
*
methods to be called on the application thread. If the player violates the threading contract, an
* {@link IllegalStateException} will be thrown.
*
* <h2 id="KeyEvents">Media Key Events Mapping</h2>
*
...
...
@@ -161,7 +162,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
* </li>
* <li>{@link Player#play()} otherwise</li>
* </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>
* </td>
* </tr>
...
...
@@ -194,16 +198,15 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
* media or remote playback, since the <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
* media sessions would make Android Auto and Bluetooth device
with display to show your apps
* media sessions would make Android Auto and Bluetooth device
s with display to show your app
* multiple times, because they list up media sessions, not media apps.
*
* <h2 id="BackwardCompatibility">Backward Compatibility with Legacy Session APIs</h2>
*
* <p>An active {@link MediaSessionCompat} is internally created with the session for the backward
* compatibility. It's used to handle incoming connection and commands from {@link
* MediaControllerCompat}, and helps to utilize existing APIs that are built with legacy media
* session APIs. Use {@link #getSessionCompatToken} to get the legacy token of {@link
* MediaSessionCompat}.
* <p>An active {@link MediaSessionCompat} is internally created with the session for backwards
* compatibility. It's used to handle incoming connections and commands from {@link
* MediaControllerCompat} instances, and helps to utilize existing APIs that are built with legacy
* media session APIs.
*
* <h2 id="CompatibilityController">Backward Compatibility with Legacy Controller APIs</h2>
*
...
...
@@ -212,10 +215,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
* {@linkplain MediaControllerCompat AndroidX controller compat}. However, {@link ControllerInfo}
* 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.
*
For SDK levels where such issues happen, session tokens could only be obtained by trust
ed
*
controllers (e.g. Bluetooth, Auto, ...), so it may be better for you to allow them as you did
* with legacy sessions.
* <p>
Neither an unknown package name nor an unknown UID mean that you should disallow a connection
*
or commands per se. For SDK levels where such issues happen, session tokens can only be obtain
ed
*
by trusted controllers (e.g. Bluetooth, Auto, ...). This means only trusted controllers can
*
connect and an app can accept such controllers in the same way as
with legacy sessions.
*/
public
class
MediaSession
{
...
...
@@ -243,7 +246,7 @@ public class MediaSession {
* Creates a builder for {@link MediaSession}.
*
* @param context The context.
* @param player The underlying player to perform playback and handle
transport control
s.
* @param player The underlying player to perform playback and handle
player command
s.
* @throws IllegalArgumentException if {@link Player#canAdvertiseSession()} returns false.
*/
public
Builder
(
Context
context
,
Player
player
)
{
...
...
@@ -254,13 +257,13 @@ public class MediaSession {
* 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.
*
* <p>A client can use this pending intent to start an activity belonging to this session.
Whe
n
*
this pending intent is for instance included in the notification
{@linkplain
* NotificationCompat.Builder#setContentIntent(PendingIntent) as the content intent}
, t
apping
* the notification will
open this activity.
*
*
<p>See <a href="https://developer.android.com/training/notify-user/navigation">'Start an
*
Activity from a Notification'</a> also
.
* <p>A client can use this pending intent to start an activity belonging to this session.
O
n
*
API levels below 33 the pending intent can be used
{@linkplain
* NotificationCompat.Builder#setContentIntent(PendingIntent) as the content intent}
. T
apping
* 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
*
a Notification'</a>). For API levels starting with 33, the media notification reads the
*
pending intent directly from the session
.
*
* @param pendingIntent The pending intent.
* @return The builder to allow chaining.
...
...
@@ -291,6 +294,13 @@ public class MediaSession {
* Sets a callback for the {@link MediaSession} to handle incoming requests from {link
* 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.
* @return The builder to allow chaining.
*/
...
...
@@ -372,7 +382,8 @@ public class MediaSession {
* @param remoteUserInfo The remote user info.
* @param trusted {@code true} if trusted, {@code false} otherwise.
* @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
* connection. The contents of this bundle may affect the connection result.
*/
...
...
libraries/session/src/main/java/androidx/media3/session/MediaSessionImpl.java
View file @
6042bec1
...
...
@@ -448,7 +448,7 @@ import org.checkerframework.checker.initialization.qual.Initialized;
public
MediaSession
.
ConnectionResult
onConnectOnHandler
(
ControllerInfo
controller
)
{
return
checkNotNull
(
callback
.
onConnect
(
instance
,
controller
),
"onConn
tex
t must return non-null future"
);
callback
.
onConnect
(
instance
,
controller
),
"onConn
ec
t must return non-null future"
);
}
public
void
onPostConnectOnHandler
(
ControllerInfo
controller
)
{
...
...
libraries/session/src/main/java/androidx/media3/session/MediaSessionService.java
View file @
6042bec1
...
...
@@ -57,26 +57,27 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/**
* 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
*
the background. The service allows other apps to know that your app supports {@link MediaSession}
*
even when your app isn't running. For example, a user voice command may start your app to play
* media.
* <p>It's highly recommended for an app to use this class if
media playback should continue while
*
in the background. The service allows other apps to know that your app supports {@link
*
MediaSession} even when your app isn't running. This way, a user voice command may be able start
*
your app to play
media.
*
* <p>To extend this class, declare the intent filter in your {@code AndroidManifest.xml}:
*
* <pre>{@code
* <service
* android:name="NameOfYourService"
* android:foregroundServiceType="mediaPlayback">
* android:foregroundServiceType="mediaPlayback"
* android:exported="true">
* <intent-filter>
* <action android:name="androidx.media3.session.MediaSessionService"/>
* </intent-filter>
* </service>
* }</pre>
*
* <p>You may also declare
{@code android.media.browse.MediaBrowserService} for compatibility with
*
{@link android.support.v4.media.MediaBrowserCompat}. This service can handle the cas
e
* automatically.
* <p>You may also declare
the action {@code android.media.browse.MediaBrowserService} for
*
compatibility with {@link android.support.v4.media.MediaBrowserCompat}. This service can handl
e
*
the case
automatically.
*
* <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
...
...
@@ -93,10 +94,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
* <h2 id="ServiceLifecycle">Service Lifecycle</h2>
*
* <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)}.
* 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.Callback#onConnect(MediaSession,
* 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
* 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
* service while the service is in the background.
* <p>The service will be destroyed when all sessions are
{@linkplain MediaController#release()
*
released}, or no controller is binding to the
service while the service is in the background.
*
* <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
* 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.
* @see #removeSession(MediaSession)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment