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
4bf42bd2
authored
Dec 12, 2018
by
eguven
Committed by
Oliver Woodman
Dec 14, 2018
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Rename TaskState to DownloadState
PiperOrigin-RevId: 225145311
parent
230a798f
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
205 additions
and
217 deletions
RELEASENOTES.md
demos/main/src/main/java/com/google/android/exoplayer2/demo/DemoDownloadService.java
demos/main/src/main/java/com/google/android/exoplayer2/demo/DownloadTracker.java
library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadManager.java
library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadService.java
library/core/src/test/java/com/google/android/exoplayer2/offline/DownloadManagerTest.java
library/ui/src/main/java/com/google/android/exoplayer2/ui/DownloadNotificationUtil.java
testutils_robolectric/src/main/java/com/google/android/exoplayer2/testutil/TestDownloadManagerListener.java
RELEASENOTES.md
View file @
4bf42bd2
...
@@ -27,6 +27,7 @@
...
@@ -27,6 +27,7 @@
(
[
#5169
](
https://github.com/google/ExoPlayer/issues/5169
)
).
(
[
#5169
](
https://github.com/google/ExoPlayer/issues/5169
)
).
*
DownloadManager:
*
DownloadManager:
*
Create only one task for all DownloadActions for the same content.
*
Create only one task for all DownloadActions for the same content.
*
Rename TaskState to DownloadState.
### 2.9.2 ###
### 2.9.2 ###
...
...
demos/main/src/main/java/com/google/android/exoplayer2/demo/DemoDownloadService.java
View file @
4bf42bd2
...
@@ -17,7 +17,7 @@ package com.google.android.exoplayer2.demo;
...
@@ -17,7 +17,7 @@ package com.google.android.exoplayer2.demo;
import
android.app.Notification
;
import
android.app.Notification
;
import
com.google.android.exoplayer2.offline.DownloadManager
;
import
com.google.android.exoplayer2.offline.DownloadManager
;
import
com.google.android.exoplayer2.offline.DownloadManager.
Task
State
;
import
com.google.android.exoplayer2.offline.DownloadManager.
Download
State
;
import
com.google.android.exoplayer2.offline.DownloadService
;
import
com.google.android.exoplayer2.offline.DownloadService
;
import
com.google.android.exoplayer2.scheduler.PlatformScheduler
;
import
com.google.android.exoplayer2.scheduler.PlatformScheduler
;
import
com.google.android.exoplayer2.ui.DownloadNotificationUtil
;
import
com.google.android.exoplayer2.ui.DownloadNotificationUtil
;
...
@@ -50,40 +50,40 @@ public class DemoDownloadService extends DownloadService {
...
@@ -50,40 +50,40 @@ public class DemoDownloadService extends DownloadService {
}
}
@Override
@Override
protected
Notification
getForegroundNotification
(
TaskState
[]
task
States
)
{
protected
Notification
getForegroundNotification
(
DownloadState
[]
download
States
)
{
return
DownloadNotificationUtil
.
buildProgressNotification
(
return
DownloadNotificationUtil
.
buildProgressNotification
(
/* context= */
this
,
/* context= */
this
,
R
.
drawable
.
ic_download
,
R
.
drawable
.
ic_download
,
CHANNEL_ID
,
CHANNEL_ID
,
/* contentIntent= */
null
,
/* contentIntent= */
null
,
/* message= */
null
,
/* message= */
null
,
task
States
);
download
States
);
}
}
@Override
@Override
protected
void
on
TaskStateChanged
(
TaskState
task
State
)
{
protected
void
on
DownloadStateChanged
(
DownloadState
download
State
)
{
if
(
task
State
.
action
.
isRemoveAction
)
{
if
(
download
State
.
action
.
isRemoveAction
)
{
return
;
return
;
}
}
Notification
notification
=
null
;
Notification
notification
=
null
;
if
(
taskState
.
state
==
Task
State
.
STATE_COMPLETED
)
{
if
(
downloadState
.
state
==
Download
State
.
STATE_COMPLETED
)
{
notification
=
notification
=
DownloadNotificationUtil
.
buildDownloadCompletedNotification
(
DownloadNotificationUtil
.
buildDownloadCompletedNotification
(
/* context= */
this
,
/* context= */
this
,
R
.
drawable
.
ic_download_done
,
R
.
drawable
.
ic_download_done
,
CHANNEL_ID
,
CHANNEL_ID
,
/* contentIntent= */
null
,
/* contentIntent= */
null
,
Util
.
fromUtf8Bytes
(
task
State
.
action
.
data
));
Util
.
fromUtf8Bytes
(
download
State
.
action
.
data
));
}
else
if
(
taskState
.
state
==
Task
State
.
STATE_FAILED
)
{
}
else
if
(
downloadState
.
state
==
Download
State
.
STATE_FAILED
)
{
notification
=
notification
=
DownloadNotificationUtil
.
buildDownloadFailedNotification
(
DownloadNotificationUtil
.
buildDownloadFailedNotification
(
/* context= */
this
,
/* context= */
this
,
R
.
drawable
.
ic_download_done
,
R
.
drawable
.
ic_download_done
,
CHANNEL_ID
,
CHANNEL_ID
,
/* contentIntent= */
null
,
/* contentIntent= */
null
,
Util
.
fromUtf8Bytes
(
task
State
.
action
.
data
));
Util
.
fromUtf8Bytes
(
download
State
.
action
.
data
));
}
}
int
notificationId
=
FOREGROUND_NOTIFICATION_ID
+
1
+
taskState
.
taskI
d
;
int
notificationId
=
FOREGROUND_NOTIFICATION_ID
+
1
+
downloadState
.
i
d
;
NotificationUtil
.
setNotification
(
this
,
notificationId
,
notification
);
NotificationUtil
.
setNotification
(
this
,
notificationId
,
notification
);
}
}
}
}
demos/main/src/main/java/com/google/android/exoplayer2/demo/DownloadTracker.java
View file @
4bf42bd2
...
@@ -37,7 +37,7 @@ import com.google.android.exoplayer2.offline.ActionFile;
...
@@ -37,7 +37,7 @@ import com.google.android.exoplayer2.offline.ActionFile;
import
com.google.android.exoplayer2.offline.DownloadAction
;
import
com.google.android.exoplayer2.offline.DownloadAction
;
import
com.google.android.exoplayer2.offline.DownloadHelper
;
import
com.google.android.exoplayer2.offline.DownloadHelper
;
import
com.google.android.exoplayer2.offline.DownloadManager
;
import
com.google.android.exoplayer2.offline.DownloadManager
;
import
com.google.android.exoplayer2.offline.DownloadManager.
Task
State
;
import
com.google.android.exoplayer2.offline.DownloadManager.
Download
State
;
import
com.google.android.exoplayer2.offline.DownloadService
;
import
com.google.android.exoplayer2.offline.DownloadService
;
import
com.google.android.exoplayer2.offline.ProgressiveDownloadHelper
;
import
com.google.android.exoplayer2.offline.ProgressiveDownloadHelper
;
import
com.google.android.exoplayer2.offline.StreamKey
;
import
com.google.android.exoplayer2.offline.StreamKey
;
...
@@ -144,11 +144,11 @@ public class DownloadTracker implements DownloadManager.Listener {
...
@@ -144,11 +144,11 @@ public class DownloadTracker implements DownloadManager.Listener {
}
}
@Override
@Override
public
void
on
TaskStateChanged
(
DownloadManager
downloadManager
,
TaskState
task
State
)
{
public
void
on
DownloadStateChanged
(
DownloadManager
downloadManager
,
DownloadState
download
State
)
{
DownloadAction
action
=
task
State
.
action
;
DownloadAction
action
=
download
State
.
action
;
Uri
uri
=
action
.
uri
;
Uri
uri
=
action
.
uri
;
if
((
action
.
isRemoveAction
&&
taskState
.
state
==
Task
State
.
STATE_COMPLETED
)
if
((
action
.
isRemoveAction
&&
downloadState
.
state
==
Download
State
.
STATE_COMPLETED
)
||
(!
action
.
isRemoveAction
&&
taskState
.
state
==
Task
State
.
STATE_FAILED
))
{
||
(!
action
.
isRemoveAction
&&
downloadState
.
state
==
Download
State
.
STATE_FAILED
))
{
// A download has been removed, or has failed. Stop tracking it.
// A download has been removed, or has failed. Stop tracking it.
if
(
trackedDownloadStates
.
remove
(
uri
)
!=
null
)
{
if
(
trackedDownloadStates
.
remove
(
uri
)
!=
null
)
{
handleTrackedDownloadStatesChanged
();
handleTrackedDownloadStatesChanged
();
...
...
library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadManager.java
View file @
4bf42bd2
...
@@ -15,10 +15,10 @@
...
@@ -15,10 +15,10 @@
*/
*/
package
com
.
google
.
android
.
exoplayer2
.
offline
;
package
com
.
google
.
android
.
exoplayer2
.
offline
;
import
static
com
.
google
.
android
.
exoplayer2
.
offline
.
DownloadManager
.
Task
State
.
STATE_COMPLETED
;
import
static
com
.
google
.
android
.
exoplayer2
.
offline
.
DownloadManager
.
Download
State
.
STATE_COMPLETED
;
import
static
com
.
google
.
android
.
exoplayer2
.
offline
.
DownloadManager
.
Task
State
.
STATE_FAILED
;
import
static
com
.
google
.
android
.
exoplayer2
.
offline
.
DownloadManager
.
Download
State
.
STATE_FAILED
;
import
static
com
.
google
.
android
.
exoplayer2
.
offline
.
DownloadManager
.
Task
State
.
STATE_QUEUED
;
import
static
com
.
google
.
android
.
exoplayer2
.
offline
.
DownloadManager
.
Download
State
.
STATE_QUEUED
;
import
static
com
.
google
.
android
.
exoplayer2
.
offline
.
DownloadManager
.
Task
State
.
STATE_STARTED
;
import
static
com
.
google
.
android
.
exoplayer2
.
offline
.
DownloadManager
.
Download
State
.
STATE_STARTED
;
import
android.os.ConditionVariable
;
import
android.os.ConditionVariable
;
import
android.os.Handler
;
import
android.os.Handler
;
...
@@ -58,41 +58,41 @@ public final class DownloadManager {
...
@@ -58,41 +58,41 @@ public final class DownloadManager {
*/
*/
void
onInitialized
(
DownloadManager
downloadManager
);
void
onInitialized
(
DownloadManager
downloadManager
);
/**
/**
* Called when the state of a
task
changes.
* Called when the state of a
download
changes.
*
*
* @param downloadManager The reporting instance.
* @param downloadManager The reporting instance.
* @param
taskState The state of the task
.
* @param
downloadState The state of the download
.
*/
*/
void
on
TaskStateChanged
(
DownloadManager
downloadManager
,
TaskState
task
State
);
void
on
DownloadStateChanged
(
DownloadManager
downloadManager
,
DownloadState
download
State
);
/**
/**
* Called when there is no active
task
left.
* Called when there is no active
download
left.
*
*
* @param downloadManager The reporting instance.
* @param downloadManager The reporting instance.
*/
*/
void
onIdle
(
DownloadManager
downloadManager
);
void
onIdle
(
DownloadManager
downloadManager
);
}
}
/** The default maximum number of simultaneous download
task
s. */
/** The default maximum number of simultaneous downloads. */
public
static
final
int
DEFAULT_MAX_SIMULTANEOUS_DOWNLOADS
=
1
;
public
static
final
int
DEFAULT_MAX_SIMULTANEOUS_DOWNLOADS
=
1
;
/** The default minimum number of times a
task
must be retried before failing. */
/** The default minimum number of times a
download
must be retried before failing. */
public
static
final
int
DEFAULT_MIN_RETRY_COUNT
=
5
;
public
static
final
int
DEFAULT_MIN_RETRY_COUNT
=
5
;
private
static
final
String
TAG
=
"DownloadManager"
;
private
static
final
String
TAG
=
"DownloadManager"
;
private
static
final
boolean
DEBUG
=
false
;
private
static
final
boolean
DEBUG
=
false
;
private
final
int
maxActiveDownload
Task
s
;
private
final
int
maxActiveDownloads
;
private
final
int
minRetryCount
;
private
final
int
minRetryCount
;
private
final
ActionFile
actionFile
;
private
final
ActionFile
actionFile
;
private
final
DownloaderFactory
downloaderFactory
;
private
final
DownloaderFactory
downloaderFactory
;
private
final
ArrayList
<
Task
>
task
s
;
private
final
ArrayList
<
Download
>
download
s
;
private
final
ArrayList
<
Task
>
activeDownloadTask
s
;
private
final
ArrayList
<
Download
>
activeDownload
s
;
private
final
Handler
handler
;
private
final
Handler
handler
;
private
final
HandlerThread
fileIOThread
;
private
final
HandlerThread
fileIOThread
;
private
final
Handler
fileIOHandler
;
private
final
Handler
fileIOHandler
;
private
final
CopyOnWriteArraySet
<
Listener
>
listeners
;
private
final
CopyOnWriteArraySet
<
Listener
>
listeners
;
private
int
next
Task
Id
;
private
int
next
Download
Id
;
private
boolean
initialized
;
private
boolean
initialized
;
private
boolean
released
;
private
boolean
released
;
private
boolean
downloadsStopped
;
private
boolean
downloadsStopped
;
...
@@ -113,8 +113,8 @@ public final class DownloadManager {
...
@@ -113,8 +113,8 @@ public final class DownloadManager {
*
*
* @param actionFile The file in which active actions are saved.
* @param actionFile The file in which active actions are saved.
* @param downloaderFactory A factory for creating {@link Downloader}s.
* @param downloaderFactory A factory for creating {@link Downloader}s.
* @param maxSimultaneousDownloads The maximum number of simultaneous download
task
s.
* @param maxSimultaneousDownloads The maximum number of simultaneous downloads.
* @param minRetryCount The minimum number of times a
task
must be retried before failing.
* @param minRetryCount The minimum number of times a
download
must be retried before failing.
*/
*/
public
DownloadManager
(
public
DownloadManager
(
File
actionFile
,
File
actionFile
,
...
@@ -123,12 +123,12 @@ public final class DownloadManager {
...
@@ -123,12 +123,12 @@ public final class DownloadManager {
int
minRetryCount
)
{
int
minRetryCount
)
{
this
.
actionFile
=
new
ActionFile
(
actionFile
);
this
.
actionFile
=
new
ActionFile
(
actionFile
);
this
.
downloaderFactory
=
downloaderFactory
;
this
.
downloaderFactory
=
downloaderFactory
;
this
.
maxActiveDownload
Task
s
=
maxSimultaneousDownloads
;
this
.
maxActiveDownloads
=
maxSimultaneousDownloads
;
this
.
minRetryCount
=
minRetryCount
;
this
.
minRetryCount
=
minRetryCount
;
this
.
downloadsStopped
=
true
;
this
.
downloadsStopped
=
true
;
task
s
=
new
ArrayList
<>();
download
s
=
new
ArrayList
<>();
activeDownload
Task
s
=
new
ArrayList
<>();
activeDownloads
=
new
ArrayList
<>();
Looper
looper
=
Looper
.
myLooper
();
Looper
looper
=
Looper
.
myLooper
();
if
(
looper
==
null
)
{
if
(
looper
==
null
)
{
...
@@ -164,23 +164,23 @@ public final class DownloadManager {
...
@@ -164,23 +164,23 @@ public final class DownloadManager {
listeners
.
remove
(
listener
);
listeners
.
remove
(
listener
);
}
}
/** Starts the download
task
s. */
/** Starts the downloads. */
public
void
startDownloads
()
{
public
void
startDownloads
()
{
Assertions
.
checkState
(!
released
);
Assertions
.
checkState
(!
released
);
if
(
downloadsStopped
)
{
if
(
downloadsStopped
)
{
downloadsStopped
=
false
;
downloadsStopped
=
false
;
maybeStart
Task
s
();
maybeStart
Download
s
();
logd
(
"Downloads are started"
);
logd
(
"Downloads are started"
);
}
}
}
}
/** Stops all of the download
tasks. Call {@link #startDownloads()} to restart task
s. */
/** Stops all of the download
s. Call {@link #startDownloads()} to restart download
s. */
public
void
stopDownloads
()
{
public
void
stopDownloads
()
{
Assertions
.
checkState
(!
released
);
Assertions
.
checkState
(!
released
);
if
(!
downloadsStopped
)
{
if
(!
downloadsStopped
)
{
downloadsStopped
=
true
;
downloadsStopped
=
true
;
for
(
int
i
=
0
;
i
<
activeDownload
Task
s
.
size
();
i
++)
{
for
(
int
i
=
0
;
i
<
activeDownloads
.
size
();
i
++)
{
activeDownload
Task
s
.
get
(
i
).
stop
();
activeDownloads
.
get
(
i
).
stop
();
}
}
logd
(
"Downloads are stopping"
);
logd
(
"Downloads are stopping"
);
}
}
...
@@ -189,64 +189,50 @@ public final class DownloadManager {
...
@@ -189,64 +189,50 @@ public final class DownloadManager {
/**
/**
* Handles the given action.
* Handles the given action.
*
*
* <p>A task is created and added to the task queue if there isn't one already for the same
* content.
*
* @param action The action to be executed.
* @param action The action to be executed.
* @return The id of the newly created or the existing
task
.
* @return The id of the newly created or the existing
download
.
*/
*/
public
int
handleAction
(
DownloadAction
action
)
{
public
int
handleAction
(
DownloadAction
action
)
{
Assertions
.
checkState
(!
released
);
Assertions
.
checkState
(!
released
);
Task
task
=
addTask
ForAction
(
action
);
Download
download
=
getDownload
ForAction
(
action
);
if
(
initialized
)
{
if
(
initialized
)
{
saveActions
();
saveActions
();
maybeStartTasks
();
maybeStartDownloads
();
if
(
task
.
state
==
STATE_QUEUED
)
{
if
(
download
.
state
==
STATE_QUEUED
)
{
// Task did not change out of its initial state, and so its initial state won't have been
// Download did not change out of its initial state, and so its initial state won't have
// been
// reported to listeners. Do so now.
// reported to listeners. Do so now.
notifyListeners
TaskStateChange
(
task
);
notifyListeners
DownloadStateChange
(
download
);
}
}
}
}
return
task
.
id
;
return
download
.
id
;
}
}
/** Returns the number of tasks. */
/** Returns the number of downloads. */
public
int
getTaskCount
()
{
Assertions
.
checkState
(!
released
);
return
tasks
.
size
();
}
/** Returns the number of download tasks. */
public
int
getDownloadCount
()
{
public
int
getDownloadCount
()
{
int
count
=
0
;
Assertions
.
checkState
(!
released
);
for
(
int
i
=
0
;
i
<
tasks
.
size
();
i
++)
{
return
downloads
.
size
();
for
(
DownloadAction
action
:
tasks
.
get
(
i
).
actionQueue
)
{
if
(!
action
.
isRemoveAction
)
{
count
++;
}
}
}
return
count
;
}
}
/** Returns the state of a task, or null if no such task exists */
/** Returns the state of a download, or null if no such download exists */
public
@Nullable
TaskState
getTaskState
(
int
taskId
)
{
@Nullable
public
DownloadState
getDownloadState
(
int
downloadId
)
{
Assertions
.
checkState
(!
released
);
Assertions
.
checkState
(!
released
);
for
(
int
i
=
0
;
i
<
task
s
.
size
();
i
++)
{
for
(
int
i
=
0
;
i
<
download
s
.
size
();
i
++)
{
Task
task
=
task
s
.
get
(
i
);
Download
download
=
download
s
.
get
(
i
);
if
(
task
.
id
==
task
Id
)
{
if
(
download
.
id
==
download
Id
)
{
return
task
.
getTask
State
();
return
download
.
getDownload
State
();
}
}
}
}
return
null
;
return
null
;
}
}
/** Returns the states of all current
task
s. */
/** Returns the states of all current
download
s. */
public
TaskState
[]
getAllTask
States
()
{
public
DownloadState
[]
getAllDownload
States
()
{
Assertions
.
checkState
(!
released
);
Assertions
.
checkState
(!
released
);
TaskState
[]
states
=
new
TaskState
[
task
s
.
size
()];
DownloadState
[]
states
=
new
DownloadState
[
download
s
.
size
()];
for
(
int
i
=
0
;
i
<
states
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
states
.
length
;
i
++)
{
states
[
i
]
=
tasks
.
get
(
i
).
getTask
State
();
states
[
i
]
=
downloads
.
get
(
i
).
getDownload
State
();
}
}
return
states
;
return
states
;
}
}
...
@@ -257,14 +243,14 @@ public final class DownloadManager {
...
@@ -257,14 +243,14 @@ public final class DownloadManager {
return
initialized
;
return
initialized
;
}
}
/** Returns whether there are no active
task
s. */
/** Returns whether there are no active
download
s. */
public
boolean
isIdle
()
{
public
boolean
isIdle
()
{
Assertions
.
checkState
(!
released
);
Assertions
.
checkState
(!
released
);
if
(!
initialized
)
{
if
(!
initialized
)
{
return
false
;
return
false
;
}
}
for
(
int
i
=
0
;
i
<
task
s
.
size
();
i
++)
{
for
(
int
i
=
0
;
i
<
download
s
.
size
();
i
++)
{
if
(
task
s
.
get
(
i
).
isStarted
())
{
if
(
download
s
.
get
(
i
).
isStarted
())
{
return
false
;
return
false
;
}
}
}
}
...
@@ -272,16 +258,17 @@ public final class DownloadManager {
...
@@ -272,16 +258,17 @@ public final class DownloadManager {
}
}
/**
/**
* Stops all of the tasks and releases resources. If the action file isn't up to date, waits for
* Stops all of the downloads and releases resources. If the action file isn't up to date, waits
* the changes to be written. The manager must not be accessed after this method has been called.
* for the changes to be written. The manager must not be accessed after this method has been
* called.
*/
*/
public
void
release
()
{
public
void
release
()
{
if
(
released
)
{
if
(
released
)
{
return
;
return
;
}
}
released
=
true
;
released
=
true
;
for
(
int
i
=
0
;
i
<
task
s
.
size
();
i
++)
{
for
(
int
i
=
0
;
i
<
download
s
.
size
();
i
++)
{
task
s
.
get
(
i
).
stop
();
download
s
.
get
(
i
).
stop
();
}
}
final
ConditionVariable
fileIOFinishedCondition
=
new
ConditionVariable
();
final
ConditionVariable
fileIOFinishedCondition
=
new
ConditionVariable
();
fileIOHandler
.
post
(
fileIOFinishedCondition:
:
open
);
fileIOHandler
.
post
(
fileIOFinishedCondition:
:
open
);
...
@@ -290,47 +277,47 @@ public final class DownloadManager {
...
@@ -290,47 +277,47 @@ public final class DownloadManager {
logd
(
"Released"
);
logd
(
"Released"
);
}
}
private
Task
addTask
ForAction
(
DownloadAction
action
)
{
private
Download
getDownload
ForAction
(
DownloadAction
action
)
{
for
(
int
i
=
0
;
i
<
task
s
.
size
();
i
++)
{
for
(
int
i
=
0
;
i
<
download
s
.
size
();
i
++)
{
Task
task
=
task
s
.
get
(
i
);
Download
download
=
download
s
.
get
(
i
);
if
(
task
.
action
.
isSameMedia
(
action
))
{
if
(
download
.
action
.
isSameMedia
(
action
))
{
task
.
addAction
(
action
);
download
.
addAction
(
action
);
logd
(
"Action is added to existing
task"
,
task
);
logd
(
"Action is added to existing
download"
,
download
);
return
task
;
return
download
;
}
}
}
}
Task
task
=
new
Task
(
nextTaskId
++,
this
,
downloaderFactory
,
action
,
minRetryCount
);
Download
download
=
tasks
.
add
(
task
);
new
Download
(
nextDownloadId
++,
this
,
downloaderFactory
,
action
,
minRetryCount
);
logd
(
"Task is added"
,
task
);
downloads
.
add
(
download
);
return
task
;
logd
(
"Download is added"
,
download
);
return
download
;
}
}
/**
/**
* Iterates through the
task queue and starts any task
if all of the following are true:
* Iterates through the
download queue and starts any download
if all of the following are true:
*
*
* <ul>
* <ul>
* <li>It hasn't started yet.
* <li>It hasn't started yet.
* <li>
If it's a download task then t
he maximum number of active downloads hasn't been reached.
* <li>
T
he maximum number of active downloads hasn't been reached.
* </ul>
* </ul>
*/
*/
private
void
maybeStart
Task
s
()
{
private
void
maybeStart
Download
s
()
{
if
(!
initialized
||
released
)
{
if
(!
initialized
||
released
)
{
return
;
return
;
}
}
boolean
skipDownloadActions
=
downloadsStopped
boolean
skipDownloads
=
downloadsStopped
||
activeDownloads
.
size
()
==
maxActiveDownloads
;
||
activeDownloadTasks
.
size
()
==
maxActiveDownloadTasks
;
for
(
int
i
=
0
;
i
<
downloads
.
size
();
i
++)
{
for
(
int
i
=
0
;
i
<
tasks
.
size
();
i
++)
{
Download
download
=
downloads
.
get
(
i
);
Task
task
=
tasks
.
get
(
i
);
if
(!
download
.
canStart
())
{
if
(!
task
.
canStart
())
{
continue
;
continue
;
}
}
boolean
isRemoveAction
=
task
.
action
.
isRemoveAction
;
boolean
isRemoveAction
=
download
.
action
.
isRemoveAction
;
if
(
isRemoveAction
||
!
skipDownload
Action
s
)
{
if
(
isRemoveAction
||
!
skipDownloads
)
{
task
.
start
();
download
.
start
();
if
(!
isRemoveAction
)
{
if
(!
isRemoveAction
)
{
activeDownload
Tasks
.
add
(
task
);
activeDownload
s
.
add
(
download
);
skipDownload
Actions
=
activeDownloadTasks
.
size
()
==
maxActiveDownloadTask
s
;
skipDownload
s
=
activeDownloads
.
size
()
==
maxActiveDownload
s
;
}
}
}
}
}
}
...
@@ -346,30 +333,30 @@ public final class DownloadManager {
...
@@ -346,30 +333,30 @@ public final class DownloadManager {
}
}
}
}
private
void
on
TaskStateChange
(
Task
task
)
{
private
void
on
DownloadStateChange
(
Download
download
)
{
if
(
released
)
{
if
(
released
)
{
return
;
return
;
}
}
boolean
stopped
=
!
task
.
isStarted
();
boolean
stopped
=
!
download
.
isStarted
();
if
(
stopped
)
{
if
(
stopped
)
{
activeDownload
Tasks
.
remove
(
task
);
activeDownload
s
.
remove
(
download
);
}
}
notifyListeners
TaskStateChange
(
task
);
notifyListeners
DownloadStateChange
(
download
);
if
(
task
.
isFinished
())
{
if
(
download
.
isFinished
())
{
tasks
.
remove
(
task
);
downloads
.
remove
(
download
);
saveActions
();
saveActions
();
}
}
if
(
stopped
)
{
if
(
stopped
)
{
maybeStart
Task
s
();
maybeStart
Download
s
();
maybeNotifyListenersIdle
();
maybeNotifyListenersIdle
();
}
}
}
}
private
void
notifyListeners
TaskStateChange
(
Task
task
)
{
private
void
notifyListeners
DownloadStateChange
(
Download
download
)
{
logd
(
"
Task state is changed"
,
task
);
logd
(
"
Download state is changed"
,
download
);
TaskState
taskState
=
task
.
getTask
State
();
DownloadState
downloadState
=
download
.
getDownload
State
();
for
(
Listener
listener
:
listeners
)
{
for
(
Listener
listener
:
listeners
)
{
listener
.
on
TaskStateChanged
(
this
,
task
State
);
listener
.
on
DownloadStateChanged
(
this
,
download
State
);
}
}
}
}
...
@@ -390,27 +377,27 @@ public final class DownloadManager {
...
@@ -390,27 +377,27 @@ public final class DownloadManager {
if
(
released
)
{
if
(
released
)
{
return
;
return
;
}
}
List
<
Task
>
pendingTasks
=
new
ArrayList
<>(
task
s
);
List
<
Download
>
pendingDownloads
=
new
ArrayList
<>(
download
s
);
task
s
.
clear
();
download
s
.
clear
();
for
(
DownloadAction
action
:
actions
)
{
for
(
DownloadAction
action
:
actions
)
{
addTask
ForAction
(
action
);
getDownload
ForAction
(
action
);
}
}
logd
(
"
Task
s are created."
);
logd
(
"
Download
s are created."
);
initialized
=
true
;
initialized
=
true
;
for
(
Listener
listener
:
listeners
)
{
for
(
Listener
listener
:
listeners
)
{
listener
.
onInitialized
(
DownloadManager
.
this
);
listener
.
onInitialized
(
DownloadManager
.
this
);
}
}
if
(!
pending
Task
s
.
isEmpty
())
{
if
(!
pending
Download
s
.
isEmpty
())
{
tasks
.
addAll
(
pendingTask
s
);
downloads
.
addAll
(
pendingDownload
s
);
saveActions
();
saveActions
();
}
}
maybeStart
Task
s
();
maybeStart
Download
s
();
for
(
int
i
=
0
;
i
<
task
s
.
size
();
i
++)
{
for
(
int
i
=
0
;
i
<
download
s
.
size
();
i
++)
{
Task
task
=
task
s
.
get
(
i
);
Download
download
=
download
s
.
get
(
i
);
if
(
task
.
state
==
STATE_QUEUED
)
{
if
(
download
.
state
==
STATE_QUEUED
)
{
//
Task
did not change out of its initial state, and so its initial state
//
Download
did not change out of its initial state, and so its initial state
// won't have been reported to listeners. Do so now.
// won't have been reported to listeners. Do so now.
notifyListeners
TaskStateChange
(
task
);
notifyListeners
DownloadStateChange
(
download
);
}
}
}
}
});
});
...
@@ -421,9 +408,9 @@ public final class DownloadManager {
...
@@ -421,9 +408,9 @@ public final class DownloadManager {
if
(
released
)
{
if
(
released
)
{
return
;
return
;
}
}
ArrayList
<
DownloadAction
>
actions
=
new
ArrayList
<>(
task
s
.
size
());
ArrayList
<
DownloadAction
>
actions
=
new
ArrayList
<>(
download
s
.
size
());
for
(
int
i
=
0
;
i
<
task
s
.
size
();
i
++)
{
for
(
int
i
=
0
;
i
<
download
s
.
size
();
i
++)
{
actions
.
addAll
(
task
s
.
get
(
i
).
actionQueue
);
actions
.
addAll
(
download
s
.
get
(
i
).
actionQueue
);
}
}
final
DownloadAction
[]
actionsArray
=
actions
.
toArray
(
new
DownloadAction
[
0
]);
final
DownloadAction
[]
actionsArray
=
actions
.
toArray
(
new
DownloadAction
[
0
]);
fileIOHandler
.
post
(
fileIOHandler
.
post
(
...
@@ -443,16 +430,16 @@ public final class DownloadManager {
...
@@ -443,16 +430,16 @@ public final class DownloadManager {
}
}
}
}
private
static
void
logd
(
String
message
,
Task
task
)
{
private
static
void
logd
(
String
message
,
Download
download
)
{
logd
(
message
+
": "
+
task
);
logd
(
message
+
": "
+
download
);
}
}
/** Represents state of a
task
. */
/** Represents state of a
download
. */
public
static
final
class
Task
State
{
public
static
final
class
Download
State
{
/**
/**
*
Task states. One of {@link #STATE_QUEUED}, {@link #STATE_STARTED}, {@link #STATE_COMPLETED}
*
Download states. One of {@link #STATE_QUEUED}, {@link #STATE_STARTED}, {@link
* or {@link #STATE_FAILED}.
*
#STATE_COMPLETED}
or {@link #STATE_FAILED}.
*
*
* <p>Transition diagram:
* <p>Transition diagram:
*
*
...
@@ -465,13 +452,13 @@ public final class DownloadManager {
...
@@ -465,13 +452,13 @@ public final class DownloadManager {
@Retention
(
RetentionPolicy
.
SOURCE
)
@Retention
(
RetentionPolicy
.
SOURCE
)
@IntDef
({
STATE_QUEUED
,
STATE_STARTED
,
STATE_COMPLETED
,
STATE_FAILED
})
@IntDef
({
STATE_QUEUED
,
STATE_STARTED
,
STATE_COMPLETED
,
STATE_FAILED
})
public
@interface
State
{}
public
@interface
State
{}
/** The
task
is waiting to be started. */
/** The
download
is waiting to be started. */
public
static
final
int
STATE_QUEUED
=
0
;
public
static
final
int
STATE_QUEUED
=
0
;
/** The
task
is currently started. */
/** The
download
is currently started. */
public
static
final
int
STATE_STARTED
=
1
;
public
static
final
int
STATE_STARTED
=
1
;
/** The
task
completed. */
/** The
download
completed. */
public
static
final
int
STATE_COMPLETED
=
2
;
public
static
final
int
STATE_COMPLETED
=
2
;
/** The
task
failed. */
/** The
download
failed. */
public
static
final
int
STATE_FAILED
=
3
;
public
static
final
int
STATE_FAILED
=
3
;
/** Returns the state string for the given state value. */
/** Returns the state string for the given state value. */
...
@@ -490,16 +477,15 @@ public final class DownloadManager {
...
@@ -490,16 +477,15 @@ public final class DownloadManager {
}
}
}
}
/** The unique
task
id. */
/** The unique
download
id. */
public
final
int
taskI
d
;
public
final
int
i
d
;
/** The action being executed. */
/** The action being executed. */
public
final
DownloadAction
action
;
public
final
DownloadAction
action
;
/** The state of the
task
. */
/** The state of the
download
. */
public
final
@State
int
state
;
public
final
@State
int
state
;
/**
/**
* The estimated download percentage, or {@link C#PERCENTAGE_UNSET} if no estimate is available
* The estimated download percentage, or {@link C#PERCENTAGE_UNSET} if no estimate is available.
* or if this is a removal task.
*/
*/
public
final
float
downloadPercentage
;
public
final
float
downloadPercentage
;
/** The total number of downloaded bytes. */
/** The total number of downloaded bytes. */
...
@@ -510,15 +496,15 @@ public final class DownloadManager {
...
@@ -510,15 +496,15 @@ public final class DownloadManager {
/** If {@link #state} is {@link #STATE_FAILED} then this is the cause, otherwise null. */
/** If {@link #state} is {@link #STATE_FAILED} then this is the cause, otherwise null. */
@Nullable
public
final
Throwable
error
;
@Nullable
public
final
Throwable
error
;
private
Task
State
(
private
Download
State
(
int
taskI
d
,
int
i
d
,
DownloadAction
action
,
DownloadAction
action
,
@State
int
state
,
@State
int
state
,
float
downloadPercentage
,
float
downloadPercentage
,
long
downloadedBytes
,
long
downloadedBytes
,
long
totalBytes
,
long
totalBytes
,
@Nullable
Throwable
error
)
{
@Nullable
Throwable
error
)
{
this
.
taskId
=
taskI
d
;
this
.
id
=
i
d
;
this
.
action
=
action
;
this
.
action
=
action
;
this
.
state
=
state
;
this
.
state
=
state
;
this
.
downloadPercentage
=
downloadPercentage
;
this
.
downloadPercentage
=
downloadPercentage
;
...
@@ -529,7 +515,7 @@ public final class DownloadManager {
...
@@ -529,7 +515,7 @@ public final class DownloadManager {
}
}
private
static
final
class
Task
{
private
static
final
class
Download
{
/** Target states for the download thread. */
/** Target states for the download thread. */
@Documented
@Documented
...
@@ -543,10 +529,10 @@ public final class DownloadManager {
...
@@ -543,10 +529,10 @@ public final class DownloadManager {
private
final
int
minRetryCount
;
private
final
int
minRetryCount
;
private
final
ArrayDeque
<
DownloadAction
>
actionQueue
;
private
final
ArrayDeque
<
DownloadAction
>
actionQueue
;
private
DownloadAction
action
;
private
DownloadAction
action
;
/** The current state of the
task
. */
/** The current state of the
download
. */
@
Task
State
.
State
private
int
state
;
@
Download
State
.
State
private
int
state
;
/**
/**
* When started, this is the target state that the
task
will transition to when the download
* When started, this is the target state that the
download
will transition to when the download
* thread stops.
* thread stops.
*/
*/
@TargetState
private
volatile
int
targetState
;
@TargetState
private
volatile
int
targetState
;
...
@@ -555,7 +541,7 @@ public final class DownloadManager {
...
@@ -555,7 +541,7 @@ public final class DownloadManager {
@MonotonicNonNull
private
DownloadThread
downloadThread
;
@MonotonicNonNull
private
DownloadThread
downloadThread
;
@MonotonicNonNull
private
Throwable
error
;
@MonotonicNonNull
private
Throwable
error
;
private
Task
(
private
Download
(
int
id
,
int
id
,
DownloadManager
downloadManager
,
DownloadManager
downloadManager
,
DownloaderFactory
downloaderFactory
,
DownloaderFactory
downloaderFactory
,
...
@@ -586,11 +572,11 @@ public final class DownloadManager {
...
@@ -586,11 +572,11 @@ public final class DownloadManager {
}
else
{
}
else
{
Assertions
.
checkState
(
state
==
STATE_QUEUED
);
Assertions
.
checkState
(
state
==
STATE_QUEUED
);
action
=
updatedAction
;
action
=
updatedAction
;
downloadManager
.
on
Task
StateChange
(
this
);
downloadManager
.
on
Download
StateChange
(
this
);
}
}
}
}
public
TaskState
getTask
State
()
{
public
DownloadState
getDownload
State
()
{
float
downloadPercentage
=
C
.
PERCENTAGE_UNSET
;
float
downloadPercentage
=
C
.
PERCENTAGE_UNSET
;
long
downloadedBytes
=
0
;
long
downloadedBytes
=
0
;
long
totalBytes
=
C
.
LENGTH_UNSET
;
long
totalBytes
=
C
.
LENGTH_UNSET
;
...
@@ -599,16 +585,16 @@ public final class DownloadManager {
...
@@ -599,16 +585,16 @@ public final class DownloadManager {
downloadedBytes
=
downloader
.
getDownloadedBytes
();
downloadedBytes
=
downloader
.
getDownloadedBytes
();
totalBytes
=
downloader
.
getTotalBytes
();
totalBytes
=
downloader
.
getTotalBytes
();
}
}
return
new
Task
State
(
return
new
Download
State
(
id
,
action
,
state
,
downloadPercentage
,
downloadedBytes
,
totalBytes
,
error
);
id
,
action
,
state
,
downloadPercentage
,
downloadedBytes
,
totalBytes
,
error
);
}
}
/** Returns whether the
task
is finished. */
/** Returns whether the
download
is finished. */
public
boolean
isFinished
()
{
public
boolean
isFinished
()
{
return
state
==
STATE_FAILED
||
state
==
STATE_COMPLETED
;
return
state
==
STATE_FAILED
||
state
==
STATE_COMPLETED
;
}
}
/** Returns whether the
task
is started. */
/** Returns whether the
download
is started. */
public
boolean
isStarted
()
{
public
boolean
isStarted
()
{
return
state
==
STATE_STARTED
;
return
state
==
STATE_STARTED
;
}
}
...
@@ -619,9 +605,9 @@ public final class DownloadManager {
...
@@ -619,9 +605,9 @@ public final class DownloadManager {
+
' '
+
' '
+
(
action
.
isRemoveAction
?
"remove"
:
"download"
)
+
(
action
.
isRemoveAction
?
"remove"
:
"download"
)
+
' '
+
' '
+
Task
State
.
getStateString
(
state
)
+
Download
State
.
getStateString
(
state
)
+
' '
+
' '
+
Task
State
.
getStateString
(
targetState
);
+
Download
State
.
getStateString
(
targetState
);
}
}
public
boolean
canStart
()
{
public
boolean
canStart
()
{
...
@@ -637,7 +623,7 @@ public final class DownloadManager {
...
@@ -637,7 +623,7 @@ public final class DownloadManager {
downloadThread
=
downloadThread
=
new
DownloadThread
(
new
DownloadThread
(
this
,
downloader
,
action
.
isRemoveAction
,
minRetryCount
,
downloadManager
.
handler
);
this
,
downloader
,
action
.
isRemoveAction
,
minRetryCount
,
downloadManager
.
handler
);
downloadManager
.
on
Task
StateChange
(
this
);
downloadManager
.
on
Download
StateChange
(
this
);
}
}
}
}
...
@@ -650,7 +636,7 @@ public final class DownloadManager {
...
@@ -650,7 +636,7 @@ public final class DownloadManager {
// Internal methods running on the main thread.
// Internal methods running on the main thread.
private
void
stopDownloadThread
()
{
private
void
stopDownloadThread
()
{
this
.
targetState
=
Task
State
.
STATE_QUEUED
;
this
.
targetState
=
Download
State
.
STATE_QUEUED
;
Assertions
.
checkNotNull
(
downloadThread
).
cancel
();
Assertions
.
checkNotNull
(
downloadThread
).
cancel
();
}
}
...
@@ -664,19 +650,19 @@ public final class DownloadManager {
...
@@ -664,19 +650,19 @@ public final class DownloadManager {
}
else
{
}
else
{
actionQueue
.
remove
();
actionQueue
.
remove
();
if
(!
actionQueue
.
isEmpty
())
{
if
(!
actionQueue
.
isEmpty
())
{
// Don't continue running. Wait to be restarted by maybeStart
Task
s().
// Don't continue running. Wait to be restarted by maybeStart
Download
s().
state
=
STATE_QUEUED
;
state
=
STATE_QUEUED
;
action
=
actionQueue
.
peek
();
action
=
actionQueue
.
peek
();
}
}
}
}
}
}
downloadManager
.
on
Task
StateChange
(
this
);
downloadManager
.
on
Download
StateChange
(
this
);
}
}
}
}
private
static
class
DownloadThread
implements
Runnable
{
private
static
class
DownloadThread
implements
Runnable
{
private
final
Task
task
;
private
final
Download
download
;
private
final
Downloader
downloader
;
private
final
Downloader
downloader
;
private
final
boolean
remove
;
private
final
boolean
remove
;
private
final
int
minRetryCount
;
private
final
int
minRetryCount
;
...
@@ -685,12 +671,12 @@ public final class DownloadManager {
...
@@ -685,12 +671,12 @@ public final class DownloadManager {
private
volatile
boolean
isCanceled
;
private
volatile
boolean
isCanceled
;
private
DownloadThread
(
private
DownloadThread
(
Task
task
,
Download
download
,
Downloader
downloader
,
Downloader
downloader
,
boolean
remove
,
boolean
remove
,
int
minRetryCount
,
int
minRetryCount
,
Handler
callbackHandler
)
{
Handler
callbackHandler
)
{
this
.
task
=
task
;
this
.
download
=
download
;
this
.
downloader
=
downloader
;
this
.
downloader
=
downloader
;
this
.
remove
=
remove
;
this
.
remove
=
remove
;
this
.
minRetryCount
=
minRetryCount
;
this
.
minRetryCount
=
minRetryCount
;
...
@@ -709,7 +695,7 @@ public final class DownloadManager {
...
@@ -709,7 +695,7 @@ public final class DownloadManager {
@Override
@Override
public
void
run
()
{
public
void
run
()
{
logd
(
"
Task is started"
,
task
);
logd
(
"
Download is started"
,
download
);
Throwable
error
=
null
;
Throwable
error
=
null
;
try
{
try
{
if
(
remove
)
{
if
(
remove
)
{
...
@@ -725,14 +711,14 @@ public final class DownloadManager {
...
@@ -725,14 +711,14 @@ public final class DownloadManager {
if
(!
isCanceled
)
{
if
(!
isCanceled
)
{
long
downloadedBytes
=
downloader
.
getDownloadedBytes
();
long
downloadedBytes
=
downloader
.
getDownloadedBytes
();
if
(
downloadedBytes
!=
errorPosition
)
{
if
(
downloadedBytes
!=
errorPosition
)
{
logd
(
"Reset error count. downloadedBytes = "
+
downloadedBytes
,
task
);
logd
(
"Reset error count. downloadedBytes = "
+
downloadedBytes
,
download
);
errorPosition
=
downloadedBytes
;
errorPosition
=
downloadedBytes
;
errorCount
=
0
;
errorCount
=
0
;
}
}
if
(++
errorCount
>
minRetryCount
)
{
if
(++
errorCount
>
minRetryCount
)
{
throw
e
;
throw
e
;
}
}
logd
(
"Download error. Retry "
+
errorCount
,
task
);
logd
(
"Download error. Retry "
+
errorCount
,
download
);
Thread
.
sleep
(
getRetryDelayMillis
(
errorCount
));
Thread
.
sleep
(
getRetryDelayMillis
(
errorCount
));
}
}
}
}
...
@@ -742,7 +728,7 @@ public final class DownloadManager {
...
@@ -742,7 +728,7 @@ public final class DownloadManager {
error
=
e
;
error
=
e
;
}
}
final
Throwable
finalError
=
error
;
final
Throwable
finalError
=
error
;
callbackHandler
.
post
(()
->
task
.
onDownloadThreadStopped
(
isCanceled
?
null
:
finalError
));
callbackHandler
.
post
(()
->
download
.
onDownloadThreadStopped
(
isCanceled
?
null
:
finalError
));
}
}
private
int
getRetryDelayMillis
(
int
errorCount
)
{
private
int
getRetryDelayMillis
(
int
errorCount
)
{
...
...
library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadService.java
View file @
4bf42bd2
...
@@ -24,7 +24,7 @@ import android.os.IBinder;
...
@@ -24,7 +24,7 @@ import android.os.IBinder;
import
android.os.Looper
;
import
android.os.Looper
;
import
android.support.annotation.Nullable
;
import
android.support.annotation.Nullable
;
import
android.support.annotation.StringRes
;
import
android.support.annotation.StringRes
;
import
com.google.android.exoplayer2.offline.DownloadManager.
Task
State
;
import
com.google.android.exoplayer2.offline.DownloadManager.
Download
State
;
import
com.google.android.exoplayer2.scheduler.Requirements
;
import
com.google.android.exoplayer2.scheduler.Requirements
;
import
com.google.android.exoplayer2.scheduler.RequirementsWatcher
;
import
com.google.android.exoplayer2.scheduler.RequirementsWatcher
;
import
com.google.android.exoplayer2.scheduler.Scheduler
;
import
com.google.android.exoplayer2.scheduler.Scheduler
;
...
@@ -71,9 +71,9 @@ public abstract class DownloadService extends Service {
...
@@ -71,9 +71,9 @@ public abstract class DownloadService extends Service {
private
static
final
String
TAG
=
"DownloadService"
;
private
static
final
String
TAG
=
"DownloadService"
;
private
static
final
boolean
DEBUG
=
false
;
private
static
final
boolean
DEBUG
=
false
;
// Keep the requirements helper for each DownloadService as long as there are
task
s (and the
// Keep the requirements helper for each DownloadService as long as there are
download
s (and the
// process is running). This allows
tasks to resume when there's no scheduler. It may also allow
// process is running). This allows
downloads to resume when there's no scheduler. It may also
//
task
s the resume more quickly than when relying on the scheduler alone.
//
allow download
s the resume more quickly than when relying on the scheduler alone.
private
static
final
HashMap
<
Class
<?
extends
DownloadService
>,
RequirementsHelper
>
private
static
final
HashMap
<
Class
<?
extends
DownloadService
>,
RequirementsHelper
>
requirementsHelpers
=
new
HashMap
<>();
requirementsHelpers
=
new
HashMap
<>();
private
static
final
Requirements
DEFAULT_REQUIREMENTS
=
private
static
final
Requirements
DEFAULT_REQUIREMENTS
=
...
@@ -99,7 +99,7 @@ public abstract class DownloadService extends Service {
...
@@ -99,7 +99,7 @@ public abstract class DownloadService extends Service {
* <p>If {@code foregroundNotificationId} isn't {@link #FOREGROUND_NOTIFICATION_ID_NONE} (value
* <p>If {@code foregroundNotificationId} isn't {@link #FOREGROUND_NOTIFICATION_ID_NONE} (value
* {@value #FOREGROUND_NOTIFICATION_ID_NONE}) the service runs in the foreground with {@link
* {@value #FOREGROUND_NOTIFICATION_ID_NONE}) the service runs in the foreground with {@link
* #DEFAULT_FOREGROUND_NOTIFICATION_UPDATE_INTERVAL}. In that case {@link
* #DEFAULT_FOREGROUND_NOTIFICATION_UPDATE_INTERVAL}. In that case {@link
* #getForegroundNotification(
Task
State[])} should be overridden in the subclass.
* #getForegroundNotification(
Download
State[])} should be overridden in the subclass.
*
*
* @param foregroundNotificationId The notification id for the foreground notification, or {@link
* @param foregroundNotificationId The notification id for the foreground notification, or {@link
* #FOREGROUND_NOTIFICATION_ID_NONE} (value {@value #FOREGROUND_NOTIFICATION_ID_NONE})
* #FOREGROUND_NOTIFICATION_ID_NONE} (value {@value #FOREGROUND_NOTIFICATION_ID_NONE})
...
@@ -110,7 +110,7 @@ public abstract class DownloadService extends Service {
...
@@ -110,7 +110,7 @@ public abstract class DownloadService extends Service {
/**
/**
* Creates a DownloadService which will run in the foreground. {@link
* Creates a DownloadService which will run in the foreground. {@link
* #getForegroundNotification(
Task
State[])} should be overridden in the subclass.
* #getForegroundNotification(
Download
State[])} should be overridden in the subclass.
*
*
* @param foregroundNotificationId The notification id for the foreground notification, must not
* @param foregroundNotificationId The notification id for the foreground notification, must not
* be 0.
* be 0.
...
@@ -128,7 +128,7 @@ public abstract class DownloadService extends Service {
...
@@ -128,7 +128,7 @@ public abstract class DownloadService extends Service {
/**
/**
* Creates a DownloadService which will run in the foreground. {@link
* Creates a DownloadService which will run in the foreground. {@link
* #getForegroundNotification(
Task
State[])} should be overridden in the subclass.
* #getForegroundNotification(
Download
State[])} should be overridden in the subclass.
*
*
* @param foregroundNotificationId The notification id for the foreground notification. Must not
* @param foregroundNotificationId The notification id for the foreground notification. Must not
* be 0.
* be 0.
...
@@ -338,29 +338,29 @@ public abstract class DownloadService extends Service {
...
@@ -338,29 +338,29 @@ public abstract class DownloadService extends Service {
*
*
* <p>Returns a notification to be displayed when this service running in the foreground.
* <p>Returns a notification to be displayed when this service running in the foreground.
*
*
* <p>This method is called when there is a
task
state change and periodically while there are
* <p>This method is called when there is a
download
state change and periodically while there are
* active
task
s. The periodic update interval can be set using {@link #DownloadService(int,
* active
download
s. The periodic update interval can be set using {@link #DownloadService(int,
* long)}.
* long)}.
*
*
* <p>On API level 26 and above, this method may also be called just before the service stops,
* <p>On API level 26 and above, this method may also be called just before the service stops,
* with an empty {@code
task
States} array. The returned notification is used to satisfy system
* with an empty {@code
download
States} array. The returned notification is used to satisfy system
* requirements for foreground services.
* requirements for foreground services.
*
*
* @param
taskStates The states of all current task
s.
* @param
downloadStates The states of all current download
s.
* @return The foreground notification to display.
* @return The foreground notification to display.
*/
*/
protected
Notification
getForegroundNotification
(
TaskState
[]
task
States
)
{
protected
Notification
getForegroundNotification
(
DownloadState
[]
download
States
)
{
throw
new
IllegalStateException
(
throw
new
IllegalStateException
(
getClass
().
getName
()
getClass
().
getName
()
+
" is started in the foreground but getForegroundNotification() is not implemented."
);
+
" is started in the foreground but getForegroundNotification() is not implemented."
);
}
}
/**
/**
* Called when the state of a
task
changes.
* Called when the state of a
download
changes.
*
*
* @param
taskState The state of the task
.
* @param
downloadState The state of the download
.
*/
*/
protected
void
on
TaskStateChanged
(
TaskState
task
State
)
{
protected
void
on
DownloadStateChanged
(
DownloadState
download
State
)
{
// Do nothing.
// Do nothing.
}
}
...
@@ -428,10 +428,11 @@ public abstract class DownloadService extends Service {
...
@@ -428,10 +428,11 @@ public abstract class DownloadService extends Service {
}
}
@Override
@Override
public
void
onTaskStateChanged
(
DownloadManager
downloadManager
,
TaskState
taskState
)
{
public
void
onDownloadStateChanged
(
DownloadService
.
this
.
onTaskStateChanged
(
taskState
);
DownloadManager
downloadManager
,
DownloadState
downloadState
)
{
DownloadService
.
this
.
onDownloadStateChanged
(
downloadState
);
if
(
foregroundNotificationUpdater
!=
null
)
{
if
(
foregroundNotificationUpdater
!=
null
)
{
if
(
taskState
.
state
==
Task
State
.
STATE_STARTED
)
{
if
(
downloadState
.
state
==
Download
State
.
STATE_STARTED
)
{
foregroundNotificationUpdater
.
startPeriodicUpdates
();
foregroundNotificationUpdater
.
startPeriodicUpdates
();
}
else
{
}
else
{
foregroundNotificationUpdater
.
update
();
foregroundNotificationUpdater
.
update
();
...
@@ -471,8 +472,8 @@ public abstract class DownloadService extends Service {
...
@@ -471,8 +472,8 @@ public abstract class DownloadService extends Service {
}
}
public
void
update
()
{
public
void
update
()
{
TaskState
[]
taskStates
=
downloadManager
.
getAllTask
States
();
DownloadState
[]
downloadStates
=
downloadManager
.
getAllDownload
States
();
startForeground
(
notificationId
,
getForegroundNotification
(
task
States
));
startForeground
(
notificationId
,
getForegroundNotification
(
download
States
));
notificationDisplayed
=
true
;
notificationDisplayed
=
true
;
if
(
periodicUpdatesStarted
)
{
if
(
periodicUpdatesStarted
)
{
handler
.
removeCallbacks
(
this
);
handler
.
removeCallbacks
(
this
);
...
...
library/core/src/test/java/com/google/android/exoplayer2/offline/DownloadManagerTest.java
View file @
4bf42bd2
...
@@ -20,8 +20,8 @@ import static org.junit.Assert.fail;
...
@@ -20,8 +20,8 @@ import static org.junit.Assert.fail;
import
android.net.Uri
;
import
android.net.Uri
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.offline.DownloadManager.
Task
State
;
import
com.google.android.exoplayer2.offline.DownloadManager.
Download
State
;
import
com.google.android.exoplayer2.offline.DownloadManager.
Task
State.State
;
import
com.google.android.exoplayer2.offline.DownloadManager.
Download
State.State
;
import
com.google.android.exoplayer2.testutil.DummyMainThread
;
import
com.google.android.exoplayer2.testutil.DummyMainThread
;
import
com.google.android.exoplayer2.testutil.RobolectricUtil
;
import
com.google.android.exoplayer2.testutil.RobolectricUtil
;
import
com.google.android.exoplayer2.testutil.TestDownloadManagerListener
;
import
com.google.android.exoplayer2.testutil.TestDownloadManagerListener
;
...
@@ -371,11 +371,11 @@ public class DownloadManagerTest {
...
@@ -371,11 +371,11 @@ public class DownloadManagerTest {
TaskWrapper
task2
=
new
DownloadRunner
(
uri2
).
postDownloadAction
().
getTask
();
TaskWrapper
task2
=
new
DownloadRunner
(
uri2
).
postDownloadAction
().
getTask
();
TaskWrapper
task3
=
new
DownloadRunner
(
uri3
).
postRemoveAction
().
getTask
();
TaskWrapper
task3
=
new
DownloadRunner
(
uri3
).
postRemoveAction
().
getTask
();
TaskState
[]
states
=
downloadManager
.
getAllTask
States
();
DownloadState
[]
states
=
downloadManager
.
getAllDownload
States
();
assertThat
(
states
).
hasLength
(
3
);
assertThat
(
states
).
hasLength
(
3
);
int
[]
taskIds
=
{
task1
.
taskId
,
task2
.
taskId
,
task3
.
taskId
};
int
[]
taskIds
=
{
task1
.
taskId
,
task2
.
taskId
,
task3
.
taskId
};
int
[]
stateTaskIds
=
{
states
[
0
].
taskId
,
states
[
1
].
taskId
,
states
[
2
].
taskI
d
};
int
[]
stateTaskIds
=
{
states
[
0
].
id
,
states
[
1
].
id
,
states
[
2
].
i
d
};
assertThat
(
stateTaskIds
).
isEqualTo
(
taskIds
);
assertThat
(
stateTaskIds
).
isEqualTo
(
taskIds
);
}
}
...
@@ -522,19 +522,19 @@ public class DownloadManagerTest {
...
@@ -522,19 +522,19 @@ public class DownloadManagerTest {
}
}
private
TaskWrapper
assertStarted
()
throws
InterruptedException
{
private
TaskWrapper
assertStarted
()
throws
InterruptedException
{
return
assertState
(
Task
State
.
STATE_STARTED
);
return
assertState
(
Download
State
.
STATE_STARTED
);
}
}
private
TaskWrapper
assertCompleted
()
{
private
TaskWrapper
assertCompleted
()
{
return
assertState
(
Task
State
.
STATE_COMPLETED
);
return
assertState
(
Download
State
.
STATE_COMPLETED
);
}
}
private
TaskWrapper
assertFailed
()
{
private
TaskWrapper
assertFailed
()
{
return
assertState
(
Task
State
.
STATE_FAILED
);
return
assertState
(
Download
State
.
STATE_FAILED
);
}
}
private
TaskWrapper
assertQueued
()
{
private
TaskWrapper
assertQueued
()
{
return
assertState
(
Task
State
.
STATE_QUEUED
);
return
assertState
(
Download
State
.
STATE_QUEUED
);
}
}
private
TaskWrapper
assertState
(
@State
int
expectedState
)
{
private
TaskWrapper
assertState
(
@State
int
expectedState
)
{
...
...
library/ui/src/main/java/com/google/android/exoplayer2/ui/DownloadNotificationUtil.java
View file @
4bf42bd2
...
@@ -23,7 +23,7 @@ import android.support.annotation.Nullable;
...
@@ -23,7 +23,7 @@ import android.support.annotation.Nullable;
import
android.support.annotation.StringRes
;
import
android.support.annotation.StringRes
;
import
android.support.v4.app.NotificationCompat
;
import
android.support.v4.app.NotificationCompat
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.offline.DownloadManager.
Task
State
;
import
com.google.android.exoplayer2.offline.DownloadManager.
Download
State
;
/** Helper for creating download notifications. */
/** Helper for creating download notifications. */
public
final
class
DownloadNotificationUtil
{
public
final
class
DownloadNotificationUtil
{
...
@@ -33,7 +33,7 @@ public final class DownloadNotificationUtil {
...
@@ -33,7 +33,7 @@ public final class DownloadNotificationUtil {
private
DownloadNotificationUtil
()
{}
private
DownloadNotificationUtil
()
{}
/**
/**
* Returns a progress notification for the given
task
states.
* Returns a progress notification for the given
download
states.
*
*
* @param context A context for accessing resources.
* @param context A context for accessing resources.
* @param smallIcon A small icon for the notification.
* @param smallIcon A small icon for the notification.
...
@@ -41,7 +41,7 @@ public final class DownloadNotificationUtil {
...
@@ -41,7 +41,7 @@ public final class DownloadNotificationUtil {
* above.
* above.
* @param contentIntent An optional content intent to send when the notification is clicked.
* @param contentIntent An optional content intent to send when the notification is clicked.
* @param message An optional message to display on the notification.
* @param message An optional message to display on the notification.
* @param
taskStates The task
states.
* @param
downloadStates The download
states.
* @return The notification.
* @return The notification.
*/
*/
public
static
Notification
buildProgressNotification
(
public
static
Notification
buildProgressNotification
(
...
@@ -50,28 +50,28 @@ public final class DownloadNotificationUtil {
...
@@ -50,28 +50,28 @@ public final class DownloadNotificationUtil {
String
channelId
,
String
channelId
,
@Nullable
PendingIntent
contentIntent
,
@Nullable
PendingIntent
contentIntent
,
@Nullable
String
message
,
@Nullable
String
message
,
TaskState
[]
task
States
)
{
DownloadState
[]
download
States
)
{
float
totalPercentage
=
0
;
float
totalPercentage
=
0
;
int
downloadTaskCount
=
0
;
int
downloadTaskCount
=
0
;
boolean
allDownloadPercentagesUnknown
=
true
;
boolean
allDownloadPercentagesUnknown
=
true
;
boolean
haveDownloadedBytes
=
false
;
boolean
haveDownloadedBytes
=
false
;
boolean
haveDownloadTasks
=
false
;
boolean
haveDownloadTasks
=
false
;
boolean
haveRemoveTasks
=
false
;
boolean
haveRemoveTasks
=
false
;
for
(
TaskState
taskState
:
task
States
)
{
for
(
DownloadState
downloadState
:
download
States
)
{
if
(
taskState
.
state
!=
Task
State
.
STATE_STARTED
if
(
downloadState
.
state
!=
Download
State
.
STATE_STARTED
&&
taskState
.
state
!=
Task
State
.
STATE_COMPLETED
)
{
&&
downloadState
.
state
!=
Download
State
.
STATE_COMPLETED
)
{
continue
;
continue
;
}
}
if
(
task
State
.
action
.
isRemoveAction
)
{
if
(
download
State
.
action
.
isRemoveAction
)
{
haveRemoveTasks
=
true
;
haveRemoveTasks
=
true
;
continue
;
continue
;
}
}
haveDownloadTasks
=
true
;
haveDownloadTasks
=
true
;
if
(
task
State
.
downloadPercentage
!=
C
.
PERCENTAGE_UNSET
)
{
if
(
download
State
.
downloadPercentage
!=
C
.
PERCENTAGE_UNSET
)
{
allDownloadPercentagesUnknown
=
false
;
allDownloadPercentagesUnknown
=
false
;
totalPercentage
+=
task
State
.
downloadPercentage
;
totalPercentage
+=
download
State
.
downloadPercentage
;
}
}
haveDownloadedBytes
|=
task
State
.
downloadedBytes
>
0
;
haveDownloadedBytes
|=
download
State
.
downloadedBytes
>
0
;
downloadTaskCount
++;
downloadTaskCount
++;
}
}
...
...
testutils_robolectric/src/main/java/com/google/android/exoplayer2/testutil/TestDownloadManagerListener.java
View file @
4bf42bd2
...
@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.testutil;
...
@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.testutil;
import
static
com
.
google
.
common
.
truth
.
Truth
.
assertThat
;
import
static
com
.
google
.
common
.
truth
.
Truth
.
assertThat
;
import
com.google.android.exoplayer2.offline.DownloadManager
;
import
com.google.android.exoplayer2.offline.DownloadManager
;
import
com.google.android.exoplayer2.offline.DownloadManager.DownloadState
;
import
java.util.HashMap
;
import
java.util.HashMap
;
import
java.util.concurrent.ArrayBlockingQueue
;
import
java.util.concurrent.ArrayBlockingQueue
;
import
java.util.concurrent.CountDownLatch
;
import
java.util.concurrent.CountDownLatch
;
...
@@ -56,12 +57,11 @@ public final class TestDownloadManagerListener implements DownloadManager.Listen
...
@@ -56,12 +57,11 @@ public final class TestDownloadManagerListener implements DownloadManager.Listen
}
}
@Override
@Override
public
void
onTaskStateChanged
(
public
void
onDownloadStateChanged
(
DownloadManager
downloadManager
,
DownloadState
downloadState
)
{
DownloadManager
downloadManager
,
DownloadManager
.
TaskState
taskState
)
{
if
(
downloadState
.
state
==
DownloadState
.
STATE_FAILED
&&
downloadError
==
null
)
{
if
(
taskState
.
state
==
DownloadManager
.
TaskState
.
STATE_FAILED
&&
downloadError
==
null
)
{
downloadError
=
downloadState
.
error
;
downloadError
=
taskState
.
error
;
}
}
getStateQueue
(
taskState
.
taskId
).
add
(
task
State
.
state
);
getStateQueue
(
downloadState
.
id
).
add
(
download
State
.
state
);
}
}
@Override
@Override
...
...
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