文件下载

作者: Anwfly | 来源:发表于2019-04-17 22:22 被阅读21次

1. OkHttp下载文件(权限处理)

public static void okDownload(String url, final String path, final ResultCallBack callBack){
        OkHttpClient client = new OkHttpClient.Builder()
                .build();

        Request request = new Request.Builder()
                .url("http://cdn.banmi.com/banmiapp/apk/banmi_330.apk")
                .get()
                .build();

        Call call = client.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();
                saveFile(inputStream,sd+"/"+"abc123.apk",body.contentLength());
            }
        });
​
    }
    /**
     * 保存文件
     * @param inputStream
     * @param path
     * @param callBack
     * @param max
     */
    private static void saveFiles(InputStream inputStream, String path, ResultCallBack callBack, long max) {
      //读写的进度
        long count = 0;
        try {
            FileOutputStream outputStream = new FileOutputStream(new File(string));

            int length = -1;
            byte[] bys = new byte[1024*10];

            while((length = inputStream.read(bys))!=-1){
                outputStream.write(bys,0,length);

                count += length;

                Log.d(TAG, "progress: "+count  +"    max:" + max);
            }

            inputStream.close();
            outputStream.close();

            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(MainActivity.this,"下载完成",Toast.LENGTH_SHORT).show();

                    InstallUtil.installApk(MainActivity.this,string);
                }
            });
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

2.Retrofit下载:

    public static void retrofitDown(final String path, final ResultCallBack callBack) {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(ApiService.mBaseUrl)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
​
        ApiService apiService = retrofit.create(ApiService.class);
        Observable<ResponseBody> download = apiService.download();
        download.subscribeOn(Schedulers.io())//io线程
                .subscribe(new Observer<ResponseBody>() {
                  //因为要写文件,所以Observer不切换到主线程
                    @Override
                    public void onSubscribe(Disposable d) {
​
                    }
​
                    @Override
                    public void onNext(ResponseBody responseBody) {
                        InputStream inputStream = responseBody.byteStream();
                        saveFiles(inputStream,path,callBack,responseBody.contentLength());
                    }
​
                    @Override
                    public void onError(Throwable e) {
                        callBack.onFail(e.getMessage());
                    }
​
                    @Override
                    public void onComplete() {
​
                    }
                });
    }

3.HttpUrlConnection下载:

这里用到了线程池:

public class ThreadManager {
    private static ThreadManager mManager;
    private final ThreadPoolExecutor mExecutor;
​
    private ThreadManager(){
        mExecutor = new ThreadPoolExecutor(5,//核心线程数量,核心池的大小
                20,//线程池最大线程数
                30,//表示线程没有任务执行时最多保持多久时间会终止
                TimeUnit.SECONDS,//时间单位
                new LinkedBlockingQueue<Runnable>(),//任务队列,用来存储等待执行的任务
                Executors.defaultThreadFactory(),//线程工厂,如何去创建线程的
                new ThreadPoolExecutor.AbortPolicy());
    }
    public static ThreadManager getInstance(){
        if (mManager == null){
            synchronized (ThreadManager.class){
                if (mManager == null){
                    mManager = new ThreadManager();
                }
            }
        }
​
        return mManager;
    }
​
    /**
     * 执行任务
     */
    public void execute(Runnable runnable){
        if(runnable==null)return;
​
        mExecutor.execute(runnable);
    }
    /**
     * 从线程池中移除任务
     */
    public void remove(Runnable runnable){
        if(runnable==null)return;
​
        mExecutor.remove(runnable);
    }
​
}
public static void httpDownload(final String url, final String path, final ResultCallBack callBack) {
        ThreadManager.getInstance().execute(new Runnable() {
            @Override
            public void run() {
            //由线程池提供线程
                try {
                    URL url1 = new URL(url);
                    HttpURLConnection conn = (HttpURLConnection) url1.openConnection();
                    int responseCode = conn.getResponseCode();
                    if (responseCode == 200){
                        InputStream inputStream = conn.getInputStream();
                        int max = conn.getContentLength();
                        saveFiles(inputStream,path,callBack,max);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    callBack.onFail(e.getMessage());
                }
            }
        });
    }

4.下载ok后,安装对应得apk,例如使用okhttp下载

private void okDown() {
        DownLoadUtil.okDownload(mUrl, "/storage/emulated/0/my.apk", new DownLoadUtil.ResultCallBack() {
            @Override
            public void onFail(String message) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        ToastUtil.showToast(MainActivity.this, "下载失败");
                    }
                });
​
            }
