文件的断点续传是指我们在下载时需要进行暂停或者网络断开等一系列事件所做的暂停操作,当我们再次进行操作的时候,将文件进行再次下载时,原先已经完成的部分就会连接上,继续下载
Main方法代码:
public class MainActivity extends AppCompatActivity {
@BindView(R.id.tv)
TextView tv;
private String path;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
initModel();
}
private void initModel() {
//进行读取文件的绝对路径
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
File externalStorageDirectory = Environment.getExternalStorageDirectory();
String absolutePath = externalStorageDirectory.getAbsolutePath();
//拼接至我们内存中下的一个文件夹
path = absolutePath + "/李大本事/";
//将我们要保存至的路径传到网络请求上
Model.getInstance().initDownLoad(path);
//接口回传
Model.getInstance().setModel(new ModelInterface() {
@Override
public void FileSuccess() {
}
@Override
public void FileFailed() {
}
//将进度通过给TextView的形式展示出来
@Override
public void Progress(final long progress) {
runOnUiThread(new Runnable() {
@Override
public void run() {
runOnUiThread(new Runnable() {
@Override
public void run() {
tv.setText(progress+"");
}
});
}
});
}
});
}
}
//点击按钮
@OnClick({R.id.btn_action, R.id.btn_stop})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.btn_action:
Model.getInstance().initStart("http://dlsw.baidu.com/sw-search-sp/soft/4b/17170/Install_WLMessenger14.0.8117.416.1393467029.exe");
break;
case R.id.btn_stop:
Model.getInstance().initStop();
break;
}
}
}
网络请求的代码:
public class Model {
private static volatile Model instance;
private String absolutePath;
private File file;
private long startPostion;
private Call call;
private Model(){}
public static Model getInstance(){
if(instance == null){
synchronized (Model.class){
if(instance == null){
instance = new Model();
}
}
}
return instance;
}
private ModelInterface modelInterface;
public void setModel(ModelInterface modelInterface){
this.modelInterface = modelInterface;
}
//判断地址是否存在
public void initDownLoad(String path){
File file = new File(path);
//如果父路径不存在,就创建父路径
if(!file.getParentFile().exists()){
file.getParentFile().mkdir();
}
//如果子文件不存在,就创建
if(!file.exists()){
file.mkdir();
}
absolutePath = file.getAbsolutePath();
Log.e("----得到的地址:",absolutePath);
}
//点击开始做的操作,传递一个地址,用来拼接地址,并访问网络
public void initStart(String url){
//判断地址是否存在
if(TextUtils.isEmpty(url)){
return;
}
//判断地址中是否包含后缀名
if(url.contains(".")){
//取出包含点的后缀名
String substring_one = url.substring(url.lastIndexOf("."));
Log.e("----得到的地址文件名:",substring_one);
//判断是否有/
if(url.contains("/")){
String substring_two = url.substring(url.lastIndexOf("/"), url.lastIndexOf("."));
Log.e("----得到的地址文件名:",substring_two);
//将完全地址拼接上
String allPath = substring_two + substring_one;
//创建一个文件路径
file = new File(absolutePath, allPath);
Log.e("----得到的地址:",absolutePath+"--"+allPath);
}
}
//用来记录当前的下载进度
startPostion = 0;
//如果当前文件已存在,就将文件长度赋值给初始值
if(file.exists()){
startPostion = file.length();
}
//创建网络请求
OkHttpClient okHttpClient = new OkHttpClient();
Log.e("----当前文件大小",startPostion+"");
Request range = new Request.Builder()
//判断从网络读取的位置从文件大小开始
.addHeader("RANGE", "bytes=" + startPostion + "-")
.url(url)
.build();
call = okHttpClient.newCall(range);
call.enqueue(new Callback() {
private long bodyLength;
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
ResponseBody body = response.body();
//文件的大小加上之前文件的大小,才能成为100%
bodyLength = body.contentLength()+startPostion;
InputStream inputStream = body.byteStream();
byte[] bts = new byte[2048];
int len = 1;
long num = startPostion;
while((len = inputStream.read(bts,0,bts.length))!=-1){
//创建一个方法,可以在文件下的任意地方进行读写
RandomAccessFile rw = new RandomAccessFile(file, "rw");
//让文件从原先大小的位置开始操作
rw.seek(num);
//将读取的文件进行写入
rw.write(bts,0,len);
num += len;
modelInterface.Progress(num*100/bodyLength);
}
inputStream.close();
modelInterface.FileSuccess();
}
});
}
//点击暂停的操作
public void initStop(){
//判断Call对象是否正在运行而且存在
if(call.isExecuted()&&call!=null){
call.cancel();
}
}
}
网络请求的接口:
public interface ModelInterface {
void FileSuccess();
void FileFailed();
void Progress(long progress);
}