您现在的位置是:首页 > 文章详情

Android--okhttp断点下载+进度

日期:2018-03-29点击:359
版权声明:本文为博主原创文章,转载请标明出处。 https://blog.csdn.net/chaoyu168/article/details/79753962

import android.net.Uri; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.ProgressBar; import android.widget.Toast; public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private Button downloadBtn1, downloadBtn2, downloadBtn3; private Button cancelBtn1, cancelBtn2, cancelBtn3; private ProgressBar progress1, progress2, progress3; private String url1 = "http://dl175.80s.im:920/1803/西游记女儿国/西游记女儿国.mp4"; private String url2 = "http://dl174.80s.im:920/1803/湮灭/湮灭.mp4"; private String url3 = "http://dl173.80s.im:920/1803/南极之恋/南极之恋.mp4"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); downloadBtn1 = findViewById(R.id.main_btn_down1); downloadBtn2 = findViewById(R.id.main_btn_down2); downloadBtn3 = findViewById(R.id.main_btn_down3); cancelBtn1 = findViewById(R.id.main_btn_cancel1); cancelBtn2 = findViewById(R.id.main_btn_cancel2); cancelBtn3 = findViewById(R.id.main_btn_cancel3); progress1 = findViewById(R.id.main_progress1); progress2 = findViewById(R.id.main_progress2); progress3 = findViewById(R.id.main_progress3); downloadBtn1.setOnClickListener(this); downloadBtn2.setOnClickListener(this); downloadBtn3.setOnClickListener(this); cancelBtn1.setOnClickListener(this); cancelBtn2.setOnClickListener(this); cancelBtn3.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.main_btn_down1: DownloadManager.getInstance().download(url1, new DownLoadObserver() { @Override public void onNext(DownloadInfo value) { super.onNext(value); progress1.setMax((int) value.getTotal()); progress1.setProgress((int) value.getProgress()); } @Override public void onComplete() { if(downloadInfo != null){ Toast.makeText(MainActivity.this, downloadInfo.getFileName() + "-DownloadComplete", Toast.LENGTH_SHORT).show(); } } }); break; case R.id.main_btn_down2: DownloadManager.getInstance().download(url2, new DownLoadObserver() { @Override public void onNext(DownloadInfo value) { super.onNext(value); progress2.setMax((int) value.getTotal()); progress2.setProgress((int) value.getProgress()); } @Override public void onComplete() { if(downloadInfo != null){ Toast.makeText(MainActivity.this, downloadInfo.getFileName() + Uri.encode("下载完成"), Toast.LENGTH_SHORT).show(); } } }); break; case R.id.main_btn_down3: DownloadManager.getInstance().download(url3, new DownLoadObserver() { @Override public void onNext(DownloadInfo value) { super.onNext(value); progress3.setMax((int) value.getTotal()); progress3.setProgress((int) value.getProgress()); } @Override public void onComplete() { if(downloadInfo != null){ Toast.makeText(MainActivity.this, downloadInfo.getFileName() + "下载完成", Toast.LENGTH_SHORT).show(); } } }); break; case R.id.main_btn_cancel1: DownloadManager.getInstance().cancel(url1); break; case R.id.main_btn_cancel2: DownloadManager.getInstance().cancel(url2); break; case R.id.main_btn_cancel3: DownloadManager.getInstance().cancel(url3); break; } } }
import android.os.Environment; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.concurrent.atomic.AtomicReference; import io.reactivex.Observable; import io.reactivex.ObservableEmitter; import io.reactivex.ObservableOnSubscribe; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.schedulers.Schedulers; import okhttp3.Call; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; /** * Created by xiaobai on 2018/3/30/030. */ public class DownloadManager { private static final AtomicReference<DownloadManager> INSTANCE = new AtomicReference<>(); private HashMap<String, Call> downCalls;//用来存放各个下载的请求 private OkHttpClient mClient;//OKHttpClient; private String FILEPATH = Environment.getExternalStorageDirectory().getAbsolutePath()+"/"; //获得一个单例类 public static DownloadManager getInstance() { for (; ; ) { DownloadManager current = INSTANCE.get(); if (current != null) { return current; } current = new DownloadManager(); if (INSTANCE.compareAndSet(null, current)) { return current; } } } private DownloadManager() { downCalls = new HashMap<>(); mClient = new OkHttpClient.Builder().build(); } /** * 开始下载 * * @param url 下载请求的网址 * @param downLoadObserver 用来回调的接口 */ public void download(String url, DownLoadObserver downLoadObserver) { Observable.just(url) .filter(s -> !downCalls.containsKey(s))//call的map已经有了,就证明正在下载,则这次不下载 .flatMap(s -> Observable.just(createDownInfo(s))) .map(this::getRealFileName)//检测本地文件夹,生成新的文件名 .flatMap(downloadInfo -> Observable.create(new DownloadSubscribe(downloadInfo)))//下载 .observeOn(AndroidSchedulers.mainThread())//在主线程回调 .subscribeOn(Schedulers.io())//在子线程执行 .subscribe(downLoadObserver);//添加观察者 } public void cancel(String url) { Call call = downCalls.get(url); if (call != null) { call.cancel();//取消 } downCalls.remove(url); } /** * 创建DownInfo * * @param url 请求网址 * @return DownInfo */ private DownloadInfo createDownInfo(String url) { DownloadInfo downloadInfo = new DownloadInfo(url); long contentLength = getContentLength(url);//获得文件大小 downloadInfo.setTotal(contentLength); String fileName = url.substring(url.lastIndexOf("/")); downloadInfo.setFileName(fileName); return downloadInfo; } private DownloadInfo getRealFileName(DownloadInfo downloadInfo) { String fileName = downloadInfo.getFileName(); long downloadLength = 0, contentLength = downloadInfo.getTotal(); File file = new File(FILEPATH, fileName); if (file.exists()) { //找到了文件,代表已经下载过,则获取其长度 downloadLength = file.length(); } //之前下载过,需要重新来一个文件 int i = 1; while (downloadLength >= contentLength) { int dotIndex = fileName.lastIndexOf("."); String fileNameOther; if (dotIndex == -1) { fileNameOther = fileName + "(" + i + ")"; } else { fileNameOther = fileName.substring(0, dotIndex) + "(" + i + ")" + fileName.substring(dotIndex); } File newFile = new File(MyApplication.getContext().getFilesDir(), fileNameOther); file = newFile; downloadLength = newFile.length(); i++; } //设置改变过的文件名/大小 downloadInfo.setProgress(downloadLength); downloadInfo.setFileName(file.getName()); return downloadInfo; } private class DownloadSubscribe implements ObservableOnSubscribe<DownloadInfo> { private DownloadInfo downloadInfo; public DownloadSubscribe(DownloadInfo downloadInfo) { this.downloadInfo = downloadInfo; } @Override public void subscribe(ObservableEmitter<DownloadInfo> e) throws Exception { String url = downloadInfo.getUrl(); long downloadLength = downloadInfo.getProgress();//已经下载好的长度 long contentLength = downloadInfo.getTotal();//文件的总长度 //初始进度信息 e.onNext(downloadInfo); Request request = new Request.Builder() //确定下载的范围,添加此头,则服务器就可以跳过已经下载好的部分 .addHeader("RANGE", "bytes=" + downloadLength + "-" + contentLength) .url(url) .build(); Call call = mClient.newCall(request); downCalls.put(url, call);//把这个添加到call里,方便取消 Response response = call.execute(); File file = new File(MyApplication.getContext().getFilesDir(), downloadInfo.getFileName()); InputStream is = null; FileOutputStream fileOutputStream = null; try { is = response.body().byteStream(); fileOutputStream = new FileOutputStream(file, true); byte[] buffer = new byte[2048];//缓冲数组2kB int len; while ((len = is.read(buffer)) != -1) { fileOutputStream.write(buffer, 0, len); downloadLength += len; downloadInfo.setProgress(downloadLength); e.onNext(downloadInfo); } fileOutputStream.flush(); downCalls.remove(url); } finally { //关闭IO流 IOUtil.closeAll(is, fileOutputStream); } e.onComplete();//完成 } } /** * 获取下载长度 * * @param downloadUrl * @return */ private long getContentLength(String downloadUrl) { Request request = new Request.Builder() .url(downloadUrl) .build(); try { Response response = mClient.newCall(request).execute(); if (response != null && response.isSuccessful()) { long contentLength = response.body().contentLength(); response.close(); return contentLength == 0 ? DownloadInfo.TOTAL_ERROR : contentLength; } } catch (IOException e) { e.printStackTrace(); } return DownloadInfo.TOTAL_ERROR; } } 
APK和DEMO下载: https://download.csdn.net/download/chaoyu168/10317361

分享一个简单的下载工具类;

import android.os.Environment; import android.support.annotation.NonNull; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import okhttp3.Call; import okhttp3.Callback; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; /** *下载工具 */ public class DownloadUtil { private static DownloadUtil downloadUtil; private final OkHttpClient okHttpClient; public static DownloadUtil get() { if (downloadUtil == null) { downloadUtil = new DownloadUtil(); } return downloadUtil; } private DownloadUtil() { okHttpClient = new OkHttpClient(); } /** * @param url 下载连接 * @param saveDir 储存下载文件的SDCard目录 * @param listener 下载监听 */ public void download(final String url, final String saveDir, final OnDownloadListener listener) { Request request = new Request.Builder().url(url).build(); okHttpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { // 下载失败 listener.onDownloadFailed(); } @Override public void onResponse(Call call, Response response) throws IOException { InputStream is = null; byte[] buf = new byte[2048]; int len = 0; FileOutputStream fos = null; // 储存下载文件的目录 String savePath = isExistDir(saveDir); try { is = response.body().byteStream(); long total = response.body().contentLength(); File file = new File(savePath, getNameFromUrl(url)); fos = new FileOutputStream(file); long sum = 0; while ((len = is.read(buf)) != -1) { fos.write(buf, 0, len); sum += len; int progress = (int) (sum * 1.0f / total * 100); // 下载中 listener.onDownloading(progress); } fos.flush(); // 下载完成 listener.onDownloadSuccess(); } catch (Exception e) { listener.onDownloadFailed(); } finally { try { if (is != null) is.close(); } catch (IOException e) { } try { if (fos != null) fos.close(); } catch (IOException e) { } } } }); } /** * @param saveDir * @return * @throws IOException * 判断下载目录是否存在 */ private String isExistDir(String saveDir) throws IOException { // 下载位置 File downloadFile = new File(Environment.getExternalStorageDirectory(), saveDir); if (!downloadFile.mkdirs()) { downloadFile.createNewFile(); } String savePath = downloadFile.getAbsolutePath(); return savePath; } /** * @param url * @return * 从下载连接中解析出文件名 */ @NonNull private String getNameFromUrl(String url) { return url.substring(url.lastIndexOf("/") + 1); } public interface OnDownloadListener { /** * 下载成功 */ void onDownloadSuccess(); /** * @param progress * 下载进度 */ void onDownloading(int progress); /** * 下载失败 */ void onDownloadFailed(); } } 

原文链接:https://yq.aliyun.com/articles/631450
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章