Retrofit:
public interface RetrofitZj {
/* @Streaming*//*大文件需要加入这个判断,防止下载过程中写入到内存中*//*
@GET
Observable<ResponseBody> download(@Header("RANGE") String start, @Url String url);*/
@Streaming
@GET
Observable<ResponseBody> download(@Header("RANGE") String start, @Url String url);
}
public class RetrofitAPI {
private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
private static Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl("http://result.eolinker.com/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create());
public static <S> S createService(Class<S> serviceClass) {
Retrofit retrofit = builder.client(httpClient.build()).build();
return retrofit.create(serviceClass);
}
}
Bean:
@Entity
public class Bean {
@Id
private Long id;
@Property(nameInDb = "RANGE")
private Long range;
@Property(nameInDb = "START")
private Long start;
@Property(nameInDb = "END")
private Long end;
@Property(nameInDb = "ThREADNUM")
private String ThreadNum;
}
public class DBManager {
private static Context mContext;
private static DBManager instance;
BeanDao beanDao;
Bean bean;
private DBManager() {
}
public static DBManager getInstance(Context context) {
if (instance == null) {
instance = new DBManager();
if (mContext == null) {
mContext = context;
}
// 数据库对象
// 数据库对象
DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(mContext, "student.db", null);
DaoMaster daoMaster = new DaoMaster(devOpenHelper.getWritableDb());
DaoSession daoSession = daoMaster.newSession();
instance.beanDao = daoSession.getBeanDao();
}
return instance;
}
/** 添加数据 */
public void addToCityInfoTable(Bean item)
{
beanDao.insert(item);
}
/** 查询 */
/** 通过城市id查找其类型id */
public List<Bean> getCityInfoList(int threadNum) {
QueryBuilder<Bean> qb = beanDao.queryBuilder();
qb.where(BeanDao.Properties.ThreadNum.eq(threadNum));
List<Bean> list = qb.list();
Log.i("========", "getCityInfoList: " + list);
return list;
}
public void updateInfo(int id,long rang){
QueryBuilder<Bean> qb = beanDao.queryBuilder();
qb.where(BeanDao.Properties.ThreadNum.eq(id));
List<Bean> list = qb.list();
Bean bean2 = list.get(0);
bean2.setRange(rang);
beanDao.update(bean2);
}
}
Model接口:
public interface IDownLoadModel {
void getData(String start, String url, String url2, GetCallback callback);
void setGetProgress(DownLoadModel.getProgress getProgress);
interface GetCallback {
void GetComplete(ResponseBody responseBody);
}
void stop();
void jixu();
void getProgress();
}
Model实现类:
public class DownLoadModel implements IDownLoadModel {
private static final String DOWNLOAD_INIT = "1";
private static final String DOWNLOAD_ING = "2";
private static final String DOWNLOAD_PAUSE = "3";
public DownLoadModel.getProgress getProgress;
private String stateDownload = DOWNLOAD_ING;//当前线程状态
String url3 = "";
Context context;
private long l;
public DownLoadModel(Context context) {
this.context = context;
}
@Override
public void getData(String start, String url, final String url2, final GetCallback callback) {
this.url3 = url;
RetrofitAPI.createService(RetrofitZj.class).download(start, url3)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<ResponseBody>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(ResponseBody responseBody) {
l = responseBody.contentLength();
Log.i("=====length=====", "onNext: " + l);
downloadFile(l, url2);
}
});
}
@Override
public void stop() {
stateDownload = DOWNLOAD_PAUSE;
}
@Override
public void jixu() {
stateDownload = DOWNLOAD_ING;
}
@Override
public void getProgress() {
}
public void downloadFile(long length, String url2) {
final File file = new File(url2);
if (!file.exists()) {
try {
file.createNewFile();
} catch (Exception e) {
e.printStackTrace();
}
}
int threadNum = 5;
long blockSize = length / threadNum;
long startPosition = 0;
long end = 0;
// //四舍五入--- 让一个数字+0。5在四舍五入 就变成 向上取整
//计算出下载块以后 创建线程执行下载操作
for (int i = 0; i < threadNum; i++) {
List<Bean> cityInfoList = DBManager.getInstance(context).getCityInfoList(i);
if (cityInfoList.size() > 0) {
Long range = cityInfoList.get(0).getRange();
Long start = cityInfoList.get(0).getStart();
Long end1 = cityInfoList.get(0).getEnd();
startPosition = range + start;
end = end1;
Log.i("=====", "downloadFile: " + startPosition + "==" + end);
} else {
startPosition = blockSize * i;
//让最后一个线程下载的大小是正好的, 总长度 - 除了最后一个块的大小和
if (i == threadNum - 1) {
blockSize = length - blockSize * (threadNum - 1);
}
end = startPosition + blockSize - 1;
Bean bean2 = new Bean();
bean2.setThreadNum(i + "");
bean2.setRange((long) 0);
bean2.setStart(startPosition);
bean2.setEnd(end);
DBManager.getInstance(context).addToCityInfoTable(bean2);
}
downloadTask(startPosition, file, end, length, i);
}
}
public void downloadTask(final long startPosition, final File file, long end, final long length, final int i) {
//计算开始位置
String range = "bytes=" + startPosition + "-" + end;
RetrofitAPI.createService(RetrofitZj.class).download(range, url3)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(new Observer<ResponseBody>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(ResponseBody responseBody) {
BufferedInputStream bis = null;
RandomAccessFile raf = null;
try {
bis = new BufferedInputStream(responseBody.byteStream());
raf = new RandomAccessFile(file, "rwd");
raf.seek(startPosition);
byte[] buff = new byte[1024 * 8];
int len = 0;
List<Bean> cityInfoList = DBManager.getInstance(context).getCityInfoList(i);
long length2 = cityInfoList.get(0).getRange();
Log.i("=====继续length2=======", "onNext: " + length2);
while ((len = bis.read(buff)) != -1) {
Log.i("===循环继续====", "onNext: ");
if (stateDownload == DOWNLOAD_ING) {
Log.i("===继续下载====", "onNext: ");
length2 += len;
raf.write(buff, 0, len);
handler.sendEmptyMessage((int) len);
} else if (stateDownload == DOWNLOAD_PAUSE) {
//更新数据库
DBManager.getInstance(context).updateInfo(i, length2);
break;
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bis != null) {
try {
bis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (raf != null) {
try {
raf.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
});
}
public void setGetProgress(DownLoadModel.getProgress getProgress) {
this.getProgress = getProgress;
}
public interface getProgress {
void getProgress_length(long l);
}
private long downloadedSize = 0;
@SuppressLint("HandlerLeak")
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//每次每个线程回来的长度
int length = msg.what;
synchronized (this) {
downloadedSize += length;
}
getProgress.getProgress_length(downloadedSize * 100 / l);
Log.i("downloadedSize", "handleMessage: " + downloadedSize);
Log.i("百分比", "handleMessage: " + downloadedSize * 100 / l);
}
};
}
View接口:
public interface IDownLoadView {
void getData(ResponseBody responseBody);
void getPro(long length);
}
Presenter:
public class DownLoadPresenter implements BasePresenter<IDownLoadView> {
Context context;
SoftReference<IDownLoadView> softReference;
IDownLoadModel model;
public DownLoadPresenter(Context context,IDownLoadView view) {
this.context = context;
atteach(view);
model = new DownLoadModel(context);
}
public void down(final String start, final String url, final String url2) {
model.getData(start, url, url2, new IDownLoadModel.GetCallback() {
@Override
public void GetComplete(ResponseBody responseBody) {
}
});
}
public void stop(){
model.stop();
}
public void jixu(){
model.jixu();
}
public void setProgress(){
model.setGetProgress(new DownLoadModel.getProgress() {
@Override
public void getProgress_length(long l) {
softReference.get().getPro(l);
}
});
}
@Override
public void atteach(IDownLoadView view) {
softReference = new SoftReference<IDownLoadView>(view);
}
@Override
public void deatch() {
softReference.clear();
}
}
Activity:
public class MainActivity extends BaseActivity<DownLoadPresenter> implements IDownLoadView, View.OnClickListener {
private String video_url;
String url = "http://ww.baidu.com.mp4";
private Button mBtn;
public static long MAX_SIZE;
private VideoView mWb;
private Button mStopBtn;
private Button mJxBtn;
private ProgressBar mPb;
private TextView mTv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
// Intent intent = getIntent();
// video_url = intent.getStringExtra("video_url");
// Log.i("11111111111111111", "onCreate: " + video_url);
// // initPlayer();
presenter.setProgress();
}
@Override
public void createPresenter() {
presenter = new DownLoadPresenter(this, this);
}
private void initView() {
mBtn = (Button) findViewById(R.id.btn);
mBtn.setOnClickListener(this);
mStopBtn = (Button) findViewById(R.id.btn_stop);
mStopBtn.setOnClickListener(this);
mJxBtn = (Button) findViewById(R.id.btn_jx);
mJxBtn.setOnClickListener(this);
mPb = (ProgressBar) findViewById(R.id.pb);
mTv = (TextView) findViewById(R.id.tv);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn:
String url2 = getCacheDir() + "haha.mp4";
presenter.down(String.valueOf(0), url, url2);
break;
case R.id.btn_stop:// TODO 17/11/22
presenter.stop();
break;
case R.id.btn_jx:// TODO 17/11/22
String url3 = getCacheDir() + "haha.mp4";
presenter.jixu();
presenter.down(String.valueOf(0), url, url3);
break;
default:
break;
}
}
@Override
public void getData(ResponseBody responseBody) {
}
@Override
public void getPro(long length) {
mPb.setMax(100);
mPb.setProgress((int) length);
//mTv.setText(length+"%");
}
}
布局:
<Button
android:id="@+id/btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="下载" />
<Button
android:id="@+id/btn_stop"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/btn"
android:text="暂停" />
<Button
android:id="@+id/btn_jx"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/btn_stop"
android:text="继续" />
<ProgressBar
android:id="@+id/pb"
style="@style/Base.Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/btn_jx" />
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_below="@+id/pb"
android:layout_height="wrap_content" />