Android IjkPlayer 播放本地(Raw) 视频

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

你可能感兴趣的:(Android IjkPlayer 播放本地(Raw) 视频)