前言
關(guān)于ExoPlayer的使用,很多前人已經(jīng)幫我們翻譯了官方文檔,例如ExoPlayer使用,這里不再闡述。
但是上述文章一般就是將官方文檔翻譯一下,針對(duì)具體的使用,可能會(huì)遇到很多難以解決問(wèn)題。
正文
某天,我想用ExoPlayer播放一段存放在res/raw文件夾下的ogg格式的音頻,在之前代碼中,使用Mediaplayer播放,一切正常。
但是,有了高逼格的ExoPlayer,肯定要放棄Mediaplayer啊,畢竟程序員都是喜新厭舊的嘛(手動(dòng)滑稽)。所以,那就根據(jù)官方API開(kāi)整,這里就放核心代碼
DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory selectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(selectionFactory);
currentPlayer = ExoPlayerFactory.newSimpleInstance(this.context, trackSelector);
DataSource.Factory dataSourceFactory = buildDataSourceFactory(this.context, bandwidthMeter);
ExtractorMediaSource mediaSource = new ExtractorMediaSource(FmManager.getUriById(context, resId),
dataSourceFactory, new DefaultExtractorsFactory(), null, null);
LoopingMediaSource loopingMediaSource = new LoopingMediaSource(mediaSource); //循環(huán)播放
currentPlayer.prepare(loopingMediaSource);
currentPlayer.addListener(this);
currentPlayer.setPlayWhenReady(true);
private DataSource.Factory buildDataSourceFactory(Context context, DefaultBandwidthMeter bandwidthMeter) {
return new DefaultDataSourceFactory(context,
Util.getUserAgent(context, context.getString(R.string.app_name)), bandwidthMeter);
}
//根據(jù)raw資源ID獲取URI
public static Uri getUriById(Context context, int rawId) {
String basePath = "android.resource://";
StringBuilder stringBuilder = new StringBuilder(basePath);
String uriStr = stringBuilder.append(context.getPackageName()).append("/").append(rawId).toString();
return Uri.parse(uriStr);
}
代碼基本是根據(jù)官方Demo提供的,一運(yùn)行,哎喲,報(bào)錯(cuò)了:
com.google.android.exoplayer.upstream.HttpDataSource$HttpDataSourceException: Unable to connect to android.resource://```
納尼?報(bào)資源找不到,可是獲取Uri的方法沒(méi)錯(cuò)啊,打開(kāi)Chrome,上Google,不搜不要緊,一搜好多人都遇到這個(gè)問(wèn)題,看來(lái)代碼沒(méi)寫錯(cuò),那就一個(gè)個(gè)帖子找吧。
找來(lái)找去,大家的解決辦法竟然是將raw中音頻資源放到assets目錄下,這真是沒(méi)辦法的辦法,但是轉(zhuǎn)念一想,Google不至于這么坑爹吧,難道放在raw中的資源就無(wú)法使用了么?
打開(kāi)官方文檔(http://google.github.io/ExoPlayer/doc/reference/)

這里肯定是和raw資源有關(guān),繼續(xù)往下看

1.使用buildRawResourceUri(int rawResourceId)傳入資源ID,得到Uri
public static Uri buildRawResourceUri(int rawResourceId)
Builds a Uri for the specified raw resource identifier.```
2.使用DataSpec(Uri uri),得到DataSpec對(duì)象,
DataSpec(Uri uri)
Construct a DataSpec for the given uri and with key set to null.```
3.創(chuàng)建RawResourceDataSource對(duì)象,最后使用 open(DataSpec dataSpec)打開(kāi)之前的DataSpec對(duì)象
public long open(DataSpec dataSpec)
throws RawResourceDataSource.RawResourceDataSourceException
Description copied from interface: DataSource
Opens the source to read the specified data. ```
4.使用RawResourceDataSource的getUri();得到Uri
public Uri getUri()
Description copied from interface: DataSource
When the source is open, returns the Uri from which data is being read. The returned Uri will be identical to the one passed DataSource.open(DataSpec) in the DataSpec unless redirection has occurred. If redirection has occurred, the Uri after redirection is returned.```
那就修改根據(jù)資源ID獲取Uri的方法,完整代碼如下:
DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory selectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(selectionFactory);
currentPlayer = ExoPlayerFactory.newSimpleInstance(this.context, trackSelector);
try {
DataSpec dataSpec = new DataSpec(RawResourceDataSource.buildRawResourceUri(this.resId));
RawResourceDataSource rawResourceDataSource = new RawResourceDataSource(context);
rawResourceDataSource.open(dataSpec);
DataSource.Factory factory = () -> rawResourceDataSource;
ExtractorMediaSource mediaSource = new ExtractorMediaSource(rawResourceDataSource.getUri(),
factory, new DefaultExtractorsFactory(), null, null);
LoopingMediaSource loopingMediaSource = new LoopingMediaSource(mediaSource);
currentPlayer.prepare(loopingMediaSource);
currentPlayer.addListener(this);
currentPlayer.setPlayWhenReady(true);
} catch (RawResourceDataSource.RawResourceDataSourceException e) {
e.printStackTrace();
}
重新編譯運(yùn)行,ok,順利播放,看來(lái)還是官方靠譜
----------------
####總結(jié)
針對(duì)ExoPlayer播放raw中資源,不同于Mediaplayer方式,需要通過(guò)下列代碼獲取Uri,才能成功
DataSpec dataSpec = new DataSpec(RawResourceDataSource.buildRawResourceUri(this.resId));
RawResourceDataSource rawResourceDataSource = new RawResourceDataSource(context);
rawResourceDataSource.open(dataSpec);
rawResourceDataSource.getUri()```