OkHttp、Retrofit、Http、断点下载

//初始化SD卡

private void initSD() {

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) ==

                PackageManager.PERMISSION_GRANTED) {

            readSD();

        } else {

            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission

                    .WRITE_EXTERNAL_STORAGE}, 100);

        }

    }



//权限处理

    @Override

    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,

                                          @NonNull int[] grantResults) {

        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        switch (requestCode) {

            case 100:

                if (grantResults.length > 0 && grantResults[0] == PackageManager

                        .PERMISSION_GRANTED) {

                    readSD();

                }

                break;

        }

    }



//读取SD卡

    private void readSD() {

        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {

            sd = Environment.getExternalStorageDirectory();

        }

    }


private void moreHttp() {

        ThreadManager.getThreadManager().execute(new Runnable() {

            @Override

            public void run() {

                try {

                    //1.通过网络加载获取文件长度

                    URL urlStr = new URL(url);

                    HttpURLConnection con = (HttpURLConnection) urlStr.openConnection();

                    int contentLength = con.getContentLength();

                    Log.e(TAG, "run: " + contentLength);

                    //2.c创建空白文件,指定长度

                    RandomAccessFile rw = new RandomAccessFile(mDownPath, "rw");

                    rw.setLength(contentLength);

                    //3.各自线程设置下载对应的长度

                    long block = contentLength / THREAD_COUNT;

                    //4.创建指定个数的线程并给定下载范围下载

                    for (int i = 0; i < THREAD_COUNT; i++) {

                        long start = i * block;

                        long end = (i + 1) * block - 1;

                        if (i == THREAD_COUNT - 1) {

                            end = contentLength - 1;

                        }

                        //4.开始各自线程的下载即可(加请求范围头,判断状态码206,从对应线程开始位置写入数据)

                        //down(i, start, end);//多线程下载

                        downContinue(i, start, end);//多线程断点下载

                    }

                } catch (MalformedURLException e) {

                    e.printStackTrace();

                } catch (IOException e) {

                    e.printStackTrace();

                }

            }

        });

    }



   //断点下载

private void downContinue(final int threadId, final long start, final long end) {

        Log.d(TAG, "线程: " + threadId + ",下载范围:" + start + "--" + end);

        ThreadManager.getThreadManager().execute(new Runnable() {

            @Override

            public void run() {

                //记录当前线程下载位置

                long currentPosition = start;

                //获取sp中的下载位置,如果为0,说明没有下载过或者下载完成过

                long position = (long)SharedPreferencesUtils.getParam(MainActivity.this, threadId + "",

                        0L);

                if (position == 0){//没有下载记录

                    currentPosition = start;

                    Log.d(TAG, "非断点续传: "+threadId+",currentPosition:"+currentPosition);

                }else{//有级录

                    currentPosition = position;

                    Log.d(TAG, "断点续传: "+threadId+",currentPosition:"+currentPosition);

                }

                URL urlStr = null;

                try {

                    urlStr = new URL(url);

                    HttpURLConnection con = (HttpURLConnection) urlStr.openConnection();

                    //设置请求部分数据资源:Range:bytes=10-30

                    con.setRequestProperty("Range", "bytes=" + currentPosition + "-" + end);

                    int responseCode = con.getResponseCode();

                    Log.d(TAG, "responseCode: " + responseCode);

                    //206,请求部分资源

                    if (responseCode == 206) {

                        InputStream inputStream = con.getInputStream();

                        RandomAccessFile rw = new RandomAccessFile(mDownPath, "rw");

                        //设置当前线程写入的位置

                        rw.seek(currentPosition);

                        int length = -1;

                        byte[] bys = new byte[1024 * 10];

                        while ((length = inputStream.read(bys)) != -1) {

                            rw.write(bys, 0, length);

                            currentPosition += length;

                            Log.d(TAG, "线程: " + threadId + "开始:" + start + " 当前下载:" + currentPosition + " " +

                                    "结束:" + end);

                            //将当前写入的位置保存

                            SharedPreferencesUtils.setParam(MainActivity.this,threadId+"",currentPosition);

                            if (threadId == 0){

                                pb.setMax((int)end);

                                pb.setProgress((int)currentPosition);

                            }else  if (threadId == 1){

                                pb1.setMax((int)end);

                                pb1.setProgress((int)currentPosition);

                            }else  if (threadId == 2){

                                pb2.setMax((int)end);

                                pb2.setProgress((int)currentPosition);

                            }

                        }

                        inputStream.close();

                        rw.close();

                        Log.d(TAG, "线程: " + threadId + "下载玩完毕");

                        //完成下载后将当前的写入位置置零

                        SharedPreferencesUtils.setParam(MainActivity.this,threadId+"",0L);

                    }

                } catch (MalformedURLException e) {

                    e.printStackTrace();

                } catch (IOException e) {

                    e.printStackTrace();

                }

            }

        });

    }

    private void down(final int threadId, final long start, final long end) {

        Log.d(TAG, "线程: " + threadId + ",下载范围:" + start + "--" + end);

        ThreadManager.getThreadManager().execute(new Runnable() {

            @Override

            public void run() {

                URL urlStr = null;

                try {

                    urlStr = new URL(url);

                    HttpURLConnection con = (HttpURLConnection) urlStr.openConnection();

                    //设置请求部分数据资源:Range:bytes=10-30

                    con.setRequestProperty("Range", "bytes=" + start + "-" + end);

                    int responseCode = con.getResponseCode();

                    Log.d(TAG, "responseCode: " + responseCode);

                    //206,请求部分资源

                    if (responseCode == 206) {

                        InputStream inputStream = con.getInputStream();

                        RandomAccessFile rw = new RandomAccessFile(mDownPath, "rw");

                        rw.seek(start);

                        int count = (int) start;

                        int length = -1;

                        byte[] bys = new byte[1024 * 10];

                        while ((length = inputStream.read(bys)) != -1) {

                            rw.write(bys, 0, length);

                            count += length;

                            Log.d(TAG, "线程: " + threadId + "开始:" + start + " 当前下载:" + count + " " +

                                    "结束:" + end);

                            if (threadId == 0){

                                pb.setMax((int)end);

                                pb.setProgress((int)count);

                            }else  if (threadId == 1){

                                pb1.setMax((int)end);

                                pb1.setProgress((int)count);

                            }else  if (threadId == 2){

                                pb2.setMax((int)end);

                                pb2.setProgress((int)count);

                            }

                        }

                        inputStream.close();

                        rw.close();

                    }

                } catch (MalformedURLException e) {

                    e.printStackTrace();

                } catch (IOException e) {

                    e.printStackTrace();

                }

            }

        });

    }




    //Http下载

