Using Exoplayer, I'm trying to play an audio file from a byte array. I'm trying to use the ByteArrayDataSource, but am getting an error when calling the constructor: new ByteArrayDataSource(data);
Here is the code I've come up with:
使用Exoplayer,我尝试从字节数组中播放音频文件。我试图使用ByteArrayDataSource,但是在调用构造函数:new ByteArrayDataSource(data)时,我得到了一个错误;下面是我想到的代码:
private void prepareExoPlayerFromByteArray(byte[] data){
exoPlayer = ExoPlayerFactory.newSimpleInstance(this, new DefaultTrackSelector(null), new DefaultLoadControl());
exoPlayer.addListener(eventListener);
final ByteArrayDataSource byteArrayDataSource = new ByteArrayDataSource(data);
/*
DataSpec dataSpec = new DataSpec(byteArrayDataSource.getUri());
try {
byteArrayDataSource.open(dataSpec);
} catch (IOException e) {
e.printStackTrace();
}
*/
DataSource.Factory factory = new DataSource.Factory() {
@Override
public DataSource createDataSource() {
return byteArrayDataSource;
}
};
MediaSource audioSource = new ExtractorMediaSource(byteArrayDataSource.getUri(),
factory, new DefaultExtractorsFactory(),null,null);
exoPlayer.prepare(audioSource);
}
The error I'm getting is this:
我得到的错误是:
E/ExoPlayerImplInternal: Internal runtime error.
java.lang.NullPointerException
at com.google.android.exoplayer2.util.Assertions.checkNotNull(Assertions.java:107)
at com.google.android.exoplayer2.source.ExtractorMediaPeriod$ExtractingLoadable.<init>(ExtractorMediaPeriod.java:591)
at com.google.android.exoplayer2.source.ExtractorMediaPeriod.startLoading(ExtractorMediaPeriod.java:452)
at com.google.android.exoplayer2.source.ExtractorMediaPeriod.prepare(ExtractorMediaPeriod.java:165)
at com.google.android.exoplayer2.ExoPlayerImplInternal.maybeUpdateLoadingPeriod(ExoPlayerImplInternal.java:1260)
at com.google.android.exoplayer2.ExoPlayerImplInternal.updatePeriods(ExoPlayerImplInternal.java:1102)
at com.google.android.exoplayer2.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:447)
at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:300)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:234)
at android.os.HandlerThread.run(HandlerThread.java:61)
at com.google.android.exoplayer2.util.PriorityHandlerThread.run(PriorityHandlerThread.java:40)
The error seems to come from the constructor of ByteArrayDataSource and is saying that the data passed to it is null, which it isn't as I check before calling it and there are 14002427 bytes in that array.
这个错误似乎来自ByteArrayDataSource的构造函数,它说传递给它的数据是null,我在调用它之前检查过它,这个数组中有14002427字节。
/**
* @param data The data to be read.
*/
public ByteArrayDataSource(byte[] data) {
Assertions.checkNotNull(data);
Assertions.checkArgument(data.length > 0);
this.data = data;
}
What am I doing wrong and how do I get around it? Does anyone have a working example of playing an audio file with Exoplayer by passing a byte array as a source?
我做错了什么,我该怎么做呢?有没有人有一个通过传递字节数组作为源来播放音频文件的例子?
2 个解决方案
#1
1
class UriByteDataHelper {
public Uri getUri(byte[] data) {
try {
URL url = new URL(null, "bytes:///" + "audio", new BytesHandler(data));
return Uri.parse( url.toURI().toString());
} catch (MalformedURLException e) {
throw new RuntimeException(e);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
class BytesHandler extends URLStreamHandler {
byte[] mData;
public BytesHandler(byte[] data) {
mData = data;
}
@Override
protected URLConnection openConnection(URL u) throws IOException {
return new ByteUrlConnection(u, mData);
}
}
class ByteUrlConnection extends URLConnection {
byte[] mData;
public ByteUrlConnection(URL url, byte[] data) {
super(url);
mData = data;
}
@Override
public void connect() throws IOException {
}
@Override
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(mData);
}
}
}
private void prepareExoPlayerFromByteArray(byte[] data){
exoPlayer = ExoPlayerFactory.newSimpleInstance(this, new DefaultTrackSelector(null), new DefaultLoadControl());
exoPlayer.addListener(eventListener);
final MByteArrayDataSource byteArrayDataSource = new MByteArrayDataSource(data);
Log.i(TAG,"ByteArrayDataSource constructed.");
Uri audioByteUri = new UriByteDataHelper().getUri(data);
DataSpec dataSpec = new DataSpec(audioByteUri);
try {
byteArrayDataSource.open(dataSpec);
} catch (IOException e) {
e.printStackTrace();
}
DataSource.Factory factory = new DataSource.Factory() {
@Override
public DataSource createDataSource() {
return byteArrayDataSource;
}
};
Log.i(TAG,"DataSource.Factory constructed.");
MediaSource audioSource = new ExtractorMediaSource(audioByteUri,
factory, new DefaultExtractorsFactory(),null,null);
Log.i(TAG,"Audio source constructed.");
exoPlayer.prepare(audioSource);
initMediaControls();
}
#2
0
byteArrayDataSource.getUri() is going to be null, if you dont call
如果不调用,byteArrayDataSource.getUri()将为空
byteArrayDataSource.open(DataSpec dataSpec). Look at code;
byteArrayDataSource。open(DataSpec DataSpec)。看代码;
public final class ByteArrayDataSource implements DataSource {
private final byte[] data;
private Uri uri;
private int readPosition;
private int bytesRemaining;
/**
* @param data The data to be read.
*/
public ByteArrayDataSource(byte[] data) {
Assertions.checkNotNull(data);
Assertions.checkArgument(data.length > 0);
this.data = data;
}
@Override
public long open(DataSpec dataSpec) throws IOException {
uri = dataSpec.uri;
readPosition = (int) dataSpec.position;
bytesRemaining = (int) ((dataSpec.length == C.LENGTH_UNSET)
? (data.length - dataSpec.position) : dataSpec.length);
if (bytesRemaining <= 0 || readPosition + bytesRemaining > data.length) {
throw new IOException("Unsatisfiable range: [" + readPosition + ", " + dataSpec.length
+ "], length: " + data.length);
}
return bytesRemaining;
}
@Override
public int read(byte[] buffer, int offset, int readLength) throws IOException {
if (readLength == 0) {
return 0;
} else if (bytesRemaining == 0) {
return C.RESULT_END_OF_INPUT;
}
readLength = Math.min(readLength, bytesRemaining);
System.arraycopy(data, readPosition, buffer, offset, readLength);
readPosition += readLength;
bytesRemaining -= readLength;
return readLength;
}
@Override
public Uri getUri() {
return uri;
}
@Override
public void close() throws IOException {
uri = null;
}
}
#1
1
class UriByteDataHelper {
public Uri getUri(byte[] data) {
try {
URL url = new URL(null, "bytes:///" + "audio", new BytesHandler(data));
return Uri.parse( url.toURI().toString());
} catch (MalformedURLException e) {
throw new RuntimeException(e);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
class BytesHandler extends URLStreamHandler {
byte[] mData;
public BytesHandler(byte[] data) {
mData = data;
}
@Override
protected URLConnection openConnection(URL u) throws IOException {
return new ByteUrlConnection(u, mData);
}
}
class ByteUrlConnection extends URLConnection {
byte[] mData;
public ByteUrlConnection(URL url, byte[] data) {
super(url);
mData = data;
}
@Override
public void connect() throws IOException {
}
@Override
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(mData);
}
}
}
private void prepareExoPlayerFromByteArray(byte[] data){
exoPlayer = ExoPlayerFactory.newSimpleInstance(this, new DefaultTrackSelector(null), new DefaultLoadControl());
exoPlayer.addListener(eventListener);
final MByteArrayDataSource byteArrayDataSource = new MByteArrayDataSource(data);
Log.i(TAG,"ByteArrayDataSource constructed.");
Uri audioByteUri = new UriByteDataHelper().getUri(data);
DataSpec dataSpec = new DataSpec(audioByteUri);
try {
byteArrayDataSource.open(dataSpec);
} catch (IOException e) {
e.printStackTrace();
}
DataSource.Factory factory = new DataSource.Factory() {
@Override
public DataSource createDataSource() {
return byteArrayDataSource;
}
};
Log.i(TAG,"DataSource.Factory constructed.");
MediaSource audioSource = new ExtractorMediaSource(audioByteUri,
factory, new DefaultExtractorsFactory(),null,null);
Log.i(TAG,"Audio source constructed.");
exoPlayer.prepare(audioSource);
initMediaControls();
}
#2
0
byteArrayDataSource.getUri() is going to be null, if you dont call
如果不调用,byteArrayDataSource.getUri()将为空
byteArrayDataSource.open(DataSpec dataSpec). Look at code;
byteArrayDataSource。open(DataSpec DataSpec)。看代码;
public final class ByteArrayDataSource implements DataSource {
private final byte[] data;
private Uri uri;
private int readPosition;
private int bytesRemaining;
/**
* @param data The data to be read.
*/
public ByteArrayDataSource(byte[] data) {
Assertions.checkNotNull(data);
Assertions.checkArgument(data.length > 0);
this.data = data;
}
@Override
public long open(DataSpec dataSpec) throws IOException {
uri = dataSpec.uri;
readPosition = (int) dataSpec.position;
bytesRemaining = (int) ((dataSpec.length == C.LENGTH_UNSET)
? (data.length - dataSpec.position) : dataSpec.length);
if (bytesRemaining <= 0 || readPosition + bytesRemaining > data.length) {
throw new IOException("Unsatisfiable range: [" + readPosition + ", " + dataSpec.length
+ "], length: " + data.length);
}
return bytesRemaining;
}
@Override
public int read(byte[] buffer, int offset, int readLength) throws IOException {
if (readLength == 0) {
return 0;
} else if (bytesRemaining == 0) {
return C.RESULT_END_OF_INPUT;
}
readLength = Math.min(readLength, bytesRemaining);
System.arraycopy(data, readPosition, buffer, offset, readLength);
readPosition += readLength;
bytesRemaining -= readLength;
return readLength;
}
@Override
public Uri getUri() {
return uri;
}
@Override
public void close() throws IOException {
uri = null;
}
}