​
            @Override
            public void onProgress(long progress, long max) {
                mPb.setMax((int) max);
                mPb.setProgress((int) progress);
            }
​
            @Override
            public void onSuccess(final String path) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        ToastUtil.showToast(MainActivity.this, "下载成功");
                        mPath = path;
                        installApk(mPath);
                    }
                });
            }
        });
    }
    //安装apk,交给InstallUtil完成
    private void installApk(String path) {
        InstallUtil.installApk(this, path);
    }
​
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == InstallUtil.UNKNOWN_CODE) {
            //8.0安装未受信任来源的app,需要再次执行安装流程,包含权限判等
            InstallUtil.installApk(this, mPath);
        }
    }

5.多线程断点续传--下载:

private void moreDown() {
        ThreadManager.getInstance().execute(new Runnable() {
            @Override
            public void run() {
                try {
                    URL url = new URL(mUrl);
                    HttpURLConnection con = (HttpURLConnection) url.openConnection();
                    //1.获取要下载文件的大小
                    long contentLength = con.getContentLength();
                    Log.d(TAG, "contentLength: " + contentLength);
​
                    //2.创建与下载文件同样大小的空壳文件
                    RandomAccessFile raf = new RandomAccessFile(mDownPath, "rw");
                    raf.setLength(contentLength);
​
                    //3.计算各个线程下载的范围
                     /*
                     * 线程个数 THREAD_COUNT = 3 以3个线程为空 每个线程编号从0开始 0线程 1线程 2线程
                     * 文件长度contentLength 以11bytes为例
                     * 每个线程下载长度 blockSize = contentLength / THREAD_COUNT 11 / 3 = 3
                     * 线程threadId start下载起点 end下载的终点 0线程 0 ~ 2 1线程 3 ~ 5 2线程 6 ~ 8 9
                     * 10(contentLength - 1)
                     * 线程threadId 下载的 start = threadId * blockSize end = (threadId + 1)* blockSize - 1
                     * 如果是下载最后一部分线程end = contentLength - 1
                     */
                    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;
                        }
​
                        //开启线程下载
                        down(i, start, end);
                    }
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
​
    }
​
    /**
     * 开启线程下载对应范围的数据
     *
     * @param threadId
     * @param start
     * @param end
     */
    private void down(final int threadId, final long start, final long end) {
        Log.d(TAG, "线程: " + threadId + ",下载范围:" + start + "--" + end);
        ThreadManager.getInstance().execute(new Runnable() {
            @Override
            public void run() {
                try {
​
                    //记录当前线程下载位置
                    long currentPosition = start;
                    //获取sp中的下载位置,如果为0,说明没有下载过或者下载完成过
                    long position = (long) SharedPreferencesUtils.getParam(MainActivity.this,
                            "" + threadId, 0L);
​
                    if (position != 0){
                        //有以前未下载完成的,接着下载
                        currentPosition = position;
                        Log.d(TAG, "断点续传: "+threadId+",currentPosition:"+currentPosition);
                    }else {
                        Log.d(TAG, "非断点续传: "+threadId);
                    }
​
                    URL url = new URL(mUrl);
                    HttpURLConnection con = (HttpURLConnection) url.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 count = 0;
                        //本次需下载的数据总长度
                        long length = end - currentPosition;
                        byte[] bytes = new byte[2048];
                        int len;
​
                        while ((len = inputStream.read(bytes)) != -1) {
                            //写入
                            rw.write(bytes, 0, len);
                            //计数器累加
                            count += len;
                            //下载的当前位置累加
                            currentPosition+=len;
                            //将当前写入的位置保存
                            SharedPreferencesUtils.setParam(MainActivity.this,threadId+"",currentPosition);
                            Log.d(TAG, "线程: " + threadId + "总长度:" + length + "下载:" + count);
                        }
​
                        inputStream.close();
                        rw.close();
​
                        Log.d(TAG, "线程: " + threadId + "下载完毕");
                        //完成下载后将当前的写入位置置零
                        SharedPreferencesUtils.setParam(MainActivity.this,threadId+"",0L);
                    }
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
​
            }
        });
    }

完整代码如下:

MainActivity

public class MainActivity extends AppCompatActivity {
​
    private static final String TAG = "MainActivity";
    @BindView(R.id.btn_ok)
    Button mBtnOk;
    @BindView(R.id.btn_http)
    Button mBtnHttp;
    @BindView(R.id.pb)
    ProgressBar mPb;
    @BindView(R.id.btn_retrofit)
    Button mBtnRetrofit;
    @BindView(R.id.btn_more)
    Button mBtnMore;
    @BindView(R.id.btn_pause)
    Button mBtnPause;
    @BindView(R.id.pb2)
    ProgressBar mPb2;
    @BindView(R.id.pb3)
    ProgressBar mPb3;
    @BindView(R.id.btn_install)
    Button mBtnInstall;
    private String mUrl = "http://cdn.banmi.com/banmiapp/apk/banmi_330.apk";
    private String mPath;
    //线程数量
    private static int THREAD_COUNT = 3;
    private String mDownPath = "/storage/emulated/0/down.apk";
​
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        initPer();
    }
​
    private void initPer() {
        if (ActivityCompat.checkSelfPermission(this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
​
        } else {
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 100);
        }
    }
​
    @OnClick({R.id.btn_ok, R.id.btn_http, R.id.pb, R.id.btn_retrofit, R.id.btn_more, R.id.btn_pause, R.id.pb2, R.id.pb3, R.id.btn_install})
    public void onClick(View v) {
        switch (v.getId()) {
            default:
                break;
            case R.id.btn_ok:
                okDown();
                break;
            case R.id.btn_http:
                httpDown();
                break;
            case R.id.btn_retrofit:
                retrofitDown();
                break;
            case R.id.btn_more:
                moreDown();
                break;
            case R.id.btn_install:
                installApk(mDownPath);
                break;
        }
    }
​
    @Override
    protected void onDestroy() {
        super.onDestroy();
    }
​
    private void moreDown() {
        ThreadManager.getInstance().execute(new Runnable() {
            @Override
            public void run() {
                try {
                    URL url = new URL(mUrl);
                    HttpURLConnection con = (HttpURLConnection) url.openConnection();
                    //1.获取要下载文件的大小
                    long contentLength = con.getContentLength();
                    Log.d(TAG, "contentLength: " + contentLength);
​
                    //2.创建与下载文件同样大小的空壳文件
                    RandomAccessFile raf = new RandomAccessFile(mDownPath, "rw");
                    raf.setLength(contentLength);
​
                    //3.计算各个线程下载的范围
                     /*
                     * 线程个数 THREAD_COUNT = 3 以3个线程为空 每个线程编号从0开始 0线程 1线程 2线程
                     * 文件长度contentLength 以11bytes为例
                     * 每个线程下载长度 blockSize = contentLength / THREAD_COUNT 11 / 3 = 3
                     * 线程threadId start下载起点 end下载的终点 0线程 0 ~ 2 1线程 3 ~ 5 2线程 6 ~ 8 9
                     * 10(contentLength - 1)
                     * 线程threadId 下载的 start = threadId * blockSize end = (threadId + 1)* blockSize - 1
                     * 如果是下载最后一部分线程end = contentLength - 1
                     */
                    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;
                        }
​
                        //开启线程下载
                        down(i, start, end);
                    }
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
​
    }
​
    /**
     * 开启线程下载对应范围的数据
     *
     * @param threadId
     * @param start
     * @param end
     */
    private void down(final int threadId, final long start, final long end) {
        Log.d(TAG, "线程: " + threadId + ",下载范围:" + start + "--" + end);
        ThreadManager.getInstance().execute(new Runnable() {
            @Override
            public void run() {
                try {
​
                    //记录当前线程下载位置
                    long currentPosition = start;
                    //获取sp中的下载位置,如果为0,说明没有下载过或者下载完成过
                    long position = (long) SharedPreferencesUtils.getParam(MainActivity.this,
                            "" + threadId, 0L);
​
                    if (position != 0){
                        //有以前未下载完成的,接着下载
                        currentPosition = position;
                        Log.d(TAG, "断点续传: "+threadId+",currentPosition:"+currentPosition);
                    }else {
                        Log.d(TAG, "非断点续传: "+threadId);
                    }
​
                    URL url = new URL(mUrl);
                    HttpURLConnection con = (HttpURLConnection) url.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 count = 0;
                        //本次需下载的数据总长度
                        long length = end - currentPosition;
                        byte[] bytes = new byte[2048];
                        int len;
​
                        while ((len = inputStream.read(bytes)) != -1) {
                            //写入
                            rw.write(bytes, 0, len);
                            //计数器累加
                            count += len;
                            //下载的当前位置累加
                            currentPosition+=len;
                            //将当前写入的位置保存
                            SharedPreferencesUtils.setParam(MainActivity.this,threadId+"",currentPosition);
                            Log.d(TAG, "线程: " + threadId + "总长度:" + length + "下载:" + count);
                        }
​
                        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 retrofitDown() {
        DownLoadUtil.retrofitDown("/storage/emulated/0/my.apk", new DownLoadUtil.ResultCallBack() {
            @Override
            public void onFail(String message) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        ToastUtil.showToast(MainActivity.this, "下载失败");
                    }
                });
​
            }
​
            @Override
            public void onProgress(long progress, long max) {
                mPb.setMax((int) max);
                mPb.setProgress((int) progress);
            }
​
            @Override
            public void onSuccess(final String path) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        ToastUtil.showToast(MainActivity.this, "下载成功");
                        mPath = path;
                        installApk(mPath);
                    }
                });
            }
        });
    }
​
    private void httpDown() {
        DownLoadUtil.httpDownload(mUrl, "/storage/emulated/0/my.apk", new DownLoadUtil.ResultCallBack() {
            @Override
            public void onFail(String message) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        ToastUtil.showToast(MainActivity.this, "下载失败");
                    }
                });
​
            }
