public class MainActivity extends Activity {
protected final int DOWNLOAD_ERROR = 1;
private final int THREADE_ERROR = 2;
private final int DOWNLOAD_FINISH =3;
private int threadcount;
private long blocksize;
private int threaddowncount = 3;
EditText et_Path;
EditText et_count;
List<ProgressBar>pds=null;
LinearLayout licontent;
/**
* 安卓下的消息处理器
*/
private Handler handler=new Handler(){
public void handleMessage(Message msg) {
switch (msg.what) {
case DOWNLOAD_ERROR:
Toast.makeText(getApplicationContext(), "下载失败", 0).show();
break;
case THREADE_ERROR:
Toast.makeText(getApplicationContext(), "下载进程出错", 0).show();
break;
case DOWNLOAD_FINISH:
Toast.makeText(getApplicationContext(), "下载成功", 0).show();
break;
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_Path = (EditText) findViewById(R.id.fileurl);
et_count=(EditText) findViewById(R.id.count);
licontent=(LinearLayout) findViewById(R.id.ll_containt);
}
public void download(View view) {
Toast.makeText(this, "开始下载", 0).show();
String etcount=et_count.getText().toString();
threaddowncount=Integer.valueOf(etcount);
licontent.removeAllViews();
pds=new ArrayList<ProgressBar>();
for (int i = 0; i < threaddowncount; i++) {
ProgressBar pd=(ProgressBar) view.inflate(this, R.layout.pd, null);
licontent.addView(pd);
pds.add(pd);
}
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
String path = "http://192.168.0.101:8080/duoxianchengxiazai/Android.rar";// 定义下载文件地址
URL url = new URL(path);// 利用url 开启下载
HttpURLConnection conn = (HttpURLConnection) url
.openConnection();// 打开这个url获得一个连接
conn.setReadTimeout(5000);// 设置超时时间
conn.setRequestMethod("GET");// 设置请求方法 大写 get和psot两种
int code = conn.getResponseCode();// 获得状态码 标示是否请求成功
if (code == 200) {
long size = conn.getContentLength();// 获得要下载文件的大小
Log.i("文件大小", size + "");
//threadcount = 3;// 定义下载的线程数量
threadcount=threaddowncount;
blocksize = size / threaddowncount;// 得到 一个线程需要下载的文件块大小
// 首先在本地创建一个和下载文件一模一样大小的文件
File sd=Environment.getExternalStorageDirectory();
boolean bool=sd.canRead();
File file = new File(Environment.getExternalStorageDirectory(),getfilename(path));
RandomAccessFile ra = new RandomAccessFile(file, "rw");// rw
// 如果没有就新建
ra.setLength(size);// 设置本地文件大小
// 开启若干个线程,分别去下载相对应的资源
for (int i = 1; i <= threadcount; i++) {
// long starindex = (i - 1) * blocksize + 1;
// long endindex = i * blocksize;//本来是这样的
// 因为服务器是从0开始而不是从1开始
// 所以不可用
long starindex = (i - 1) * blocksize + 0;
long endindex = i * blocksize - 1;
if (i == threadcount) {
endindex = size - 1;
}
int max=(int)(endindex-starindex);
pds.get(i-1).setMax(max);
threaddownload th = new threaddownload(i,
starindex, endindex, path);
th.start();
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
Message msg=Message.obtain();
msg.what=DOWNLOAD_ERROR;
handler.sendMessage(msg);
}
}
}).start();
}
/**
* 内部线程类
*
* @author Administrator
*
*/
public class threaddownload extends Thread {
private int threadid;
private long starindex;
private long endindex;
private String path;
public threaddownload(int threadid, long starindex, long endindex,
String path) {
super();
this.threadid = threadid;
this.starindex = starindex;
this.endindex = endindex;
this.path = path;
}
// 重写父类run方法
public void run() {
try {
int total = 0;// 断电续传加的代码 定义 下载多少
File fileinfo = new File( Environment.getExternalStorageDirectory(),threadid + ".txt");// 断点续传加的代码
// 定义已经下载的保存文件
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url
.openConnection();
conn.setReadTimeout(5000);
conn.setRequestMethod("GET");
// 这里是断点续传操作 需要在这里接着上次下载的大小开始下载
if (fileinfo.exists() && fileinfo.length() > 0) {
FileInputStream fs = new FileInputStream(fileinfo);
BufferedReader buff = new BufferedReader(
new InputStreamReader(fs));
// 获得上次下载的大小
String lasttoalstr = buff.readLine();
int lasttotal = Integer.parseInt(lasttoalstr);
Log.i("上次下载", lasttoalstr);
starindex += lasttotal;
total += lasttotal;
fs.close();
}
conn.setRequestProperty("range", "bytes=" + starindex + "-"
+ endindex);// 这里是设置 要请求文件的位置 连个参数
// 如"range","bytes=1214-125456"
int code = conn.getResponseCode();// 得到状态码 因为是下载服务器部分文件
// 所以这个状态码 是206
System.out.println("code:" + code);
InputStream is = conn.getInputStream();// 得到输出流
File file =new File(Environment.getExternalStorageDirectory(),getfilename(path));
RandomAccessFile ra = new RandomAccessFile(file, "rw");
ra.seek(starindex);// 开始写文件的地址
int len = 0;
byte[] buffer = new byte[1024];
while ((len = is.read(buffer)) != -1) {
ra.write(buffer, 0, len);// 循环写入到ra所指的的文件里
total += len;// 断点续传加的代码 把已经写入的本地硬盘的文件保存起来
// FileOutputStream fos = new FileOutputStream(fileinfo);//
// 断点续传加的代码 这里是先写入到缓存区里 不可用
RandomAccessFile rf = new RandomAccessFile(fileinfo, "rwd");// 这里是立即写入到本地硬盘,而不是先存放到缓冲区里
rf.write(String.valueOf(total).getBytes());// 断点续传加的代码把已经下载好的文件保存到对应的txt里
rf.close();
pds.get(threadid-1).setProgress(total);
}
is.close();
ra.close();
} catch (Exception e) {
e.printStackTrace();
Message msg=Message.obtain();
msg.what=THREADE_ERROR;
handler.sendMessage(msg);
} finally {
// 定义同步 锁
synchronized (MainActivity.class) {
Log.i("线程:" + threadid, "下载完毕");
threaddowncount--;
if (threaddowncount < 1) {
Log.i("线程:" + threadid, "下载完毕删除文件");
for (int i = 1; i <= threadcount; i++) {
File fi = new File(Environment.getExternalStorageDirectory(),i + ".txt");
System.out.println(fi.delete());
Message msg=Message.obtain();
msg.what=DOWNLOAD_FINISH;
handler.sendMessage(msg);
}
}
}
}
}
}
private String getfilename( String path)
{
int fileindex=path.lastIndexOf("/")+1;
return path.substring(fileindex);
}
权限
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
布局文件
<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"
tools:context=".MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="请输入要下载的文件地址" />
<EditText
android:id="@+id/fileurl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="http://192.168.0.101:8080/duoxianchengxiazai/Android.rar" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="请输入要开启的线程" />
<EditText
android:id="@+id/count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="number"
android:text="3" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="download"
android:text="下载" />
<LinearLayout
android:id="@+id/ll_containt"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</LinearLayout>
</LinearLayout>
进度条布局
<?xml version="1.0" encoding="utf-8"?>
<ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/progressBar1"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />