安卓队列缓存文件,包括断点续传

46 篇文章 1 订阅
20 篇文章 1 订阅

想起来之前做视频缓存的工具类,没事记一下,中间用了一个开源的缓存的进度库,其他的都是自己写的

其中网络请求时用的OkHttp3

缓存进度库用的是:

    compile 'io.github.lizhangqu:coreprogress:1.0.2'

封装的工具类:DownloadUtil.java


import android.text.TextUtils;
import android.util.Log;

import com.hkzr.docopad.minterface.OnDownloadListener;

import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import io.github.lizhangqu.coreprogress.ProgressHelper;
import io.github.lizhangqu.coreprogress.ProgressUIListener;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;

/**
 * 创   建:  lt
 * 作   用:   断点下载的类
 * 使用方法:
 * 注意事项:
 */

public class DownloadUtil {
    private Call call;
    private static DownloadUtil downloadUtil;
    private OkHttpClient okHttpClient;
    private List<Object[]> list;//call,url,startBytes,path,OnDownloadListener
    private OnDownloadListener onDownloadListener;
    private final static int ADD = 0;
    private final static int CANCEL = 1;
    private final static int SET = 2;

    private DownloadUtil() {
        okHttpClient = new OkHttpClient.Builder()
                .connectTimeout(30, TimeUnit.SECONDS)//设置超时时间之类的
                .readTimeout(30, TimeUnit.SECONDS)
                .writeTimeout(30, TimeUnit.SECONDS).build();
        list = new ArrayList<>();
    }

    /**
     * 单例初始化
     */
    public static DownloadUtil init() {
        if (downloadUtil == null) {
            synchronized (DownloadUtil.class) {
                if (downloadUtil == null) {
                    downloadUtil = new DownloadUtil();
                }
            }
        }
        return downloadUtil;
    }

    /**
     * 添加下载请求
     *
     * @param startBytes         从第几个字节开始
     * @param path               保存的路径
     * @param url                下载链接
     * @param onDownloadListener 回调
     */
    public void addDownload(long startBytes, String path, String url, OnDownloadListener onDownloadListener) {
        //添加Range头
        //传入链接
        Call call = okHttpClient.newCall(new Request.Builder().addHeader("RANGE", "bytes=" + startBytes + "-").url(url).get().build());
        list.add(new Object[]{call, url, startBytes, path, onDownloadListener});
        loop(ADD);
    }