​
            @Override
            public void onProgress(long progress, long max) {
                mPb.setMax((int) max);
                mPb.setProgress((int) progress);
            }
​
            @Override
            public void onSuccess(final String path) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        ToastUtil.showToast(MainActivity.this, "下载成功");
                        mPath = path;
                        installApk(mPath);
                    }
                });
            }
        });
    }
​
    private void okDown() {
        DownLoadUtil.okDownload(mUrl, "/storage/emulated/0/my.apk", new DownLoadUtil.ResultCallBack() {
            @Override
            public void onFail(String message) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        ToastUtil.showToast(MainActivity.this, "下载失败");
                    }
                });
​
            }
​
            @Override
            public void onProgress(long progress, long max) {
                mPb.setMax((int) max);
                mPb.setProgress((int) progress);
            }
​
            @Override
            public void onSuccess(final String path) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        ToastUtil.showToast(MainActivity.this, "下载成功");
                        mPath = path;
                        installApk(mPath);
                    }
                });
            }
        });
    }
​
    private void installApk(String path) {
        InstallUtil.installApk(this, path);
    }
​
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == InstallUtil.UNKNOWN_CODE) {
            InstallUtil.installApk(this, mPath);//再次执行安装流程,包含权限判等
        }
    }
}

DownLoadUtil类:

