update: 在更改代码完后记得 Bulid -> Clean Project, 不然可能因为缓存造成失败.
平时播放视频用的是官方DEMO下的IjkVideoView, 如果按照传统方法播放raw资源文件下的视频是不行的.
//该方法适用在系统自带的VideoView中使用, 在Ijk中无法识别
String path = "android.resource://" + getPackageName() + "/" + R.raw.filename;
查阅了半天资料, 试了多种方式, 最后筛选了其中有用的两篇, 现整理出来大家可以直接拿去用.
1. 实现接口IMediaDataSource
public class RawDataSourceProvider implements IMediaDataSource {
private AssetFileDescriptor mDescriptor;
private byte[] mMediaBytes;
public RawDataSourceProvider(AssetFileDescriptor descriptor) {
this.mDescriptor = descriptor;
}
@Override
public int readAt(long position, byte[] buffer, int offset, int size) throws IOException {
if(position + 1 >= mMediaBytes.length){
return -1;
}
int length;
if(position + size < mMediaBytes.length){
length = size;
}else{
length = (int) (mMediaBytes.length - position);
if(length > buffer.length)
length = buffer.length ;
length--;
}
System.arraycopy(mMediaBytes, (int) position, buffer, offset, length);
return length;
}
@Override
public long getSize() throws IOException {
long length = mDescriptor.getLength();
if(mMediaBytes == null){
InputStream inputStream = mDescriptor.createInputStream();
mMediaBytes = readBytes(inputStream);
}
return length;
}
@Override
public void close() throws IOException {
if(mDescriptor != null)
mDescriptor.close();
mDescriptor = null;
mMediaBytes = null;
}
private byte[] readBytes(InputStream inputStream) throws IOException {
ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
byteBuffer.write(buffer, 0, len);
}
return byteBuffer.toByteArray();
}
public static RawDataSourceProvider create(Context context, Uri uri){
try {
AssetFileDescriptor fileDescriptor = context.getContentResolver().openAssetFileDescriptor(uri, "r");
return new RawDataSourceProvider(fileDescriptor);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
2. 在IjkVideoView的openVideo()中进行修改
因为我的项目都是在4.4以上, 并且需求简单, 只是普通的方法一个视频, 所以没有过多的测试, 这里如果大家有什么需求, 请自己完善.
// 我将此段代码添加在else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH){} 中
//判断Uri是否是包含android.resource
if(mUri.getScheme().equals(ContentResolver.SCHEME_ANDROID_RESOURCE)){
RawDataSourceProvider rawDataSourceProvider = RawDataSourceProvider.create(context, mUri);
mMediaPlayer.setDataSource(rawDataSourceProvider);
}
完成.
接下来只要像平时一样使用就可以了, setVideoPath的path(或者setVideoUri) 获取依然使用开头的方式拼接.
参考和部分代码来源:
https://github.com/Bilibili/ijkplayer/issues/1013
http://www.cnblogs.com/xwgblog/p/5287151.html