Android多线程下载

来源:互联网 发布:js改变div的style 编辑:程序博客网 时间:2024/04/28 20:11


开发思路:

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 stubMessage msg = new Message();msg.what = DOWNLOAD_MAX;msg.obj = length;mHandler.sendMessage(msg);}public void getLength(int length) {// TODO Auto-generated method stubMessage 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 blocke.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);}


 

0 0
原创粉丝点击