android断点下载

断点下载由于4g比较慢 所以广泛应用,但是出了5g后估计就没啥用了哈哈
主要就是两点
第一:添加动态请求头 Range:bytes=start-end
范围 从开始到结束的位置
第二:就是RandomAccessFile类的使用

下载代码

  @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        try {

            File directory = Environment.getExternalStorageDirectory();
            final File file = new File(directory, "4567.apk");
            final RandomAccessFile accessFile = new RandomAccessFile(file, "rw");
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl("https://www.wandoujia.com/")

                    .build();
            RetrofitService retrofitService = retrofit.create(RetrofitService.class);
            String range=String.format("bytes=%d-",file.length());
            Call<ResponseBody> call = retrofitService.breadPointRetrofit(range);
            call.enqueue(new Callback<ResponseBody>() {
                @Override
                public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                    try {
                        ResponseBody body = response.body();
                        InputStream inputStream = body.byteStream();
                        long contentLength = body.contentLength();
                        byte[] bytes = new byte[1024];
                        int len;
                        accessFile.seek(file.length());
                        while ((len=inputStream.read(bytes))!=-1){
                            accessFile.write(bytes,0,len);
                            long length = file.length();
                            int l = (int) (length * 100 / contentLength);
                            Log.i("tag", "onResponse: "+l);
                            if (l == 50) {
                                Log.i("tag", "onResponse: "+"下载一半可以打一次性断点来实验");
                            }
                            EventBus.getDefault().post(l);

                        }
                        EventBus.getDefault().post(file);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void onFailure(Call<ResponseBody> call, Throwable t) {

                }
            });

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


        return super.onStartCommand(intent, flags, startId);
    }

response接口


public interface RetrofitService {

    @GET("https://www.wandoujia.com/apps/604363/download/dot?ch=detail_normal_dl")
    Call<ResponseBody> breadPointRetrofit(@Header("range") String range);
}

下载进度和下载安装

  @Subscribe(threadMode = ThreadMode.MAIN)
    public void breadPoint(Integer index) {
        progressbar.setProgress(index);
        tv.setText("当前进度:" + index);

    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    private void downloadApp(File file) {
        //        判断小于7.0版本
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {

            Intent intent = new Intent(Intent.ACTION_VIEW);
            //        7.0版本的uri方法
            Uri uri = Uri.fromFile(file);
            intent.setDataAndType(uri, "application/vnd.android.package-archive");
            startActivityForResult(intent, 2);
        } else {
            Intent intent = new Intent(Intent.ACTION_VIEW);
            //        7.0以上版本用fileprovider
            Uri uri = FileProvider.getUriForFile(this, "com.example.breadpointdownload" + "" +
                    ".provider", file);

            intent.setDataAndType(uri, "application/vnd.android.package-archive");
            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            startActivityForResult(intent, 2);

        }


    }

fileprovider之前有提过 这里也就不多说它的注册了

其实上面的代码有两个坑 专业人士可能看出来了有些新手估计还是一脸懵逼状态 第一在服务里retrofit的call请求是主线程工作 所以发送eventbus的时候虽然刷新ui但是最终结果还是一下就出了 如果没有evenbus直接会报错 第二就是eventbus在view中接收file值的时候用的修饰符错误 应该是public否则会接收不到值 以下是修改后的代码

 @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        try {

            File directory = Environment.getExternalStorageDirectory();
            final File file = new File(directory, "4567.apk");
            final RandomAccessFile accessFile = new RandomAccessFile(file, "rw");
            Retrofit retrofit = new Retrofit.Builder().baseUrl("https://www.wandoujia.com/")

                    .build();
            RetrofitService retrofitService = retrofit.create(RetrofitService.class);
            String range = String.format("bytes=%d-", file.length());
            final Call<ResponseBody> call = retrofitService.breadPointRetrofit(range);
//我们在这里开了一个线程池来操作耗时操作
            Executors.newCachedThreadPool().execute(new Runnable() {
                @Override
                public void run() {

                    try {
//查看当前线程名字
                        Log.i("tag", "run: " + Thread.currentThread().getName());
                        Response<ResponseBody> response = call.execute();
                        Log.i("tag", "onResponse: " + Thread.currentThread().getName());
                        ResponseBody body = response.body();
                        InputStream inputStream = body.byteStream();
                        long contentLength = body.contentLength();
                        byte[] bytes = new byte[1024];
                        int len;
                        accessFile.seek(file.length());
                        while ((len = inputStream.read(bytes)) != -1) {
                            accessFile.write(bytes, 0, len);
                            long length = file.length();
                            int l = (int) (length * 100 / contentLength);
                            Log.i("tag", "下载进度: " + l);

                            EventBus.getDefault().post(l);

                        }
                        EventBus.getDefault().post(file);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                }
            });


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


        return super.onStartCommand(intent, flags, startId);
    }

view界面的private修饰符改成public就可以了

总结:在使用retrofit或者rxjava的时候一定要注意当前线程是主线程还是子线程!还有就是eventbus传值的时候方法修饰符一定要public修饰!否则是很难受的

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 一、断点下载原理及步骤 对于断点下载,就是下载的过程中,都会出现一些异常情况,导致下载中断。虽说可以重新下载,但是...
    Mr_Dream阅读 5,245评论 0 2
  • 之前给大家分享了一下关于断点下载的基本套路和逻辑下面引入线程池来完成断点下载!主要就是让大家更深入的了解一下断点下...
    Ad大成阅读 4,421评论 0 2
  • 前言 断点续传是一个很传统的话题;现在但凡包含下载功能的软件,大部分都会有断点续传的功能;因此对于断点续传的实现,...
    IAM四十二阅读 6,716评论 2 5
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 13,907评论 1 32
  • 在讲故事之前,先让我科普一下。 咳!…… 十九世纪初,美国展开一场向西部扩张的西进运动,一批批冒险家纷纷向太平洋西...
    兔子之书阅读 1,837评论 0 1

友情链接更多精彩内容