Further clean up DownloadActions + DownloadActivity
- Made parts of DownloadActions public that were previously hidden. This is necessary so that when an app is listening to the DownloadManager, it can tell something about the tasks. - Simplified DownloadActivity some more. The helpers may migrate into their corresponding modules at some point, and also be converted to return structured TrackGroupArrays rather than a flat list of Formats. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=195269824
This commit is contained in:
parent
5a1431c904
commit
c5bf7f4513
@ -20,15 +20,14 @@ import static com.google.android.exoplayer2.demo.PlayerActivity.EXTENSION_EXTRA;
|
|||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import android.util.SparseBooleanArray;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
|
import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.offline.DownloadAction;
|
import com.google.android.exoplayer2.offline.DownloadAction;
|
||||||
import com.google.android.exoplayer2.offline.DownloadService;
|
import com.google.android.exoplayer2.offline.DownloadService;
|
||||||
import com.google.android.exoplayer2.offline.ProgressiveDownloadAction;
|
import com.google.android.exoplayer2.offline.ProgressiveDownloadAction;
|
||||||
@ -70,11 +69,9 @@ public class DownloadActivity extends Activity {
|
|||||||
private String sampleName;
|
private String sampleName;
|
||||||
|
|
||||||
private TrackNameProvider trackNameProvider;
|
private TrackNameProvider trackNameProvider;
|
||||||
private AsyncTask manifestDownloaderTask;
|
private DownloadHelper<? extends Parcelable> downloadHelper;
|
||||||
|
|
||||||
private DownloadUtilMethods downloadUtilMethods;
|
|
||||||
private ListView representationList;
|
private ListView representationList;
|
||||||
private ArrayAdapter<RepresentationItem> arrayAdapter;
|
private ArrayAdapter<String> arrayAdapter;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
@ -100,37 +97,44 @@ public class DownloadActivity extends Activity {
|
|||||||
int type = Util.inferContentType(sampleUri, extension);
|
int type = Util.inferContentType(sampleUri, extension);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case C.TYPE_DASH:
|
case C.TYPE_DASH:
|
||||||
downloadUtilMethods = new DashDownloadUtilMethods(sampleUri, manifestDataSourceFactory);
|
downloadHelper = new DashDownloadHelper(sampleUri, manifestDataSourceFactory);
|
||||||
break;
|
break;
|
||||||
case C.TYPE_SS:
|
case C.TYPE_SS:
|
||||||
downloadUtilMethods = new SsDownloadUtilMethods(sampleUri, manifestDataSourceFactory);
|
downloadHelper = new SsDownloadHelper(sampleUri, manifestDataSourceFactory);
|
||||||
break;
|
break;
|
||||||
case C.TYPE_HLS:
|
case C.TYPE_HLS:
|
||||||
downloadUtilMethods = new HlsDownloadUtilMethods(sampleUri, manifestDataSourceFactory);
|
downloadHelper = new HlsDownloadHelper(sampleUri, manifestDataSourceFactory);
|
||||||
break;
|
break;
|
||||||
case C.TYPE_OTHER:
|
case C.TYPE_OTHER:
|
||||||
downloadUtilMethods = new ProgressiveDownloadUtilMethods(sampleUri);
|
downloadHelper = new ProgressiveDownloadHelper(sampleUri);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IllegalStateException("Unsupported type: " + type);
|
throw new IllegalStateException("Unsupported type: " + type);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateRepresentationsList();
|
new Thread() {
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onStart() {
|
public void run() {
|
||||||
super.onStart();
|
try {
|
||||||
updateRepresentationsList();
|
downloadHelper.init();
|
||||||
}
|
runOnUiThread(
|
||||||
|
new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
protected void onStop() {
|
public void run() {
|
||||||
if (manifestDownloaderTask != null) {
|
onInitialized();
|
||||||
manifestDownloaderTask.cancel(true);
|
|
||||||
manifestDownloaderTask = null;
|
|
||||||
}
|
}
|
||||||
super.onStop();
|
});
|
||||||
|
} catch (IOException e) {
|
||||||
|
runOnUiThread(
|
||||||
|
new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
onInitializationError();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method is referenced in the layout file
|
// This method is referenced in the layout file
|
||||||
@ -141,21 +145,31 @@ public class DownloadActivity extends Activity {
|
|||||||
startDownload();
|
startDownload();
|
||||||
} else if (id == R.id.remove_all_button) {
|
} else if (id == R.id.remove_all_button) {
|
||||||
removeDownload();
|
removeDownload();
|
||||||
} else if (id == R.id.refresh_button) {
|
|
||||||
updateRepresentationsList();
|
|
||||||
} else if (id == R.id.play_button) {
|
} else if (id == R.id.play_button) {
|
||||||
playDownload();
|
playDownload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onInitialized() {
|
||||||
|
for (int i = 0; i < downloadHelper.getTrackCount(); i++) {
|
||||||
|
arrayAdapter.add(trackNameProvider.getTrackName(downloadHelper.getTrackFormat(i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onInitializationError() {
|
||||||
|
Toast.makeText(
|
||||||
|
getApplicationContext(), R.string.download_manifest_load_error, Toast.LENGTH_LONG)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
private void startDownload() {
|
private void startDownload() {
|
||||||
ArrayList<Object> representationKeys = getSelectedRepresentationKeys();
|
int[] selectedTrackIndices = getSelectedTrackIndices();
|
||||||
if (!representationKeys.isEmpty()) {
|
if (selectedTrackIndices.length > 0) {
|
||||||
DownloadService.addDownloadAction(
|
DownloadService.addDownloadAction(
|
||||||
this,
|
this,
|
||||||
DemoDownloadService.class,
|
DemoDownloadService.class,
|
||||||
downloadUtilMethods.getDownloadAction(
|
downloadHelper.getDownloadAction(
|
||||||
/* isRemoveAction= */ false, sampleName, representationKeys));
|
/* isRemoveAction= */ false, sampleName, selectedTrackIndices));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,123 +177,87 @@ public class DownloadActivity extends Activity {
|
|||||||
DownloadService.addDownloadAction(
|
DownloadService.addDownloadAction(
|
||||||
this,
|
this,
|
||||||
DemoDownloadService.class,
|
DemoDownloadService.class,
|
||||||
downloadUtilMethods.getDownloadAction(
|
downloadHelper.getDownloadAction(/* isRemoveAction= */ true, sampleName));
|
||||||
/* isRemoveAction= */ true, sampleName, Collections.emptyList()));
|
|
||||||
for (int i = 0; i < representationList.getChildCount(); i++) {
|
for (int i = 0; i < representationList.getChildCount(); i++) {
|
||||||
representationList.setItemChecked(i, false);
|
representationList.setItemChecked(i, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("SuspiciousToArrayCall")
|
|
||||||
private void playDownload() {
|
private void playDownload() {
|
||||||
ArrayList<Object> selectedRepresentationKeys = getSelectedRepresentationKeys();
|
int[] selectedTrackIndices = getSelectedTrackIndices();
|
||||||
if (selectedRepresentationKeys.isEmpty()) {
|
List<? extends Parcelable> keys = downloadHelper.getTrackKeys(selectedTrackIndices);
|
||||||
|
if (keys.isEmpty()) {
|
||||||
playerIntent.removeExtra(PlayerActivity.MANIFEST_FILTER_EXTRA);
|
playerIntent.removeExtra(PlayerActivity.MANIFEST_FILTER_EXTRA);
|
||||||
} else {
|
} else {
|
||||||
Parcelable[] parcelables = new Parcelable[selectedRepresentationKeys.size()];
|
Parcelable[] keysArray = keys.toArray(new Parcelable[selectedTrackIndices.length]);
|
||||||
selectedRepresentationKeys.toArray(parcelables);
|
playerIntent.putExtra(PlayerActivity.MANIFEST_FILTER_EXTRA, new ParcelableArray<>(keysArray));
|
||||||
playerIntent.putExtra(
|
|
||||||
PlayerActivity.MANIFEST_FILTER_EXTRA, new ParcelableArray<>(parcelables));
|
|
||||||
}
|
}
|
||||||
startActivity(playerIntent);
|
startActivity(playerIntent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateRepresentationsList() {
|
private int[] getSelectedTrackIndices() {
|
||||||
if (manifestDownloaderTask != null) {
|
ArrayList<Integer> checkedIndices = new ArrayList<>();
|
||||||
manifestDownloaderTask.cancel(true);
|
for (int i = 0; i < representationList.getChildCount(); i++) {
|
||||||
|
if (representationList.isItemChecked(i)) {
|
||||||
|
checkedIndices.add(i);
|
||||||
}
|
}
|
||||||
manifestDownloaderTask = new ManifestDownloaderTask().execute();
|
}
|
||||||
|
return Util.toArray(checkedIndices);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArrayList<Object> getSelectedRepresentationKeys() {
|
private abstract static class DownloadHelper<K extends Parcelable> {
|
||||||
SparseBooleanArray checked = representationList.getCheckedItemPositions();
|
|
||||||
ArrayList<Object> representations = new ArrayList<>(checked.size());
|
protected static final Format DUMMY_FORMAT =
|
||||||
for (int i = 0; i < checked.size(); i++) {
|
Format.createContainerFormat(null, null, null, null, Format.NO_VALUE, 0, null);
|
||||||
if (checked.valueAt(i)) {
|
|
||||||
int position = checked.keyAt(i);
|
protected final Uri uri;
|
||||||
RepresentationItem item =
|
protected final DataSource.Factory dataSourceFactory;
|
||||||
(RepresentationItem) representationList.getItemAtPosition(position);
|
protected final List<Format> trackFormats;
|
||||||
representations.add(item.key);
|
protected final List<K> trackKeys;
|
||||||
}
|
|
||||||
}
|
public DownloadHelper(Uri uri, DataSource.Factory dataSourceFactory) {
|
||||||
return representations;
|
this.uri = uri;
|
||||||
|
this.dataSourceFactory = dataSourceFactory;
|
||||||
|
trackFormats = new ArrayList<>();
|
||||||
|
trackKeys = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class RepresentationItem {
|
public abstract void init() throws IOException;
|
||||||
|
|
||||||
public final Parcelable key;
|
public int getTrackCount() {
|
||||||
public final String title;
|
return trackFormats.size();
|
||||||
|
|
||||||
public RepresentationItem(Parcelable key, String title) {
|
|
||||||
this.key = key;
|
|
||||||
this.title = title;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public Format getTrackFormat(int trackIndex) {
|
||||||
public String toString() {
|
return trackFormats.get(trackIndex);
|
||||||
return title;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class ManifestDownloaderTask
|
public List<K> getTrackKeys(int... trackIndices) {
|
||||||
extends AsyncTask<Void, Void, List<RepresentationItem>> {
|
if (trackFormats.size() == 1 && trackFormats.get(0) == DUMMY_FORMAT) {
|
||||||
|
return Collections.emptyList();
|
||||||
@Override
|
|
||||||
protected List<RepresentationItem> doInBackground(Void... ignore) {
|
|
||||||
try {
|
|
||||||
return downloadUtilMethods.loadRepresentationItems(trackNameProvider);
|
|
||||||
} catch (IOException | InterruptedException e) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
List<K> keys = new ArrayList<>(trackIndices.length);
|
||||||
|
for (int trackIndex : trackIndices) {
|
||||||
|
keys.add(trackKeys.get(trackIndex));
|
||||||
}
|
}
|
||||||
|
return keys;
|
||||||
@Override
|
|
||||||
protected void onPostExecute(List<RepresentationItem> items) {
|
|
||||||
if (items == null) {
|
|
||||||
Toast.makeText(
|
|
||||||
getApplicationContext(), R.string.download_manifest_load_error, Toast.LENGTH_LONG)
|
|
||||||
.show();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
arrayAdapter.clear();
|
|
||||||
for (RepresentationItem representationItem : items) {
|
|
||||||
arrayAdapter.add(representationItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private abstract static class DownloadUtilMethods {
|
|
||||||
|
|
||||||
protected final Uri manifestUri;
|
|
||||||
|
|
||||||
public DownloadUtilMethods(Uri manifestUri) {
|
|
||||||
this.manifestUri = manifestUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract List<RepresentationItem> loadRepresentationItems(
|
|
||||||
TrackNameProvider trackNameProvider) throws IOException, InterruptedException;
|
|
||||||
|
|
||||||
public abstract DownloadAction getDownloadAction(
|
public abstract DownloadAction getDownloadAction(
|
||||||
boolean isRemoveAction, String sampleName, List<Object> representationKeys);
|
boolean isRemoveAction, String sampleName, int... trackIndices);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class DashDownloadUtilMethods extends DownloadUtilMethods {
|
private static final class DashDownloadHelper extends DownloadHelper<RepresentationKey> {
|
||||||
|
|
||||||
private final DataSource.Factory manifestDataSourceFactory;
|
public DashDownloadHelper(Uri uri, DataSource.Factory dataSourceFactory) {
|
||||||
|
super(uri, dataSourceFactory);
|
||||||
public DashDownloadUtilMethods(Uri manifestUri, DataSource.Factory manifestDataSourceFactory) {
|
|
||||||
super(manifestUri);
|
|
||||||
this.manifestDataSourceFactory = manifestDataSourceFactory;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<RepresentationItem> loadRepresentationItems(TrackNameProvider trackNameProvider)
|
public void init() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
DataSource dataSource = dataSourceFactory.createDataSource();
|
||||||
DataSource dataSource = manifestDataSourceFactory.createDataSource();
|
DashManifest manifest = ParsingLoadable.load(dataSource, new DashManifestParser(), uri);
|
||||||
DashManifest manifest =
|
|
||||||
ParsingLoadable.load(dataSource, new DashManifestParser(), manifestUri);
|
|
||||||
|
|
||||||
ArrayList<RepresentationItem> items = new ArrayList<>();
|
|
||||||
for (int periodIndex = 0; periodIndex < manifest.getPeriodCount(); periodIndex++) {
|
for (int periodIndex = 0; periodIndex < manifest.getPeriodCount(); periodIndex++) {
|
||||||
List<AdaptationSet> adaptationSets = manifest.getPeriod(periodIndex).adaptationSets;
|
List<AdaptationSet> adaptationSets = manifest.getPeriod(periodIndex).adaptationSets;
|
||||||
for (int adaptationIndex = 0; adaptationIndex < adaptationSets.size(); adaptationIndex++) {
|
for (int adaptationIndex = 0; adaptationIndex < adaptationSets.size(); adaptationIndex++) {
|
||||||
@ -287,119 +265,98 @@ public class DownloadActivity extends Activity {
|
|||||||
adaptationSets.get(adaptationIndex).representations;
|
adaptationSets.get(adaptationIndex).representations;
|
||||||
int representationsCount = representations.size();
|
int representationsCount = representations.size();
|
||||||
for (int i = 0; i < representationsCount; i++) {
|
for (int i = 0; i < representationsCount; i++) {
|
||||||
RepresentationKey key = new RepresentationKey(periodIndex, adaptationIndex, i);
|
trackFormats.add(representations.get(i).format);
|
||||||
String trackName = trackNameProvider.getTrackName(representations.get(i).format);
|
trackKeys.add(new RepresentationKey(periodIndex, adaptationIndex, i));
|
||||||
items.add(new RepresentationItem(key, trackName));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return items;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DownloadAction getDownloadAction(
|
public DownloadAction getDownloadAction(
|
||||||
boolean isRemoveAction, String sampleName, List<Object> representationKeys) {
|
boolean isRemoveAction, String sampleName, int... trackIndices) {
|
||||||
RepresentationKey[] keys =
|
return new DashDownloadAction(uri, isRemoveAction, sampleName, getTrackKeys(trackIndices));
|
||||||
representationKeys.toArray(new RepresentationKey[representationKeys.size()]);
|
}
|
||||||
return new DashDownloadAction(isRemoveAction, sampleName, manifestUri, keys);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
private static final class HlsDownloadHelper extends DownloadHelper<RenditionKey> {
|
||||||
|
|
||||||
private static final class HlsDownloadUtilMethods extends DownloadUtilMethods {
|
public HlsDownloadHelper(Uri uri, DataSource.Factory dataSourceFactory) {
|
||||||
|
super(uri, dataSourceFactory);
|
||||||
private final DataSource.Factory manifestDataSourceFactory;
|
|
||||||
|
|
||||||
public HlsDownloadUtilMethods(Uri manifestUri, DataSource.Factory manifestDataSourceFactory) {
|
|
||||||
super(manifestUri);
|
|
||||||
this.manifestDataSourceFactory = manifestDataSourceFactory;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<RepresentationItem> loadRepresentationItems(TrackNameProvider trackNameProvider)
|
public void init() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
DataSource dataSource = dataSourceFactory.createDataSource();
|
||||||
DataSource dataSource = manifestDataSourceFactory.createDataSource();
|
HlsPlaylist<?> playlist = ParsingLoadable.load(dataSource, new HlsPlaylistParser(), uri);
|
||||||
HlsPlaylist<?> playlist =
|
|
||||||
ParsingLoadable.load(dataSource, new HlsPlaylistParser(), manifestUri);
|
|
||||||
|
|
||||||
ArrayList<RepresentationItem> items = new ArrayList<>();
|
|
||||||
if (playlist instanceof HlsMediaPlaylist) {
|
if (playlist instanceof HlsMediaPlaylist) {
|
||||||
items.add(new RepresentationItem(null, "Stream"));
|
trackFormats.add(DUMMY_FORMAT);
|
||||||
} else {
|
} else {
|
||||||
HlsMasterPlaylist masterPlaylist = (HlsMasterPlaylist) playlist;
|
HlsMasterPlaylist masterPlaylist = (HlsMasterPlaylist) playlist;
|
||||||
addRepresentationItems(masterPlaylist.variants, RenditionKey.GROUP_VARIANTS, items);
|
addRepresentationItems(masterPlaylist.variants, RenditionKey.GROUP_VARIANTS);
|
||||||
addRepresentationItems(masterPlaylist.audios, RenditionKey.GROUP_AUDIOS, items);
|
addRepresentationItems(masterPlaylist.audios, RenditionKey.GROUP_AUDIOS);
|
||||||
addRepresentationItems(masterPlaylist.subtitles, RenditionKey.GROUP_SUBTITLES, items);
|
addRepresentationItems(masterPlaylist.subtitles, RenditionKey.GROUP_SUBTITLES);
|
||||||
}
|
}
|
||||||
return items;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addRepresentationItems(
|
private void addRepresentationItems(List<HlsUrl> renditions, int renditionGroup) {
|
||||||
List<HlsUrl> renditions, int renditionGroup, List<RepresentationItem> out) {
|
|
||||||
for (int i = 0; i < renditions.size(); i++) {
|
for (int i = 0; i < renditions.size(); i++) {
|
||||||
out.add(new RepresentationItem(new RenditionKey(renditionGroup, i), renditions.get(i).url));
|
trackFormats.add(renditions.get(i).format);
|
||||||
|
trackKeys.add(new RenditionKey(renditionGroup, i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DownloadAction getDownloadAction(
|
public DownloadAction getDownloadAction(
|
||||||
boolean isRemoveAction, String sampleName, List<Object> representationKeys) {
|
boolean isRemoveAction, String sampleName, int... trackIndices) {
|
||||||
RenditionKey[] keys = representationKeys.toArray(new RenditionKey[representationKeys.size()]);
|
return new HlsDownloadAction(uri, isRemoveAction, sampleName, getTrackKeys(trackIndices));
|
||||||
return new HlsDownloadAction(isRemoveAction, sampleName, manifestUri, keys);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class SsDownloadUtilMethods extends DownloadUtilMethods {
|
private static final class SsDownloadHelper extends DownloadHelper<TrackKey> {
|
||||||
|
|
||||||
private final DataSource.Factory manifestDataSourceFactory;
|
public SsDownloadHelper(Uri uri, DataSource.Factory dataSourceFactory) {
|
||||||
|
super(uri, dataSourceFactory);
|
||||||
public SsDownloadUtilMethods(Uri manifestUri, DataSource.Factory manifestDataSourceFactory) {
|
|
||||||
super(manifestUri);
|
|
||||||
this.manifestDataSourceFactory = manifestDataSourceFactory;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<RepresentationItem> loadRepresentationItems(TrackNameProvider trackNameProvider)
|
public void init() throws IOException {
|
||||||
throws IOException, InterruptedException {
|
DataSource dataSource = dataSourceFactory.createDataSource();
|
||||||
DataSource dataSource = manifestDataSourceFactory.createDataSource();
|
SsManifest manifest = ParsingLoadable.load(dataSource, new SsManifestParser(), uri);
|
||||||
SsManifest manifest = ParsingLoadable.load(dataSource, new SsManifestParser(), manifestUri);
|
|
||||||
|
|
||||||
ArrayList<RepresentationItem> items = new ArrayList<>();
|
|
||||||
for (int i = 0; i < manifest.streamElements.length; i++) {
|
for (int i = 0; i < manifest.streamElements.length; i++) {
|
||||||
SsManifest.StreamElement streamElement = manifest.streamElements[i];
|
SsManifest.StreamElement streamElement = manifest.streamElements[i];
|
||||||
for (int j = 0; j < streamElement.formats.length; j++) {
|
for (int j = 0; j < streamElement.formats.length; j++) {
|
||||||
TrackKey key = new TrackKey(i, j);
|
trackFormats.add(streamElement.formats[j]);
|
||||||
String trackName = trackNameProvider.getTrackName(streamElement.formats[j]);
|
trackKeys.add(new TrackKey(i, j));
|
||||||
items.add(new RepresentationItem(key, trackName));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return items;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DownloadAction getDownloadAction(
|
public DownloadAction getDownloadAction(
|
||||||
boolean isRemoveAction, String sampleName, List<Object> representationKeys) {
|
boolean isRemoveAction, String sampleName, int... trackIndices) {
|
||||||
TrackKey[] keys = representationKeys.toArray(new TrackKey[representationKeys.size()]);
|
return new SsDownloadAction(uri, isRemoveAction, sampleName, getTrackKeys(trackIndices));
|
||||||
return new SsDownloadAction(isRemoveAction, sampleName, manifestUri, keys);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class ProgressiveDownloadUtilMethods extends DownloadUtilMethods {
|
private static final class ProgressiveDownloadHelper extends DownloadHelper<Parcelable> {
|
||||||
|
|
||||||
public ProgressiveDownloadUtilMethods(Uri manifestUri) {
|
public ProgressiveDownloadHelper(Uri uri) {
|
||||||
super(manifestUri);
|
super(uri, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<RepresentationItem> loadRepresentationItems(TrackNameProvider trackNameProvider) {
|
public void init() {
|
||||||
return Collections.singletonList(new RepresentationItem(null, "Stream"));
|
trackFormats.add(DUMMY_FORMAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DownloadAction getDownloadAction(
|
public DownloadAction getDownloadAction(
|
||||||
boolean isRemoveAction, String sampleName, List<Object> representationKeys) {
|
boolean isRemoveAction, String sampleName, int... trackIndices) {
|
||||||
return new ProgressiveDownloadAction(
|
return new ProgressiveDownloadAction(
|
||||||
isRemoveAction, sampleName, manifestUri, /* customCacheKey= */ null);
|
uri, isRemoveAction, sampleName, /* customCacheKey= */ null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,12 +37,6 @@
|
|||||||
android:onClick="onClick"
|
android:onClick="onClick"
|
||||||
android:text="@string/download_remove_all"/>
|
android:text="@string/download_remove_all"/>
|
||||||
|
|
||||||
<Button android:id="@+id/refresh_button"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:onClick="onClick"
|
|
||||||
android:text="@string/download_refresh"/>
|
|
||||||
|
|
||||||
<Button android:id="@+id/play_button"
|
<Button android:id="@+id/play_button"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -51,8 +51,6 @@
|
|||||||
|
|
||||||
<string name="download_remove_all">Remove all</string>
|
<string name="download_remove_all">Remove all</string>
|
||||||
|
|
||||||
<string name="download_refresh">Refresh</string>
|
|
||||||
|
|
||||||
<string name="download_only_single_period_non_drm_protected">Currently only downloading of single period non-DRM protected content is demonstrated in this app.</string>
|
<string name="download_only_single_period_non_drm_protected">Currently only downloading of single period non-DRM protected content is demonstrated in this app.</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.offline;
|
package com.google.android.exoplayer2.offline;
|
||||||
|
|
||||||
|
import android.net.Uri;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
@ -90,21 +91,25 @@ public abstract class DownloadAction {
|
|||||||
public final String type;
|
public final String type;
|
||||||
/** The action version. */
|
/** The action version. */
|
||||||
public final int version;
|
public final int version;
|
||||||
|
/** The uri being downloaded or removed. */
|
||||||
|
public final Uri uri;
|
||||||
/** Whether this is a remove action. If false, this is a download action. */
|
/** Whether this is a remove action. If false, this is a download action. */
|
||||||
public final boolean isRemoveAction;
|
public final boolean isRemoveAction;
|
||||||
/** Custom data for this action. May be the empty string if no custom data was specified. */
|
/** Custom data for this action, or the empty string if no custom data was specified. */
|
||||||
public final String data;
|
public final String data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param type The type of the action.
|
* @param type The type of the action.
|
||||||
* @param version The action version.
|
* @param version The action version.
|
||||||
|
* @param uri The uri being downloaded or removed.
|
||||||
* @param isRemoveAction Whether this is a remove action. If false, this is a download action.
|
* @param isRemoveAction Whether this is a remove action. If false, this is a download action.
|
||||||
* @param data Optional custom data for this action. If null, an empty string is used.
|
* @param data Optional custom data for this action.
|
||||||
*/
|
*/
|
||||||
protected DownloadAction(
|
protected DownloadAction(
|
||||||
String type, int version, boolean isRemoveAction, @Nullable String data) {
|
String type, int version, Uri uri, boolean isRemoveAction, @Nullable String data) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.version = version;
|
this.version = version;
|
||||||
|
this.uri = uri;
|
||||||
this.isRemoveAction = isRemoveAction;
|
this.isRemoveAction = isRemoveAction;
|
||||||
this.data = data != null ? data : "";
|
this.data = data != null ? data : "";
|
||||||
}
|
}
|
||||||
@ -121,12 +126,14 @@ public abstract class DownloadAction {
|
|||||||
return output.toByteArray();
|
return output.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns whether this is an action for the same media as the {@code other}. */
|
||||||
|
public boolean isSameMedia(DownloadAction other) {
|
||||||
|
return uri.equals(other.uri);
|
||||||
|
}
|
||||||
|
|
||||||
/** Serializes itself into the {@code output}. */
|
/** Serializes itself into the {@code output}. */
|
||||||
protected abstract void writeToStream(DataOutputStream output) throws IOException;
|
protected abstract void writeToStream(DataOutputStream output) throws IOException;
|
||||||
|
|
||||||
/** Returns whether this is an action for the same media as the {@code other}. */
|
|
||||||
protected abstract boolean isSameMedia(DownloadAction other);
|
|
||||||
|
|
||||||
/** Creates a {@link Downloader} with the given parameters. */
|
/** Creates a {@link Downloader} with the given parameters. */
|
||||||
protected abstract Downloader createDownloader(
|
protected abstract Downloader createDownloader(
|
||||||
DownloaderConstructorHelper downloaderConstructorHelper);
|
DownloaderConstructorHelper downloaderConstructorHelper);
|
||||||
@ -137,13 +144,18 @@ public abstract class DownloadAction {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
DownloadAction that = (DownloadAction) o;
|
DownloadAction that = (DownloadAction) o;
|
||||||
return data.equals(that.data) && isRemoveAction == that.isRemoveAction;
|
return type.equals(that.type)
|
||||||
|
&& version == that.version
|
||||||
|
&& uri.equals(that.uri)
|
||||||
|
&& isRemoveAction == that.isRemoveAction
|
||||||
|
&& data.equals(that.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result = data.hashCode();
|
int result = uri.hashCode();
|
||||||
result = 31 * result + (isRemoveAction ? 1 : 0);
|
result = 31 * result + (isRemoveAction ? 1 : 0);
|
||||||
|
result = 31 * result + data.hashCode();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,6 @@ package com.google.android.exoplayer2.offline;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.upstream.cache.CacheUtil;
|
import com.google.android.exoplayer2.upstream.cache.CacheUtil;
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
@ -27,7 +26,7 @@ import java.io.IOException;
|
|||||||
/** An action to download or remove downloaded progressive streams. */
|
/** An action to download or remove downloaded progressive streams. */
|
||||||
public final class ProgressiveDownloadAction extends DownloadAction {
|
public final class ProgressiveDownloadAction extends DownloadAction {
|
||||||
|
|
||||||
private static final String TYPE = "ProgressiveDownloadAction";
|
private static final String TYPE = "progressive";
|
||||||
private static final int VERSION = 0;
|
private static final int VERSION = 0;
|
||||||
|
|
||||||
public static final Deserializer DESERIALIZER =
|
public static final Deserializer DESERIALIZER =
|
||||||
@ -35,28 +34,26 @@ public final class ProgressiveDownloadAction extends DownloadAction {
|
|||||||
@Override
|
@Override
|
||||||
public ProgressiveDownloadAction readFromStream(int version, DataInputStream input)
|
public ProgressiveDownloadAction readFromStream(int version, DataInputStream input)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
Uri uri = Uri.parse(input.readUTF());
|
||||||
boolean isRemoveAction = input.readBoolean();
|
boolean isRemoveAction = input.readBoolean();
|
||||||
String data = input.readUTF();
|
String data = input.readUTF();
|
||||||
Uri uri = Uri.parse(input.readUTF());
|
|
||||||
String customCacheKey = input.readBoolean() ? input.readUTF() : null;
|
String customCacheKey = input.readBoolean() ? input.readUTF() : null;
|
||||||
return new ProgressiveDownloadAction(isRemoveAction, data, uri, customCacheKey);
|
return new ProgressiveDownloadAction(uri, isRemoveAction, data, customCacheKey);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private final Uri uri;
|
public final @Nullable String customCacheKey;
|
||||||
private final @Nullable String customCacheKey;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param uri Uri of the data to be downloaded.
|
||||||
* @param isRemoveAction Whether this is a remove action. If false, this is a download action.
|
* @param isRemoveAction Whether this is a remove action. If false, this is a download action.
|
||||||
* @param data Optional custom data for this action. If null, an empty string is used.
|
* @param data Optional custom data for this action. If null, an empty string is used.
|
||||||
* @param uri Uri of the data to be downloaded.
|
|
||||||
* @param customCacheKey A custom key that uniquely identifies the original stream. If not null it
|
* @param customCacheKey A custom key that uniquely identifies the original stream. If not null it
|
||||||
* is used for cache indexing.
|
* is used for cache indexing.
|
||||||
*/
|
*/
|
||||||
public ProgressiveDownloadAction(
|
public ProgressiveDownloadAction(
|
||||||
boolean isRemoveAction, @Nullable String data, Uri uri, @Nullable String customCacheKey) {
|
Uri uri, boolean isRemoveAction, @Nullable String data, @Nullable String customCacheKey) {
|
||||||
super(TYPE, VERSION, isRemoveAction, data);
|
super(TYPE, VERSION, uri, isRemoveAction, data);
|
||||||
this.uri = Assertions.checkNotNull(uri);
|
|
||||||
this.customCacheKey = customCacheKey;
|
this.customCacheKey = customCacheKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,9 +64,9 @@ public final class ProgressiveDownloadAction extends DownloadAction {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void writeToStream(DataOutputStream output) throws IOException {
|
protected void writeToStream(DataOutputStream output) throws IOException {
|
||||||
|
output.writeUTF(uri.toString());
|
||||||
output.writeBoolean(isRemoveAction);
|
output.writeBoolean(isRemoveAction);
|
||||||
output.writeUTF(data);
|
output.writeUTF(data);
|
||||||
output.writeUTF(uri.toString());
|
|
||||||
boolean customCacheKeySet = customCacheKey != null;
|
boolean customCacheKeySet = customCacheKey != null;
|
||||||
output.writeBoolean(customCacheKeySet);
|
output.writeBoolean(customCacheKeySet);
|
||||||
if (customCacheKeySet) {
|
if (customCacheKeySet) {
|
||||||
@ -78,11 +75,9 @@ public final class ProgressiveDownloadAction extends DownloadAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isSameMedia(DownloadAction other) {
|
public boolean isSameMedia(DownloadAction other) {
|
||||||
if (!(other instanceof ProgressiveDownloadAction)) {
|
return ((other instanceof ProgressiveDownloadAction)
|
||||||
return false;
|
&& getCacheKey().equals(((ProgressiveDownloadAction) other).getCacheKey()));
|
||||||
}
|
|
||||||
return getCacheKey().equals(((ProgressiveDownloadAction) other).getCacheKey());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -94,13 +89,12 @@ public final class ProgressiveDownloadAction extends DownloadAction {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ProgressiveDownloadAction that = (ProgressiveDownloadAction) o;
|
ProgressiveDownloadAction that = (ProgressiveDownloadAction) o;
|
||||||
return uri.equals(that.uri) && Util.areEqual(customCacheKey, that.customCacheKey);
|
return Util.areEqual(customCacheKey, that.customCacheKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result = super.hashCode();
|
int result = super.hashCode();
|
||||||
result = 31 * result + uri.hashCode();
|
|
||||||
result = 31 * result + (customCacheKey != null ? customCacheKey.hashCode() : 0);
|
result = 31 * result + (customCacheKey != null ? customCacheKey.hashCode() : 0);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -21,14 +21,16 @@ import com.google.android.exoplayer2.util.Assertions;
|
|||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link DownloadAction} for {@link SegmentDownloader}s.
|
* {@link DownloadAction} for {@link SegmentDownloader}s.
|
||||||
*
|
*
|
||||||
* @param <K> The type of the representation key object.
|
* @param <K> The type of the representation key object.
|
||||||
*/
|
*/
|
||||||
public abstract class SegmentDownloadAction<K extends Comparable> extends DownloadAction {
|
public abstract class SegmentDownloadAction<K extends Comparable<K>> extends DownloadAction {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for {@link SegmentDownloadAction} {@link Deserializer}s.
|
* Base class for {@link SegmentDownloadAction} {@link Deserializer}s.
|
||||||
@ -44,78 +46,68 @@ public abstract class SegmentDownloadAction<K extends Comparable> extends Downlo
|
|||||||
@Override
|
@Override
|
||||||
public final DownloadAction readFromStream(int version, DataInputStream input)
|
public final DownloadAction readFromStream(int version, DataInputStream input)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
Uri uri = Uri.parse(input.readUTF());
|
||||||
boolean isRemoveAction = input.readBoolean();
|
boolean isRemoveAction = input.readBoolean();
|
||||||
String data = input.readUTF();
|
String data = input.readUTF();
|
||||||
Uri manifestUri = Uri.parse(input.readUTF());
|
|
||||||
int keyCount = input.readInt();
|
int keyCount = input.readInt();
|
||||||
K[] keys = createKeyArray(keyCount);
|
List<K> keys = new ArrayList<>();
|
||||||
for (int i = 0; i < keyCount; i++) {
|
for (int i = 0; i < keyCount; i++) {
|
||||||
keys[i] = readKey(input);
|
keys.add(readKey(input));
|
||||||
}
|
}
|
||||||
return createDownloadAction(isRemoveAction, data, manifestUri, keys);
|
return createDownloadAction(uri, isRemoveAction, data, keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Deserializes a key from the {@code input}. */
|
/** Deserializes a key from the {@code input}. */
|
||||||
protected abstract K readKey(DataInputStream input) throws IOException;
|
protected abstract K readKey(DataInputStream input) throws IOException;
|
||||||
|
|
||||||
/** Returns a key array. */
|
|
||||||
protected abstract K[] createKeyArray(int keyCount);
|
|
||||||
|
|
||||||
/** Returns a {@link DownloadAction}. */
|
/** Returns a {@link DownloadAction}. */
|
||||||
protected abstract DownloadAction createDownloadAction(
|
protected abstract DownloadAction createDownloadAction(
|
||||||
boolean isRemoveAction, String data, Uri manifestUri, K[] keys);
|
Uri manifestUri, boolean isRemoveAction, String data, List<K> keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final Uri manifestUri;
|
public final List<K> keys;
|
||||||
protected final K[] keys;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param type The type of the action.
|
* @param type The type of the action.
|
||||||
* @param version The action version.
|
* @param version The action version.
|
||||||
|
* @param uri The URI of the media being downloaded.
|
||||||
* @param isRemoveAction Whether the data will be removed. If {@code false} it will be downloaded.
|
* @param isRemoveAction Whether the data will be removed. If {@code false} it will be downloaded.
|
||||||
* @param data Optional custom data for this action. If null, an empty string is used.
|
* @param data Optional custom data for this action.
|
||||||
* @param manifestUri The {@link Uri} of the manifest to be downloaded.
|
* @param keys Keys of tracks to be downloaded. If empty, all tracks will be downloaded. If {@code
|
||||||
* @param keys Keys of representations to be downloaded. If empty, all representations are
|
* removeAction} is true, {@code keys} must be empty.
|
||||||
* downloaded. If {@code removeAction} is true, {@code keys} must be an empty array.
|
|
||||||
*/
|
*/
|
||||||
protected SegmentDownloadAction(
|
protected SegmentDownloadAction(
|
||||||
String type,
|
String type,
|
||||||
int version,
|
int version,
|
||||||
|
Uri uri,
|
||||||
boolean isRemoveAction,
|
boolean isRemoveAction,
|
||||||
@Nullable String data,
|
@Nullable String data,
|
||||||
Uri manifestUri,
|
List<K> keys) {
|
||||||
K[] keys) {
|
super(type, version, uri, isRemoveAction, data);
|
||||||
super(type, version, isRemoveAction, data);
|
|
||||||
this.manifestUri = manifestUri;
|
|
||||||
if (isRemoveAction) {
|
if (isRemoveAction) {
|
||||||
Assertions.checkArgument(keys.length == 0);
|
Assertions.checkArgument(keys.isEmpty());
|
||||||
this.keys = keys;
|
this.keys = Collections.emptyList();
|
||||||
} else {
|
} else {
|
||||||
this.keys = keys.clone();
|
ArrayList<K> mutableKeys = new ArrayList<>(keys);
|
||||||
Arrays.sort(this.keys);
|
Collections.sort(mutableKeys);
|
||||||
|
this.keys = Collections.unmodifiableList(mutableKeys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void writeToStream(DataOutputStream output) throws IOException {
|
public final void writeToStream(DataOutputStream output) throws IOException {
|
||||||
|
output.writeUTF(uri.toString());
|
||||||
output.writeBoolean(isRemoveAction);
|
output.writeBoolean(isRemoveAction);
|
||||||
output.writeUTF(data);
|
output.writeUTF(data);
|
||||||
output.writeUTF(manifestUri.toString());
|
output.writeInt(keys.size());
|
||||||
output.writeInt(keys.length);
|
for (int i = 0; i < keys.size(); i++) {
|
||||||
for (K key : keys) {
|
writeKey(output, keys.get(i));
|
||||||
writeKey(output, key);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Serializes the {@code key} into the {@code output}. */
|
/** Serializes the {@code key} into the {@code output}. */
|
||||||
protected abstract void writeKey(DataOutputStream output, K key) throws IOException;
|
protected abstract void writeKey(DataOutputStream output, K key) throws IOException;
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSameMedia(DownloadAction other) {
|
|
||||||
return other instanceof SegmentDownloadAction
|
|
||||||
&& manifestUri.equals(((SegmentDownloadAction<?>) other).manifestUri);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) {
|
if (this == o) {
|
||||||
@ -125,14 +117,13 @@ public abstract class SegmentDownloadAction<K extends Comparable> extends Downlo
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
SegmentDownloadAction<?> that = (SegmentDownloadAction<?>) o;
|
SegmentDownloadAction<?> that = (SegmentDownloadAction<?>) o;
|
||||||
return manifestUri.equals(that.manifestUri) && Arrays.equals(keys, that.keys);
|
return keys.equals(that.keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result = super.hashCode();
|
int result = super.hashCode();
|
||||||
result = 31 * result + manifestUri.hashCode();
|
result = 31 * result + keys.hashCode();
|
||||||
result = 31 * result + Arrays.hashCode(keys);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@ package com.google.android.exoplayer2.offline;
|
|||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.upstream.DataSource;
|
import com.google.android.exoplayer2.upstream.DataSource;
|
||||||
import com.google.android.exoplayer2.upstream.DataSpec;
|
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||||
@ -77,20 +76,16 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M, K>, K>
|
|||||||
/**
|
/**
|
||||||
* @param manifestUri The {@link Uri} of the manifest to be downloaded.
|
* @param manifestUri The {@link Uri} of the manifest to be downloaded.
|
||||||
* @param constructorHelper a {@link DownloaderConstructorHelper} instance.
|
* @param constructorHelper a {@link DownloaderConstructorHelper} instance.
|
||||||
* @param trackKeys Track keys to select when downloading. If null or empty, all tracks are
|
* @param trackKeys Track keys to select when downloading. If empty, all tracks are downloaded.
|
||||||
* downloaded.
|
|
||||||
*/
|
*/
|
||||||
public SegmentDownloader(
|
public SegmentDownloader(
|
||||||
Uri manifestUri, DownloaderConstructorHelper constructorHelper, @Nullable K[] trackKeys) {
|
Uri manifestUri, DownloaderConstructorHelper constructorHelper, List<K> trackKeys) {
|
||||||
this.manifestUri = manifestUri;
|
this.manifestUri = manifestUri;
|
||||||
this.cache = constructorHelper.getCache();
|
this.cache = constructorHelper.getCache();
|
||||||
this.dataSource = constructorHelper.buildCacheDataSource(false);
|
this.dataSource = constructorHelper.buildCacheDataSource(false);
|
||||||
this.offlineDataSource = constructorHelper.buildCacheDataSource(true);
|
this.offlineDataSource = constructorHelper.buildCacheDataSource(true);
|
||||||
this.priorityTaskManager = constructorHelper.getPriorityTaskManager();
|
this.priorityTaskManager = constructorHelper.getPriorityTaskManager();
|
||||||
keys = new ArrayList<>();
|
keys = new ArrayList<>(trackKeys);
|
||||||
if (trackKeys != null) {
|
|
||||||
Collections.addAll(this.keys, trackKeys);
|
|
||||||
}
|
|
||||||
totalSegments = C.LENGTH_UNSET;
|
totalSegments = C.LENGTH_UNSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ package com.google.android.exoplayer2.offline;
|
|||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import android.net.Uri;
|
||||||
import com.google.android.exoplayer2.offline.DownloadAction.Deserializer;
|
import com.google.android.exoplayer2.offline.DownloadAction.Deserializer;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
@ -236,7 +237,7 @@ public class ActionFileTest {
|
|||||||
public static final int VERSION = 0;
|
public static final int VERSION = 0;
|
||||||
|
|
||||||
private FakeDownloadAction(String type, String data) {
|
private FakeDownloadAction(String type, String data) {
|
||||||
super(type, VERSION, /* isRemoveAction= */ false, data);
|
super(type, VERSION, Uri.parse("http://test.com"), /* isRemoveAction= */ false, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -244,37 +245,11 @@ public class ActionFileTest {
|
|||||||
output.writeUTF(data);
|
output.writeUTF(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isSameMedia(DownloadAction other) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Downloader createDownloader(DownloaderConstructorHelper downloaderConstructorHelper) {
|
protected Downloader createDownloader(DownloaderConstructorHelper downloaderConstructorHelper) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// auto generated code
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (o == null || getClass() != o.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
FakeDownloadAction that = (FakeDownloadAction) o;
|
|
||||||
return version == that.version && data.equals(that.data) && type.equals(that.type);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int result = type.hashCode();
|
|
||||||
result = 31 * result + version;
|
|
||||||
result = 31 * result + data.hashCode();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,8 @@ package com.google.android.exoplayer2.offline;
|
|||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.ConditionVariable;
|
import android.os.ConditionVariable;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.offline.DownloadManager.DownloadListener;
|
import com.google.android.exoplayer2.offline.DownloadManager.DownloadListener;
|
||||||
import com.google.android.exoplayer2.offline.DownloadManager.TaskState;
|
import com.google.android.exoplayer2.offline.DownloadManager.TaskState;
|
||||||
@ -62,14 +62,20 @@ public class DownloadManagerTest {
|
|||||||
|
|
||||||
private static final int MIN_RETRY_COUNT = 3;
|
private static final int MIN_RETRY_COUNT = 3;
|
||||||
|
|
||||||
private DownloadManager downloadManager;
|
private Uri uri1;
|
||||||
|
private Uri uri2;
|
||||||
|
private Uri uri3;
|
||||||
|
private DummyMainThread dummyMainThread;
|
||||||
private File actionFile;
|
private File actionFile;
|
||||||
private TestDownloadListener testDownloadListener;
|
private TestDownloadListener testDownloadListener;
|
||||||
private DummyMainThread dummyMainThread;
|
private DownloadManager downloadManager;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
|
uri1 = Uri.parse("http://abc.com/media1");
|
||||||
|
uri2 = Uri.parse("http://abc.com/media2");
|
||||||
|
uri3 = Uri.parse("http://abc.com/media3");
|
||||||
dummyMainThread = new DummyMainThread();
|
dummyMainThread = new DummyMainThread();
|
||||||
actionFile = Util.createTempFile(RuntimeEnvironment.application, "ExoPlayerTest");
|
actionFile = Util.createTempFile(RuntimeEnvironment.application, "ExoPlayerTest");
|
||||||
testDownloadListener = new TestDownloadListener();
|
testDownloadListener = new TestDownloadListener();
|
||||||
@ -85,17 +91,17 @@ public class DownloadManagerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDownloadActionRuns() throws Throwable {
|
public void testDownloadActionRuns() throws Throwable {
|
||||||
doTestActionRuns(createDownloadAction("media 1"));
|
doTestActionRuns(createDownloadAction(uri1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveActionRuns() throws Throwable {
|
public void testRemoveActionRuns() throws Throwable {
|
||||||
doTestActionRuns(createRemoveAction("media 1"));
|
doTestActionRuns(createRemoveAction(uri1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDownloadRetriesThenFails() throws Throwable {
|
public void testDownloadRetriesThenFails() throws Throwable {
|
||||||
FakeDownloadAction downloadAction = createDownloadAction("media 1");
|
FakeDownloadAction downloadAction = createDownloadAction(uri1);
|
||||||
downloadAction.post();
|
downloadAction.post();
|
||||||
FakeDownloader fakeDownloader = downloadAction.getFakeDownloader();
|
FakeDownloader fakeDownloader = downloadAction.getFakeDownloader();
|
||||||
fakeDownloader.enableDownloadIOException = true;
|
fakeDownloader.enableDownloadIOException = true;
|
||||||
@ -110,11 +116,11 @@ public class DownloadManagerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDownloadNoRetryWhenCanceled() throws Throwable {
|
public void testDownloadNoRetryWhenCanceled() throws Throwable {
|
||||||
FakeDownloadAction downloadAction = createDownloadAction("media 1").ignoreInterrupts();
|
FakeDownloadAction downloadAction = createDownloadAction(uri1).ignoreInterrupts();
|
||||||
downloadAction.getFakeDownloader().enableDownloadIOException = true;
|
downloadAction.getFakeDownloader().enableDownloadIOException = true;
|
||||||
downloadAction.post().assertStarted();
|
downloadAction.post().assertStarted();
|
||||||
|
|
||||||
FakeDownloadAction removeAction = createRemoveAction("media 1").post();
|
FakeDownloadAction removeAction = createRemoveAction(uri1).post();
|
||||||
|
|
||||||
downloadAction.unblock().assertCanceled();
|
downloadAction.unblock().assertCanceled();
|
||||||
removeAction.unblock();
|
removeAction.unblock();
|
||||||
@ -124,7 +130,7 @@ public class DownloadManagerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDownloadRetriesThenContinues() throws Throwable {
|
public void testDownloadRetriesThenContinues() throws Throwable {
|
||||||
FakeDownloadAction downloadAction = createDownloadAction("media 1");
|
FakeDownloadAction downloadAction = createDownloadAction(uri1);
|
||||||
downloadAction.post();
|
downloadAction.post();
|
||||||
FakeDownloader fakeDownloader = downloadAction.getFakeDownloader();
|
FakeDownloader fakeDownloader = downloadAction.getFakeDownloader();
|
||||||
fakeDownloader.enableDownloadIOException = true;
|
fakeDownloader.enableDownloadIOException = true;
|
||||||
@ -143,7 +149,7 @@ public class DownloadManagerTest {
|
|||||||
@Test
|
@Test
|
||||||
@SuppressWarnings({"NonAtomicVolatileUpdate", "NonAtomicOperationOnVolatileField"})
|
@SuppressWarnings({"NonAtomicVolatileUpdate", "NonAtomicOperationOnVolatileField"})
|
||||||
public void testDownloadRetryCountResetsOnProgress() throws Throwable {
|
public void testDownloadRetryCountResetsOnProgress() throws Throwable {
|
||||||
FakeDownloadAction downloadAction = createDownloadAction("media 1");
|
FakeDownloadAction downloadAction = createDownloadAction(uri1);
|
||||||
downloadAction.post();
|
downloadAction.post();
|
||||||
FakeDownloader fakeDownloader = downloadAction.getFakeDownloader();
|
FakeDownloader fakeDownloader = downloadAction.getFakeDownloader();
|
||||||
fakeDownloader.enableDownloadIOException = true;
|
fakeDownloader.enableDownloadIOException = true;
|
||||||
@ -163,41 +169,41 @@ public class DownloadManagerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDifferentMediaDownloadActionsStartInParallel() throws Throwable {
|
public void testDifferentMediaDownloadActionsStartInParallel() throws Throwable {
|
||||||
doTestActionsRunInParallel(createDownloadAction("media 1"), createDownloadAction("media 2"));
|
doTestActionsRunInParallel(createDownloadAction(uri1), createDownloadAction(uri2));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDifferentMediaDifferentActionsStartInParallel() throws Throwable {
|
public void testDifferentMediaDifferentActionsStartInParallel() throws Throwable {
|
||||||
doTestActionsRunInParallel(createDownloadAction("media 1"), createRemoveAction("media 2"));
|
doTestActionsRunInParallel(createDownloadAction(uri1), createRemoveAction(uri2));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSameMediaDownloadActionsStartInParallel() throws Throwable {
|
public void testSameMediaDownloadActionsStartInParallel() throws Throwable {
|
||||||
doTestActionsRunInParallel(createDownloadAction("media 1"), createDownloadAction("media 1"));
|
doTestActionsRunInParallel(createDownloadAction(uri1), createDownloadAction(uri1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSameMediaRemoveActionWaitsDownloadAction() throws Throwable {
|
public void testSameMediaRemoveActionWaitsDownloadAction() throws Throwable {
|
||||||
doTestActionsRunSequentially(createDownloadAction("media 1"), createRemoveAction("media 1"));
|
doTestActionsRunSequentially(createDownloadAction(uri1), createRemoveAction(uri1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSameMediaDownloadActionWaitsRemoveAction() throws Throwable {
|
public void testSameMediaDownloadActionWaitsRemoveAction() throws Throwable {
|
||||||
doTestActionsRunSequentially(createRemoveAction("media 1"), createDownloadAction("media 1"));
|
doTestActionsRunSequentially(createRemoveAction(uri1), createDownloadAction(uri1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSameMediaRemoveActionWaitsRemoveAction() throws Throwable {
|
public void testSameMediaRemoveActionWaitsRemoveAction() throws Throwable {
|
||||||
doTestActionsRunSequentially(createRemoveAction("media 1"), createRemoveAction("media 1"));
|
doTestActionsRunSequentially(createRemoveAction(uri1), createRemoveAction(uri1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSameMediaMultipleActions() throws Throwable {
|
public void testSameMediaMultipleActions() throws Throwable {
|
||||||
FakeDownloadAction downloadAction1 = createDownloadAction("media 1").ignoreInterrupts();
|
FakeDownloadAction downloadAction1 = createDownloadAction(uri1).ignoreInterrupts();
|
||||||
FakeDownloadAction downloadAction2 = createDownloadAction("media 1").ignoreInterrupts();
|
FakeDownloadAction downloadAction2 = createDownloadAction(uri1).ignoreInterrupts();
|
||||||
FakeDownloadAction removeAction1 = createRemoveAction("media 1");
|
FakeDownloadAction removeAction1 = createRemoveAction(uri1);
|
||||||
FakeDownloadAction downloadAction3 = createDownloadAction("media 1");
|
FakeDownloadAction downloadAction3 = createDownloadAction(uri1);
|
||||||
FakeDownloadAction removeAction2 = createRemoveAction("media 1");
|
FakeDownloadAction removeAction2 = createRemoveAction(uri1);
|
||||||
|
|
||||||
// Two download actions run in parallel.
|
// Two download actions run in parallel.
|
||||||
downloadAction1.post().assertStarted();
|
downloadAction1.post().assertStarted();
|
||||||
@ -229,9 +235,9 @@ public class DownloadManagerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMultipleRemoveActionWaitsLastCancelsAllOther() throws Throwable {
|
public void testMultipleRemoveActionWaitsLastCancelsAllOther() throws Throwable {
|
||||||
FakeDownloadAction removeAction1 = createRemoveAction("media 1").ignoreInterrupts();
|
FakeDownloadAction removeAction1 = createRemoveAction(uri1).ignoreInterrupts();
|
||||||
FakeDownloadAction removeAction2 = createRemoveAction("media 1");
|
FakeDownloadAction removeAction2 = createRemoveAction(uri1);
|
||||||
FakeDownloadAction removeAction3 = createRemoveAction("media 1");
|
FakeDownloadAction removeAction3 = createRemoveAction(uri1);
|
||||||
|
|
||||||
removeAction1.post().assertStarted();
|
removeAction1.post().assertStarted();
|
||||||
removeAction2.post().assertDoesNotStart();
|
removeAction2.post().assertDoesNotStart();
|
||||||
@ -247,9 +253,9 @@ public class DownloadManagerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetTasks() throws Throwable {
|
public void testGetTasks() throws Throwable {
|
||||||
FakeDownloadAction removeAction = createRemoveAction("media 1");
|
FakeDownloadAction removeAction = createRemoveAction(uri1);
|
||||||
FakeDownloadAction downloadAction1 = createDownloadAction("media 1");
|
FakeDownloadAction downloadAction1 = createDownloadAction(uri1);
|
||||||
FakeDownloadAction downloadAction2 = createDownloadAction("media 1");
|
FakeDownloadAction downloadAction2 = createDownloadAction(uri1);
|
||||||
|
|
||||||
removeAction.post().assertStarted();
|
removeAction.post().assertStarted();
|
||||||
downloadAction1.post().assertDoesNotStart();
|
downloadAction1.post().assertDoesNotStart();
|
||||||
@ -264,9 +270,9 @@ public class DownloadManagerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMultipleWaitingDownloadActionStartsInParallel() throws Throwable {
|
public void testMultipleWaitingDownloadActionStartsInParallel() throws Throwable {
|
||||||
FakeDownloadAction removeAction = createRemoveAction("media 1");
|
FakeDownloadAction removeAction = createRemoveAction(uri1);
|
||||||
FakeDownloadAction downloadAction1 = createDownloadAction("media 1");
|
FakeDownloadAction downloadAction1 = createDownloadAction(uri1);
|
||||||
FakeDownloadAction downloadAction2 = createDownloadAction("media 1");
|
FakeDownloadAction downloadAction2 = createDownloadAction(uri1);
|
||||||
|
|
||||||
removeAction.post().assertStarted();
|
removeAction.post().assertStarted();
|
||||||
downloadAction1.post().assertDoesNotStart();
|
downloadAction1.post().assertDoesNotStart();
|
||||||
@ -283,9 +289,9 @@ public class DownloadManagerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDifferentMediaDownloadActionsPreserveOrder() throws Throwable {
|
public void testDifferentMediaDownloadActionsPreserveOrder() throws Throwable {
|
||||||
FakeDownloadAction removeAction = createRemoveAction("media 1").ignoreInterrupts();
|
FakeDownloadAction removeAction = createRemoveAction(uri1).ignoreInterrupts();
|
||||||
FakeDownloadAction downloadAction1 = createDownloadAction("media 1");
|
FakeDownloadAction downloadAction1 = createDownloadAction(uri1);
|
||||||
FakeDownloadAction downloadAction2 = createDownloadAction("media 2");
|
FakeDownloadAction downloadAction2 = createDownloadAction(uri2);
|
||||||
|
|
||||||
removeAction.post().assertStarted();
|
removeAction.post().assertStarted();
|
||||||
downloadAction1.post().assertDoesNotStart();
|
downloadAction1.post().assertDoesNotStart();
|
||||||
@ -302,9 +308,9 @@ public class DownloadManagerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDifferentMediaRemoveActionsDoNotPreserveOrder() throws Throwable {
|
public void testDifferentMediaRemoveActionsDoNotPreserveOrder() throws Throwable {
|
||||||
FakeDownloadAction downloadAction = createDownloadAction("media 1").ignoreInterrupts();
|
FakeDownloadAction downloadAction = createDownloadAction(uri1).ignoreInterrupts();
|
||||||
FakeDownloadAction removeAction1 = createRemoveAction("media 1");
|
FakeDownloadAction removeAction1 = createRemoveAction(uri1);
|
||||||
FakeDownloadAction removeAction2 = createRemoveAction("media 2");
|
FakeDownloadAction removeAction2 = createRemoveAction(uri2);
|
||||||
|
|
||||||
downloadAction.post().assertStarted();
|
downloadAction.post().assertStarted();
|
||||||
removeAction1.post().assertDoesNotStart();
|
removeAction1.post().assertDoesNotStart();
|
||||||
@ -321,11 +327,11 @@ public class DownloadManagerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStopAndResume() throws Throwable {
|
public void testStopAndResume() throws Throwable {
|
||||||
FakeDownloadAction download1Action = createDownloadAction("media 1");
|
FakeDownloadAction download1Action = createDownloadAction(uri1);
|
||||||
FakeDownloadAction remove2Action = createRemoveAction("media 2");
|
FakeDownloadAction remove2Action = createRemoveAction(uri2);
|
||||||
FakeDownloadAction download2Action = createDownloadAction("media 2");
|
FakeDownloadAction download2Action = createDownloadAction(uri2);
|
||||||
FakeDownloadAction remove1Action = createRemoveAction("media 1");
|
FakeDownloadAction remove1Action = createRemoveAction(uri1);
|
||||||
FakeDownloadAction download3Action = createDownloadAction("media 3");
|
FakeDownloadAction download3Action = createDownloadAction(uri3);
|
||||||
|
|
||||||
download1Action.post().assertStarted();
|
download1Action.post().assertStarted();
|
||||||
remove2Action.post().assertStarted();
|
remove2Action.post().assertStarted();
|
||||||
@ -371,9 +377,9 @@ public class DownloadManagerTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testResumeBeforeTotallyStopped() throws Throwable {
|
public void testResumeBeforeTotallyStopped() throws Throwable {
|
||||||
setUpDownloadManager(2);
|
setUpDownloadManager(2);
|
||||||
FakeDownloadAction download1Action = createDownloadAction("media 1").ignoreInterrupts();
|
FakeDownloadAction download1Action = createDownloadAction(uri1).ignoreInterrupts();
|
||||||
FakeDownloadAction download2Action = createDownloadAction("media 2");
|
FakeDownloadAction download2Action = createDownloadAction(uri2);
|
||||||
FakeDownloadAction download3Action = createDownloadAction("media 3");
|
FakeDownloadAction download3Action = createDownloadAction(uri3);
|
||||||
|
|
||||||
download1Action.post().assertStarted();
|
download1Action.post().assertStarted();
|
||||||
download2Action.post().assertStarted();
|
download2Action.post().assertStarted();
|
||||||
@ -481,12 +487,12 @@ public class DownloadManagerTest {
|
|||||||
testDownloadListener.blockUntilTasksCompleteAndThrowAnyDownloadError();
|
testDownloadListener.blockUntilTasksCompleteAndThrowAnyDownloadError();
|
||||||
}
|
}
|
||||||
|
|
||||||
private FakeDownloadAction createDownloadAction(String mediaId) {
|
private FakeDownloadAction createDownloadAction(Uri uri) {
|
||||||
return new FakeDownloadAction(/* isRemoveAction= */ false, mediaId);
|
return new FakeDownloadAction(uri, /* isRemoveAction= */ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private FakeDownloadAction createRemoveAction(String mediaId) {
|
private FakeDownloadAction createRemoveAction(Uri uri) {
|
||||||
return new FakeDownloadAction(/* isRemoveAction= */ true, mediaId);
|
return new FakeDownloadAction(uri, /* isRemoveAction= */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void runOnMainThread(final Runnable r) throws Throwable {
|
private void runOnMainThread(final Runnable r) throws Throwable {
|
||||||
@ -530,28 +536,20 @@ public class DownloadManagerTest {
|
|||||||
|
|
||||||
private class FakeDownloadAction extends DownloadAction {
|
private class FakeDownloadAction extends DownloadAction {
|
||||||
|
|
||||||
private final String mediaId;
|
|
||||||
private final FakeDownloader downloader;
|
private final FakeDownloader downloader;
|
||||||
private final BlockingQueue<Integer> states;
|
private final BlockingQueue<Integer> states;
|
||||||
|
|
||||||
private FakeDownloadAction(boolean isRemoveAction, @Nullable String mediaId) {
|
private FakeDownloadAction(Uri uri, boolean isRemoveAction) {
|
||||||
super("FakeDownloadAction", /* version= */ 0, isRemoveAction, mediaId);
|
super("Fake", /* version= */ 0, uri, isRemoveAction, /* data= */ null);
|
||||||
this.mediaId = mediaId;
|
|
||||||
this.downloader = new FakeDownloader(isRemoveAction);
|
this.downloader = new FakeDownloader(isRemoveAction);
|
||||||
this.states = new ArrayBlockingQueue<>(10);
|
this.states = new ArrayBlockingQueue<>(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void writeToStream(DataOutputStream output) throws IOException {
|
protected void writeToStream(DataOutputStream output) {
|
||||||
// do nothing.
|
// do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isSameMedia(DownloadAction other) {
|
|
||||||
return other instanceof FakeDownloadAction
|
|
||||||
&& mediaId.equals(((FakeDownloadAction) other).mediaId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Downloader createDownloader(DownloaderConstructorHelper downloaderConstructorHelper) {
|
protected Downloader createDownloader(DownloaderConstructorHelper downloaderConstructorHelper) {
|
||||||
return downloader;
|
return downloader;
|
||||||
|
@ -49,20 +49,20 @@ public class ProgressiveDownloadActionTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDownloadActionIsNotRemoveAction() throws Exception {
|
public void testDownloadActionIsNotRemoveAction() throws Exception {
|
||||||
ProgressiveDownloadAction action = new ProgressiveDownloadAction(false, null, uri1, null);
|
ProgressiveDownloadAction action = new ProgressiveDownloadAction(uri1, false, null, null);
|
||||||
assertThat(action.isRemoveAction).isFalse();
|
assertThat(action.isRemoveAction).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveActionisRemoveAction() throws Exception {
|
public void testRemoveActionisRemoveAction() throws Exception {
|
||||||
ProgressiveDownloadAction action2 = new ProgressiveDownloadAction(true, null, uri1, null);
|
ProgressiveDownloadAction action2 = new ProgressiveDownloadAction(uri1, true, null, null);
|
||||||
assertThat(action2.isRemoveAction).isTrue();
|
assertThat(action2.isRemoveAction).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateDownloader() throws Exception {
|
public void testCreateDownloader() throws Exception {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
ProgressiveDownloadAction action = new ProgressiveDownloadAction(false, null, uri1, null);
|
ProgressiveDownloadAction action = new ProgressiveDownloadAction(uri1, false, null, null);
|
||||||
DownloaderConstructorHelper constructorHelper = new DownloaderConstructorHelper(
|
DownloaderConstructorHelper constructorHelper = new DownloaderConstructorHelper(
|
||||||
Mockito.mock(Cache.class), DummyDataSource.FACTORY);
|
Mockito.mock(Cache.class), DummyDataSource.FACTORY);
|
||||||
assertThat(action.createDownloader(constructorHelper)).isNotNull();
|
assertThat(action.createDownloader(constructorHelper)).isNotNull();
|
||||||
@ -70,75 +70,75 @@ public class ProgressiveDownloadActionTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSameUriCacheKeyDifferentAction_IsSameMedia() throws Exception {
|
public void testSameUriCacheKeyDifferentAction_IsSameMedia() throws Exception {
|
||||||
ProgressiveDownloadAction action1 = new ProgressiveDownloadAction(true, null, uri1, null);
|
ProgressiveDownloadAction action1 = new ProgressiveDownloadAction(uri1, true, null, null);
|
||||||
ProgressiveDownloadAction action2 = new ProgressiveDownloadAction(false, null, uri1, null);
|
ProgressiveDownloadAction action2 = new ProgressiveDownloadAction(uri1, false, null, null);
|
||||||
assertSameMedia(action1, action2);
|
assertSameMedia(action1, action2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNullCacheKeyDifferentUriAction_IsNotSameMedia() throws Exception {
|
public void testNullCacheKeyDifferentUriAction_IsNotSameMedia() throws Exception {
|
||||||
ProgressiveDownloadAction action3 = new ProgressiveDownloadAction(true, null, uri2, null);
|
ProgressiveDownloadAction action3 = new ProgressiveDownloadAction(uri2, true, null, null);
|
||||||
ProgressiveDownloadAction action4 = new ProgressiveDownloadAction(false, null, uri1, null);
|
ProgressiveDownloadAction action4 = new ProgressiveDownloadAction(uri1, false, null, null);
|
||||||
assertNotSameMedia(action3, action4);
|
assertNotSameMedia(action3, action4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSameCacheKeyDifferentUriAction_IsSameMedia() throws Exception {
|
public void testSameCacheKeyDifferentUriAction_IsSameMedia() throws Exception {
|
||||||
ProgressiveDownloadAction action5 = new ProgressiveDownloadAction(true, null, uri2, "key");
|
ProgressiveDownloadAction action5 = new ProgressiveDownloadAction(uri2, true, null, "key");
|
||||||
ProgressiveDownloadAction action6 = new ProgressiveDownloadAction(false, null, uri1, "key");
|
ProgressiveDownloadAction action6 = new ProgressiveDownloadAction(uri1, false, null, "key");
|
||||||
assertSameMedia(action5, action6);
|
assertSameMedia(action5, action6);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSameUriDifferentCacheKeyAction_IsNotSameMedia() throws Exception {
|
public void testSameUriDifferentCacheKeyAction_IsNotSameMedia() throws Exception {
|
||||||
ProgressiveDownloadAction action7 = new ProgressiveDownloadAction(true, null, uri1, "key");
|
ProgressiveDownloadAction action7 = new ProgressiveDownloadAction(uri1, true, null, "key");
|
||||||
ProgressiveDownloadAction action8 = new ProgressiveDownloadAction(false, null, uri1, "key2");
|
ProgressiveDownloadAction action8 = new ProgressiveDownloadAction(uri1, false, null, "key2");
|
||||||
assertNotSameMedia(action7, action8);
|
assertNotSameMedia(action7, action8);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSameUriNullCacheKeyAction_IsNotSameMedia() throws Exception {
|
public void testSameUriNullCacheKeyAction_IsNotSameMedia() throws Exception {
|
||||||
ProgressiveDownloadAction action1 = new ProgressiveDownloadAction(true, null, uri1, "key");
|
ProgressiveDownloadAction action1 = new ProgressiveDownloadAction(uri1, true, null, "key");
|
||||||
ProgressiveDownloadAction action2 = new ProgressiveDownloadAction(false, null, uri1, null);
|
ProgressiveDownloadAction action2 = new ProgressiveDownloadAction(uri1, false, null, null);
|
||||||
assertNotSameMedia(action1, action2);
|
assertNotSameMedia(action1, action2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEquals() throws Exception {
|
public void testEquals() throws Exception {
|
||||||
ProgressiveDownloadAction action1 = new ProgressiveDownloadAction(true, null, uri1, null);
|
ProgressiveDownloadAction action1 = new ProgressiveDownloadAction(uri1, true, null, null);
|
||||||
assertThat(action1.equals(action1)).isTrue();
|
assertThat(action1.equals(action1)).isTrue();
|
||||||
|
|
||||||
ProgressiveDownloadAction action2 = new ProgressiveDownloadAction(true, null, uri1, null);
|
ProgressiveDownloadAction action2 = new ProgressiveDownloadAction(uri1, true, null, null);
|
||||||
ProgressiveDownloadAction action3 = new ProgressiveDownloadAction(true, null, uri1, null);
|
ProgressiveDownloadAction action3 = new ProgressiveDownloadAction(uri1, true, null, null);
|
||||||
assertThat(action2.equals(action3)).isTrue();
|
assertThat(action2.equals(action3)).isTrue();
|
||||||
|
|
||||||
ProgressiveDownloadAction action4 = new ProgressiveDownloadAction(true, null, uri1, null);
|
ProgressiveDownloadAction action4 = new ProgressiveDownloadAction(uri1, true, null, null);
|
||||||
ProgressiveDownloadAction action5 = new ProgressiveDownloadAction(false, null, uri1, null);
|
ProgressiveDownloadAction action5 = new ProgressiveDownloadAction(uri1, false, null, null);
|
||||||
assertThat(action4.equals(action5)).isFalse();
|
assertThat(action4.equals(action5)).isFalse();
|
||||||
|
|
||||||
ProgressiveDownloadAction action6 = new ProgressiveDownloadAction(true, null, uri1, null);
|
ProgressiveDownloadAction action6 = new ProgressiveDownloadAction(uri1, true, null, null);
|
||||||
ProgressiveDownloadAction action7 = new ProgressiveDownloadAction(true, null, uri1, "key");
|
ProgressiveDownloadAction action7 = new ProgressiveDownloadAction(uri1, true, null, "key");
|
||||||
assertThat(action6.equals(action7)).isFalse();
|
assertThat(action6.equals(action7)).isFalse();
|
||||||
|
|
||||||
ProgressiveDownloadAction action8 = new ProgressiveDownloadAction(true, null, uri1, "key2");
|
ProgressiveDownloadAction action8 = new ProgressiveDownloadAction(uri1, true, null, "key2");
|
||||||
ProgressiveDownloadAction action9 = new ProgressiveDownloadAction(true, null, uri1, "key");
|
ProgressiveDownloadAction action9 = new ProgressiveDownloadAction(uri1, true, null, "key");
|
||||||
assertThat(action8.equals(action9)).isFalse();
|
assertThat(action8.equals(action9)).isFalse();
|
||||||
|
|
||||||
ProgressiveDownloadAction action10 = new ProgressiveDownloadAction(true, null, uri1, null);
|
ProgressiveDownloadAction action10 = new ProgressiveDownloadAction(uri1, true, null, null);
|
||||||
ProgressiveDownloadAction action11 = new ProgressiveDownloadAction(true, null, uri2, null);
|
ProgressiveDownloadAction action11 = new ProgressiveDownloadAction(uri2, true, null, null);
|
||||||
assertThat(action10.equals(action11)).isFalse();
|
assertThat(action10.equals(action11)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSerializerGetType() throws Exception {
|
public void testSerializerGetType() throws Exception {
|
||||||
ProgressiveDownloadAction action = new ProgressiveDownloadAction(false, null, uri1, null);
|
ProgressiveDownloadAction action = new ProgressiveDownloadAction(uri1, false, null, null);
|
||||||
assertThat(action.type).isNotNull();
|
assertThat(action.type).isNotNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSerializerWriteRead() throws Exception {
|
public void testSerializerWriteRead() throws Exception {
|
||||||
doTestSerializationRoundTrip(new ProgressiveDownloadAction(false, null, uri1, null));
|
doTestSerializationRoundTrip(new ProgressiveDownloadAction(uri1, false, null, null));
|
||||||
doTestSerializationRoundTrip(new ProgressiveDownloadAction(true, null, uri2, "key"));
|
doTestSerializationRoundTrip(new ProgressiveDownloadAction(uri2, true, null, "key"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertSameMedia(
|
private void assertSameMedia(
|
||||||
|
@ -24,11 +24,12 @@ import com.google.android.exoplayer2.source.dash.manifest.RepresentationKey;
|
|||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/** An action to download or remove downloaded DASH streams. */
|
/** An action to download or remove downloaded DASH streams. */
|
||||||
public final class DashDownloadAction extends SegmentDownloadAction<RepresentationKey> {
|
public final class DashDownloadAction extends SegmentDownloadAction<RepresentationKey> {
|
||||||
|
|
||||||
private static final String TYPE = "DashDownloadAction";
|
private static final String TYPE = "dash";
|
||||||
private static final int VERSION = 0;
|
private static final int VERSION = 0;
|
||||||
|
|
||||||
public static final Deserializer DESERIALIZER =
|
public static final Deserializer DESERIALIZER =
|
||||||
@ -39,30 +40,28 @@ public final class DashDownloadAction extends SegmentDownloadAction<Representati
|
|||||||
return new RepresentationKey(input.readInt(), input.readInt(), input.readInt());
|
return new RepresentationKey(input.readInt(), input.readInt(), input.readInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected RepresentationKey[] createKeyArray(int keyCount) {
|
|
||||||
return new RepresentationKey[keyCount];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DownloadAction createDownloadAction(
|
protected DownloadAction createDownloadAction(
|
||||||
boolean isRemoveAction, String data, Uri manifestUri, RepresentationKey[] keys) {
|
Uri uri, boolean isRemoveAction, String data, List<RepresentationKey> keys) {
|
||||||
return new DashDownloadAction(isRemoveAction, data, manifestUri, keys);
|
return new DashDownloadAction(uri, isRemoveAction, data, keys);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see SegmentDownloadAction#SegmentDownloadAction(String, int, boolean, String, Uri,
|
* @param uri The DASH manifest URI.
|
||||||
* Comparable[])
|
* @param isRemoveAction Whether the data will be removed. If {@code false} it will be downloaded.
|
||||||
|
* @param data Optional custom data for this action. If null, an empty string is used.
|
||||||
|
* @param keys Keys of representations to be downloaded. If empty, all representations are
|
||||||
|
* downloaded. If {@code removeAction} is true, {@code keys} must be empty.
|
||||||
*/
|
*/
|
||||||
public DashDownloadAction(
|
public DashDownloadAction(
|
||||||
boolean isRemoveAction, @Nullable String data, Uri manifestUri, RepresentationKey... keys) {
|
Uri uri, boolean isRemoveAction, @Nullable String data, List<RepresentationKey> keys) {
|
||||||
super(TYPE, VERSION, isRemoveAction, data, manifestUri, keys);
|
super(TYPE, VERSION, uri, isRemoveAction, data, keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DashDownloader createDownloader(DownloaderConstructorHelper constructorHelper) {
|
protected DashDownloader createDownloader(DownloaderConstructorHelper constructorHelper) {
|
||||||
return new DashDownloader(manifestUri, constructorHelper, keys);
|
return new DashDownloader(uri, constructorHelper, keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -49,8 +49,11 @@ import java.util.List;
|
|||||||
* new DownloaderConstructorHelper(cache, factory);
|
* new DownloaderConstructorHelper(cache, factory);
|
||||||
* // Create a downloader for the first representation of the first adaptation set of the first
|
* // Create a downloader for the first representation of the first adaptation set of the first
|
||||||
* // period.
|
* // period.
|
||||||
* DashDownloader dashDownloader = new DashDownloader(
|
* DashDownloader dashDownloader =
|
||||||
* manifestUrl, constructorHelper, new RepresentationKey[] {new RepresentationKey(0, 0, 0)});
|
* new DashDownloader(
|
||||||
|
* manifestUrl,
|
||||||
|
* constructorHelper,
|
||||||
|
* Collections.singletonList(new RepresentationKey(0, 0, 0)));
|
||||||
* // Perform the download.
|
* // Perform the download.
|
||||||
* dashDownloader.download();
|
* dashDownloader.download();
|
||||||
* // Access downloaded data using CacheDataSource
|
* // Access downloaded data using CacheDataSource
|
||||||
@ -60,11 +63,11 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public final class DashDownloader extends SegmentDownloader<DashManifest, RepresentationKey> {
|
public final class DashDownloader extends SegmentDownloader<DashManifest, RepresentationKey> {
|
||||||
|
|
||||||
/** @see SegmentDownloader#SegmentDownloader(Uri, DownloaderConstructorHelper, Object[]) */
|
/** @see SegmentDownloader#SegmentDownloader(Uri, DownloaderConstructorHelper, List) */
|
||||||
public DashDownloader(
|
public DashDownloader(
|
||||||
Uri manifestUri,
|
Uri manifestUri,
|
||||||
DownloaderConstructorHelper constructorHelper,
|
DownloaderConstructorHelper constructorHelper,
|
||||||
@Nullable RepresentationKey[] trackKeys) {
|
List<RepresentationKey> trackKeys) {
|
||||||
super(manifestUri, constructorHelper, trackKeys);
|
super(manifestUri, constructorHelper, trackKeys);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,6 +28,8 @@ import java.io.ByteArrayOutputStream;
|
|||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
@ -51,141 +53,120 @@ public class DashDownloadActionTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDownloadActionIsNotRemoveAction() throws Exception {
|
public void testDownloadActionIsNotRemoveAction() {
|
||||||
DashDownloadAction action =
|
DashDownloadAction action = newAction(uri1, /* isRemoveAction= */ false, /* data= */ null);
|
||||||
new DashDownloadAction(/* isRemoveAction= */ false, /* data= */ null, uri1);
|
|
||||||
assertThat(action.isRemoveAction).isFalse();
|
assertThat(action.isRemoveAction).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveActionisRemoveAction() throws Exception {
|
public void testRemoveActionisRemoveAction() {
|
||||||
DashDownloadAction action2 =
|
DashDownloadAction action2 = newAction(uri1, /* isRemoveAction= */ true, /* data= */ null);
|
||||||
new DashDownloadAction(/* isRemoveAction= */ true, /* data= */ null, uri1);
|
|
||||||
assertThat(action2.isRemoveAction).isTrue();
|
assertThat(action2.isRemoveAction).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateDownloader() throws Exception {
|
public void testCreateDownloader() {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
DashDownloadAction action =
|
DashDownloadAction action = newAction(uri1, /* isRemoveAction= */ false, /* data= */ null);
|
||||||
new DashDownloadAction(/* isRemoveAction= */ false, /* data= */ null, uri1);
|
|
||||||
DownloaderConstructorHelper constructorHelper = new DownloaderConstructorHelper(
|
DownloaderConstructorHelper constructorHelper = new DownloaderConstructorHelper(
|
||||||
Mockito.mock(Cache.class), DummyDataSource.FACTORY);
|
Mockito.mock(Cache.class), DummyDataSource.FACTORY);
|
||||||
assertThat(action.createDownloader(constructorHelper)).isNotNull();
|
assertThat(action.createDownloader(constructorHelper)).isNotNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSameUriDifferentAction_IsSameMedia() throws Exception {
|
public void testSameUriDifferentAction_IsSameMedia() {
|
||||||
DashDownloadAction action1 =
|
DashDownloadAction action1 = newAction(uri1, /* isRemoveAction= */ true, /* data= */ null);
|
||||||
new DashDownloadAction(/* isRemoveAction= */ true, /* data= */ null, uri1);
|
DashDownloadAction action2 = newAction(uri1, /* isRemoveAction= */ false, /* data= */ null);
|
||||||
DashDownloadAction action2 =
|
|
||||||
new DashDownloadAction(/* isRemoveAction= */ false, /* data= */ null, uri1);
|
|
||||||
assertThat(action1.isSameMedia(action2)).isTrue();
|
assertThat(action1.isSameMedia(action2)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDifferentUriAndAction_IsNotSameMedia() throws Exception {
|
public void testDifferentUriAndAction_IsNotSameMedia() {
|
||||||
DashDownloadAction action3 =
|
DashDownloadAction action3 = newAction(uri2, /* isRemoveAction= */ true, /* data= */ null);
|
||||||
new DashDownloadAction(/* isRemoveAction= */ true, /* data= */ null, uri2);
|
DashDownloadAction action4 = newAction(uri1, /* isRemoveAction= */ false, /* data= */ null);
|
||||||
DashDownloadAction action4 =
|
|
||||||
new DashDownloadAction(/* isRemoveAction= */ false, /* data= */ null, uri1);
|
|
||||||
assertThat(action3.isSameMedia(action4)).isFalse();
|
assertThat(action3.isSameMedia(action4)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("EqualsWithItself")
|
@SuppressWarnings("EqualsWithItself")
|
||||||
@Test
|
@Test
|
||||||
public void testEquals() throws Exception {
|
public void testEquals() {
|
||||||
DashDownloadAction action1 =
|
DashDownloadAction action1 = newAction(uri1, /* isRemoveAction= */ true, /* data= */ null);
|
||||||
new DashDownloadAction(/* isRemoveAction= */ true, /* data= */ null, uri1);
|
|
||||||
assertThat(action1.equals(action1)).isTrue();
|
assertThat(action1.equals(action1)).isTrue();
|
||||||
|
|
||||||
DashDownloadAction action2 =
|
DashDownloadAction action2 = newAction(uri1, /* isRemoveAction= */ true, /* data= */ null);
|
||||||
new DashDownloadAction(/* isRemoveAction= */ true, /* data= */ null, uri1);
|
DashDownloadAction action3 = newAction(uri1, /* isRemoveAction= */ true, /* data= */ null);
|
||||||
DashDownloadAction action3 =
|
|
||||||
new DashDownloadAction(/* isRemoveAction= */ true, /* data= */ null, uri1);
|
|
||||||
assertEqual(action2, action3);
|
assertEqual(action2, action3);
|
||||||
|
|
||||||
DashDownloadAction action4 =
|
DashDownloadAction action4 = newAction(uri1, /* isRemoveAction= */ true, /* data= */ null);
|
||||||
new DashDownloadAction(/* isRemoveAction= */ true, /* data= */ null, uri1);
|
DashDownloadAction action5 = newAction(uri1, /* isRemoveAction= */ false, /* data= */ null);
|
||||||
DashDownloadAction action5 =
|
|
||||||
new DashDownloadAction(/* isRemoveAction= */ false, /* data= */ null, uri1);
|
|
||||||
assertNotEqual(action4, action5);
|
assertNotEqual(action4, action5);
|
||||||
|
|
||||||
DashDownloadAction action6 =
|
DashDownloadAction action6 = newAction(uri1, /* isRemoveAction= */ false, /* data= */ null);
|
||||||
new DashDownloadAction(/* isRemoveAction= */ false, /* data= */ null, uri1);
|
|
||||||
DashDownloadAction action7 =
|
DashDownloadAction action7 =
|
||||||
new DashDownloadAction(
|
newAction(
|
||||||
/* isRemoveAction= */ false, /* data= */ null, uri1, new RepresentationKey(0, 0, 0));
|
uri1, /* isRemoveAction= */ false, /* data= */ null, new RepresentationKey(0, 0, 0));
|
||||||
assertNotEqual(action6, action7);
|
assertNotEqual(action6, action7);
|
||||||
|
|
||||||
DashDownloadAction action8 =
|
DashDownloadAction action8 =
|
||||||
new DashDownloadAction(
|
newAction(
|
||||||
/* isRemoveAction= */ false, /* data= */ null, uri1, new RepresentationKey(1, 1, 1));
|
uri1, /* isRemoveAction= */ false, /* data= */ null, new RepresentationKey(1, 1, 1));
|
||||||
DashDownloadAction action9 =
|
DashDownloadAction action9 =
|
||||||
new DashDownloadAction(
|
newAction(
|
||||||
/* isRemoveAction= */ false, /* data= */ null, uri1, new RepresentationKey(0, 0, 0));
|
uri1, /* isRemoveAction= */ false, /* data= */ null, new RepresentationKey(0, 0, 0));
|
||||||
assertNotEqual(action8, action9);
|
assertNotEqual(action8, action9);
|
||||||
|
|
||||||
DashDownloadAction action10 =
|
DashDownloadAction action10 = newAction(uri1, /* isRemoveAction= */ true, /* data= */ null);
|
||||||
new DashDownloadAction(/* isRemoveAction= */ true, /* data= */ null, uri1);
|
DashDownloadAction action11 = newAction(uri2, /* isRemoveAction= */ true, /* data= */ null);
|
||||||
DashDownloadAction action11 =
|
|
||||||
new DashDownloadAction(/* isRemoveAction= */ true, /* data= */ null, uri2);
|
|
||||||
assertNotEqual(action10, action11);
|
assertNotEqual(action10, action11);
|
||||||
|
|
||||||
DashDownloadAction action12 =
|
DashDownloadAction action12 =
|
||||||
new DashDownloadAction(
|
newAction(
|
||||||
|
uri1,
|
||||||
/* isRemoveAction= */ false,
|
/* isRemoveAction= */ false,
|
||||||
/* data= */ null,
|
/* data= */ null,
|
||||||
uri1,
|
|
||||||
new RepresentationKey(0, 0, 0),
|
new RepresentationKey(0, 0, 0),
|
||||||
new RepresentationKey(1, 1, 1));
|
new RepresentationKey(1, 1, 1));
|
||||||
DashDownloadAction action13 =
|
DashDownloadAction action13 =
|
||||||
new DashDownloadAction(
|
newAction(
|
||||||
|
uri1,
|
||||||
/* isRemoveAction= */ false,
|
/* isRemoveAction= */ false,
|
||||||
/* data= */ null,
|
/* data= */ null,
|
||||||
uri1,
|
|
||||||
new RepresentationKey(1, 1, 1),
|
new RepresentationKey(1, 1, 1),
|
||||||
new RepresentationKey(0, 0, 0));
|
new RepresentationKey(0, 0, 0));
|
||||||
assertEqual(action12, action13);
|
assertEqual(action12, action13);
|
||||||
|
|
||||||
DashDownloadAction action14 =
|
DashDownloadAction action14 =
|
||||||
new DashDownloadAction(
|
newAction(
|
||||||
/* isRemoveAction= */ false, /* data= */ null, uri1, new RepresentationKey(0, 0, 0));
|
uri1, /* isRemoveAction= */ false, /* data= */ null, new RepresentationKey(0, 0, 0));
|
||||||
DashDownloadAction action15 =
|
DashDownloadAction action15 =
|
||||||
new DashDownloadAction(
|
newAction(
|
||||||
|
uri1,
|
||||||
/* isRemoveAction= */ false,
|
/* isRemoveAction= */ false,
|
||||||
/* data= */ null,
|
/* data= */ null,
|
||||||
uri1,
|
|
||||||
new RepresentationKey(1, 1, 1),
|
new RepresentationKey(1, 1, 1),
|
||||||
new RepresentationKey(0, 0, 0));
|
new RepresentationKey(0, 0, 0));
|
||||||
assertNotEqual(action14, action15);
|
assertNotEqual(action14, action15);
|
||||||
|
|
||||||
DashDownloadAction action16 =
|
DashDownloadAction action16 = newAction(uri1, /* isRemoveAction= */ false, /* data= */ null);
|
||||||
new DashDownloadAction(/* isRemoveAction= */ false, /* data= */ null, uri1);
|
DashDownloadAction action17 = newAction(uri1, /* isRemoveAction= */ false, /* data= */ null);
|
||||||
DashDownloadAction action17 =
|
|
||||||
new DashDownloadAction(
|
|
||||||
/* isRemoveAction= */ false, /* data= */ null, uri1, new RepresentationKey[0]);
|
|
||||||
assertEqual(action16, action17);
|
assertEqual(action16, action17);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSerializerGetType() throws Exception {
|
public void testSerializerGetType() {
|
||||||
DashDownloadAction action =
|
DashDownloadAction action = newAction(uri1, /* isRemoveAction= */ false, /* data= */ null);
|
||||||
new DashDownloadAction(/* isRemoveAction= */ false, /* data= */ null, uri1);
|
|
||||||
assertThat(action.type).isNotNull();
|
assertThat(action.type).isNotNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSerializerWriteRead() throws Exception {
|
public void testSerializerWriteRead() throws Exception {
|
||||||
|
doTestSerializationRoundTrip(newAction(uri1, /* isRemoveAction= */ false, /* data= */ null));
|
||||||
|
doTestSerializationRoundTrip(newAction(uri1, /* isRemoveAction= */ true, /* data= */ null));
|
||||||
doTestSerializationRoundTrip(
|
doTestSerializationRoundTrip(
|
||||||
new DashDownloadAction(/* isRemoveAction= */ false, /* data= */ null, uri1));
|
newAction(
|
||||||
doTestSerializationRoundTrip(
|
uri2,
|
||||||
new DashDownloadAction(/* isRemoveAction= */ true, /* data= */ null, uri1));
|
|
||||||
doTestSerializationRoundTrip(
|
|
||||||
new DashDownloadAction(
|
|
||||||
/* isRemoveAction= */ false,
|
/* isRemoveAction= */ false,
|
||||||
/* data= */ null,
|
/* data= */ null,
|
||||||
uri2,
|
|
||||||
new RepresentationKey(0, 0, 0),
|
new RepresentationKey(0, 0, 0),
|
||||||
new RepresentationKey(1, 1, 1)));
|
new RepresentationKey(1, 1, 1)));
|
||||||
}
|
}
|
||||||
@ -214,4 +195,10 @@ public class DashDownloadActionTest {
|
|||||||
assertThat(action).isEqualTo(action2);
|
assertThat(action).isEqualTo(action2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static DashDownloadAction newAction(
|
||||||
|
Uri uri, boolean isRemoveAction, String data, RepresentationKey... keys) {
|
||||||
|
ArrayList<RepresentationKey> keysList = new ArrayList<>();
|
||||||
|
Collections.addAll(keysList, keys);
|
||||||
|
return new DashDownloadAction(uri, isRemoveAction, data, keysList);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,8 @@ import com.google.android.exoplayer2.upstream.cache.SimpleCache;
|
|||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@ -302,7 +304,14 @@ public class DashDownloaderTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private DashDownloader getDashDownloader(Factory factory, RepresentationKey... keys) {
|
private DashDownloader getDashDownloader(Factory factory, RepresentationKey... keys) {
|
||||||
return new DashDownloader(TEST_MPD_URI, new DownloaderConstructorHelper(cache, factory), keys);
|
return new DashDownloader(
|
||||||
|
TEST_MPD_URI, new DownloaderConstructorHelper(cache, factory), keysList(keys));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ArrayList<RepresentationKey> keysList(RepresentationKey... keys) {
|
||||||
|
ArrayList<RepresentationKey> keysList = new ArrayList<>();
|
||||||
|
Collections.addAll(keysList, keys);
|
||||||
|
return keysList;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ import static com.google.android.exoplayer2.testutil.CacheAsserts.assertCachedDa
|
|||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.ConditionVariable;
|
import android.os.ConditionVariable;
|
||||||
import com.google.android.exoplayer2.offline.DownloadManager;
|
import com.google.android.exoplayer2.offline.DownloadManager;
|
||||||
import com.google.android.exoplayer2.offline.DownloaderConstructorHelper;
|
import com.google.android.exoplayer2.offline.DownloaderConstructorHelper;
|
||||||
@ -36,6 +37,8 @@ import com.google.android.exoplayer2.upstream.cache.NoOpCacheEvictor;
|
|||||||
import com.google.android.exoplayer2.upstream.cache.SimpleCache;
|
import com.google.android.exoplayer2.upstream.cache.SimpleCache;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
@ -244,11 +247,11 @@ public class DownloadManagerDashTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleDownloadAction(RepresentationKey... keys) {
|
private void handleDownloadAction(RepresentationKey... keys) {
|
||||||
downloadManager.handleAction(new DashDownloadAction(false, null, TEST_MPD_URI, keys));
|
downloadManager.handleAction(newAction(TEST_MPD_URI, false, null, keys));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleRemoveAction() {
|
private void handleRemoveAction() {
|
||||||
downloadManager.handleAction(new DashDownloadAction(true, null, TEST_MPD_URI));
|
downloadManager.handleAction(newAction(TEST_MPD_URI, true, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createDownloadManager() {
|
private void createDownloadManager() {
|
||||||
@ -272,4 +275,11 @@ public class DownloadManagerDashTest {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static DashDownloadAction newAction(
|
||||||
|
Uri uri, boolean isRemoveAction, String data, RepresentationKey... keys) {
|
||||||
|
ArrayList<RepresentationKey> keysList = new ArrayList<>();
|
||||||
|
Collections.addAll(keysList, keys);
|
||||||
|
return new DashDownloadAction(uri, isRemoveAction, data, keysList);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ import static com.google.android.exoplayer2.testutil.CacheAsserts.assertCachedDa
|
|||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.net.Uri;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.offline.DownloadManager;
|
import com.google.android.exoplayer2.offline.DownloadManager;
|
||||||
import com.google.android.exoplayer2.offline.DownloadManager.TaskState;
|
import com.google.android.exoplayer2.offline.DownloadManager.TaskState;
|
||||||
@ -43,6 +44,8 @@ import com.google.android.exoplayer2.util.ConditionVariable;
|
|||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
@ -219,11 +222,11 @@ public class DownloadServiceDashTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void removeAll() throws Throwable {
|
private void removeAll() throws Throwable {
|
||||||
callDownloadServiceOnStart(new DashDownloadAction(true, null, TEST_MPD_URI));
|
callDownloadServiceOnStart(newAction(TEST_MPD_URI, true, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void downloadKeys(RepresentationKey... keys) throws Throwable {
|
private void downloadKeys(RepresentationKey... keys) {
|
||||||
callDownloadServiceOnStart(new DashDownloadAction(false, null, TEST_MPD_URI, keys));
|
callDownloadServiceOnStart(newAction(TEST_MPD_URI, false, null, keys));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void callDownloadServiceOnStart(final DashDownloadAction action) {
|
private void callDownloadServiceOnStart(final DashDownloadAction action) {
|
||||||
@ -238,4 +241,11 @@ public class DownloadServiceDashTest {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static DashDownloadAction newAction(
|
||||||
|
Uri uri, boolean isRemoveAction, String data, RepresentationKey... keys) {
|
||||||
|
ArrayList<RepresentationKey> keysList = new ArrayList<>();
|
||||||
|
Collections.addAll(keysList, keys);
|
||||||
|
return new DashDownloadAction(uri, isRemoveAction, data, keysList);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,11 +24,12 @@ import com.google.android.exoplayer2.source.hls.playlist.RenditionKey;
|
|||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/** An action to download or remove downloaded HLS streams. */
|
/** An action to download or remove downloaded HLS streams. */
|
||||||
public final class HlsDownloadAction extends SegmentDownloadAction<RenditionKey> {
|
public final class HlsDownloadAction extends SegmentDownloadAction<RenditionKey> {
|
||||||
|
|
||||||
private static final String TYPE = "HlsDownloadAction";
|
private static final String TYPE = "hls";
|
||||||
private static final int VERSION = 0;
|
private static final int VERSION = 0;
|
||||||
|
|
||||||
public static final Deserializer DESERIALIZER =
|
public static final Deserializer DESERIALIZER =
|
||||||
@ -41,30 +42,28 @@ public final class HlsDownloadAction extends SegmentDownloadAction<RenditionKey>
|
|||||||
return new RenditionKey(renditionGroup, trackIndex);
|
return new RenditionKey(renditionGroup, trackIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected RenditionKey[] createKeyArray(int keyCount) {
|
|
||||||
return new RenditionKey[keyCount];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DownloadAction createDownloadAction(
|
protected DownloadAction createDownloadAction(
|
||||||
boolean isRemoveAction, String data, Uri manifestUri, RenditionKey[] keys) {
|
Uri uri, boolean isRemoveAction, String data, List<RenditionKey> keys) {
|
||||||
return new HlsDownloadAction(isRemoveAction, data, manifestUri, keys);
|
return new HlsDownloadAction(uri, isRemoveAction, data, keys);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see SegmentDownloadAction#SegmentDownloadAction(String, int, boolean, String, Uri,
|
* @param uri The HLS playlist URI.
|
||||||
* Comparable[])
|
* @param isRemoveAction Whether the data will be removed. If {@code false} it will be downloaded.
|
||||||
|
* @param data Optional custom data for this action.
|
||||||
|
* @param keys Keys of renditions to be downloaded. If empty, all renditions are downloaded. If
|
||||||
|
* {@code removeAction} is true, {@code keys} must empty.
|
||||||
*/
|
*/
|
||||||
public HlsDownloadAction(
|
public HlsDownloadAction(
|
||||||
boolean isRemoveAction, @Nullable String data, Uri manifestUri, RenditionKey... keys) {
|
Uri uri, boolean isRemoveAction, @Nullable String data, List<RenditionKey> keys) {
|
||||||
super(TYPE, VERSION, isRemoveAction, data, manifestUri, keys);
|
super(TYPE, VERSION, uri, isRemoveAction, data, keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected HlsDownloader createDownloader(DownloaderConstructorHelper constructorHelper) {
|
protected HlsDownloader createDownloader(DownloaderConstructorHelper constructorHelper) {
|
||||||
return new HlsDownloader(manifestUri, constructorHelper, keys);
|
return new HlsDownloader(uri, constructorHelper, keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -37,9 +37,11 @@ import java.util.List;
|
|||||||
/** A downloader for HLS streams. */
|
/** A downloader for HLS streams. */
|
||||||
public final class HlsDownloader extends SegmentDownloader<HlsMasterPlaylist, RenditionKey> {
|
public final class HlsDownloader extends SegmentDownloader<HlsMasterPlaylist, RenditionKey> {
|
||||||
|
|
||||||
/** @see SegmentDownloader#SegmentDownloader(Uri, DownloaderConstructorHelper, Object[]) */
|
/** @see SegmentDownloader#SegmentDownloader(Uri, DownloaderConstructorHelper, List) */
|
||||||
public HlsDownloader(
|
public HlsDownloader(
|
||||||
Uri manifestUri, DownloaderConstructorHelper constructorHelper, RenditionKey[] trackKeys) {
|
Uri manifestUri,
|
||||||
|
DownloaderConstructorHelper constructorHelper,
|
||||||
|
List<RenditionKey> trackKeys) {
|
||||||
super(manifestUri, constructorHelper, trackKeys);
|
super(manifestUri, constructorHelper, trackKeys);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +35,6 @@ import static com.google.android.exoplayer2.testutil.CacheAsserts.assertCachedDa
|
|||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import com.google.android.exoplayer2.offline.DownloaderConstructorHelper;
|
import com.google.android.exoplayer2.offline.DownloaderConstructorHelper;
|
||||||
import com.google.android.exoplayer2.source.hls.playlist.RenditionKey;
|
import com.google.android.exoplayer2.source.hls.playlist.RenditionKey;
|
||||||
import com.google.android.exoplayer2.testutil.FakeDataSet;
|
import com.google.android.exoplayer2.testutil.FakeDataSet;
|
||||||
@ -44,6 +43,8 @@ import com.google.android.exoplayer2.upstream.cache.NoOpCacheEvictor;
|
|||||||
import com.google.android.exoplayer2.upstream.cache.SimpleCache;
|
import com.google.android.exoplayer2.upstream.cache.SimpleCache;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@ -78,7 +79,7 @@ public class HlsDownloaderTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() throws Exception {
|
public void tearDown() {
|
||||||
Util.recursiveDelete(tempFolder);
|
Util.recursiveDelete(tempFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,7 +133,7 @@ public class HlsDownloaderTest {
|
|||||||
.setRandomData(MEDIA_PLAYLIST_3_DIR + "fileSequence1.ts", 14)
|
.setRandomData(MEDIA_PLAYLIST_3_DIR + "fileSequence1.ts", 14)
|
||||||
.setRandomData(MEDIA_PLAYLIST_3_DIR + "fileSequence2.ts", 15);
|
.setRandomData(MEDIA_PLAYLIST_3_DIR + "fileSequence2.ts", 15);
|
||||||
|
|
||||||
HlsDownloader downloader = getHlsDownloader(MASTER_PLAYLIST_URI, null);
|
HlsDownloader downloader = getHlsDownloader(MASTER_PLAYLIST_URI, getKeys());
|
||||||
downloader.download();
|
downloader.download();
|
||||||
|
|
||||||
assertCachedData(cache, fakeDataSet);
|
assertCachedData(cache, fakeDataSet);
|
||||||
@ -152,7 +153,7 @@ public class HlsDownloaderTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDownloadMediaPlaylist() throws Exception {
|
public void testDownloadMediaPlaylist() throws Exception {
|
||||||
HlsDownloader downloader = getHlsDownloader(MEDIA_PLAYLIST_1_URI);
|
HlsDownloader downloader = getHlsDownloader(MEDIA_PLAYLIST_1_URI, getKeys());
|
||||||
downloader.download();
|
downloader.download();
|
||||||
|
|
||||||
assertCachedData(
|
assertCachedData(
|
||||||
@ -175,21 +176,21 @@ public class HlsDownloaderTest {
|
|||||||
.setRandomData("fileSequence1.ts", 11)
|
.setRandomData("fileSequence1.ts", 11)
|
||||||
.setRandomData("fileSequence2.ts", 12);
|
.setRandomData("fileSequence2.ts", 12);
|
||||||
|
|
||||||
HlsDownloader downloader = getHlsDownloader(ENC_MEDIA_PLAYLIST_URI);
|
HlsDownloader downloader = getHlsDownloader(ENC_MEDIA_PLAYLIST_URI, getKeys());
|
||||||
downloader.download();
|
downloader.download();
|
||||||
assertCachedData(cache, fakeDataSet);
|
assertCachedData(cache, fakeDataSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
private HlsDownloader getHlsDownloader(String mediaPlaylistUri, @Nullable RenditionKey... keys) {
|
private HlsDownloader getHlsDownloader(String mediaPlaylistUri, List<RenditionKey> keys) {
|
||||||
Factory factory = new Factory(null).setFakeDataSet(fakeDataSet);
|
Factory factory = new Factory(null).setFakeDataSet(fakeDataSet);
|
||||||
return new HlsDownloader(
|
return new HlsDownloader(
|
||||||
Uri.parse(mediaPlaylistUri), new DownloaderConstructorHelper(cache, factory), keys);
|
Uri.parse(mediaPlaylistUri), new DownloaderConstructorHelper(cache, factory), keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static RenditionKey[] getKeys(int... variantIndices) {
|
private static ArrayList<RenditionKey> getKeys(int... variantIndices) {
|
||||||
RenditionKey[] renditionKeys = new RenditionKey[variantIndices.length];
|
ArrayList<RenditionKey> renditionKeys = new ArrayList<>();
|
||||||
for (int i = 0; i < variantIndices.length; i++) {
|
for (int variantIndex : variantIndices) {
|
||||||
renditionKeys[i] = new RenditionKey(RenditionKey.GROUP_VARIANTS, variantIndices[i]);
|
renditionKeys.add(new RenditionKey(RenditionKey.GROUP_VARIANTS, variantIndex));
|
||||||
}
|
}
|
||||||
return renditionKeys;
|
return renditionKeys;
|
||||||
}
|
}
|
||||||
|
@ -24,11 +24,12 @@ import com.google.android.exoplayer2.source.smoothstreaming.manifest.TrackKey;
|
|||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/** An action to download or remove downloaded SmoothStreaming streams. */
|
/** An action to download or remove downloaded SmoothStreaming streams. */
|
||||||
public final class SsDownloadAction extends SegmentDownloadAction<TrackKey> {
|
public final class SsDownloadAction extends SegmentDownloadAction<TrackKey> {
|
||||||
|
|
||||||
private static final String TYPE = "SsDownloadAction";
|
private static final String TYPE = "ss";
|
||||||
private static final int VERSION = 0;
|
private static final int VERSION = 0;
|
||||||
|
|
||||||
public static final Deserializer DESERIALIZER =
|
public static final Deserializer DESERIALIZER =
|
||||||
@ -39,30 +40,28 @@ public final class SsDownloadAction extends SegmentDownloadAction<TrackKey> {
|
|||||||
return new TrackKey(input.readInt(), input.readInt());
|
return new TrackKey(input.readInt(), input.readInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected TrackKey[] createKeyArray(int keyCount) {
|
|
||||||
return new TrackKey[keyCount];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DownloadAction createDownloadAction(
|
protected DownloadAction createDownloadAction(
|
||||||
boolean isRemoveAction, String data, Uri manifestUri, TrackKey[] keys) {
|
Uri uri, boolean isRemoveAction, String data, List<TrackKey> keys) {
|
||||||
return new SsDownloadAction(isRemoveAction, data, manifestUri, keys);
|
return new SsDownloadAction(uri, isRemoveAction, data, keys);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see SegmentDownloadAction#SegmentDownloadAction(String, int, boolean, String, Uri,
|
* @param uri The SmoothStreaming manifest URI.
|
||||||
* Comparable[])
|
* @param isRemoveAction Whether the data will be removed. If {@code false} it will be downloaded.
|
||||||
|
* @param data Optional custom data for this action.
|
||||||
|
* @param keys Keys of tracks to be downloaded. If empty, all tracks are downloaded. If {@code
|
||||||
|
* removeAction} is true, {@code keys} must be empty.
|
||||||
*/
|
*/
|
||||||
public SsDownloadAction(
|
public SsDownloadAction(
|
||||||
boolean isRemoveAction, @Nullable String data, Uri manifestUri, TrackKey... keys) {
|
Uri uri, boolean isRemoveAction, @Nullable String data, List<TrackKey> keys) {
|
||||||
super(TYPE, VERSION, isRemoveAction, data, manifestUri, keys);
|
super(TYPE, VERSION, uri, isRemoveAction, data, keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected SsDownloader createDownloader(DownloaderConstructorHelper constructorHelper) {
|
protected SsDownloader createDownloader(DownloaderConstructorHelper constructorHelper) {
|
||||||
return new SsDownloader(manifestUri, constructorHelper, keys);
|
return new SsDownloader(uri, constructorHelper, keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -42,8 +42,11 @@ import java.util.List;
|
|||||||
* DownloaderConstructorHelper constructorHelper =
|
* DownloaderConstructorHelper constructorHelper =
|
||||||
* new DownloaderConstructorHelper(cache, factory);
|
* new DownloaderConstructorHelper(cache, factory);
|
||||||
* // Create a downloader for the first track of the first stream element.
|
* // Create a downloader for the first track of the first stream element.
|
||||||
* SsDownloader ssDownloader = new SsDownloader(
|
* SsDownloader ssDownloader =
|
||||||
* manifestUrl, constructorHelper, new TrackKey[] {new TrackKey(0, 0)});
|
* new SsDownloader(
|
||||||
|
* manifestUrl,
|
||||||
|
* constructorHelper,
|
||||||
|
* Collections.singletonList(new TrackKey(0, 0)));
|
||||||
* // Perform the download.
|
* // Perform the download.
|
||||||
* ssDownloader.download();
|
* ssDownloader.download();
|
||||||
* // Access downloaded data using CacheDataSource
|
* // Access downloaded data using CacheDataSource
|
||||||
@ -53,9 +56,9 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public final class SsDownloader extends SegmentDownloader<SsManifest, TrackKey> {
|
public final class SsDownloader extends SegmentDownloader<SsManifest, TrackKey> {
|
||||||
|
|
||||||
/** @see SegmentDownloader#SegmentDownloader(Uri, DownloaderConstructorHelper, Object[]) */
|
/** @see SegmentDownloader#SegmentDownloader(Uri, DownloaderConstructorHelper, List) */
|
||||||
public SsDownloader(
|
public SsDownloader(
|
||||||
Uri manifestUri, DownloaderConstructorHelper constructorHelper, TrackKey[] trackKeys) {
|
Uri manifestUri, DownloaderConstructorHelper constructorHelper, List<TrackKey> trackKeys) {
|
||||||
super(SsUtil.fixManifestUri(manifestUri), constructorHelper, trackKeys);
|
super(SsUtil.fixManifestUri(manifestUri), constructorHelper, trackKeys);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,7 +72,7 @@ public final class SsDownloader extends SegmentDownloader<SsManifest, TrackKey>
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<Segment> getSegments(
|
protected List<Segment> getSegments(
|
||||||
DataSource dataSource, SsManifest manifest, boolean allowIncompleteList) throws IOException {
|
DataSource dataSource, SsManifest manifest, boolean allowIncompleteList) {
|
||||||
ArrayList<Segment> segments = new ArrayList<>();
|
ArrayList<Segment> segments = new ArrayList<>();
|
||||||
for (StreamElement streamElement : manifest.streamElements) {
|
for (StreamElement streamElement : manifest.streamElements) {
|
||||||
for (int i = 0; i < streamElement.formats.length; i++) {
|
for (int i = 0; i < streamElement.formats.length; i++) {
|
||||||
|
@ -123,8 +123,7 @@ public final class DashDownloadTest extends ActivityInstrumentationTestCase2<Hos
|
|||||||
}
|
}
|
||||||
DownloaderConstructorHelper constructorHelper =
|
DownloaderConstructorHelper constructorHelper =
|
||||||
new DownloaderConstructorHelper(cache, httpDataSourceFactory);
|
new DownloaderConstructorHelper(cache, httpDataSourceFactory);
|
||||||
return new DashDownloader(
|
return new DashDownloader(MANIFEST_URI, constructorHelper, keys);
|
||||||
MANIFEST_URI, constructorHelper, keys.toArray(new RepresentationKey[keys.size()]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user