//下载线程类 package com.retrofitmoredownload.net; import android.annotation.SuppressLint; import android.content.Context; import android.text.TextUtils; import android.util.Log; import com.retrofitmoredownload.bean.DaoBean.FileBean; import com.retrofitmoredownload.utils.DaoUtils; import java.io.BufferedInputStream; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.util.List; import okhttp3.ResponseBody; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; import rx.Observer; import rx.schedulers.Schedulers; /** * Created by on 2017/11/9. */ public class DownloadThread extends Thread{ private String downloadUrl = ""; private String path; private int threadNum = 5; private String TAG="=======DownloadThread======="; private boolean isDown; private Context context; String range=null; private int[] LENG={0}; private String contentLength; private boolean isFirst=true; public void setDown(boolean down) { isDown = down; } public DownloadThread(String downloadUrl, String path,Context context) { this.downloadUrl = downloadUrl; this.path = path; this.context=context; } @Override public void run() { RetrofitUtils.download(RequestApi.BASE_URL4).getFileLenght().enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { final long l = response.body().contentLength(); downloadTask(Long.valueOf(l)); } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { } }); } @SuppressLint("LongLogTag") public void downloadTask(final long length){ final File file = new File(path); if(!file.exists()){ try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } //例如 1000kb 3 333 long blockSize = length/threadNum; //计算出下载块以后 创建线程执行下载操作 for (int i = 0; i < threadNum; i++) { final long startPos; //计算开始位置 final long[] startPosition = {blockSize * i}; //让最后一个线程下载的大小是正好的, 总长度 - 除了最后一个块的大小和 if(i == threadNum - 1){ blockSize = length - blockSize * (threadNum - 1); } //获取到保存数据库中的下载长度 List<FileBean> query = DaoUtils.getInstance(context).Query(downloadUrl,String.valueOf(i)); if (query!=null&&query.size()>0) { //获取已下载的长度 contentLength = query.get(0).getContentLength(); long lon = startPosition[0] + Long.parseLong(contentLength); Log.i(TAG, "downloadTask: 继续下载的开始位置:"+lon); startPos=lon; range = "bytes=" + (startPosition[0]+Integer.parseInt(contentLength)) + "-" + (startPosition[0] + blockSize - 1); Log.i("=======SQL=======", "downloadTask: " + range); } else { DaoUtils.getInstance(context).Insert(downloadUrl,String.valueOf(i),String.valueOf(0)); startPos=startPosition[0]; range = "bytes=" +startPosition[0] + "-" +(startPosition[0] + blockSize - 1); Log.i("=======first=======", "downloadTask: " + range); } final int finalI = i; final int[] num = {0}; RetrofitUtils.download(RequestApi.BASE_URL4).downloadFile(range). subscribeOn(Schedulers.io()). observeOn(Schedulers.io()). subscribe(new Observer<ResponseBody>() { @Override public void onCompleted() { Log.i(TAG, "onCompleted: "); } @Override public void onError(Throwable e) { e.printStackTrace(); Log.i(TAG, "onError: e:"+e.toString()); } @Override public void onNext(ResponseBody responseBody) { RandomAccessFile raf=null; BufferedInputStream bis=null; try { bis = new BufferedInputStream(responseBody.byteStream()); raf = new RandomAccessFile(file, "rwd"); raf.seek(startPos); byte[] buff = new byte[1024 * 8]; int len = 0; while ((len = bis.read(buff)) != -1) { if (isDown) { raf.write(buff, 0, len); if (!TextUtils.isEmpty(contentLength)) { if (isFirst) { num[0] = Integer.parseInt(contentLength)+len; isFirst=false; }else { num[0] = num[0] + len; } Log.i(TAG, "onNext: num[0]:"+num[0]); }else { num[0] = num[0] + len; } rP.retrunProgre(len,length); //更新数据库中的数据 DaoUtils.getInstance(context).Update(String.valueOf(finalI),String.valueOf(num[0]),downloadUrl); }else { break; } } } catch (IOException e) { e.printStackTrace(); }finally { if (raf!=null) { try { raf.close(); } catch (IOException e) { e.printStackTrace(); } } if (bis!=null) { try { bis.close(); } catch (IOException e) { e.printStackTrace(); } } } } }); } } public void setThreadNum(int threadNum){ this.threadNum = threadNum; } private ReturnProgress rP; public void setrP(ReturnProgress rP) { this.rP = rP; } public interface ReturnProgress{ void retrunProgre(long len,long length); } } 简单封装的Retrofit类package com.retrofitmoredownload.net; import java.util.concurrent.TimeUnit; import okhttp3.OkHttpClient; import retrofit2.Retrofit; import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; import retrofit2.converter.scalars.ScalarsConverterFactory; /** * Created by yfeng on 2017/11/16. */ public class RetrofitUtils { public static RequestApi download(String baseurl){ OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(5, TimeUnit.SECONDS) .readTimeout(5, TimeUnit.SECONDS) .build(); Retrofit retrofit = new Retrofit.Builder() .client(client) .addConverterFactory(ScalarsConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .baseUrl(baseurl) .build(); RequestApi api = retrofit.create(RequestApi.class); return api; } }Retrofit接口类package com.retrofitmoredownload.net; import okhttp3.ResponseBody; import retrofit2.Call; import retrofit2.http.Header; import retrofit2.http.POST; import retrofit2.http.Streaming; import rx.Observable; /** * Created by yfeng on 2017/11/16. */ public interface RequestApi { public static final String BASE_URL = "http://mirror.aarnet.edu.au"; public static final String BASE_URL2 = "http://2449.vod.myqcloud.com/2449_bfbbfa3cea8f11e5aac3db03cda99974.f20.mp4"; public static final String BASE_URL3 = "http://video.jiecao.fm/5/1/自取其辱.mp4"; public static final String BASE_URL4 = "http://ips.ifeng.com"; @Streaming @POST("/video19.ifeng.com/video09/2014/06/16/1989823-102-086-0009.mp4") Observable<ResponseBody> downloadFile(@Header("Range") String range); @Streaming @POST("/video19.ifeng.com/video09/2014/06/16/1989823-102-086-0009.mp4") Call<ResponseBody> getFileLenght(); }
点击开始下载按钮,执行如下:downloadThread = new DownloadThread("%E8%87%AA%E5%8F%96%E5%85%B6%E8%BE%B1.mp4", path,this); downloadThread.setThreadNum(3); downloadThread.setrP(this); downloadThread.setDown(true); downloadThread.start();
点击暂停如下
downloadThread.setDown(false); 权限<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
依赖// Retrofit库 compile 'com.squareup.retrofit2:retrofit:2.0.2' // Okhttp库 compile 'com.squareup.okhttp3:okhttp:3.1.2' compile 'com.squareup.retrofit2:converter-gson:2.0.2' compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0' compile 'io.reactivex:rxjava:1.0.14' compile 'io.reactivex:rxandroid:1.0.1' compile 'com.squareup.retrofit2:converter-scalars:2.0.0' compile 'cn.jzvd:jiaozivideoplayer:6.0.0' compile 'com.github.bumptech.glide:glide:3.7.0' compile 'org.greenrobot:greendao:3.1.0'
数据库工具类:package com.retrofitmoredownload.utils; import android.content.Context; import com.retrofitmoredownload.MyApp; import com.retrofitmoredownload.bean.DaoBean.FileBean; import com.retrofitmoredownload.bean.DaoBean.FileBeanDao; import java.util.List; /** * User: * Date: 2017-11-22 09:09 * Description: */ public class DaoUtils { private final MyApp myApp; private static DaoUtils utils; private DaoUtils(Context context) { myApp = (MyApp) context.getApplicationContext(); } public static DaoUtils getInstance(Context context){ if (utils==null) { synchronized (DaoUtils.class){ if (utils==null) { utils=new DaoUtils(context); } } } return utils; } /** * * 保存数据库数据 * @param downPath * @param threadid * @param contentlength */ public void Insert(String downPath,String threadid,String contentlength){ FileBeanDao fileBeanDao = myApp.getDaoSession().getFileBeanDao(); fileBeanDao.insert(new FileBean(null,downPath,contentlength,threadid)); } /** * 格局下载地址删除数据库数据 * @param downPath */ public void Delete(String downPath){ FileBeanDao fileBeanDao = myApp.getDaoSession().getFileBeanDao(); List<FileBean> list = fileBeanDao.queryBuilder().where(FileBeanDao.Properties.Path.eq(downPath)).build().list(); for (FileBean fileBean : list) { Long id = fileBean.getId(); fileBeanDao.deleteByKey(id); } } /** * 更新数据库指定的数据信息 * @param threadid * @param contentlength * @param downpath */ public void Update(String threadid,String contentlength,String downpath){ List<FileBean> list = myApp.getDaoSession().getFileBeanDao().queryBuilder().where(FileBeanDao.Properties.Path.eq(downpath), FileBeanDao.Properties.ThreadId.eq(threadid)).build().list(); for (FileBean fileBean : list) { Long id = fileBean.getId(); myApp.getDaoSession().getFileBeanDao().update(new FileBean(id,downpath,contentlength,threadid)); } } /** * 查询数据 * @param path * @return */ public List<FileBean> Query(String path,String threadid){ List<FileBean> list = myApp.getDaoSession().getFileBeanDao().queryBuilder().where(FileBeanDao.Properties.Path.eq(path), FileBeanDao.Properties.ThreadId.eq(threadid)).build().list(); return list; } }
GreenDao数据库Bean类package com.retrofitmoredownload.bean.DaoBean; import org.greenrobot.greendao.annotation.Entity; import org.greenrobot.greendao.annotation.Id; import org.greenrobot.greendao.annotation.Property; import org.greenrobot.greendao.annotation.Generated; /** * User: * Date: 2017-11-21 22:31 * Description: */ @Entity public class FileBean { @Id(autoincrement = true) private Long id; @Property(nameInDb = "PATH") private String path; @Property(nameInDb = "CONTENTLENGTH") private String contentLength; @Property(nameInDb = "THREADID") private String ThreadId; public String getThreadId() { return this.ThreadId; } public void setThreadId(String ThreadId) { this.ThreadId = ThreadId; } public String getContentLength() { return this.contentLength; } public void setContentLength(String contentLength) { this.contentLength = contentLength; } public String getPath() { return this.path; } public void setPath(String path) { this.path = path; } public Long getId() { return this.id; } public void setId(Long id) { this.id = id; } @Generated(hash = 1644617568) public FileBean(Long id, String path, String contentLength, String ThreadId) { this.id = id; this.path = path; this.contentLength = contentLength; this.ThreadId = ThreadId; } @Generated(hash = 1910776192) public FileBean() { } }
Retrofit多线程断点下载
最新推荐文章于 2021-05-26 07:10:07 发布