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
df2e37ac
authored
Dec 15, 2021
by
jaewan
Committed by
tonihei
Jan 05, 2022
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Utilize CommandButton for customizing Notification
PiperOrigin-RevId: 416421456
parent
531ff0e1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
188 additions
and
274 deletions
libraries/session/src/main/java/androidx/media3/session/PlayerNotificationManager.java
libraries/session/src/main/java/androidx/media3/session/PlayerNotificationManager.java
View file @
df2e37ac
...
@@ -15,6 +15,8 @@
...
@@ -15,6 +15,8 @@
*/
*/
package
androidx
.
media3
.
session
;
package
androidx
.
media3
.
session
;
import
static
androidx
.
media3
.
common
.
Player
.
COMMAND_INVALID
;
import
static
androidx
.
media3
.
common
.
Player
.
COMMAND_PLAY_PAUSE
;
import
static
androidx
.
media3
.
common
.
Player
.
COMMAND_SEEK_BACK
;
import
static
androidx
.
media3
.
common
.
Player
.
COMMAND_SEEK_BACK
;
import
static
androidx
.
media3
.
common
.
Player
.
COMMAND_SEEK_FORWARD
;
import
static
androidx
.
media3
.
common
.
Player
.
COMMAND_SEEK_FORWARD
;
import
static
androidx
.
media3
.
common
.
Player
.
COMMAND_SEEK_TO_NEXT
;
import
static
androidx
.
media3
.
common
.
Player
.
COMMAND_SEEK_TO_NEXT
;
...
@@ -40,6 +42,7 @@ import android.content.Intent;
...
@@ -40,6 +42,7 @@ import android.content.Intent;
import
android.content.IntentFilter
;
import
android.content.IntentFilter
;
import
android.graphics.Bitmap
;
import
android.graphics.Bitmap
;
import
android.graphics.Color
;
import
android.graphics.Color
;
import
android.net.Uri
;
import
android.os.Handler
;
import
android.os.Handler
;
import
android.os.Looper
;
import
android.os.Looper
;
import
android.os.Message
;
import
android.os.Message
;
...
@@ -53,6 +56,8 @@ import androidx.core.app.NotificationManagerCompat;
...
@@ -53,6 +56,8 @@ import androidx.core.app.NotificationManagerCompat;
import
androidx.media.app.NotificationCompat.MediaStyle
;
import
androidx.media.app.NotificationCompat.MediaStyle
;
import
androidx.media3.common.C
;
import
androidx.media3.common.C
;
import
androidx.media3.common.Player
;
import
androidx.media3.common.Player
;
import
androidx.media3.common.util.BundleableUtil
;
import
androidx.media3.common.util.Log
;
import
androidx.media3.common.util.NotificationUtil
;
import
androidx.media3.common.util.NotificationUtil
;
import
androidx.media3.common.util.UnstableApi
;
import
androidx.media3.common.util.UnstableApi
;
import
androidx.media3.common.util.Util
;
import
androidx.media3.common.util.Util
;
...
@@ -62,7 +67,6 @@ import java.lang.annotation.RetentionPolicy;
...
@@ -62,7 +67,6 @@ import java.lang.annotation.RetentionPolicy;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Map
;
...
@@ -180,12 +184,12 @@ public class PlayerNotificationManager {
...
@@ -180,12 +184,12 @@ public class PlayerNotificationManager {
*
*
* <p>If multiple {@link PlayerNotificationManager} instances are in use at the same time, the
* <p>If multiple {@link PlayerNotificationManager} instances are in use at the same time, the
* {@code instanceId} must be set as an intent extra with key {@link
* {@code instanceId} must be set as an intent extra with key {@link
* PlayerNotificationManager#
EXTRA_INSTANCE_ID} to avoid sending the action to every custom
* PlayerNotificationManager#
INTENT_EXTRA_INSTANCE_ID} to avoid sending the action to every
*
action receiver. It's also necessary to ensure something is different about the actions. This
*
custom action receiver. It's also necessary to ensure something is different about the
*
may be any of the {@link Intent} attributes considered by {@link Intent#filterEquals}, or
*
actions. This may be any of the {@link Intent} attributes considered by {@link
*
different request code integers when creating the {@link PendingIntent}s with
{@link
*
Intent#filterEquals}, or different request code integers when creating the
{@link
* PendingIntent
#getBroadcast}. The easiest approach is to use the {@code instanceId} as
the
* PendingIntent
}s with {@link PendingIntent#getBroadcast}. The easiest approach is to use
the
* request code.
*
{@code instanceId} as the
request code.
*
*
* @param context The {@link Context}.
* @param context The {@link Context}.
* @param instanceId The instance id of the {@link PlayerNotificationManager}.
* @param instanceId The instance id of the {@link PlayerNotificationManager}.
...
@@ -251,12 +255,6 @@ public class PlayerNotificationManager {
...
@@ -251,12 +255,6 @@ public class PlayerNotificationManager {
protected
int
channelDescriptionResourceId
;
protected
int
channelDescriptionResourceId
;
protected
int
channelImportance
;
protected
int
channelImportance
;
protected
int
smallIconResourceId
;
protected
int
smallIconResourceId
;
protected
int
rewindActionIconResourceId
;
protected
int
playActionIconResourceId
;
protected
int
pauseActionIconResourceId
;
protected
int
fastForwardActionIconResourceId
;
protected
int
previousActionIconResourceId
;
protected
int
nextActionIconResourceId
;
@Nullable
protected
String
groupKey
;
@Nullable
protected
String
groupKey
;
/**
/**
...
@@ -288,12 +286,6 @@ public class PlayerNotificationManager {
...
@@ -288,12 +286,6 @@ public class PlayerNotificationManager {
channelImportance
=
NotificationUtil
.
IMPORTANCE_LOW
;
channelImportance
=
NotificationUtil
.
IMPORTANCE_LOW
;
mediaDescriptionAdapter
=
new
DefaultMediaDescriptionAdapter
(
/* pendingIntent= */
null
);
mediaDescriptionAdapter
=
new
DefaultMediaDescriptionAdapter
(
/* pendingIntent= */
null
);
smallIconResourceId
=
R
.
drawable
.
media3_notification_small_icon
;
smallIconResourceId
=
R
.
drawable
.
media3_notification_small_icon
;
playActionIconResourceId
=
R
.
drawable
.
media3_notification_play
;
pauseActionIconResourceId
=
R
.
drawable
.
media3_notification_pause
;
rewindActionIconResourceId
=
R
.
drawable
.
media3_notification_seek_back
;
fastForwardActionIconResourceId
=
R
.
drawable
.
media3_notification_seek_forward
;
previousActionIconResourceId
=
R
.
drawable
.
media3_notification_seek_to_previous
;
nextActionIconResourceId
=
R
.
drawable
.
media3_notification_seek_to_next
;
}
}
/**
/**
...
@@ -376,79 +368,6 @@ public class PlayerNotificationManager {
...
@@ -376,79 +368,6 @@ public class PlayerNotificationManager {
}
}
/**
/**
* The resource id of the drawable to be used as the icon of action {@link #ACTION_PLAY}.
*
* <p>The default is {@code R.drawable#media3_notification_play}.
*
* @return This builder.
*/
public
Builder
setPlayActionIconResourceId
(
int
playActionIconResourceId
)
{
this
.
playActionIconResourceId
=
playActionIconResourceId
;
return
this
;
}
/**
* The resource id of the drawable to be used as the icon of action {@link #ACTION_PAUSE}.
*
* <p>The default is {@code R.drawable#media3_notification_pause}.
*
* @return This builder.
*/
public
Builder
setPauseActionIconResourceId
(
int
pauseActionIconResourceId
)
{
this
.
pauseActionIconResourceId
=
pauseActionIconResourceId
;
return
this
;
}
/**
* The resource id of the drawable to be used as the icon of action {@link #ACTION_REWIND}.
*
* <p>The default is {@code R.drawable#media3_notification_rewind}.
*
* @return This builder.
*/
public
Builder
setRewindActionIconResourceId
(
int
rewindActionIconResourceId
)
{
this
.
rewindActionIconResourceId
=
rewindActionIconResourceId
;
return
this
;
}
/**
* The resource id of the drawable to be used as the icon of action {@link
* #ACTION_FAST_FORWARD}.
*
* <p>The default is {@code R.drawable#media3_notification_fastforward}.
*
* @return This builder.
*/
public
Builder
setFastForwardActionIconResourceId
(
int
fastForwardActionIconResourceId
)
{
this
.
fastForwardActionIconResourceId
=
fastForwardActionIconResourceId
;
return
this
;
}
/**
* The resource id of the drawable to be used as the icon of action {@link #ACTION_PREVIOUS}.
*
* <p>The default is {@code R.drawable#media3_notification_previous}.
*
* @return This builder.
*/
public
Builder
setPreviousActionIconResourceId
(
int
previousActionIconResourceId
)
{
this
.
previousActionIconResourceId
=
previousActionIconResourceId
;
return
this
;
}
/**
* The resource id of the drawable to be used as the icon of action {@link #ACTION_NEXT}.
*
* <p>The default is {@code R.drawable#media3_notification_next}.
*
* @return This builder.
*/
public
Builder
setNextActionIconResourceId
(
int
nextActionIconResourceId
)
{
this
.
nextActionIconResourceId
=
nextActionIconResourceId
;
return
this
;
}
/**
* The key of the group the media notification should belong to.
* The key of the group the media notification should belong to.
*
*
* <p>The default is {@code null}
* <p>The default is {@code null}
...
@@ -491,12 +410,6 @@ public class PlayerNotificationManager {
...
@@ -491,12 +410,6 @@ public class PlayerNotificationManager {
notificationListener
,
notificationListener
,
customActionReceiver
,
customActionReceiver
,
smallIconResourceId
,
smallIconResourceId
,
playActionIconResourceId
,
pauseActionIconResourceId
,
rewindActionIconResourceId
,
fastForwardActionIconResourceId
,
previousActionIconResourceId
,
nextActionIconResourceId
,
groupKey
);
groupKey
);
}
}
}
}
...
@@ -522,30 +435,34 @@ public class PlayerNotificationManager {
...
@@ -522,30 +435,34 @@ public class PlayerNotificationManager {
}
}
}
}
/** The action which starts playback. */
/** The action which is executed when a button in the notification is clicked. */
public
static
final
String
ACTION_PLAY
=
"androidx.media3.ui.notification.play"
;
private
static
final
String
INTENT_ACTION_COMMAND
=
"androidx.media3.session.command"
;
/** The action which pauses playback. */
public
static
final
String
ACTION_PAUSE
=
"androidx.media3.ui.notification.pause"
;
/** The action which skips to the previous media item. */
public
static
final
String
ACTION_PREVIOUS
=
"androidx.media3.ui.notification.prev"
;
/** The action which skips to the next media item. */
public
static
final
String
ACTION_NEXT
=
"androidx.media3.ui.notification.next"
;
/** The action which fast forwards. */
public
static
final
String
ACTION_FAST_FORWARD
=
"androidx.media3.ui.notification.ffwd"
;
/** The action which rewinds. */
public
static
final
String
ACTION_REWIND
=
"androidx.media3.ui.notification.rewind"
;
/** The extra key of the instance id of the player notification manager. */
public
static
final
String
EXTRA_INSTANCE_ID
=
"INSTANCE_ID"
;
/**
/**
* The action which is executed when the notification is dismissed. It cancels the notification
* The action which is executed when the notification is dismissed. It cancels the notification
* and calls {@link NotificationListener#onNotificationCancelled(int, boolean)}.
* and calls {@link NotificationListener#onNotificationCancelled(int, boolean)}.
*/
*/
private
static
final
String
ACTION_DISMISS
=
"androidx.media3.ui.notification.dismiss"
;
private
static
final
String
INTENT_ACTION_DISMISS
=
"androidx.media3.session.notification.dismiss"
;
private
static
final
String
INTENT_EXTRA_PLAYER_COMMAND
=
"androidx.media3.session.EXTRA_PLAYER_COMMAND"
;
private
static
final
String
INTENT_EXTRA_SESSION_COMMAND
=
"androidx.media3.session.EXTRA_SESSION_COMMAND"
;
private
static
final
String
INTENT_EXTRA_INSTANCE_ID
=
"androidx.media3.session.notificaiton.EXTRA_INSTANCE_ID"
;
private
static
final
String
INTENT_SCHEME
=
"media3"
;
private
static
final
int
PENDING_INTENT_FLAGS
=
(
Util
.
SDK_INT
>=
23
)
?
PendingIntent
.
FLAG_UPDATE_CURRENT
|
PendingIntent
.
FLAG_IMMUTABLE
:
PendingIntent
.
FLAG_UPDATE_CURRENT
;
private
static
final
String
TAG
=
"NotificationManager"
;
// Internal messages.
// Internal messages.
private
static
final
int
MSG_START_OR_UPDATE_NOTIFICATION
=
0
;
private
static
final
int
MSG_START_OR_UPDATE_NOTIFICATION
=
1
;
private
static
final
int
MSG_UPDATE_NOTIFICATION_BITMAP
=
1
;
private
static
final
int
MSG_UPDATE_NOTIFICATION_BITMAP
=
2
;
/**
/**
* Visibility of notification on the lock screen. One of {@link
* Visibility of notification on the lock screen. One of {@link
...
@@ -591,13 +508,17 @@ public class PlayerNotificationManager {
...
@@ -591,13 +508,17 @@ public class PlayerNotificationManager {
private
final
IntentFilter
intentFilter
;
private
final
IntentFilter
intentFilter
;
private
final
Player
.
Listener
playerListener
;
private
final
Player
.
Listener
playerListener
;
private
final
NotificationBroadcastReceiver
notificationBroadcastReceiver
;
private
final
NotificationBroadcastReceiver
notificationBroadcastReceiver
;
private
final
Map
<
String
,
NotificationCompat
.
Action
>
playbackActions
;
private
final
Map
<
String
,
NotificationCompat
.
Action
>
customActions
;
private
final
Map
<
String
,
NotificationCompat
.
Action
>
customActions
;
private
final
PendingIntent
dismissPendingIntent
;
private
final
PendingIntent
dismissPendingIntent
;
private
final
int
instanceId
;
private
final
int
instanceId
;
private
final
CommandButton
playButton
;
private
final
CommandButton
pauseButton
;
private
final
CommandButton
seekToPreviousButton
;
private
final
CommandButton
seekToNextButton
;
private
final
CommandButton
seekBackButton
;
private
final
CommandButton
seekForwardButton
;
@Nullable
private
NotificationCompat
.
Builder
builder
;
@Nullable
private
NotificationCompat
.
Builder
builder
;
@Nullable
private
List
<
NotificationCompat
.
Action
>
builderActions
;
@Nullable
private
Player
player
;
@Nullable
private
Player
player
;
private
boolean
isNotificationStarted
;
private
boolean
isNotificationStarted
;
private
int
currentNotificationTag
;
private
int
currentNotificationTag
;
...
@@ -620,12 +541,6 @@ public class PlayerNotificationManager {
...
@@ -620,12 +541,6 @@ public class PlayerNotificationManager {
@Nullable
NotificationListener
notificationListener
,
@Nullable
NotificationListener
notificationListener
,
@Nullable
CustomActionReceiver
customActionReceiver
,
@Nullable
CustomActionReceiver
customActionReceiver
,
int
smallIconResourceId
,
int
smallIconResourceId
,
int
playActionIconResourceId
,
int
pauseActionIconResourceId
,
int
rewindActionIconResourceId
,
int
fastForwardActionIconResourceId
,
int
previousActionIconResourceId
,
int
nextActionIconResourceId
,
@Nullable
String
groupKey
)
{
@Nullable
String
groupKey
)
{
context
=
context
.
getApplicationContext
();
context
=
context
.
getApplicationContext
();
this
.
context
=
context
;
this
.
context
=
context
;
...
@@ -655,29 +570,51 @@ public class PlayerNotificationManager {
...
@@ -655,29 +570,51 @@ public class PlayerNotificationManager {
badgeIconType
=
NotificationCompat
.
BADGE_ICON_SMALL
;
badgeIconType
=
NotificationCompat
.
BADGE_ICON_SMALL
;
visibility
=
NotificationCompat
.
VISIBILITY_PUBLIC
;
visibility
=
NotificationCompat
.
VISIBILITY_PUBLIC
;
// initialize actions
// initialize default buttons
playbackActions
=
playButton
=
createPlaybackActions
(
new
CommandButton
.
Builder
()
context
,
.
setDisplayName
(
context
.
getText
(
R
.
string
.
media3_controls_play_description
))
instanceId
,
.
setIconResId
(
R
.
drawable
.
media3_notification_play
)
playActionIconResourceId
,
.
setPlayerCommand
(
COMMAND_PLAY_PAUSE
)
pauseActionIconResourceId
,
.
build
();
rewindActionIconResourceId
,
pauseButton
=
fastForwardActionIconResourceId
,
new
CommandButton
.
Builder
()
previousActionIconResourceId
,
.
setDisplayName
(
context
.
getText
(
R
.
string
.
media3_controls_pause_description
))
nextActionIconResourceId
);
.
setIconResId
(
R
.
drawable
.
media3_notification_pause
)
for
(
String
action
:
playbackActions
.
keySet
())
{
.
setPlayerCommand
(
COMMAND_PLAY_PAUSE
)
intentFilter
.
addAction
(
action
);
.
build
();
}
seekToPreviousButton
=
new
CommandButton
.
Builder
()
.
setDisplayName
(
context
.
getText
(
R
.
string
.
media3_controls_seek_to_previous_description
))
.
setIconResId
(
R
.
drawable
.
media3_notification_seek_to_previous
)
.
setPlayerCommand
(
COMMAND_SEEK_TO_PREVIOUS
)
.
build
();
seekToNextButton
=
new
CommandButton
.
Builder
()
.
setDisplayName
(
context
.
getText
(
R
.
string
.
media3_controls_seek_to_next_description
))
.
setIconResId
(
R
.
drawable
.
media3_notification_seek_to_next
)
.
setPlayerCommand
(
COMMAND_SEEK_TO_NEXT
)
.
build
();
seekBackButton
=
new
CommandButton
.
Builder
()
.
setDisplayName
(
context
.
getText
(
R
.
string
.
media3_controls_seek_back_description
))
.
setIconResId
(
R
.
drawable
.
media3_notification_seek_back
)
.
setPlayerCommand
(
COMMAND_SEEK_BACK
)
.
build
();
seekForwardButton
=
new
CommandButton
.
Builder
()
.
setDisplayName
(
context
.
getText
(
R
.
string
.
media3_controls_seek_forward_description
))
.
setIconResId
(
R
.
drawable
.
media3_notification_seek_forward
)
.
setPlayerCommand
(
COMMAND_SEEK_FORWARD
)
.
build
();
intentFilter
.
addAction
(
INTENT_ACTION_COMMAND
);
intentFilter
.
addAction
(
INTENT_ACTION_DISMISS
);
intentFilter
.
addDataScheme
(
INTENT_SCHEME
);
customActions
=
customActions
=
customActionReceiver
!=
null
customActionReceiver
!=
null
?
customActionReceiver
.
createCustomActions
(
context
,
instanceId
)
?
customActionReceiver
.
createCustomActions
(
context
,
instanceId
)
:
Collections
.
emptyMap
();
:
Collections
.
emptyMap
();
for
(
String
action
:
customActions
.
keySet
())
{
dismissPendingIntent
=
createBroadcastIntent
(
context
,
INTENT_ACTION_DISMISS
,
instanceId
);
intentFilter
.
addAction
(
action
);
}
dismissPendingIntent
=
createBroadcastIntent
(
ACTION_DISMISS
,
context
,
instanceId
);
intentFilter
.
addAction
(
ACTION_DISMISS
);
}
}
/**
/**
...
@@ -844,7 +781,7 @@ public class PlayerNotificationManager {
...
@@ -844,7 +781,7 @@ public class PlayerNotificationManager {
*
*
* <ul>
* <ul>
* <li>The media is {@link Player#isPlaying() actively playing}.
* <li>The media is {@link Player#isPlaying() actively playing}.
* <li>The media is not {@link Player#isCurrent
MediaItem
Dynamic() dynamically changing its
* <li>The media is not {@link Player#isCurrent
Window
Dynamic() dynamically changing its
* duration} (like for example a live stream).
* duration} (like for example a live stream).
* <li>The media is not {@link Player#isPlayingAd() interrupted by an ad}.
* <li>The media is not {@link Player#isPlayingAd() interrupted by an ad}.
* <li>The media is played at {@link Player#getPlaybackParameters() regular speed}.
* <li>The media is played at {@link Player#getPlaybackParameters() regular speed}.
...
@@ -947,37 +884,29 @@ public class PlayerNotificationManager {
...
@@ -947,37 +884,29 @@ public class PlayerNotificationManager {
boolean
ongoing
,
boolean
ongoing
,
@Nullable
Bitmap
largeIcon
)
{
@Nullable
Bitmap
largeIcon
)
{
if
(
player
.
getPlaybackState
()
==
Player
.
STATE_IDLE
&&
player
.
getCurrentTimeline
().
isEmpty
())
{
if
(
player
.
getPlaybackState
()
==
Player
.
STATE_IDLE
&&
player
.
getCurrentTimeline
().
isEmpty
())
{
builderActions
=
null
;
return
null
;
return
null
;
}
}
List
<
String
>
actionNames
=
getActions
(
player
);
if
(
builder
==
null
)
{
List
<
NotificationCompat
.
Action
>
actions
=
new
ArrayList
<>(
actionNames
.
size
());
for
(
int
i
=
0
;
i
<
actionNames
.
size
();
i
++)
{
String
actionName
=
actionNames
.
get
(
i
);
@Nullable
NotificationCompat
.
Action
action
=
playbackActions
.
containsKey
(
actionName
)
?
playbackActions
.
get
(
actionName
)
:
customActions
.
get
(
actionName
);
if
(
action
!=
null
)
{
actions
.
add
(
action
);
}
}
if
(
builder
==
null
||
!
actions
.
equals
(
builderActions
))
{
builder
=
new
NotificationCompat
.
Builder
(
context
,
channelId
);
builder
=
new
NotificationCompat
.
Builder
(
context
,
channelId
);
builderActions
=
actions
;
}
for
(
int
i
=
0
;
i
<
actions
.
size
();
i
++)
{
List
<
CommandButton
>
actionButtons
=
getActionButtons
(
player
);
builder
.
addAction
(
actions
.
get
(
i
));
for
(
int
i
=
0
;
i
<
actionButtons
.
size
();
i
++)
{
}
CommandButton
button
=
actionButtons
.
get
(
i
);
NotificationCompat
.
Action
action
=
new
NotificationCompat
.
Action
(
button
.
iconResId
,
button
.
displayName
,
createBroadcastIntent
(
context
,
button
,
instanceId
));
builder
.
addAction
(
action
);
}
}
MediaStyle
mediaStyle
=
new
MediaStyle
();
MediaStyle
mediaStyle
=
new
MediaStyle
();
if
(
mediaSessionToken
!=
null
)
{
if
(
mediaSessionToken
!=
null
)
{
mediaStyle
.
setMediaSession
(
mediaSessionToken
);
mediaStyle
.
setMediaSession
(
mediaSessionToken
);
}
}
mediaStyle
.
setShowActionsInCompactView
(
getActionIndicesForCompactView
(
actionNames
,
player
));
mediaStyle
.
setShowActionsInCompactView
(
getActionButtonIndicesForCompactView
(
actionButtons
,
player
));
// Configure dismiss action prior to API 21 ('x' button).
// Configure dismiss action prior to API 21 ('x' button).
mediaStyle
.
setShowCancelButton
(!
ongoing
);
mediaStyle
.
setShowCancelButton
(!
ongoing
);
mediaStyle
.
setCancelButtonIntent
(
dismissPendingIntent
);
mediaStyle
.
setCancelButtonIntent
(
dismissPendingIntent
);
...
@@ -1002,7 +931,7 @@ public class PlayerNotificationManager {
...
@@ -1002,7 +931,7 @@ public class PlayerNotificationManager {
&&
useChronometer
&&
useChronometer
&&
player
.
isPlaying
()
&&
player
.
isPlaying
()
&&
!
player
.
isPlayingAd
()
&&
!
player
.
isPlayingAd
()
&&
!
player
.
isCurrent
MediaItem
Dynamic
()
&&
!
player
.
isCurrent
Window
Dynamic
()
&&
player
.
getPlaybackParameters
().
speed
==
1
f
)
{
&&
player
.
getPlaybackParameters
().
speed
==
1
f
)
{
builder
builder
.
setWhen
(
System
.
currentTimeMillis
()
-
player
.
getContentPosition
())
.
setWhen
(
System
.
currentTimeMillis
()
-
player
.
getContentPosition
())
...
@@ -1040,42 +969,39 @@ public class PlayerNotificationManager {
...
@@ -1040,42 +969,39 @@ public class PlayerNotificationManager {
* omitted:
* omitted:
*
*
* <pre>
* <pre>
* +------------------------------------------------
-----------------
+
* +------------------------------------------------+
* | prev | << | play/pause | >> | next |
custom actions |
* | prev | << | play/pause | >> | next |
* +------------------------------------------------
-----------------
+
* +------------------------------------------------+
* </pre>
* </pre>
*
*
* <p>This method can be safely overridden. However, the names must be of the playback actions
* <p>This method can be safely overridden.
* {@link #ACTION_PAUSE}, {@link #ACTION_PLAY}, {@link #ACTION_FAST_FORWARD}, {@link
* #ACTION_REWIND}, {@link #ACTION_NEXT} or {@link #ACTION_PREVIOUS}, or a key contained in the
* map returned by {@link CustomActionReceiver#createCustomActions(Context, int)}. Otherwise the
* action name is ignored.
*/
*/
protected
List
<
String
>
getActions
(
Player
player
)
{
// Disclaimer: Custom action support is temporarily removed, but will be added back in next CL.
protected
List
<
CommandButton
>
getActionButtons
(
Player
player
)
{
boolean
enablePrevious
=
player
.
isCommandAvailable
(
COMMAND_SEEK_TO_PREVIOUS
);
boolean
enablePrevious
=
player
.
isCommandAvailable
(
COMMAND_SEEK_TO_PREVIOUS
);
boolean
enableRewind
=
player
.
isCommandAvailable
(
COMMAND_SEEK_BACK
);
boolean
enableRewind
=
player
.
isCommandAvailable
(
COMMAND_SEEK_BACK
);
boolean
enableFastForward
=
player
.
isCommandAvailable
(
COMMAND_SEEK_FORWARD
);
boolean
enableFastForward
=
player
.
isCommandAvailable
(
COMMAND_SEEK_FORWARD
);
boolean
enableNext
=
player
.
isCommandAvailable
(
COMMAND_SEEK_TO_NEXT
);
boolean
enableNext
=
player
.
isCommandAvailable
(
COMMAND_SEEK_TO_NEXT
);
List
<
String
>
stringActi
ons
=
new
ArrayList
<>();
List
<
CommandButton
>
butt
ons
=
new
ArrayList
<>();
if
(
enablePrevious
)
{
if
(
enablePrevious
)
{
stringActions
.
add
(
ACTION_PREVIOUS
);
buttons
.
add
(
seekToPreviousButton
);
}
}
if
(
enableRewind
)
{
if
(
enableRewind
)
{
stringActions
.
add
(
ACTION_REWIND
);
buttons
.
add
(
seekBackButton
);
}
}
if
(
shouldShowPauseButton
(
player
))
{
if
(
shouldShowPauseButton
(
player
))
{
stringActions
.
add
(
ACTION_PAUSE
);
buttons
.
add
(
pauseButton
);
}
else
{
}
else
{
stringActions
.
add
(
ACTION_PLAY
);
buttons
.
add
(
playButton
);
}
}
if
(
enableFastForward
)
{
if
(
enableFastForward
)
{
stringActions
.
add
(
ACTION_FAST_FORWARD
);
buttons
.
add
(
seekForwardButton
);
}
}
if
(
enableNext
)
{
if
(
enableNext
)
{
stringActions
.
add
(
ACTION_NEXT
);
buttons
.
add
(
seekToNextButton
);
}
}
return
stringActi
ons
;
return
butt
ons
;
}
}
/**
/**
...
@@ -1084,29 +1010,41 @@ public class PlayerNotificationManager {
...
@@ -1084,29 +1010,41 @@ public class PlayerNotificationManager {
* <p>This method can be overridden. The indices must refer to the list of actions passed as the
* <p>This method can be overridden. The indices must refer to the list of actions passed as the
* first parameter.
* first parameter.
*
*
* @param action
Names The name
s of the actions included in the notification.
* @param action
Buttons The button
s of the actions included in the notification.
* @param player The player for which a notification is being built.
* @param player The player for which a notification is being built.
*/
*/
@SuppressWarnings
(
"unused"
)
@SuppressWarnings
(
"unused"
)
protected
int
[]
getActionIndicesForCompactView
(
List
<
String
>
actionNames
,
Player
player
)
{
protected
int
[]
getActionButtonIndicesForCompactView
(
int
pauseActionIndex
=
actionNames
.
indexOf
(
ACTION_PAUSE
);
List
<
CommandButton
>
actionButtons
,
Player
player
)
{
int
playActionIndex
=
actionNames
.
indexOf
(
ACTION_PLAY
);
int
previousIndex
=
C
.
INDEX_UNSET
;
int
leftSideActionIndex
=
actionNames
.
indexOf
(
ACTION_PREVIOUS
);
int
nextIndex
=
C
.
INDEX_UNSET
;
int
rightSideActionIndex
=
actionNames
.
indexOf
(
ACTION_NEXT
);
int
playPauseIndex
=
C
.
INDEX_UNSET
;
for
(
int
i
=
0
;
i
<
actionButtons
.
size
();
i
++)
{
CommandButton
button
=
actionButtons
.
get
(
i
);
switch
(
button
.
playerCommand
)
{
case
COMMAND_PLAY_PAUSE:
playPauseIndex
=
i
;
break
;
case
COMMAND_SEEK_TO_PREVIOUS:
previousIndex
=
i
;
break
;
case
COMMAND_SEEK_TO_NEXT:
nextIndex
=
i
;
break
;
default
:
// Do nothing
}
}
int
[]
actionIndices
=
new
int
[
3
];
int
[]
actionIndices
=
new
int
[
3
];
int
actionCounter
=
0
;
int
actionCounter
=
0
;
if
(
leftSideActionIndex
!=
-
1
)
{
if
(
previousIndex
!=
C
.
INDEX_UNSET
)
{
actionIndices
[
actionCounter
++]
=
leftSideAction
Index
;
actionIndices
[
actionCounter
++]
=
previous
Index
;
}
}
boolean
shouldShowPauseButton
=
shouldShowPauseButton
(
player
);
if
(
playPauseIndex
!=
C
.
INDEX_UNSET
)
{
if
(
pauseActionIndex
!=
-
1
&&
shouldShowPauseButton
)
{
actionIndices
[
actionCounter
++]
=
playPauseIndex
;
actionIndices
[
actionCounter
++]
=
pauseActionIndex
;
}
else
if
(
playActionIndex
!=
-
1
&&
!
shouldShowPauseButton
)
{
actionIndices
[
actionCounter
++]
=
playActionIndex
;
}
}
if
(
rightSideActionIndex
!=
-
1
)
{
if
(
nextIndex
!=
C
.
INDEX_UNSET
)
{
actionIndices
[
actionCounter
++]
=
rightSideAction
Index
;
actionIndices
[
actionCounter
++]
=
next
Index
;
}
}
return
Arrays
.
copyOf
(
actionIndices
,
actionCounter
);
return
Arrays
.
copyOf
(
actionIndices
,
actionCounter
);
}
}
...
@@ -1155,68 +1093,30 @@ public class PlayerNotificationManager {
...
@@ -1155,68 +1093,30 @@ public class PlayerNotificationManager {
return
true
;
return
true
;
}
}
private
static
Map
<
String
,
NotificationCompat
.
Action
>
createPlaybackActions
(
private
static
PendingIntent
createBroadcastIntent
(
Context
context
,
Context
context
,
CommandButton
button
,
int
instanceId
)
{
int
instanceId
,
Intent
intent
=
new
Intent
(
INTENT_ACTION_COMMAND
).
setPackage
(
context
.
getPackageName
());
int
playActionIconResourceId
,
intent
.
putExtra
(
INTENT_EXTRA_INSTANCE_ID
,
instanceId
);
int
pauseActionIconResourceId
,
intent
.
putExtra
(
INTENT_EXTRA_PLAYER_COMMAND
,
button
.
playerCommand
);
int
rewindActionIconResourceId
,
intent
.
putExtra
(
int
fastForwardActionIconResourceId
,
INTENT_EXTRA_SESSION_COMMAND
,
BundleableUtil
.
toNullableBundle
(
button
.
sessionCommand
));
int
previousActionIconResourceId
,
// Make intent distinguishable by Intent#filterEquals() due to the PendingIntent requirement.
int
nextActionIconResourceId
)
{
Uri
intentUri
=
Map
<
String
,
NotificationCompat
.
Action
>
actions
=
new
HashMap
<>();
new
Uri
.
Builder
()
actions
.
put
(
.
scheme
(
INTENT_SCHEME
)
ACTION_PLAY
,
.
appendPath
(
Integer
.
toString
(
instanceId
))
new
NotificationCompat
.
Action
(
.
appendPath
(
Integer
.
toString
(
button
.
playerCommand
))
playActionIconResourceId
,
.
appendPath
(
button
.
sessionCommand
==
null
?
"null"
:
button
.
sessionCommand
.
customAction
)
context
.
getString
(
R
.
string
.
media3_controls_play_description
),
.
build
();
createBroadcastIntent
(
ACTION_PLAY
,
context
,
instanceId
)));
intent
.
setData
(
intentUri
);
actions
.
put
(
return
PendingIntent
.
getBroadcast
(
context
,
instanceId
,
intent
,
PENDING_INTENT_FLAGS
);
ACTION_PAUSE
,
new
NotificationCompat
.
Action
(
pauseActionIconResourceId
,
context
.
getString
(
R
.
string
.
media3_controls_pause_description
),
createBroadcastIntent
(
ACTION_PAUSE
,
context
,
instanceId
)));
actions
.
put
(
ACTION_REWIND
,
new
NotificationCompat
.
Action
(
rewindActionIconResourceId
,
context
.
getString
(
R
.
string
.
media3_controls_seek_back_description
),
createBroadcastIntent
(
ACTION_REWIND
,
context
,
instanceId
)));
actions
.
put
(
ACTION_FAST_FORWARD
,
new
NotificationCompat
.
Action
(
fastForwardActionIconResourceId
,
context
.
getString
(
R
.
string
.
media3_controls_seek_forward_description
),
createBroadcastIntent
(
ACTION_FAST_FORWARD
,
context
,
instanceId
)));
actions
.
put
(
ACTION_PREVIOUS
,
new
NotificationCompat
.
Action
(
previousActionIconResourceId
,
context
.
getString
(
R
.
string
.
media3_controls_seek_to_previous_description
),
createBroadcastIntent
(
ACTION_PREVIOUS
,
context
,
instanceId
)));
actions
.
put
(
ACTION_NEXT
,
new
NotificationCompat
.
Action
(
nextActionIconResourceId
,
context
.
getString
(
R
.
string
.
media3_controls_seek_to_next_description
),
createBroadcastIntent
(
ACTION_NEXT
,
context
,
instanceId
)));
return
actions
;
}
}
private
static
PendingIntent
createBroadcastIntent
(
private
static
PendingIntent
createBroadcastIntent
(
String
action
,
Context
context
,
int
instanceId
)
{
Context
context
,
String
action
,
int
instanceId
)
{
Intent
intent
=
new
Intent
(
action
).
setPackage
(
context
.
getPackageName
());
Intent
intent
=
new
Intent
(
action
).
setPackage
(
context
.
getPackageName
());
intent
.
putExtra
(
EXTRA_INSTANCE_ID
,
instanceId
);
intent
.
putExtra
(
INTENT_EXTRA_INSTANCE_ID
,
instanceId
);
return
PendingIntent
.
getBroadcast
(
context
,
instanceId
,
intent
,
PENDING_INTENT_FLAGS
);
int
pendingFlags
;
if
(
Util
.
SDK_INT
>=
23
)
{
pendingFlags
=
PendingIntent
.
FLAG_UPDATE_CURRENT
|
PendingIntent
.
FLAG_IMMUTABLE
;
}
else
{
pendingFlags
=
PendingIntent
.
FLAG_UPDATE_CURRENT
;
}
return
PendingIntent
.
getBroadcast
(
context
,
instanceId
,
intent
,
pendingFlags
);
}
}
@SuppressWarnings
(
"nullness:argument"
)
@SuppressWarnings
(
"nullness:argument"
)
...
@@ -1251,28 +1151,42 @@ public class PlayerNotificationManager {
...
@@ -1251,28 +1151,42 @@ public class PlayerNotificationManager {
Player
player
=
PlayerNotificationManager
.
this
.
player
;
Player
player
=
PlayerNotificationManager
.
this
.
player
;
if
(
player
==
null
if
(
player
==
null
||
!
isNotificationStarted
||
!
isNotificationStarted
||
intent
.
getIntExtra
(
EXTRA_INSTANCE_ID
,
instanceId
)
!=
instanceId
)
{
||
intent
.
getIntExtra
(
INTENT_
EXTRA_INSTANCE_ID
,
instanceId
)
!=
instanceId
)
{
return
;
return
;
}
}
String
action
=
intent
.
getAction
();
String
action
=
intent
.
getAction
();
if
(
ACTION_PLAY
.
equals
(
action
))
{
if
(
INTENT_ACTION_COMMAND
.
equals
(
action
))
{
if
(
player
.
getPlaybackState
()
==
Player
.
STATE_IDLE
)
{
@Player
.
Command
player
.
prepare
();
int
playerCommand
=
intent
.
getIntExtra
(
INTENT_EXTRA_PLAYER_COMMAND
,
COMMAND_INVALID
);
}
else
if
(
player
.
getPlaybackState
()
==
Player
.
STATE_ENDED
)
{
switch
(
playerCommand
)
{
player
.
seekToDefaultPosition
(
player
.
getCurrentMediaItemIndex
());
case
COMMAND_PLAY_PAUSE:
if
(!
player
.
getPlayWhenReady
())
{
if
(
player
.
getPlaybackState
()
==
Player
.
STATE_IDLE
)
{
player
.
prepare
();
}
else
if
(
player
.
getPlaybackState
()
==
Player
.
STATE_ENDED
)
{
player
.
seekToDefaultPosition
(
player
.
getCurrentWindowIndex
());
}
}
else
{
player
.
pause
();
}
break
;
case
COMMAND_SEEK_TO_PREVIOUS:
player
.
seekToPrevious
();
break
;
case
COMMAND_SEEK_BACK:
player
.
seekBack
();
break
;
case
COMMAND_SEEK_FORWARD:
player
.
seekForward
();
break
;
case
COMMAND_SEEK_TO_NEXT:
player
.
seekToNext
();
break
;
default
:
Log
.
w
(
TAG
,
"Unsupported player command, playerCommand="
+
playerCommand
);
break
;
}
}
player
.
play
();
}
else
if
(
INTENT_ACTION_DISMISS
.
equals
(
action
))
{
}
else
if
(
ACTION_PAUSE
.
equals
(
action
))
{
player
.
pause
();
}
else
if
(
ACTION_PREVIOUS
.
equals
(
action
))
{
player
.
seekToPrevious
();
}
else
if
(
ACTION_REWIND
.
equals
(
action
))
{
player
.
seekBack
();
}
else
if
(
ACTION_FAST_FORWARD
.
equals
(
action
))
{
player
.
seekForward
();
}
else
if
(
ACTION_NEXT
.
equals
(
action
))
{
player
.
seekToNext
();
}
else
if
(
ACTION_DISMISS
.
equals
(
action
))
{
stopNotification
(
/* dismissedByUser= */
true
);
stopNotification
(
/* dismissedByUser= */
true
);
}
else
if
(
action
!=
null
}
else
if
(
action
!=
null
&&
customActionReceiver
!=
null
&&
customActionReceiver
!=
null
...
...
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