android 客戶端多線程下載

/**** 在配置文件中加入如下權限 A:訪問網絡的權限 B.C:能夠對SD操做的權限 ***/ <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"/>java

/**主類?/ package com.example.downloadandprogressor;android

import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.app.Activity; import android.view.Menu; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast;網絡

public class MainActivity extends Activity {多線程

/***
 * 這個Activity操做是把網絡資源下載到
 * 本地的SD卡中去
 * 咱們採用的是多線程技術進行操做下載
 * 因爲手機的硬件資源有限--最好是開啓的線程5條如下爲好
 * 本操做也有進度條進行顯示
 * 這裏要注意的問題是:耗時的操做必須在子線程中操做--其實
 * 這裏的操做最好由Service後臺操做纔好
 * 問題2:更新UI組件必需要在主線程中進行
 * 不然是不會有效果的
 * 
 */

private Handler myhandler =null;

private EditText url=null;
private Button down = null;
private Button exit=null;
private TextView sm=null;
private ProgressBar progrressbar=null;

protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);
	//獲取各個組件
	url=(EditText)findViewById(R.id.urlE);
	down=(Button)findViewById(R.id.down);
	exit=(Button)findViewById(R.id.tcxz);//退出按鈕
	sm=(TextView)findViewById(R.id.jd);
	progrressbar=(ProgressBar)findViewById(R.id.progressbar);
	myhandler = new MyHander();//這裏負責子線程和主線程的交互--更新UI
	down.setOnClickListener(new View.OnClickListener() {
		
		
		public void onClick(View v) {
			String path=url.getText().toString();
			startLoad(path,3);
			
		}

		
	});
	
	exit.setOnClickListener(new View.OnClickListener() {
		
		
		public void onClick(View v) {
			
			System.exit(0);
			
		}
	});
	
}

protected void startLoad(String path, int i) {
	
	try {
		DownLoadService.load(path,i,this.progrressbar,this.myhandler);
	} catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
	// Inflate the menu; this adds items to the action bar if it is present.
	getMenuInflater().inflate(R.menu.activity_main, menu);
	return true;
}

private final class MyHander extends Handler{

	/***
	 * 因爲更新UI要在主線程進行
	 * 又由於在子線程要有數據要返回給主線程
	 * 因此就要進行Handler操做
	 * 才能提供一個主線程和子線程交互的平臺
	 * 
	 */
	
	public void handleMessage(Message msg) {
		// TODO Auto-generated method stub
		super.handleMessage(msg);
		
		if(msg.what==1){
			
			
			
		int size=msg.getData().getInt("size");
		progrressbar.setProgress(size);//設置當前的值
		
		if(progrressbar.getProgress()== progrressbar.getMax()){
			
			Toast.makeText(getApplicationContext(), "下載完成", Toast.LENGTH_LONG).show();
			sm.setText("100%");
		}else{
			
			float v = (float)progrressbar.getProgress() / (float)progrressbar.getMax();
			int k = (int)(v*100);
			sm.setText(k+"%");
		}
		
			
		}
		
	}
	
}

} /*負責下載的類service?/ package com.example.downloadandprogressor;app

import java.io.File; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL;dom

import android.os.Environment; import android.os.Handler; import android.widget.ProgressBar;ide

public class DownLoadService {this

public static void load(String path, int i,ProgressBar progrressbar,Handler myhandler) throws Exception{
	
	URL url = new URL(path);
	HttpURLConnection con = (HttpURLConnection)url.openConnection();
	con.setReadTimeout(5000);
	con.setRequestMethod("GET");
	//獲取網絡資源的長度
	int len = con.getContentLength();
	//獲取SD卡路徑
	String sdpath=DownLoadService.getSDpath();
	if(sdpath==null){
		System.out.println("-------------沒有SD卡-------------------");
		return;
	}
	//建立一個本地的文件--並和其網絡的資源大小同樣
	File file = new File(sdpath,DownLoadService.getContentName(path));
	RandomAccessFile af = new RandomAccessFile(file, "rwd");
	//設置其文件的大小
	af.setLength(len);
	//計算每一個線程要下載的區域
	int block = (len%i) == 0 ? len/i : len/i+1;
	//爲進度條設置最大的值
	progrressbar.setMax(len);

	
	//開始開啓子線程進行下載
	for(int j=0;j<i;j++){
		
		new DownLoadThread(j,file,url,block,myhandler).start();
	}
	
	
}

private static String getContentName(String path) {
	
	return path.substring(path.lastIndexOf("/")+1);
}

private static String getSDpath() {
	String SDpath=null;
	if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
		SDpath=Environment.getExternalStorageDirectory().getPath();
	}
	return SDpath;
}

} /**負責下載的線程類?*/ package com.example.downloadandprogressor;url

import java.io.File; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL;.net

import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.widget.Toast;

public class DownLoadThread extends Thread {

public static int size=0;

private int j;//線程的ID
private File file;//本地文件
private URL url;//網絡資源路徑
private int block;//下載的塊
private Handler myhandler;//負責和線程進行交互


public DownLoadThread(int j, File file, URL url, int block,Handler myhandler) {
	
	this.j=j;
	this.file=file;
	this.url=url;
	this.block=block;
	this.myhandler=myhandler;
	
}

public void run() {
	
	try{
		HttpURLConnection con = (HttpURLConnection)url.openConnection();
		con.setReadTimeout(5000);
		con.setRequestMethod("GET");
		//計算開始點和結束點
		int start = (j*block);
		int end = (j+1)*block-1;
		
		RandomAccessFile af = new RandomAccessFile(file,"rwd");
		af.seek(start);//尋找寫入的位置
		//設置請求的頭文件--因爲是多線程下載--因此要設置區域下載大小的頭文件bytes=1-11
		con.setRequestProperty("Range", "bytes="+start+"-"+end);
		//根據返回的狀態嘛判斷是否成功
		if(con.getResponseCode() == 206 ){//下載連接成功的狀態嗎爲 206
			InputStream in = con.getInputStream();
			byte[] buf = new byte[1024];
			int len=0;
			while((len=in.read(buf))!=-1){
				//計算目前總的下載量
				DownLoadThread.getSize(len,this.myhandler);
				af.write(buf,0,len);
			}
			af.close();
			in.close();
			System.out.println("第"+j+"線程完成下載");
		}else{
			System.out.println("第"+j+"線程沒法完成下載");
		}
		
	}catch(Exception e){
		e.printStackTrace();
	}
	
	
}

private synchronized  static void getSize(int len,Handler myhandler) {
	
	DownLoadThread.size+=len;
	Message msg = new Message();
	Bundle b = new Bundle();
	b.putInt("size", DownLoadThread.size);
	msg.setData(b);
	msg.what=1;
	myhandler.sendMessage(msg);
	
}

}

相關文章
相關標籤/搜索