大多数人多ExoPlayer的了解,仅限于ExoPlayer是一个高效的播放器,目前在播放器之中,ExoPlayer也算是独树一帜了,ExoPlayer在Github上非常火,使用的人非常多,可见ExoPlayer的功能、性能还是优化的相当不错的。
我们使用一个开源库,会用当然是好的,如果在第一步会用之后,还能深入分析其中的原理方法,将开源的东西消化一下,还在原有的基础上扩展原有的功能,修复原有项目的问题。最终也能在开源项目的基础上优化开源项目。得到符合我们业务场景的功能。
1.DataSource分析
DataSource在ExoPlayer中就是请求url的接口类,当然要看你播放的url是什么schema的,代码流程就不分析了,感兴趣可以自己看一下. 你输入一个url,这个url是什么schema,然后用对应schema的子DataSource去请求. 在DefaultDataSource.java中:
public long open(DataSpec dataSpec) throws IOException {
Assertions.checkState(dataSource == null);
// Choose the correct source for the scheme.
String scheme = dataSpec.uri.getScheme();
if (Util.isLocalFileUri(dataSpec.uri)) {
String uriPath = dataSpec.uri.getPath();
if (uriPath != null && uriPath.startsWith("/android_asset/")) {
dataSource = getAssetDataSource();
} else {
dataSource = getFileDataSource();
}
} else if (SCHEME_ASSET.equals(scheme)) {
dataSource = getAssetDataSource();
} else if (SCHEME_CONTENT.equals(scheme)) {
dataSource = getContentDataSource();
} else if (SCHEME_RTMP.equals(scheme)) {
dataSource = getRtmpDataSource();
} else if (SCHEME_UDP.equals(scheme)) {
dataSource = getUdpDataSource();
} else if (DataSchemeDataSource.SCHEME_DATA.equals(scheme)) {
dataSource = getDataSchemeDataSource();
} else if (SCHEME_RAW.equals(scheme)) {
dataSource = getRawResourceDataSource();
} else {
dataSource = baseDataSource;
}
// Open the source and return.
return dataSource.open(dataSpec);
}
DataSource接口中的方法如下:
/**
* A component from which streams of data can be read.
*/
public interface DataSource {
void addTransferListener(TransferListener transferListener);
long open(DataSpec dataSpec) throws IOException;
int read(byte[] buffer, int offset, int readLength) throws IOException;
@Nullable Uri getUri();
default Map<String, List<String>> getResponseHeaders() {
return Collections.emptyMap();
}
void close() throws IOException;
}
- addTransferListener : 增加数据传输的监听
- open : 发起请求的地方,可以是网络请求,也可以是请求本地文件
- read : 读流数据
- getUri : 获取请求的uri
- getResponseHeaders : 获取请求的response header
- close : 关掉流
这几个操作是必须的操作,当然你可以根据自己的业务需求增加额外的接口.
主要看一下TransferListener中的传入监听接口
public interface TransferListener {
void onTransferInitializing(DataSource source, DataSpec dataSpec, boolean isNetwork);
void onTransferStart(DataSource source, DataSpec dataSpec, boolean isNetwork);
void onBytesTransferred(
DataSource source, DataSpec dataSpec, boolean isNetwork, int bytesTransferred);
void onTransferEnd(DataSource source, DataSpec dataSpec, boolean isNetwork);
}
其中的onBytesTransferred( DataSource source, DataSpec dataSpec, boolean isNetwork, int bytesTransferred)函数回调告诉开发者当前已经加载了多少流数据,方便做流量控制. ExoPlayer 这方面还是很贴心的.
DataSource之间的类关系如下:
2.okhttp替换源生的网络请求
原生的网络请求核心处理在DefaultHttpDataSource.java中,okhttp在链接复用、多线程控制、定制化方面做得比较好,我们在ExoPlayer中也想接入okhttp库。如何使用?
- 需要引入两个类,如上,OkHttpDataSourceFactory.java和OkHttpDataSource.java
- 在buildDataSource的时候用OkHttpDataSourceFactory替换DefaultHtttpDataSourceFactory就可以了。
具体可以参考github.com/JeffMony/Pl…