Android多线程下载


开发思路:

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);
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值