版权声明:本文为博主原创文章,转载请标明出处。 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();
}
}