Improve DataSource implementations:

1. Make DefaultUriDataSource robust against exceptions through from close().
2. Make AssetDataSource handle file:///android_asset/ URIs.
This commit is contained in:
Oliver Woodman 2015-05-19 14:05:50 +01:00
parent 672906060c
commit 059b80c1ab
4 changed files with 26 additions and 10 deletions

View File

@ -16,6 +16,7 @@
package com.google.android.exoplayer.upstream; package com.google.android.exoplayer.upstream;
import com.google.android.exoplayer.C; import com.google.android.exoplayer.C;
import com.google.android.exoplayer.util.Assertions;
import android.content.res.AssetManager; import android.content.res.AssetManager;
@ -24,9 +25,9 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
/** /**
* A local asset {@link DataSource}. * A local asset {@link UriDataSource}.
*/ */
public final class AssetDataSource implements DataSource { public final class AssetDataSource implements UriDataSource {
/** /**
* Thrown when IOException is encountered during local asset read operation. * Thrown when IOException is encountered during local asset read operation.
@ -42,6 +43,7 @@ public final class AssetDataSource implements DataSource {
private final AssetManager assetManager; private final AssetManager assetManager;
private final TransferListener listener; private final TransferListener listener;
private String uriString;
private InputStream assetInputStream; private InputStream assetInputStream;
private long bytesRemaining; private long bytesRemaining;
private boolean opened; private boolean opened;
@ -66,10 +68,16 @@ public final class AssetDataSource implements DataSource {
@Override @Override
public long open(DataSpec dataSpec) throws AssetDataSourceException { public long open(DataSpec dataSpec) throws AssetDataSourceException {
try { try {
// Lose the '/' prefix in the path or else AssetManager won't find our file uriString = dataSpec.uri.toString();
assetInputStream = assetManager.open(dataSpec.uri.getPath().substring(1), String path = dataSpec.uri.getPath();
AssetManager.ACCESS_RANDOM); if (path.startsWith("/android_asset/")) {
assetInputStream.skip(dataSpec.position); path = path.substring(15);
} else if (path.startsWith("/")) {
path = path.substring(1);
}
assetInputStream = assetManager.open(path, AssetManager.ACCESS_RANDOM);
long skipped = assetInputStream.skip(dataSpec.position);
Assertions.checkState(skipped == dataSpec.position);
bytesRemaining = dataSpec.length == C.LENGTH_UNBOUNDED ? assetInputStream.available() bytesRemaining = dataSpec.length == C.LENGTH_UNBOUNDED ? assetInputStream.available()
: dataSpec.length; : dataSpec.length;
if (bytesRemaining < 0) { if (bytesRemaining < 0) {
@ -110,6 +118,11 @@ public final class AssetDataSource implements DataSource {
} }
} }
@Override
public String getUri() {
return uriString;
}
@Override @Override
public void close() throws AssetDataSourceException { public void close() throws AssetDataSourceException {
if (assetInputStream != null) { if (assetInputStream != null) {

View File

@ -100,8 +100,11 @@ public final class DefaultUriDataSource implements UriDataSource {
@Override @Override
public void close() throws IOException { public void close() throws IOException {
if (dataSource != null) { if (dataSource != null) {
dataSource.close(); try {
dataSource = null; dataSource.close();
} finally {
dataSource = null;
}
} }
} }

View File

@ -22,7 +22,7 @@ import java.io.IOException;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
/** /**
* A local file {@link DataSource}. * A local file {@link UriDataSource}.
*/ */
public final class FileDataSource implements UriDataSource { public final class FileDataSource implements UriDataSource {

View File

@ -25,7 +25,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
* An HTTP specific extension to {@link DataSource}. * An HTTP specific extension to {@link UriDataSource}.
*/ */
public interface HttpDataSource extends UriDataSource { public interface HttpDataSource extends UriDataSource {