    /**
     * 下载请求
     *
     * @param startBytes 从第几个字节开始
     * @param path       保存的路径
     */
    private void download(final long startBytes, final String path) {
        Log.i("lllttt", "DownloadUtil : " + startBytes);
        //回调
        try {
            call.enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    //失败了
                    if (onDownloadListener != null) {
                        onDownloadListener.onFailure(e);
                    }
                }

                @Override
                public void onResponse(Call call, Response response) {
                    ResponseBody body = response.body();
                    ResponseBody responseBody = ProgressHelper.withProgress(body, new ProgressUIListener() {
                        @Override
                        public void onUIProgressChanged(long numBytes, long totalBytes, float percent, float speed) {
                            if (onDownloadListener != null) {
                                onDownloadListener.onProgress(numBytes, totalBytes, percent, speed);
                            }
                        }

                        @Override
                        public void onUIProgressStart(long totalBytes) {
                            if (onDownloadListener != null) {
                                onDownloadListener.onStart(totalBytes);
                            }
                        }

                        @Override
                        public void onUIProgressFinish() {
                            if (onDownloadListener != null) {
                                onDownloadListener.onFinish();
                            }
                            try {
                                list.remove(0);
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                            DownloadUtil.this.call = null;
                            onDownloadListener = null;
                            loop(ADD);
                        }
                    });
                    save(responseBody, startBytes, path);
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void save(ResponseBody body, long startsPoint, String path) {
        InputStream in = body.byteStream();
        FileChannel channelOut = null;
        // 随机访问文件,可以指定断点续传的起始位置
        RandomAccessFile randomAccessFile = null;
        try {
            randomAccessFile = new RandomAccessFile(path, "rwd");
            //Chanel NIO中的用法,由于RandomAccessFile没有使用缓存策略,直接使用会使得下载速度变慢,亲测缓存下载3.3秒的文件,用普通的RandomAccessFile需要20多秒。
            channelOut = randomAccessFile.getChannel();
            randomAccessFile.seek(startsPoint);
            // 内存映射,直接使用RandomAccessFile,是用其seek方法指定下载的起始位置,使用缓存下载,在这里指定下载位置。
            MappedByteBuffer mappedBuffer = channelOut.map(FileChannel.MapMode.READ_WRITE, startsPoint, body.contentLength());
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = in.read(buffer)) != -1) {
                mappedBuffer.put(buffer, 0, len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
                if (channelOut != null) {
                    channelOut.close();
                }
                if (randomAccessFile != null) {
                    randomAccessFile.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 停止下载(暂停)
     *
     * @param url 下载路径
     */
    public void cancelDownload(String url) {
        loop(CANCEL, url);
    }

    /**
     * 停止所有
     */
    public void cancelAllDownload() {
        if (list != null)
            list.clear();
        if (call != null)
            call.cancel();
        call = null;
        if (onDownloadListener != null)
            onDownloadListener.onFailure(null);
        this.onDownloadListener = null;
    }

    /**
     * 开始某个下载任务
     *
     * @param url 链接
     */
    public void startDownLoad(long startBytes, String path, String url, OnDownloadListener onDownloadListener) {
        if (startBytes < 0) //todo
            startBytes = 0;
        //查询有没有这个下载链接,有就让他挪到第一位,没有就添加到第一位
        if (list != null && list.size() == 1 && !isHave(url)) {
            //如果只有几个暂停的,并开启了一个暂停的,并把第二个暂停的打开
            //应该把那个下载中的放为等待中,这个为开始下载
            Object[] objects = list.get(0);
            this.call.cancel();
            this.call = null;
            this.onDownloadListener = null;
            Call call = okHttpClient.newCall(new Request.Builder().addHeader("RANGE", "bytes=" + startBytes + "-").url(url).get().build());
            list.add(0, new Object[]{call, url, startBytes, path, onDownloadListener});
            loop(ADD);
        }
        if (isHave(url)) {
            //挪到第一位
            Object[] objs = null;
            for (Object[] objects : list) {
                if (objects[1].equals(url)) {
                    objs = objects;
                    break;
                }
            }
            if (list == null || list.size() <= 1) {
                loop(ADD);
            } else {
                list.remove(objs);
                list.add(1, objs);
                loop(CANCEL, String.valueOf(list.get(0)[1]));
            }
        } else {
            //添加到第一位
            Call c = okHttpClient.newCall(new Request.Builder().addHeader("RANGE", "bytes=" + startBytes + "-").url(url).get().build());
            list.add(0, new Object[]{c, url, startBytes, path, onDownloadListener});
            if (call != null)
                this.call.cancel();
            this.call = null;
            loop(ADD);
        }
    }

    /**
     * 判断这个任务是否在运行
     *
     * @param url 链接
     */
    public boolean isRun(String url) {
        if (list == null || list.size() == 0) {
            return false;
        }
        return list.get(0)[1].equals(url);
    }

    /**
     * 判断这个任务是否存在
     *
     * @param url 链接
     */
    public boolean isHave(String url) {
        if (list == null || list.size() == 0) {
            return false;
        }
        for (Object[] obj : list) {
            if (TextUtils.equals((String) obj[1], url))
                return true;
        }
        return false;
    }

    /**
     * 判断是否还有任务
     */
    public boolean isHave() {
        if (list == null)
            return false;
        return !(list.size() == 0);
    }

    /**
     * 给没有回调的下载请求设置回调
     *
     * @param url                视频下载链接
     * @param onDownloadListener 下载回调
     */
    public void setListener(String url, OnDownloadListener onDownloadListener) {
        loop(SET, url, onDownloadListener);
    }

    private void loop(int i) {
        loop(i, null);
    }

    private void loop(int i, String url) {
        loop(i, url, null);
    }

    /**
     * 轮询
     */
    private void loop(int i, String url, OnDownloadListener onDownloadListener) {
        if (list == null || list.size() == 0)
            return;
        switch (i) {
            case ADD:
                if (call != null)
                    return;
                Object[] objects = list.get(0);
                this.call = (Call) objects[0];
                this.onDownloadListener = (OnDownloadListener) objects[4];
                download((long) objects[2], (String) objects[3]);
                break;
            case CANCEL:
                for (int j = 0; j < list.size(); j++) {
                    Object[] objs = list.get(j);
                    if (objs[1].equals(url)) {
                        //如果url一样
                        ((Call) objs[0]).cancel();
                        list.remove(objs);
                        if (j == 0) {
                            call = null;
                            this.onDownloadListener = null;
                            loop(ADD);
                        }
                    }
                }
                break;
            case SET:
                for (int j = 0; j < list.size(); j++) {
                    if (list.get(j)[1].equals(url)) {
                        //如果url一样
                        list.get(j)[4] = onDownloadListener;
                        if (j == 0)
                            this.onDownloadListener = onDownloadListener;
                    }
                }
                break;
        }
    }

}

回调:OnDownloadListener.java


/**
 * 创   建:  lt
 * 作   用:   下载的回调
 * 使用方法:
 * 注意事项:
 */

public interface OnDownloadListener {
    /**
     * 下载失败
     */
    void onFailure(Exception e);

    /**
     * 下载开始
     *
     * @param totalBytes 一共多少字节
     */
    void onStart(long totalBytes);

    /**
     * 下载完成
     */
    void onFinish();

    /**
     * 下载中(不是第一次的话,会使总字节数发生变化,所以要在第一次下载的时候保存总字节数,然后自己计算百分比)
     *
     * @param numBytes   已经下载了多少字节
     * @param totalBytes 总字节
     * @param percent    万分比(乘以100为百分比)
     * @param speed      下载速度(* 1000 / 1024 / 1024 =M/s?)
     */
    void onProgress(long numBytes, long totalBytes, float percent, float speed);
}

下载用的服务:VideoCacheService.java


import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;

import com.hkzr.docopad.app.App;
import com.hkzr.docopad.greendao.VideoCacheInfoDao;
import com.hkzr.docopad.minterface.OnDownloadListener;
import com.hkzr.docopad.model.VideoCacheInfo;
import com.hkzr.docopad.utils.DownloadUtil;
import com.hkzr.docopad.utils.NetUtil;
import com.hkzr.docopad.utils.SDCardUtil;
import com.hkzr.docopad.utils.ToastUtil;

import java.util.ArrayList;
import java.util.List;

public class VideoCacheService extends Service {

    private DownloadUtil init;
    private boolean isCheck = false;//是否在检查网络和存储空间中

    public VideoCacheService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        return new BindVideoCache();
    }

    @Override
    public void onCreate() {
        super.onCreate();
        init = DownloadUtil.init();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    public void oneLoad(String videoName, long videoSize, String videoUrl,
                        int lookProgress, String videoId, long videoDuration
            , String videoImg, String savePath) {
        //如果sd卡可用,并且大于视频大小就可以走
        //如果内部存储大于视频大小就可以走
        if (!(SDCardUtil.isSDCardEnabled() && SDCardUtil.getSDCardAllSize() > videoSize || SDCardUtil.getAvailableInternalMemorySize() > videoSize)) {
            ToastUtil.showToast("磁盘已满,请清理足够的存储空间");
            return;
        }
        VideoCacheInfo videoCacheInfo = new VideoCacheInfo(null,//id
                videoName,//视频名称
                videoSize,//视频大小
                videoUrl,//视频路径
                0,//下载的百分比进度
                lookProgress,//播放的百分比进度
                videoId,//视频的id
                videoDuration,//视频持续时长,毫秒单位?
                videoImg,//视频预览图片
                savePath,//保存路径
                0,//下载字节数
                VideoCacheInfo.STAUS_NO_START);//状态,未开始
        App.ormDao.getVideoCacheInfoDao().insert(videoCacheInfo);
        load(0, savePath, videoUrl, null);
    }

    public void load(final long startBytes, String path, final String url, final OnDownloadListener onDownloadListener) {
        //如果磁盘满了或者无网络,则无需添加到队列中
        if (!NetUtil.isNetworkAvailable(getApplicationContext())) {
            ToastUtil.showToast("当前无网络,请检查网络链接后重试");
            if (onDownloadListener != null)
                onDownloadListener.onFailure(null);
            return;
        }
        init.addDownload(startBytes, path, url, onDownloadListener);
        if (!isCheck) {
            isCheck = true;
            handler.sendEmptyMessage(0);
        }
    }

    public void cancel(String url) {
        init.cancelDownload(url);
        for (VideoCacheInfo info : App.ormDao.getVideoCacheInfoDao().queryBuilder().where(VideoCacheInfoDao.Properties.VideoUrl.eq(url)).list()) {
            info.setStatus(VideoCacheInfo.STATUS_PAUSED);
            App.ormDao.getVideoCacheInfoDao().update(info);
        }
    }

    public void cancelAll() {
        init.cancelAllDownload();
        for (VideoCacheInfo info : App.ormDao.loadAll(VideoCacheInfo.class)) {
            if (info.getStatus() != VideoCacheInfo.STATUS_FINISH && info.getStatus() != VideoCacheInfo.STATUS_PAUSED) {
                info.setStatus(VideoCacheInfo.STAUS_NO_START);
                App.ormDao.getVideoCacheInfoDao().update(info);
            }
        }
    }

    public boolean isHave(String url) {
        return init.isHave(url);
    }

    public void setListener(String url, OnDownloadListener onDownloadListener) {
        if (!NetUtil.isNetworkAvailable(getApplicationContext())) {
            ToastUtil.showToast("当前无网络,请检查网络链接后重试");
            if (onDownloadListener != null)
                onDownloadListener.onFailure(null);
            return;
        }
        init.setListener(url, onDownloadListener);
    }

    public void startDownLoad(long startBytes, String path, String url, OnDownloadListener onDownloadListener) {
        if (!NetUtil.isNetworkAvailable(getApplicationContext())) {
            ToastUtil.showToast("当前无网络,请检查网络链接后重试");
            if (onDownloadListener != null)
                onDownloadListener.onFailure(null);
            return;
        }
        for (VideoCacheInfo info : App.ormDao.getVideoCacheInfoDao().queryBuilder().where(VideoCacheInfoDao.Properties.VideoUrl.eq(url)).list()) {
            info.setStatus(VideoCacheInfo.STATUS_STARTED);
            App.ormDao.getVideoCacheInfoDao().update(info);
        }
        init.startDownLoad(startBytes, path, url, onDownloadListener);
        if (!isCheck) {
            isCheck = true;
            handler.sendEmptyMessage(0);
        }
    }

    public void startAll() {
        List<VideoCacheInfo> videoCacheInfos = App.ormDao.getVideoCacheInfoDao().loadAll();
        if (videoCacheInfos == null || videoCacheInfos.size() == 0)
            return;
        List<VideoCacheInfo> list = new ArrayList<>();
        for (VideoCacheInfo info : videoCacheInfos) {
            if ((info.getStatus() == VideoCacheInfo.STAUS_NO_START || info.getStatus() == VideoCacheInfo.STATUS_STARTED) && !isHave(info.getVideoUrl())) {
                //表示需要下载,并且没在队列中
                list.add(info);
            }
        }
        if (list.size() == 0)
            return;
        for (VideoCacheInfo info : list) {
            load(info.getDownloadSpeed(), info.getLocalPath(), info.getVideoUrl(), null);
        }
    }

    Handler handler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            if (!init.isHave()) {
                //如果没有任务了就不检查了
                isCheck = false;
                return;
            }
            //还有任务就检查网络和内部存储
            if (!NetUtil.isNetworkAvailable(getApplicationContext())) {
                //没有网络就提醒,并暂停所有任务
                init.cancelAllDownload();
                ToastUtil.showToast("当前无网络,已暂停缓存任务");
                isCheck=false;
                return;
            }
            if ((SDCardUtil.isSDCardEnabled() && SDCardUtil.getSDCardAllSize() < 60 * 1024)
                    || SDCardUtil.getAvailableInternalMemorySize() < 60 * 1024 * 1024) {
                init.cancelAllDownload();
                ToastUtil.showToast("存储空间不足,已暂停缓存任务");
                isCheck=false;
                return;
            }
            handler.sendEmptyMessageDelayed(0, 6000);
        }
    };

    public boolean isRun(String url) {
        return init.isRun(url);
    }

    public class BindVideoCache extends Binder {
        /**
         * 第一次添加下载请求
         *
         * @param videoName     视频名称
         * @param videoSize     视频大小
         * @param videoUrl      视频路径
         * @param lookProgress  播放的百分比进度
         * @param videoId       视频的id
         * @param videoDuration 视频持续时长,毫秒单位?
         * @param videoImg      视频预览图片
         * @param savePath      保存路径
         */
        public void mOneLoad(String videoName, long videoSize, String videoUrl,
                             int lookProgress, String videoId, long videoDuration
                , String videoImg, String savePath) {//ps:其实这个方法根据设计模式原则应该是直接传一个对象的,懒得改了
            oneLoad(videoName, videoSize, videoUrl,
                    lookProgress, videoId, videoDuration
                    , videoImg, savePath);
        }

        /**
         * 开始下载(非第一次下载)
         *
         * @param startBytes         从第几个字节开始
         * @param path               保存的路径
         * @param url                下载链接
         * @param onDownloadListener 回调
         */
        public void mLoad(long startBytes, String path, String url, OnDownloadListener onDownloadListener) {
            load(startBytes, path, url, onDownloadListener);
        }

        /**
         * 停止下载(暂停)
         *
         * @param url 下载路径
         */
        public void mCancel(String url) {
            cancel(url);
        }

        /**
         * 停止所有
         */
        public void mCancelAll() {
            cancelAll();
        }

        /**
         * 判断缓存队列中是否存在该任务
         *
         * @param url 任务链接
         * @return 是否存在
         */
        public boolean mIsHave(String url) {
            return isHave(url);
        }

        /**
         * 设置回调
         *
         * @param url                视频链接
         * @param onDownloadListener 下载回调
         */
        public void mSetListener(String url, OnDownloadListener onDownloadListener) {
            setListener(url, onDownloadListener);
        }

        /**
         * 开始下载(暂停或停止后)
         *
         * @param startBytes         从第几个字节开始
         * @param path               保存的路径
         * @param url                下载链接
         * @param onDownloadListener 回调
         */
        public void mStartDownLoad(long startBytes, String path, String url, OnDownloadListener onDownloadListener) {
            startDownLoad(startBytes, path, url, onDownloadListener);
        }

        /**
         * 判断是否正在下载
         *
         * @param url 视频链接
         */
        public boolean mIsRun(String url) {
            return isRun(url);
        }


        /**
         * 是否在缓存中或缓存过
         *
         * @param vid 视频id
         */
        public boolean isVideoCacheOrCacheing(String vid) {
            List<VideoCacheInfo> list = App.ormDao.getVideoCacheInfoDao().queryBuilder().where(VideoCacheInfoDao.Properties.VideoId.eq(vid)).list();
            if (list != null && list.size() > 0) {
                //表示缓存过了或在缓存队列中
                return true;
            }
            return false;
        }

        /**
         * 加载并开始所有等待中和缓存中的任务,无监听
         * 如果已被加载,则不理会
         */
        public void mStartAll() {
            startAll();
        }
    }

}

附加一个缓存时使用的Bean类,使用了GreenDao来保存下载的进度和本地磁盘位置等信息:VideoCacheInfo.java


import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Generated;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.Keep;
import org.greenrobot.greendao.annotation.Transient;

import java.io.Serializable;

/**
 * 作   用:   缓存视频的bean类
 */

@Entity
public class VideoCacheInfo implements Serializable {
    /**
     * 0:  未开始, 正等待
     * 1:  已经开始
     * 2: 已停止,未完成
     * 3:  已暂停
     * 4:  已完成
     */
    @Transient
    public static final int STAUS_NO_START = 0;
    @Transient
    public static final int STATUS_STARTED = 1;
    @Transient
    public static final int STATUS_STOPED = 2;
    @Transient
    public static final int STATUS_PAUSED = 3;
    @Transient
    public static final int STATUS_FINISH = 4;

    @Id(autoincrement = true)
    private Long id;

    @Transient
    private HistoryBean history;

    private String videoName;//视频名称
    private long videoSize;//视频大小
    private String videoUrl;//视频链接
    private int downProgress;//下载进度
    private int lookProgress = -1;//观看进度
    private String videoId;//服务器id
    private long videoDuration;//视频持续时间
    private String videoIcon;//图片静态图片
    private String localPath;//本地存放路径
    private long downloadSpeed = 0;//下载字节数
    private int status = STAUS_NO_START;//状态
    @Transient
    private boolean isCheck;



    @Generated(hash = 1303373854)
    public VideoCacheInfo(Long id, String videoName, long videoSize,
            String videoUrl, int downProgress, int lookProgress, String videoId,
            long videoDuration, String videoIcon, String localPath,
            long downloadSpeed, int status) {
        this.id = id;
        this.videoName = videoName;
        this.videoSize = videoSize;
        this.videoUrl = videoUrl;
        this.downProgress = downProgress;
        this.lookProgress = lookProgress;
        this.videoId = videoId;
        this.videoDuration = videoDuration;
        this.videoIcon = videoIcon;
        this.localPath = localPath;
        this.downloadSpeed = downloadSpeed;
        this.status = status;
    }

    @Generated(hash = 843470261)
    public VideoCacheInfo() {
    }

    

    public int getLookProgress() {
        return lookProgress;
    }

    public void setLookProgress(int lookProgress) {
        this.lookProgress = lookProgress;
    }

    public boolean isCheck() {
        return isCheck;
    }

    public void setCheck(boolean check) {
        isCheck = check;
    }


    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getVideoName() {
        return videoName;
    }

    public void setVideoName(String videoName) {
        this.videoName = videoName;
    }

    public long getVideoSize() {
        return videoSize;
    }

    public void setVideoSize(long videoSize) {
        this.videoSize = videoSize;
    }

    public String getVideoUrl() {
        return videoUrl;
    }

    public void setVideoUrl(String videoUrl) {
        this.videoUrl = videoUrl;
    }

    public int getDownProgress() {
        return downProgress;
    }

    public void setDownProgress(int downProgress) {
        this.downProgress = downProgress;
    }

    public String getVideoId() {
        return videoId;
    }

    public void setVideoId(String videoId) {
        this.videoId = videoId;
    }

    public long getVideoDuration() {
        return videoDuration;
    }

    public void setVideoDuration(long videoDuration) {
        this.videoDuration = videoDuration;
    }

    public String getVideoIcon() {
        return videoIcon;
    }

    public void setVideoIcon(String videoIcon) {
        this.videoIcon = videoIcon;
    }

    public long getDownloadSpeed() {
        return downloadSpeed;
    }

    public void setDownloadSpeed(long downloadSpeed) {
        this.downloadSpeed = downloadSpeed;
    }

    @Keep
    public HistoryBean getHistory() {
        return history;
    }

    @Keep
    public void setHistory(HistoryBean history) {
        this.history = history;
    }

    public String getLocalPath() {
        return localPath;
    }

    public void setLocalPath(String localPath) {
        this.localPath = localPath;
    }

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    @Override
    public String toString() {
        return "VideoCacheInfo{" +
                "id=" + id +
                ", history=" + history +
                ", videoName='" + videoName + '\'' +
                ", videoSize='" + videoSize + '\'' +
                ", videoUrl='" + videoUrl + '\'' +
                ", downProgress=" + downProgress +
                ", videoId='" + videoId + '\'' +
                ", videoDuration=" + videoDuration +
                ", videoIcon='" + videoIcon + '\'' +
                ", localPath='" + localPath + '\'' +
                ", downloadSpeed=" + downloadSpeed +
                ", status=" + status +
                '}';
    }

}

有帮助或者有问题可以留言

对Kotlin或KMP感兴趣的同学可以进Q群 101786950

如果这篇文章对您有帮助的话

可以扫码请我喝瓶饮料或咖啡(如果对什么比较感兴趣可以在备注里写出来)

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值