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
a263fb16
authored
Feb 08, 2019
by
aquilescanta
Committed by
Andrew Lewis
Feb 18, 2019
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Remove default-receiver-related classes from Cast demo app
PiperOrigin-RevId: 233073011
parent
6f1daff3
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
10 additions
and
502 deletions
demos/cast/build.gradle
demos/cast/src/main/AndroidManifest.xml
demos/cast/src/main/java/com/google/android/exoplayer2/castdemo/DefaultReceiverPlayerManager.java
demos/cast/src/main/java/com/google/android/exoplayer2/castdemo/MainActivity.java
demos/cast/src/main/java/com/google/android/exoplayer2/castdemo/PlayerManager.java
demos/cast/build.gradle
View file @
a263fb16
...
...
@@ -48,22 +48,6 @@ android {
// The demo app does not have translations.
disable
'MissingTranslation'
}
flavorDimensions
"receiver"
productFlavors
{
exoCast
{
dimension
"receiver"
manifestPlaceholders
=
[
castOptionsProvider:
"com.google.android.exoplayer2.ext.cast.ExoCastOptionsProvider"
]
}
defaultCast
{
dimension
"receiver"
manifestPlaceholders
=
[
castOptionsProvider:
"com.google.android.exoplayer2.ext.cast.DefaultCastOptionsProvider"
]
}
}
}
dependencies
{
...
...
demos/cast/src/main/AndroidManifest.xml
View file @
a263fb16
...
...
@@ -23,7 +23,7 @@
android:largeHeap=
"true"
android:allowBackup=
"false"
>
<meta-data
android:name=
"com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
android:value=
"
${castOptionsProvider}
"
/>
android:value=
"
com.google.android.exoplayer2.ext.cast.ExoCastOptionsProvider
"
/>
<activity
android:name=
"com.google.android.exoplayer2.castdemo.MainActivity"
android:configChanges=
"keyboard|keyboardHidden|orientation|screenSize|screenLayout|smallestScreenSize|uiMode"
...
...
demos/cast/src/main/java/com/google/android/exoplayer2/castdemo/DefaultReceiverPlayerManager.java
deleted
100644 → 0
View file @
6f1daff3
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
google
.
android
.
exoplayer2
.
castdemo
;
import
android.content.Context
;
import
android.net.Uri
;
import
android.support.annotation.Nullable
;
import
android.view.KeyEvent
;
import
android.view.View
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.DefaultRenderersFactory
;
import
com.google.android.exoplayer2.ExoPlayerFactory
;
import
com.google.android.exoplayer2.Player
;
import
com.google.android.exoplayer2.Player.DiscontinuityReason
;
import
com.google.android.exoplayer2.Player.EventListener
;
import
com.google.android.exoplayer2.Player.TimelineChangeReason
;
import
com.google.android.exoplayer2.RenderersFactory
;
import
com.google.android.exoplayer2.SimpleExoPlayer
;
import
com.google.android.exoplayer2.Timeline
;
import
com.google.android.exoplayer2.Timeline.Period
;
import
com.google.android.exoplayer2.ext.cast.CastPlayer
;
import
com.google.android.exoplayer2.ext.cast.MediaItem
;
import
com.google.android.exoplayer2.ext.cast.SessionAvailabilityListener
;
import
com.google.android.exoplayer2.source.ConcatenatingMediaSource
;
import
com.google.android.exoplayer2.source.MediaSource
;
import
com.google.android.exoplayer2.source.ProgressiveMediaSource
;
import
com.google.android.exoplayer2.source.dash.DashMediaSource
;
import
com.google.android.exoplayer2.source.hls.HlsMediaSource
;
import
com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource
;
import
com.google.android.exoplayer2.trackselection.DefaultTrackSelector
;
import
com.google.android.exoplayer2.ui.PlayerControlView
;
import
com.google.android.exoplayer2.ui.PlayerView
;
import
com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory
;
import
com.google.android.gms.cast.MediaInfo
;
import
com.google.android.gms.cast.MediaMetadata
;
import
com.google.android.gms.cast.MediaQueueItem
;
import
com.google.android.gms.cast.framework.CastContext
;
import
java.util.ArrayList
;
/** Manages players and an internal media queue for the ExoPlayer/Cast demo app. */
/* package */
class
DefaultReceiverPlayerManager
implements
EventListener
,
SessionAvailabilityListener
,
PlayerManager
{
private
static
final
String
USER_AGENT
=
"ExoCastDemoPlayer"
;
private
static
final
DefaultHttpDataSourceFactory
DATA_SOURCE_FACTORY
=
new
DefaultHttpDataSourceFactory
(
USER_AGENT
);
private
final
PlayerView
localPlayerView
;
private
final
PlayerControlView
castControlView
;
private
final
SimpleExoPlayer
exoPlayer
;
private
final
CastPlayer
castPlayer
;
private
final
ArrayList
<
MediaItem
>
mediaQueue
;
private
final
QueueChangesListener
queueChangesListener
;
private
final
ConcatenatingMediaSource
concatenatingMediaSource
;
private
boolean
castMediaQueueCreationPending
;
private
int
currentItemIndex
;
private
Player
currentPlayer
;
/**
* Creates a new manager for {@link SimpleExoPlayer} and {@link CastPlayer}.
*
* @param queueChangesListener A {@link QueueChangesListener} for queue position changes.
* @param localPlayerView The {@link PlayerView} for local playback.
* @param castControlView The {@link PlayerControlView} to control remote playback.
* @param context A {@link Context}.
* @param castContext The {@link CastContext}.
*/
public
DefaultReceiverPlayerManager
(
QueueChangesListener
queueChangesListener
,
PlayerView
localPlayerView
,
PlayerControlView
castControlView
,
Context
context
,
CastContext
castContext
)
{
this
.
queueChangesListener
=
queueChangesListener
;
this
.
localPlayerView
=
localPlayerView
;
this
.
castControlView
=
castControlView
;
mediaQueue
=
new
ArrayList
<>();
currentItemIndex
=
C
.
INDEX_UNSET
;
concatenatingMediaSource
=
new
ConcatenatingMediaSource
();
DefaultTrackSelector
trackSelector
=
new
DefaultTrackSelector
();
RenderersFactory
renderersFactory
=
new
DefaultRenderersFactory
(
context
);
exoPlayer
=
ExoPlayerFactory
.
newSimpleInstance
(
context
,
renderersFactory
,
trackSelector
);
exoPlayer
.
addListener
(
this
);
localPlayerView
.
setPlayer
(
exoPlayer
);
castPlayer
=
new
CastPlayer
(
castContext
);
castPlayer
.
addListener
(
this
);
castPlayer
.
setSessionAvailabilityListener
(
this
);
castControlView
.
setPlayer
(
castPlayer
);
setCurrentPlayer
(
castPlayer
.
isCastSessionAvailable
()
?
castPlayer
:
exoPlayer
);
}
// Queue manipulation methods.
/**
* Plays a specified queue item in the current player.
*
* @param itemIndex The index of the item to play.
*/
public
void
selectQueueItem
(
int
itemIndex
)
{
setCurrentItem
(
itemIndex
,
C
.
TIME_UNSET
,
true
);
}
/**
* Returns the index of the currently played item.
*/
public
int
getCurrentItemIndex
()
{
return
currentItemIndex
;
}
/**
* Appends {@code item} to the media queue.
*
* @param item The {@link MediaItem} to append.
*/
public
void
addItem
(
MediaItem
item
)
{
mediaQueue
.
add
(
item
);
concatenatingMediaSource
.
addMediaSource
(
buildMediaSource
(
item
));
if
(
currentPlayer
==
castPlayer
)
{
castPlayer
.
addItems
(
buildMediaQueueItem
(
item
));
}
}
/**
* Returns the size of the media queue.
*/
public
int
getMediaQueueSize
()
{
return
mediaQueue
.
size
();
}
/**
* Returns the item at the given index in the media queue.
*
* @param position The index of the item.
* @return The item at the given index in the media queue.
*/
public
MediaItem
getItem
(
int
position
)
{
return
mediaQueue
.
get
(
position
);
}
/**
* Removes the item at the given index from the media queue.
*
* @param itemIndex The index of the item to remove.
* @return Whether the removal was successful.
*/
public
boolean
removeItem
(
int
itemIndex
)
{
concatenatingMediaSource
.
removeMediaSource
(
itemIndex
);
if
(
currentPlayer
==
castPlayer
)
{
if
(
castPlayer
.
getPlaybackState
()
!=
Player
.
STATE_IDLE
)
{
Timeline
castTimeline
=
castPlayer
.
getCurrentTimeline
();
if
(
castTimeline
.
getPeriodCount
()
<=
itemIndex
)
{
return
false
;
}
castPlayer
.
removeItem
((
int
)
castTimeline
.
getPeriod
(
itemIndex
,
new
Period
()).
id
);
}
}
mediaQueue
.
remove
(
itemIndex
);
if
(
itemIndex
==
currentItemIndex
&&
itemIndex
==
mediaQueue
.
size
())
{
maybeSetCurrentItemAndNotify
(
C
.
INDEX_UNSET
);
}
else
if
(
itemIndex
<
currentItemIndex
)
{
maybeSetCurrentItemAndNotify
(
currentItemIndex
-
1
);
}
return
true
;
}
/**
* Moves an item within the queue.
*
* @param fromIndex The index of the item to move.
* @param toIndex The target index of the item in the queue.
* @return Whether the item move was successful.
*/
public
boolean
moveItem
(
int
fromIndex
,
int
toIndex
)
{
// Player update.
concatenatingMediaSource
.
moveMediaSource
(
fromIndex
,
toIndex
);
if
(
currentPlayer
==
castPlayer
&&
castPlayer
.
getPlaybackState
()
!=
Player
.
STATE_IDLE
)
{
Timeline
castTimeline
=
castPlayer
.
getCurrentTimeline
();
int
periodCount
=
castTimeline
.
getPeriodCount
();
if
(
periodCount
<=
fromIndex
||
periodCount
<=
toIndex
)
{
return
false
;
}
int
elementId
=
(
int
)
castTimeline
.
getPeriod
(
fromIndex
,
new
Period
()).
id
;
castPlayer
.
moveItem
(
elementId
,
toIndex
);
}
mediaQueue
.
add
(
toIndex
,
mediaQueue
.
remove
(
fromIndex
));
// Index update.
if
(
fromIndex
==
currentItemIndex
)
{
maybeSetCurrentItemAndNotify
(
toIndex
);
}
else
if
(
fromIndex
<
currentItemIndex
&&
toIndex
>=
currentItemIndex
)
{
maybeSetCurrentItemAndNotify
(
currentItemIndex
-
1
);
}
else
if
(
fromIndex
>
currentItemIndex
&&
toIndex
<=
currentItemIndex
)
{
maybeSetCurrentItemAndNotify
(
currentItemIndex
+
1
);
}
return
true
;
}
// Miscellaneous methods.
/**
* Dispatches a given {@link KeyEvent} to the corresponding view of the current player.
*
* @param event The {@link KeyEvent}.
* @return Whether the event was handled by the target view.
*/
public
boolean
dispatchKeyEvent
(
KeyEvent
event
)
{
if
(
currentPlayer
==
exoPlayer
)
{
return
localPlayerView
.
dispatchKeyEvent
(
event
);
}
else
/* currentPlayer == castPlayer */
{
return
castControlView
.
dispatchKeyEvent
(
event
);
}
}
/**
* Releases the manager and the players that it holds.
*/
public
void
release
()
{
currentItemIndex
=
C
.
INDEX_UNSET
;
mediaQueue
.
clear
();
concatenatingMediaSource
.
clear
();
castPlayer
.
setSessionAvailabilityListener
(
null
);
castPlayer
.
release
();
localPlayerView
.
setPlayer
(
null
);
exoPlayer
.
release
();
}
// Player.EventListener implementation.
@Override
public
void
onPlayerStateChanged
(
boolean
playWhenReady
,
int
playbackState
)
{
updateCurrentItemIndex
();
}
@Override
public
void
onPositionDiscontinuity
(
@DiscontinuityReason
int
reason
)
{
updateCurrentItemIndex
();
}
@Override
public
void
onTimelineChanged
(
Timeline
timeline
,
@Nullable
Object
manifest
,
@TimelineChangeReason
int
reason
)
{
updateCurrentItemIndex
();
if
(
currentPlayer
==
castPlayer
&&
timeline
.
isEmpty
())
{
castMediaQueueCreationPending
=
true
;
}
}
// CastPlayer.SessionAvailabilityListener implementation.
@Override
public
void
onCastSessionAvailable
()
{
setCurrentPlayer
(
castPlayer
);
}
@Override
public
void
onCastSessionUnavailable
()
{
setCurrentPlayer
(
exoPlayer
);
}
// Internal methods.
private
void
updateCurrentItemIndex
()
{
int
playbackState
=
currentPlayer
.
getPlaybackState
();
maybeSetCurrentItemAndNotify
(
playbackState
!=
Player
.
STATE_IDLE
&&
playbackState
!=
Player
.
STATE_ENDED
?
currentPlayer
.
getCurrentWindowIndex
()
:
C
.
INDEX_UNSET
);
}
private
void
setCurrentPlayer
(
Player
currentPlayer
)
{
if
(
this
.
currentPlayer
==
currentPlayer
)
{
return
;
}
// View management.
if
(
currentPlayer
==
exoPlayer
)
{
localPlayerView
.
setVisibility
(
View
.
VISIBLE
);
castControlView
.
hide
();
}
else
/* currentPlayer == castPlayer */
{
localPlayerView
.
setVisibility
(
View
.
GONE
);
castControlView
.
show
();
}
// Player state management.
long
playbackPositionMs
=
C
.
TIME_UNSET
;
int
windowIndex
=
C
.
INDEX_UNSET
;
boolean
playWhenReady
=
false
;
if
(
this
.
currentPlayer
!=
null
)
{
int
playbackState
=
this
.
currentPlayer
.
getPlaybackState
();
if
(
playbackState
!=
Player
.
STATE_ENDED
)
{
playbackPositionMs
=
this
.
currentPlayer
.
getCurrentPosition
();
playWhenReady
=
this
.
currentPlayer
.
getPlayWhenReady
();
windowIndex
=
this
.
currentPlayer
.
getCurrentWindowIndex
();
if
(
windowIndex
!=
currentItemIndex
)
{
playbackPositionMs
=
C
.
TIME_UNSET
;
windowIndex
=
currentItemIndex
;
}
}
this
.
currentPlayer
.
stop
(
true
);
}
else
{
// This is the initial setup. No need to save any state.
}
this
.
currentPlayer
=
currentPlayer
;
// Media queue management.
castMediaQueueCreationPending
=
currentPlayer
==
castPlayer
;
if
(
currentPlayer
==
exoPlayer
)
{
exoPlayer
.
prepare
(
concatenatingMediaSource
);
}
// Playback transition.
if
(
windowIndex
!=
C
.
INDEX_UNSET
)
{
setCurrentItem
(
windowIndex
,
playbackPositionMs
,
playWhenReady
);
}
}
/**
* Starts playback of the item at the given position.
*
* @param itemIndex The index of the item to play.
* @param positionMs The position at which playback should start.
* @param playWhenReady Whether the player should proceed when ready to do so.
*/
private
void
setCurrentItem
(
int
itemIndex
,
long
positionMs
,
boolean
playWhenReady
)
{
maybeSetCurrentItemAndNotify
(
itemIndex
);
if
(
castMediaQueueCreationPending
)
{
MediaQueueItem
[]
items
=
new
MediaQueueItem
[
mediaQueue
.
size
()];
for
(
int
i
=
0
;
i
<
items
.
length
;
i
++)
{
items
[
i
]
=
buildMediaQueueItem
(
mediaQueue
.
get
(
i
));
}
castMediaQueueCreationPending
=
false
;
castPlayer
.
loadItems
(
items
,
itemIndex
,
positionMs
,
Player
.
REPEAT_MODE_OFF
);
}
else
{
currentPlayer
.
seekTo
(
itemIndex
,
positionMs
);
currentPlayer
.
setPlayWhenReady
(
playWhenReady
);
}
}
private
void
maybeSetCurrentItemAndNotify
(
int
currentItemIndex
)
{
if
(
this
.
currentItemIndex
!=
currentItemIndex
)
{
int
oldIndex
=
this
.
currentItemIndex
;
this
.
currentItemIndex
=
currentItemIndex
;
queueChangesListener
.
onQueuePositionChanged
(
oldIndex
,
currentItemIndex
);
}
}
private
static
MediaSource
buildMediaSource
(
MediaItem
item
)
{
Uri
uri
=
item
.
media
.
uri
;
switch
(
item
.
mimeType
)
{
case
DemoUtil
.
MIME_TYPE_SS
:
return
new
SsMediaSource
.
Factory
(
DATA_SOURCE_FACTORY
).
createMediaSource
(
uri
);
case
DemoUtil
.
MIME_TYPE_DASH
:
return
new
DashMediaSource
.
Factory
(
DATA_SOURCE_FACTORY
).
createMediaSource
(
uri
);
case
DemoUtil
.
MIME_TYPE_HLS
:
return
new
HlsMediaSource
.
Factory
(
DATA_SOURCE_FACTORY
).
createMediaSource
(
uri
);
case
DemoUtil
.
MIME_TYPE_VIDEO_MP4
:
return
new
ProgressiveMediaSource
.
Factory
(
DATA_SOURCE_FACTORY
).
createMediaSource
(
uri
);
default
:
{
throw
new
IllegalStateException
(
"Unsupported type: "
+
item
.
mimeType
);
}
}
}
private
static
MediaQueueItem
buildMediaQueueItem
(
MediaItem
item
)
{
MediaMetadata
movieMetadata
=
new
MediaMetadata
(
MediaMetadata
.
MEDIA_TYPE_MOVIE
);
movieMetadata
.
putString
(
MediaMetadata
.
KEY_TITLE
,
item
.
title
);
MediaInfo
mediaInfo
=
new
MediaInfo
.
Builder
(
item
.
media
.
uri
.
toString
())
.
setStreamType
(
MediaInfo
.
STREAM_TYPE_BUFFERED
)
.
setContentType
(
item
.
mimeType
)
.
setMetadata
(
movieMetadata
)
.
build
();
return
new
MediaQueueItem
.
Builder
(
mediaInfo
).
build
();
}
}
demos/cast/src/main/java/com/google/android/exoplayer2/castdemo/MainActivity.java
View file @
a263fb16
...
...
@@ -38,7 +38,6 @@ import com.google.android.exoplayer2.SimpleExoPlayer;
import
com.google.android.exoplayer2.ext.cast.MediaItem
;
import
com.google.android.exoplayer2.ui.PlayerControlView
;
import
com.google.android.exoplayer2.ui.PlayerView
;
import
com.google.android.gms.cast.CastMediaControlIntent
;
import
com.google.android.gms.cast.framework.CastButtonFactory
;
import
com.google.android.gms.cast.framework.CastContext
;
import
com.google.android.gms.dynamite.DynamiteModule
;
...
...
@@ -49,13 +48,13 @@ import java.util.Collections;
* Cast extension.
*/
public
class
MainActivity
extends
AppCompatActivity
implements
OnClickListener
,
PlayerManager
.
QueueChangesListener
{
implements
OnClickListener
,
ExoCast
PlayerManager
.
QueueChangesListener
{
private
final
MediaItem
.
Builder
mediaItemBuilder
;
private
PlayerView
localPlayerView
;
private
PlayerControlView
castControlView
;
private
PlayerManager
playerManager
;
private
ExoCast
PlayerManager
playerManager
;
private
RecyclerView
mediaQueueList
;
private
MediaQueueListAdapter
mediaQueueListAdapter
;
private
CastContext
castContext
;
...
...
@@ -117,29 +116,13 @@ public class MainActivity extends AppCompatActivity
// There is no Cast context to work with. Do nothing.
return
;
}
String
applicationId
=
castContext
.
getCastOptions
().
getReceiverApplicationId
();
switch
(
applicationId
)
{
case
CastMediaControlIntent
.
DEFAULT_MEDIA_RECEIVER_APPLICATION_ID
:
playerManager
=
new
DefaultReceiverPlayerManager
(
/* queueChangesListener= */
this
,
localPlayerView
,
castControlView
,
/* context= */
this
,
castContext
);
break
;
case
ExoCastOptionsProvider
.
RECEIVER_ID
:
playerManager
=
new
ExoCastPlayerManager
(
/* queueChangesListener= */
this
,
localPlayerView
,
castControlView
,
/* context= */
this
,
castContext
);
break
;
default
:
throw
new
IllegalStateException
(
"Illegal receiver app id: "
+
applicationId
);
}
playerManager
=
new
ExoCastPlayerManager
(
/* queueChangesListener= */
this
,
localPlayerView
,
castControlView
,
/* context= */
this
,
castContext
);
mediaQueueList
.
setAdapter
(
mediaQueueListAdapter
);
}
...
...
demos/cast/src/main/java/com/google/android/exoplayer2/castdemo/PlayerManager.java
deleted
100644 → 0
View file @
6f1daff3
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
google
.
android
.
exoplayer2
.
castdemo
;
import
android.view.KeyEvent
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.ext.cast.MediaItem
;
/** Manages the players in the Cast demo app. */
interface
PlayerManager
{
/** Listener for changes in the media queue. */
interface
QueueChangesListener
{
/** Called when the currently played item of the media queue changes. */
void
onQueuePositionChanged
(
int
previousIndex
,
int
newIndex
);
/** Called when the media queue changes due to modifications not caused by this manager. */
void
onQueueContentsExternallyChanged
();
}
/** Redirects the given {@code keyEvent} to the active player. */
boolean
dispatchKeyEvent
(
KeyEvent
keyEvent
);
/** Appends the given {@link MediaItem} to the media queue. */
void
addItem
(
MediaItem
mediaItem
);
/** Returns the number of items in the media queue. */
int
getMediaQueueSize
();
/** Selects the item at the given position for playback. */
void
selectQueueItem
(
int
position
);
/**
* Returns the position of the item currently being played, or {@link C#INDEX_UNSET} if no item is
* being played.
*/
int
getCurrentItemIndex
();
/** Returns the {@link MediaItem} at the given {@code position}. */
MediaItem
getItem
(
int
position
);
/** Moves the item at position {@code from} to position {@code to}. */
boolean
moveItem
(
int
from
,
int
to
);
/** Removes the item at position {@code index}. */
boolean
removeItem
(
int
index
);
/** Releases any acquired resources. */
void
release
();
}
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