public class DownLoadUtil {
    private static final String TAG = "DownLoadUtil";
​
    public static void okDownload(String url, final String path, final ResultCallBack callBack){
        OkHttpClient client = new OkHttpClient.Builder()
                .build();
​
        Request request = new Request.Builder()
                .url(url)
                .get()
                .build();
        //异步调用,不用再新建线程了
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                callBack.onFail(e.getMessage());
            }
​
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                InputStream inputStream = response.body().byteStream();
                saveFiles(inputStream,path,callBack,response.body().contentLength());
            }
        });
​
    }
​
    /**
     * 保存文件
     * @param inputStream
     * @param path
     * @param callBack
     * @param max
     */
    private static void saveFiles(InputStream inputStream, String path, ResultCallBack callBack, long max) {
        File file = new File(path);
        int len;
        byte[] bytes = new byte[4096];
        //读写的进度
        long count = 0;
        try {
            //输出流
            FileOutputStream fos = new FileOutputStream(file);
            while ((len = inputStream.read(bytes)) != -1){
                fos.write(bytes,0,len);
                count+=len;
                //传递当前读写的进度
                callBack.onProgress(count,max);
                Log.d(TAG, "progress: "+count);
            }
            fos.close();
            inputStream.close();
            //完成写入
            callBack.onSuccess(path);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
​
    public static void httpDownload(final String url, final String path, final ResultCallBack callBack) {
        ThreadManager.getInstance().execute(new Runnable() {
            @Override
            public void run() {
                try {
                    URL url1 = new URL(url);
                    HttpURLConnection conn = (HttpURLConnection) url1.openConnection();
                    int responseCode = conn.getResponseCode();
                    if (responseCode == 200){
                        InputStream inputStream = conn.getInputStream();
                        int max = conn.getContentLength();
                        saveFiles(inputStream,path,callBack,max);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    callBack.onFail(e.getMessage());
                }
            }
        });
    }
​
    public static void retrofitDown(final String path, final ResultCallBack callBack) {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(ApiService.mBaseUrl)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
​
        ApiService apiService = retrofit.create(ApiService.class);
        Observable<ResponseBody> download = apiService.download();
        download.subscribeOn(Schedulers.io())
                .subscribe(new Observer<ResponseBody>() {
                    @Override
                    public void onSubscribe(Disposable d) {
​
                    }
​
                    @Override
                    public void onNext(ResponseBody responseBody) {
                        InputStream inputStream = responseBody.byteStream();
                        saveFiles(inputStream,path,callBack,responseBody.contentLength());
                    }
​
                    @Override
                    public void onError(Throwable e) {
                        callBack.onFail(e.getMessage());
                    }
​
                    @Override
                    public void onComplete() {
​
                    }
                });
    }
​
    /**
     * 结果的回调
     */
    public interface ResultCallBack{
        void onFail(String message);
​
        void onProgress(long progress, long max);
​
        void onSuccess(String path);
    }
}

ThreadManager类

public class ThreadManager {
    private static ThreadManager mManager;
    private final ThreadPoolExecutor mExecutor;
​
    private ThreadManager(){
        mExecutor = new ThreadPoolExecutor(5,//核心线程数量,核心池的大小
                20,//线程池最大线程数
                30,//表示线程没有任务执行时最多保持多久时间会终止
                TimeUnit.SECONDS,//时间单位
                new LinkedBlockingQueue<Runnable>(),//任务队列,用来存储等待执行的任务
                Executors.defaultThreadFactory(),//线程工厂,如何去创建线程的
                new ThreadPoolExecutor.AbortPolicy());
    }
    public static ThreadManager getInstance(){
        if (mManager == null){
            synchronized (ThreadManager.class){
                if (mManager == null){
                    mManager = new ThreadManager();
                }
            }
        }
​
        return mManager;
    }
​
    /**
     * 执行任务
     */
    public void execute(Runnable runnable){
        if(runnable==null)return;
​
        mExecutor.execute(runnable);
    }
    /**
     * 从线程池中移除任务
     */
    public void remove(Runnable runnable){
        if(runnable==null)return;
​
        mExecutor.remove(runnable);
    }
​
}

InstallUtil类

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 文件的路径
     */
    public 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 文件路径
     */
    @RequiresApi(api = Build.VERSION_CODES.N)
    public 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
     */
    @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();
    }
}

