开发思路:
1、首先确定开辟的线程数 int threadsize = 3;
文件的大小 int filesize ;
2、计算每条线程的下载量 int block = filesize%threadsize == 0?filesize/threadsize:filesize/threadsize+1;
3、计算出每条线程的下载开始和结束位置
for(int threadid = 0;threadid<threadsize;threadid++){//开启三条线程
int startposition = threadid*block;
int endposition = (threadid+1)*block-1;
}
4、申请网络资源
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//告诉http协议从哪里下载开始和哪里结束
conn.setRequestProperty("Range", "bytes="+startposition+"-"+endposition);
5、随机访问文件 用到RandomAccessFile 这个类
//跳转到要写入的位置
acf.seek(startposition);
类的设计
UI(MainActivity)
DownloadManager //下载管理器
int threadsize ;
public void download(String path,File dir){
//1 联网获取文件的大小
//2 计算每条线程的下载量
//3 开启线程下载
}
DownloadThread extends Thread{
String path;
int threadid;
int block;
File dir;
Listener l;
//设计一个接口(解耦合)
interface ProgressBarListener{
void getMax(int length);//最大值
void getLength(int length);//每次下载的数据量
}
在MAinActivity中
public class MainActivity extends Activity {
protected static final int DOWNLOAD_ERROR = 0;
protected static final int DOWNLOAD_MAX = 1;
protected static final int DOWNLOAD_LENGTH = 2;
private EditText et_path;
private ProgressBar pb;
private TextView tv_info;
private DownloadManager manager;
private Handler mHandler = new Handler(){
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case DOWNLOAD_ERROR:
Toast.makeText(getApplicationContext(), "下载失败", 1).show();
break;
case DOWNLOAD_MAX:
int max = (Integer) msg.obj;
pb.setMax(max);
break;
case DOWNLOAD_LENGTH:
int length = (Integer) msg.obj;
int now = pb.getProgress()+length;
pb.setProgress(now);
//计算百分比
float precent = (float)now/pb.getMax();
int info = (int) (precent*100);
tv_info.setText("下载:"+info+"%");
break;
default:
break;
}
};
};
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
et_path = (EditText) findViewById(R.id.et_path);
pb = (ProgressBar) findViewById(R.id.pb);
tv_info = (TextView) findViewById(R.id.tv_info);
}
public void download(View v){
final String path = et_path.getText().toString();
manager = new DownloadManager(new ProgressBarListener() {
public void getMax(int length) {
// TODO Auto-generated method stub
Message msg = new Message();
msg.what = DOWNLOAD_MAX;
msg.obj = length;
mHandler.sendMessage(msg);
}
public void getLength(int length) {
// TODO Auto-generated method stub
Message msg = new Message();
msg.what = DOWNLOAD_LENGTH;
msg.obj = length;
mHandler.sendMessage(msg);
}
});
//判断SD卡是否存在
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
//下载耗时的操作
new Thread(){
public void run() {
try {
manager.download(path, Environment.getExternalStorageDirectory());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
Message msg = new Message();
msg.what = DOWNLOAD_ERROR;
mHandler.sendMessage(msg);
}
};
}.start();
}else{
//sdcard不存在
Toast.makeText(this, "sdcard不存在", 1).show();
}
}
}
在DownloadManager中
public class DownloadManager {
private final static int threadsize = 3;
private ProgressBarListener listener;
public DownloadManager(ProgressBarListener listener) {
super();
this.listener = listener;
}
/**
* 下载方法
* @param path 下载路径
* @param dir 保存路径
* @throws Exception
*/
public void download(String path,File dir) throws Exception{
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setConnectTimeout(5000);
if(conn.getResponseCode() == 200){
//文件大小
int filesize = conn.getContentLength();
//在本地创建一个和服务上大小一样的文件
File file = new File(dir, getName(path));
RandomAccessFile acf = new RandomAccessFile(file, "rwd");
//设置随机访问文件的长度
acf.setLength(filesize);
//告诉监听器
listener.getMax(filesize);
//计算每条线程下载量
int block = filesize%threadsize==0?filesize/threadsize:filesize/threadsize+1;
//开启三条线程去下载
for(int threadid=0;threadid<threadsize;threadid++){
new DownloadThread(threadid, path, dir, block, listener).start();
}
}
}
//获取文件的名字
public String getName(String path){
return path.substring(path.lastIndexOf("/")+1);
}
}
在DownloadThread类中
public class DownloadThread extends Thread {
private int threadid;
private String path;
private File dir;
private int block;
private ProgressBarListener listener;
private int startposition;
private int endposition;
public DownloadThread(int threadid, String path, File dir, int block,
ProgressBarListener listener) {
super();
this.threadid = threadid;
this.path = path;
this.dir = dir;
this.block = block;
this.listener = listener;
startposition = threadid*block;
endposition = (threadid+1)*block-1;
}
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
try {
File file = new File(dir,getName(path));
RandomAccessFile acf = new RandomAccessFile(file, "rwd");
//跳转到要写入的位置
acf.seek(startposition);
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setConnectTimeout(5000);
//告诉http协议从哪里下载开始和哪里结束
conn.setRequestProperty("Range", "bytes="+startposition+"-"+endposition);
//不要在对相应码进行判断
InputStream is = conn.getInputStream();
byte[] buffer = new byte[1024];
int len = 0;
while((len = is.read(buffer))!= -1){
//写入数据
acf.write(buffer, 0, len);
listener.getLength(len);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//获取文件的名字
public String getName(String path){
return path.substring(path.lastIndexOf("/")+1);
}
}
在ProgressBarListener接口中
public interface ProgressBarListener {
//获取最大值
public void getMax(int length);
//获取每次的下载量
public void getLength(int length);
}