private void http(final String path) {

        ThreadManager.getThreadManager().execute(new Runnable() {

            @Override

            public void run() {

                try {

                    URL urlStr = new URL(url);

                    HttpURLConnection con = (HttpURLConnection) urlStr.openConnection();

                    int responseCode = con.getResponseCode();

                    if (responseCode == 200) {

                        InputStream inputStream = con.getInputStream();

                        int max = con.getContentLength();

                        saveFile(inputStream, path, max);

                    }

                } catch (MalformedURLException e) {

                    e.printStackTrace();

                } catch (IOException e) {

                    e.printStackTrace();

                }

            }

        });

    }



  //retrofit下载

  private void retrofit(final String path) {

        Retrofit retrofit = new Retrofit.Builder()

                .baseUrl(MyServer.Url)

                .addConverterFactory(GsonConverterFactory.create())

                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())

                .build();

        MyServer myServer = retrofit.create(MyServer.class);

        Observable download = myServer.download();

        download.subscribeOn(Schedulers.io())

                .subscribe(new Observer() {

                    @Override

                    public void onSubscribe(Disposable d) {

                    }

                    @Override

                    public void onNext(ResponseBody responseBody) {

                        long max = responseBody.contentLength();

                        InputStream inputStream = responseBody.byteStream();

                        saveFile(inputStream, path, max);

                    }

                    @Override

                    public void onError(Throwable e) {

                        Log.e(TAG, "onError: " + e.getMessage());

                    }

                    @Override

                    public void onComplete() {

                    }

                });

    }

//OkHttp下载

    private void ok(final String path) {

        OkHttpClient okHttpClient = new OkHttpClient.Builder()

                .build();

        Request request = new Request.Builder()

                .url(url)

                .get()

                .build();

        Call call = okHttpClient.newCall(request);

        call.enqueue(new Callback() {

            @Override

            public void onFailure(Call call, IOException e) {

                Log.e(TAG, "onFailure: " + e.getMessage());

            }

            @Override

            public void onResponse(Call call, Response response) throws IOException {

                ResponseBody body = response.body();

                InputStream inputStream = body.byteStream();

                long max = body.contentLength();

                //文件下载保存

                saveFile(inputStream, path, max);

            }

        });

    }

