这里下载的斗鱼
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<EditText
android:id="@+id/et_path"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入要下载的文件资源路径"
android:text="http://dl001.liqucn.com/upload/2018/286/s/A_Sixrooms_xiuchang_9372-xiuchang_liqu_5.9.6_20180604-104643.apk" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="download"
android:text="下载" />
<ProgressBar
android:id="@+id/pb0"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ProgressBar
android:id="@+id/pb1"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ProgressBar
android:id="@+id/pb2"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
public class MainActivity extends Activity {
private EditText et_path;
private ProgressBar pb0;
private ProgressBar pb1;
private ProgressBar pb2;
/**
* 开启几个线程从服务器下载数据
*/
public static int threadCount = 3;
public static int runningThreadCount;
private String path;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化控件
et_path = (EditText) findViewById(R.id.et_path);
pb0 = (ProgressBar) findViewById(R.id.pb0);
pb1 = (ProgressBar) findViewById(R.id.pb1);
pb2 = (ProgressBar) findViewById(R.id.pb2);
}
//下载按钮的点击事件
public void download(View view) {
path = et_path.getText().toString().trim();
if (TextUtils.isEmpty(path) || (!path.startsWith("http://"))) {
Toast.makeText(this, "对不起路径不合法", 0).show();
return;
}
new Thread(){
public void run() {
try {
//1.获取服务器上的目标文件的大小
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
int code = conn.getResponseCode();
if (code == 200) {
int length = conn.getContentLength();
System.out.println("服务器文件的长度为:" + length);
//2.在本地创建一个跟原始文件同样大小的文件
RandomAccessFile raf = new RandomAccessFile(Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+getFileName(path), "rw");
raf.setLength(length);
raf.close();
//3.计算每个线程下载的起始位置和结束位置
int blocksize = length / threadCount;
runningThreadCount = threadCount;
for (int threadId = 0; threadId < threadCount; threadId++) {
int startIndex = threadId * blocksize;
int endIndex = (threadId + 1) * blocksize - 1;
if (threadId == (threadCount - 1)) {
endIndex = length - 1;
}
//4.开启多个子线程开始下载
new DownloadThread(threadId, startIndex, endIndex).start();
}
}
} catch (Exception e) {
e.printStackTrace();
}
};
}.start();
}
private class DownloadThread extends Thread {
/**
* 线程id
*/
private int threadId;
/**
* 线程下载的理论开始位置
*/
private int startIndex;
/**
* 线程下载的结束位置
*/
private int endIndex;
/**
* 当前线程下载到文件的那一个位置了.
*/
private int currentPosition;
public DownloadThread(int threadId, int startIndex, int endIndex) {
this.threadId = threadId;
this.startIndex = startIndex;
this.endIndex = endIndex;
System.out.println(threadId + "号线程下载的范围为:" + startIndex
+ " ~~ " + endIndex);
currentPosition = startIndex;
}
@Override
public void run() {
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//检查当前线程是否已经下载过一部分的数据了
File info = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+threadId+".position");
RandomAccessFile raf = new RandomAccessFile(Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+getFileName(path), "rw");
if(info.exists()&&info.length()>0){
FileInputStream fis = new FileInputStream(info);
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
currentPosition = Integer.valueOf(br.readLine());
conn.setRequestProperty("Range", "bytes="+currentPosition+"-"+endIndex);
System.out.println("原来有下载进度,从上一次终止的位置继续下载"+"bytes="+currentPosition+"-"+endIndex);
fis.close();
raf.seek(currentPosition);//每个线程写文件的开始位置都是不一样的.
}else{
//告诉服务器 只想下载资源的一部分
conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);
System.out.println("原来没有有下载进度,新的下载"+ "bytes="+startIndex+"-"+endIndex);
raf.seek(startIndex);//每个线程写文件的开始位置都是不一样的.
}
InputStream is = conn.getInputStream();
byte[] buffer = new byte[1024];
int len = -1;
while((len = is.read(buffer))!=-1){
//把每个线程下载的数据放在自己的空间里面.
// System.out.println("线程:"+threadId+"正在下载:"+new String(buffer));
raf.write(buffer,0, len);
//5.记录下载进度
currentPosition+=len;
File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+threadId+".position");
RandomAccessFile fos = new RandomAccessFile(file,"rwd");
//System.out.println("线程:"+threadId+"写到了"+currentPosition);
fos.write(String.valueOf(currentPosition).getBytes());
fos.close();//fileoutstream数据是不一定被写入到底层设备里面的,有可能是存储在缓存里面.
//raf 的 rwd模式,数据是立刻被存储到底层硬盘设备里面.
//更新进度条的显示
int max = endIndex - startIndex;
int progress = currentPosition - startIndex;
if(threadId==0){
pb0.setMax(max);
pb0.setProgress(progress);
}else if(threadId==1){
pb1.setMax(max);
pb1.setProgress(progress);
}else if(threadId==2){
pb2.setMax(max);
pb2.setProgress(progress);
}
}
raf.close();
is.close();
System.out.println("线程:"+threadId+"下载完毕了...");
File f = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+threadId+".position");
f.renameTo(new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+threadId+".position.finish"));
synchronized (MainActivity.class) {
runningThreadCount--;
//6.删除临时文件
if(runningThreadCount<=0){
for(int i=0;i<threadCount;i++){
File ft = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+i+".position.finish");
ft.delete();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 获取一个文件名称
* @param path
* @return
*/
public String getFileName(String path){
int start = path.lastIndexOf("/")+1;
return path.substring(start);
}
}