SharedPreferencesUtils工具类:

public class SharedPreferencesUtils {
    /**
     * 保存在手机里面的文件名
     */
    private static final String FILE_NAME = "share_date";
    
    
    /**
     * 保存数据的方法,我们需要拿到保存数据的具体类型,然后根据类型调用不同的保存方法
     * @param context
     * @param key
     * @param object 
     */
    public static void setParam(Context context , String key, Object object){
        
        String type = object.getClass().getSimpleName();
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        
        if("String".equals(type)){
            editor.putString(key, (String)object);
        }
        else if("Integer".equals(type)){
            editor.putInt(key, (Integer)object);
        }
        else if("Boolean".equals(type)){
            editor.putBoolean(key, (Boolean)object);
        }
        else if("Float".equals(type)){
            editor.putFloat(key, (Float)object);
        }
        else if("Long".equals(type)){
            editor.putLong(key, (Long)object);
        }
        
        editor.commit();
    }
    
    
    /**
     * 得到保存数据的方法,我们根据默认值得到保存的数据的具体类型,然后调用相对于的方法获取值
     * @param context
     * @param key
     * @param defaultObject
     * @return
     */
    public static Object getParam(Context context , String key, Object defaultObject){
        String type = defaultObject.getClass().getSimpleName();
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
        
        if("String".equals(type)){
            return sp.getString(key, (String)defaultObject);
        }
        else if("Integer".equals(type)){
            return sp.getInt(key, (Integer)defaultObject);
        }
        else if("Boolean".equals(type)){
            return sp.getBoolean(key, (Boolean)defaultObject);
        }
        else if("Float".equals(type)){
            return sp.getFloat(key, (Float)defaultObject);
        }
        else if("Long".equals(type)){
            return sp.getLong(key, (Long)defaultObject);
        }
        
        return null;
    }
}