//保存文件

    private void saveFile(InputStream inputStream, final String path, long max) {

        try {

            FileOutputStream fos = new FileOutputStream(new File(path));

            long count = 0;

            int length = -1;

            byte[] bys = new byte[1024 * 10];

            while ((length = inputStream.read(bys)) != -1) {

                fos.write(bys, 0, length);

                count += length;

                Log.e(TAG, "count: " + count + ", max:" + max);

                //进度条和视频播放SurfaceView可以直接在子线程中刷新

                pb.setMax((int) max);

                pb.setProgress((int) count);

            }

            inputStream.close();

            fos.close();

            runOnUiThread(new Runnable() {

                @Override

                public void run() {

                    Toast.makeText(MainActivity.this, "下载完毕", Toast.LENGTH_SHORT).show();

                    //apk安装处理

                    mPath = path;

                    InstallUtil.installApk(MainActivity.this, path);

                }

            });

        } catch (FileNotFoundException e) {

            e.printStackTrace();

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

    /**

    * 8.0安装处理         下载完自动安装

    */

    private String mPath = null;

    @Override

    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {

        super.onActivityResult(requestCode, resultCode, data);

        if (resultCode == RESULT_OK && requestCode == InstallUtil.UNKNOWN_CODE) {

            InstallUtil.installApk(MainActivity.this, mPath);//再次执行安装流程,包含权限判等

        }

    }

}



//自动安装工具类

public class InstallUtil {

    public static final int UNKNOWN_CODE = 2019;

    public static void installApk(Context context, String path) {

        if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){

            startInstallO(context,path);

        }else if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.N){

            startInstallN(context,path);

        }else {

            startInstall(context,path);

        }

    }

    /**

    *android1.x-6.x

    *@param path 文件的路径

    */

    private static void startInstall(Context context, String path) {

        Intent install = new Intent(Intent.ACTION_VIEW);

        install.setDataAndType(Uri.parse("file://" + path), "application/vnd.android.package-archive");

        install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        context.startActivity(install);

    }

    /**

    * android7.x

    * @param path 文件路径

    *

    * 清单文件配置

    *         

    *            android:authorities="com.baidu.download.provider"

    *            android:name="android.support.v4.content.FileProvider"

    *            android:exported="false"

    *            android:grantUriPermissions="true">

    *           

    *                android:name="android.support.FILE_PROVIDER_PATHS"

    *                android:resource="@xml/file_paths"/>

    *       

    *

    *

    *          代表的根目录: Context.getFilesDir()

    *          代表的根目录: Environment.getExternalStorageDirectory()

    *          代表的根目录: getCacheDir()

    */

    @RequiresApi(api = Build.VERSION_CODES.N)

    private static void startInstallN(Context context, String path) {

        //参数1 上下文, 参数2 在AndroidManifest中的android:authorities值, 参数3  共享的文件

        Uri apkUri = FileProvider.getUriForFile(context, "com.baidu.download.provider", new File(path));

        Intent install = new Intent(Intent.ACTION_VIEW);

        //由于没有在Activity环境下启动Activity,设置下面的标签

        install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        //添加这一句表示对目标应用临时授权该Uri所代表的文件

        install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

        install.setDataAndType(apkUri, "application/vnd.android.package-archive");

        context.startActivity(install);

    }

    /**

    * android8.x

    *

    *       

    *

    *        调起未知应用来源

    *        回调处理:

    *

            *  private String mPath = null;

            *    @Override

            *    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {

            *        super.onActivityResult(requestCode, resultCode, data);

            *        if (resultCode == RESULT_OK && requestCode == InstallUtil.UNKNOWN_CODE) {

            *            InstallUtil.installApk(MainActivity.this,mPath);//再次执行安装流程,包含权限判等

            *        }

            *    }

    *

    */

    @RequiresApi(api = Build.VERSION_CODES.O)

    private static void startInstallO(final Context context, String path) {

        boolean isGranted = context.getPackageManager().canRequestPackageInstalls();

        if (isGranted) startInstallN(context,path);//安装应用的逻辑(写自己的就可以)

        else new AlertDialog.Builder(context)

                .setCancelable(false)

                .setTitle("安装应用需要打开未知来源权限,请去设置中开启权限")

                .setPositiveButton("确定", new DialogInterface.OnClickListener() {

                    public void onClick(DialogInterface d, int w) {

                        Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);

                        Activity act = (Activity) context;

                        act.startActivityForResult(intent, UNKNOWN_CODE);

                    }

                })

                .show();

    }

}

你可能感兴趣的:(OkHttp、Retrofit、Http、断点下载)