retrofit2断点下载

这里先说一下断点下载的实现方法,在下载的过程中如果中断,记录下已下载的大小,当再次下载时我们就从已下载的文件长度开始,从而实现断点下载。这里主要以retrofit2网络框架为例

定义下载后存储路径

 		//文件存储路径
        final String patch = context.getExternalCacheDir() + "/downlaod/";

这里获取的是 SDCard/Android/data/你的应用包名/cache/目录,一般存放临时缓存数据。

定义接口

        @Streaming //下载大文件
        @GET
        Observable<ResponseBody> executeDownload(@Header("Range") String range, @Url() String url);

http协议从1.1开始支持获取文件的部分内容,这为并行下载以及断点续传提供了技术支持。它通过在Header里两个参数实现的,客户端发请求时对应的是Range,服务器端响应时对应的是Content-Range。Range作为请求头表示只请求实体的一部分,指定范围 Range: bytes=开始长度-结束长度如:0-999。

下载方法

public Subscription downFile(final long range, final String url, final Context context, final DownloadCallBack downloadCallback) {
        //请求的总长度
        File file = new File(patch, "tim.apk");
        String totalLength = "-";
        if (file.exists()) {
            totalLength += file.length();
        }
        return RetofitHttp.getInstance().executeDownload("bytes=" + Long.toString(range) + totalLength, url)
                .subscribeOn(Schedulers.io())
                .observeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .subscribe(new Observer<ResponseBody>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {
                        downloadCallback.onError(e.toString());
                    }

                    @Override
                    public void onNext(ResponseBody responseBody) {
                        RandomAccessFile randomAccessFile = null;
                        InputStream inputStream = null;
                        long total = range;
                        long responseLength = 0;
                        try {
                            byte[] buf = new byte[2048];
                            int len = 0;
                            responseLength = responseBody.contentLength();
                            inputStream = responseBody.byteStream();
                            File file = new File(patch, "tim.apk");
                            File dir = new File(patch);
                            if (!dir.exists()) {
                                dir.mkdirs();
                            }
                            randomAccessFile = new RandomAccessFile(file, "rwd");
                            if (range == 0) {
                                randomAccessFile.setLength(responseLength);
                            }
                            randomAccessFile.seek(range);
                            int progress = 0;
                            int lastProgress = 0;
                            while ((len = inputStream.read(buf)) != -1) {
                                randomAccessFile.write(buf, 0, len);
                                total += len;
                                lastProgress = progress;
                                progress = (int) (total * 100 /  randomAccessFile.length());
                                if (progress > 0 && progress != lastProgress) {
                                    downloadCallback.onProgress(progress);
                                }
                            }
                            downloadCallback.onCompleted();
                        } catch (Exception e) {
                            downloadCallback.onError(e.getMessage());
                            e.printStackTrace();
                        } finally {
                            try {
                            	//此处是存储文件下载的长度
                                SharedPreferencesUtils.setParam(context, "apkLength", total);
                                if (randomAccessFile != null) {
                                    randomAccessFile.close();
                                }
                                if (inputStream != null) {
                                    inputStream.close();
                                }

                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }

                    }
                });
    }

这里我是将下载与文件处理都放置在子线程之中,避免异常

下载监听

public interface DownloadCallBack {

    void onProgress(int progress);

    void onCompleted();

    void onError(String msg);

}

下载调用

 final File file = new File(patch+"tim.apk");
            long range = 0;
            int progress = 0;
            if (file.exists()) {
                range = (long) SharedPreferencesUtils.getParam(getNonNullActivity(), "apkLength", 0L);
                progress = (int) (range * 100 / file.length());
                if (range == file.length()) {
                    mBinding.tvText.setText("100%");
                    return;
                }
            }
            HttpMethods.getInStance().downFile(range, "http://sqdd.myapp.com/myapp/qqteam/tim/down/tim.apk", getNonNullActivity(), new DownloadCallBack() {
                @Override
                public void onProgress(int progress) {
                    getNonNullActivity().runOnUiThread(() -> {
                        
                    });
                }

                @Override
                public void onCompleted() {
                    getNonNullActivity().runOnUiThread(() -> {
                      
                    });
                }

                @Override
                public void onError(String msg) {
                    getNonNullActivity().runOnUiThread(() -> {
                        
                    });

                }
            });

由于下载响应文件处理是在子线程所以监听回调如果要做UI回应的话是需要在主线程操作的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值