Make DownloadTracker use DownloadIndex
DownloadTracker will stop updating DownloadIndex when DownloadManager starts using the same DownloadIndex. PiperOrigin-RevId: 232306803
This commit is contained in:
parent
fb99c26426
commit
a5d64463c7
@ -18,7 +18,11 @@ package com.google.android.exoplayer2.demo;
|
||||
import android.app.Application;
|
||||
import com.google.android.exoplayer2.DefaultRenderersFactory;
|
||||
import com.google.android.exoplayer2.RenderersFactory;
|
||||
import com.google.android.exoplayer2.database.ExoDatabaseProvider;
|
||||
import com.google.android.exoplayer2.offline.ActionFile;
|
||||
import com.google.android.exoplayer2.offline.DefaultDownloadIndex;
|
||||
import com.google.android.exoplayer2.offline.DefaultDownloaderFactory;
|
||||
import com.google.android.exoplayer2.offline.DownloadIndexUtil;
|
||||
import com.google.android.exoplayer2.offline.DownloadManager;
|
||||
import com.google.android.exoplayer2.offline.DownloaderConstructorHelper;
|
||||
import com.google.android.exoplayer2.upstream.DataSource;
|
||||
@ -31,14 +35,17 @@ import com.google.android.exoplayer2.upstream.cache.CacheDataSource;
|
||||
import com.google.android.exoplayer2.upstream.cache.CacheDataSourceFactory;
|
||||
import com.google.android.exoplayer2.upstream.cache.NoOpCacheEvictor;
|
||||
import com.google.android.exoplayer2.upstream.cache.SimpleCache;
|
||||
import com.google.android.exoplayer2.util.Log;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Placeholder application to facilitate overriding Application methods for debugging and testing.
|
||||
*/
|
||||
public class DemoApplication extends Application {
|
||||
|
||||
private static final String TAG = "DemoApplication";
|
||||
private static final String DOWNLOAD_ACTION_FILE = "actions";
|
||||
private static final String DOWNLOAD_TRACKER_ACTION_FILE = "tracked_actions";
|
||||
private static final String DOWNLOAD_CONTENT_DIRECTORY = "downloads";
|
||||
@ -97,6 +104,16 @@ public class DemoApplication extends Application {
|
||||
|
||||
private synchronized void initDownloadManager() {
|
||||
if (downloadManager == null) {
|
||||
DefaultDownloadIndex downloadIndex = new DefaultDownloadIndex(new ExoDatabaseProvider(this));
|
||||
File actionFile = new File(getDownloadDirectory(), DOWNLOAD_TRACKER_ACTION_FILE);
|
||||
if (actionFile.exists()) {
|
||||
try {
|
||||
DownloadIndexUtil.upgradeActionFile(new ActionFile(actionFile), downloadIndex, null);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Upgrading action file failed", e);
|
||||
}
|
||||
actionFile.delete();
|
||||
}
|
||||
DownloaderConstructorHelper downloaderConstructorHelper =
|
||||
new DownloaderConstructorHelper(getDownloadCache(), buildHttpDataSourceFactory());
|
||||
downloadManager =
|
||||
@ -108,10 +125,7 @@ public class DemoApplication extends Application {
|
||||
DownloadManager.DEFAULT_MIN_RETRY_COUNT,
|
||||
DownloadManager.DEFAULT_REQUIREMENTS);
|
||||
downloadTracker =
|
||||
new DownloadTracker(
|
||||
/* context= */ this,
|
||||
buildDataSourceFactory(),
|
||||
new File(getDownloadDirectory(), DOWNLOAD_TRACKER_ACTION_FILE));
|
||||
new DownloadTracker(/* context= */ this, buildDataSourceFactory(), downloadIndex);
|
||||
downloadManager.addListener(downloadTracker);
|
||||
}
|
||||
}
|
||||
|
@ -34,11 +34,13 @@ import android.widget.Toast;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.RenderersFactory;
|
||||
import com.google.android.exoplayer2.offline.ActionFile;
|
||||
import com.google.android.exoplayer2.offline.DefaultDownloadIndex;
|
||||
import com.google.android.exoplayer2.offline.DownloadAction;
|
||||
import com.google.android.exoplayer2.offline.DownloadHelper;
|
||||
import com.google.android.exoplayer2.offline.DownloadManager;
|
||||
import com.google.android.exoplayer2.offline.DownloadService;
|
||||
import com.google.android.exoplayer2.offline.DownloadState;
|
||||
import com.google.android.exoplayer2.offline.DownloadStateCursor;
|
||||
import com.google.android.exoplayer2.offline.StreamKey;
|
||||
import com.google.android.exoplayer2.scheduler.Requirements;
|
||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||
@ -51,8 +53,8 @@ import com.google.android.exoplayer2.ui.TrackSelectionView;
|
||||
import com.google.android.exoplayer2.upstream.DataSource;
|
||||
import com.google.android.exoplayer2.util.Log;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@ -80,20 +82,21 @@ public class DownloadTracker implements DownloadManager.Listener {
|
||||
private final DataSource.Factory dataSourceFactory;
|
||||
private final TrackNameProvider trackNameProvider;
|
||||
private final CopyOnWriteArraySet<Listener> listeners;
|
||||
private final HashMap<Uri, DownloadAction> trackedDownloadStates;
|
||||
private final ActionFile actionFile;
|
||||
private final Handler actionFileWriteHandler;
|
||||
private final HashMap<Uri, DownloadState> trackedDownloadStates;
|
||||
private final DefaultDownloadIndex downloadIndex;
|
||||
private final Handler actionFileIOHandler;
|
||||
|
||||
public DownloadTracker(Context context, DataSource.Factory dataSourceFactory, File actionFile) {
|
||||
public DownloadTracker(
|
||||
Context context, DataSource.Factory dataSourceFactory, DefaultDownloadIndex downloadIndex) {
|
||||
this.context = context.getApplicationContext();
|
||||
this.dataSourceFactory = dataSourceFactory;
|
||||
this.actionFile = new ActionFile(actionFile);
|
||||
this.downloadIndex = downloadIndex;
|
||||
trackNameProvider = new DefaultTrackNameProvider(context.getResources());
|
||||
listeners = new CopyOnWriteArraySet<>();
|
||||
trackedDownloadStates = new HashMap<>();
|
||||
HandlerThread actionFileWriteThread = new HandlerThread("DownloadTracker");
|
||||
actionFileWriteThread.start();
|
||||
actionFileWriteHandler = new Handler(actionFileWriteThread.getLooper());
|
||||
actionFileIOHandler = new Handler(actionFileWriteThread.getLooper());
|
||||
loadTrackedActions();
|
||||
}
|
||||
|
||||
@ -114,7 +117,7 @@ public class DownloadTracker implements DownloadManager.Listener {
|
||||
if (!trackedDownloadStates.containsKey(uri)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return trackedDownloadStates.get(uri).getKeys();
|
||||
return Arrays.asList(trackedDownloadStates.get(uri).streamKeys);
|
||||
}
|
||||
|
||||
public void toggleDownload(
|
||||
@ -146,7 +149,7 @@ public class DownloadTracker implements DownloadManager.Listener {
|
||||
|| downloadState.state == DownloadState.STATE_FAILED) {
|
||||
// A download has been removed, or has failed. Stop tracking it.
|
||||
if (trackedDownloadStates.remove(downloadState.uri) != null) {
|
||||
handleTrackedDownloadStatesChanged();
|
||||
handleTrackedDownloadStateChanged(downloadState);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -167,27 +170,24 @@ public class DownloadTracker implements DownloadManager.Listener {
|
||||
// Internal methods
|
||||
|
||||
private void loadTrackedActions() {
|
||||
try {
|
||||
DownloadAction[] allActions = actionFile.load();
|
||||
for (DownloadAction action : allActions) {
|
||||
trackedDownloadStates.put(action.uri, action);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to load tracked actions", e);
|
||||
DownloadStateCursor downloadStates = downloadIndex.getDownloadStates();
|
||||
while (downloadStates.moveToNext()) {
|
||||
DownloadState downloadState = downloadStates.getDownloadState();
|
||||
trackedDownloadStates.put(downloadState.uri, downloadState);
|
||||
}
|
||||
downloadStates.close();
|
||||
}
|
||||
|
||||
private void handleTrackedDownloadStatesChanged() {
|
||||
private void handleTrackedDownloadStateChanged(DownloadState downloadState) {
|
||||
for (Listener listener : listeners) {
|
||||
listener.onDownloadsChanged();
|
||||
}
|
||||
final DownloadAction[] actions = trackedDownloadStates.values().toArray(new DownloadAction[0]);
|
||||
actionFileWriteHandler.post(
|
||||
actionFileIOHandler.post(
|
||||
() -> {
|
||||
try {
|
||||
actionFile.store(actions);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to store tracked actions", e);
|
||||
if (downloadState.state == DownloadState.STATE_REMOVED) {
|
||||
downloadIndex.removeDownloadState(downloadState.id);
|
||||
} else {
|
||||
downloadIndex.putDownloadState(downloadState);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -197,8 +197,9 @@ public class DownloadTracker implements DownloadManager.Listener {
|
||||
// This content is already being downloaded. Do nothing.
|
||||
return;
|
||||
}
|
||||
trackedDownloadStates.put(action.uri, action);
|
||||
handleTrackedDownloadStatesChanged();
|
||||
DownloadState downloadState = new DownloadState(action);
|
||||
trackedDownloadStates.put(downloadState.uri, downloadState);
|
||||
handleTrackedDownloadStateChanged(downloadState);
|
||||
startServiceWithAction(action);
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,7 @@ public final class DownloadIndexUtil {
|
||||
if (downloadState != null) {
|
||||
downloadState = merge(downloadState, action);
|
||||
} else {
|
||||
downloadState = convert(action);
|
||||
downloadState = new DownloadState(action);
|
||||
}
|
||||
downloadIndex.putDownloadState(downloadState);
|
||||
}
|
||||
@ -121,26 +121,4 @@ public final class DownloadIndexUtil {
|
||||
newKeys,
|
||||
action.data);
|
||||
}
|
||||
|
||||
private static DownloadState convert(DownloadAction action) {
|
||||
long currentTimeMs = System.currentTimeMillis();
|
||||
return new DownloadState(
|
||||
action.id,
|
||||
action.type,
|
||||
action.uri,
|
||||
action.customCacheKey,
|
||||
/* state= */ action.isRemoveAction
|
||||
? DownloadState.STATE_REMOVING
|
||||
: DownloadState.STATE_QUEUED,
|
||||
/* downloadPercentage= */ C.PERCENTAGE_UNSET,
|
||||
/* downloadedBytes= */ 0,
|
||||
/* totalBytes= */ C.LENGTH_UNSET,
|
||||
DownloadState.FAILURE_REASON_NONE,
|
||||
/* stopFlags= */ 0,
|
||||
/* notMetRequirements= */ 0,
|
||||
/* startTimeMs= */ currentTimeMs,
|
||||
/* updateTimeMs= */ currentTimeMs,
|
||||
action.keys.toArray(new StreamKey[0]),
|
||||
action.data);
|
||||
}
|
||||
}
|
||||
|
@ -164,6 +164,34 @@ public final class DownloadState {
|
||||
/** Not met requirements to download. */
|
||||
@Requirements.RequirementFlags public final int notMetRequirements;
|
||||
|
||||
/**
|
||||
* Creates a {@link DownloadState} using a {@link DownloadAction}.
|
||||
*
|
||||
* @param action The {@link DownloadAction}.
|
||||
*/
|
||||
public DownloadState(DownloadAction action) {
|
||||
this(action, System.currentTimeMillis());
|
||||
}
|
||||
|
||||
private DownloadState(DownloadAction action, long currentTimeMs) {
|
||||
this(
|
||||
action.id,
|
||||
action.type,
|
||||
action.uri,
|
||||
action.customCacheKey,
|
||||
/* state= */ action.isRemoveAction ? STATE_REMOVING : STATE_QUEUED,
|
||||
/* downloadPercentage= */ C.PERCENTAGE_UNSET,
|
||||
/* downloadedBytes= */ 0,
|
||||
/* totalBytes= */ C.LENGTH_UNSET,
|
||||
FAILURE_REASON_NONE,
|
||||
/* stopFlags= */ 0,
|
||||
/* notMetRequirements= */ 0,
|
||||
/* startTimeMs= */ currentTimeMs,
|
||||
/* updateTimeMs= */ currentTimeMs,
|
||||
action.keys.toArray(new StreamKey[0]),
|
||||
action.data);
|
||||
}
|
||||
|
||||
/* package */ DownloadState(
|
||||
String id,
|
||||
String type,
|
||||
|
@ -16,7 +16,7 @@
|
||||
package com.google.android.exoplayer2.offline;
|
||||
|
||||
/** Provides random read-write access to the result set returned by a database query. */
|
||||
interface DownloadStateCursor {
|
||||
public interface DownloadStateCursor {
|
||||
|
||||
/** Returns the DownloadState at the current position. */
|
||||
DownloadState getDownloadState();
|
||||
|
Loading…
x
Reference in New Issue
Block a user