相关文章

  • Android 零碎知识点和技巧

    使用DownloadManager下载文件 下载文件 监听下载结果 文件下载断点续传 1.获取已下载的文件长度. ...

  • js文件下载

    1.文件流下载 根据后台接口文件流下载 调用 2.文件地址下载 根据文件地址下载文件 调用 3.base64流下载...

  • wget下载数据

    下载单个文件 -nc: 继续下载中断的操作 下载目录下面所有文件 下载多个文件:

  • 文件下载

    由于不同的浏览器兼容不同,对于直接a标签下载文件,有的浏览器可以,有的浏览器会直接播放。为了保证下载操作的正确执行...

  • 文件下载

    常见的文件格式: 文件下载HTML 图片文件下载PHP

  • 文件下载

    IOUtils 的对应包 需要关闭流的对象放在try()内不用写关闭代码

  • 文件下载

    文件下载是实际项目中经常用的一个接口,不同于图片下载客户端自己保存就可以了,需要开放对应的接口。同时,一般会结合P...

  • 文件下载

    1.小文件下载 1.1下载方式 【NSData dataWithContentsOfURL:】 [NSURLCon...

  • 文件下载

  • 文件下载

    初始化下载管理器 添加下载 下载数据管理 创建请求 Get Post Delegate 下载数据本地化 创建任务 ...

网友评论

    本文标题:文件下载

    本文链接:https://www.haomeiwen.com/subject/eooowqtx.html