HttpClient(掌握)
發(fā)送get請求
-
創(chuàng)建一個(gè)客戶端對象
HttpClient client = new DefaultHttpClient();
-
創(chuàng)建一個(gè)get請求對象
HttpGet hg = new HttpGet(path);
-
發(fā)送get請求,建立連接,返回響應(yīng)頭對象
HttpResponse hr = hc.execute(hg);
-
獲取狀態(tài)行對象,獲取狀態(tài)碼,如果為200則說明請求成功
if(hr.getStatusLine().getStatusCode() == 200){ //拿到服務(wù)器返回的輸入流 InputStream is = hr.getEntity().getContent(); String text = Utils.getTextFromStream(is); }
發(fā)送post請求
//創(chuàng)建一個(gè)客戶端對象
HttpClient client = new DefaultHttpClient();
//創(chuàng)建一個(gè)post請求對象
HttpPost hp = new HttpPost(path);
-
往post對象里放入要提交給服務(wù)器的數(shù)據(jù)
//要提交的數(shù)據(jù)以鍵值對的形式存在BasicNameValuePair對象中 List<NameValuePair> parameters = new ArrayList<NameValuePair>(); BasicNameValuePair bnvp = new BasicNameValuePair("name", name); BasicNameValuePair bnvp2 = new BasicNameValuePair("pass", pass); parameters.add(bnvp); parameters.add(bnvp2); //創(chuàng)建實(shí)體對象舷蟀,指定進(jìn)行URL編碼的碼表 UrlEncodedFormEntity entity = new UrlEncodedFormEntity(parameters, "utf-8"); //為post請求設(shè)置實(shí)體 hp.setEntity(entity);
異步HttpClient框架(熟悉)
發(fā)送get請求
//創(chuàng)建異步的httpclient對象
AsyncHttpClient ahc = new AsyncHttpClient();
//發(fā)送get請求
ahc.get(path, new MyHandler());
-
注意AsyncHttpResponseHandler兩個(gè)方法的調(diào)用時(shí)機(jī)
class MyHandler extends AsyncHttpResponseHandler{ //http請求成功,返回碼為200,系統(tǒng)回調(diào)此方法 @Override public void onSuccess(int statusCode, Header[] headers, //responseBody的內(nèi)容就是服務(wù)器返回的數(shù)據(jù) byte[] responseBody) { Toast.makeText(MainActivity.this, new String(responseBody), 0).show(); } //http請求失敗什猖,返回碼不為200,系統(tǒng)回調(diào)此方法 @Override public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) { Toast.makeText(MainActivity.this, "返回碼不為200", 0).show(); } }
發(fā)送post請求
-
使用RequestParams對象封裝要攜帶的數(shù)據(jù)
//創(chuàng)建異步httpclient對象 AsyncHttpClient ahc = new AsyncHttpClient(); //創(chuàng)建RequestParams封裝要攜帶的數(shù)據(jù) RequestParams rp = new RequestParams(); rp.add("name", name); rp.add("pass", pass); //發(fā)送post請求 ahc.post(path, rp, new MyHandler());
多線程下載(掌握)
原理:服務(wù)器CPU分配給每條線程的時(shí)間片相同红淡,服務(wù)器帶寬平均分配給每條線程不狮,所以客戶端開啟的線程越多,就能搶占到更多的服務(wù)器資源
確定每條線程下載多少數(shù)據(jù)(掌握)
-
發(fā)送http請求至下載地址
String path = "http://192.168.1.102:8080/editplus.exe"; URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setReadTimeout(5000); conn.setConnectTimeout(5000); conn.setRequestMethod("GET");
-
獲取文件總長度在旱,然后創(chuàng)建長度一致的臨時(shí)文件
if(conn.getResponseCode() == 200){ //獲得服務(wù)器流中數(shù)據(jù)的長度 int length = conn.getContentLength(); //創(chuàng)建一個(gè)臨時(shí)文件存儲下載的數(shù)據(jù) RandomAccessFile raf = new RandomAccessFile(getFileName(path), "rwd"); //設(shè)置臨時(shí)文件的大小 raf.setLength(length); raf.close();
-
確定線程下載多少數(shù)據(jù)
//計(jì)算每個(gè)線程下載多少數(shù)據(jù) int blockSize = length / THREAD_COUNT;
計(jì)算每條線程下載數(shù)據(jù)的開始位置和結(jié)束位置(掌握)
for(int id = 1; id <= 3; id++){
//計(jì)算每個(gè)線程下載數(shù)據(jù)的開始位置和結(jié)束位置
int startIndex = (id - 1) * blockSize;
int endIndex = id * blockSize - 1;
if(id == THREAD_COUNT){
endIndex = length;
}
//開啟線程摇零,按照計(jì)算出來的開始結(jié)束位置開始下載數(shù)據(jù)
new DownLoadThread(startIndex, endIndex, id).start();
}
再次發(fā)送請求至下載地址,請求開始位置至結(jié)束位置的數(shù)據(jù)(掌握)
String path = "http://192.168.1.102:8080/editplus.exe";
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(5000);
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
//向服務(wù)器請求部分?jǐn)?shù)據(jù)
conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
conn.connect();
-
下載請求到的數(shù)據(jù)颈渊,存放至臨時(shí)文件中
if(conn.getResponseCode() == 206){ InputStream is = conn.getInputStream(); RandomAccessFile raf = new RandomAccessFile(getFileName(path), "rwd"); //指定從哪個(gè)位置開始存放數(shù)據(jù) raf.seek(startIndex); byte[] b = new byte[1024]; int len; while((len = is.read(b)) != -1){ raf.write(b, 0, len); } raf.close(); }
帶斷點(diǎn)續(xù)傳的多線程下載(掌握)
-
定義一個(gè)int變量記錄每條線程下載的數(shù)據(jù)總長度遂黍,然后加上該線程的下載開始位置,得到的結(jié)果就是下次下載時(shí)俊嗽,該線程的開始位置雾家,把得到的結(jié)果存入緩存文件
//用來記錄當(dāng)前線程總的下載長度 int total = 0; while((len = is.read(b)) != -1){ raf.write(b, 0, len); total += len; //每次下載都把新的下載位置寫入緩存文本文件 RandomAccessFile raf2 = new RandomAccessFile(threadId + ".txt", "rwd"); raf2.write((startIndex + total + "").getBytes()); raf2.close(); }
-
下次下載開始時(shí),先讀取緩存文件中的值绍豁,得到的值就是該線程新的開始位置
FileInputStream fis = new FileInputStream(file); BufferedReader br = new BufferedReader(new InputStreamReader(fis)); String text = br.readLine(); int newStartIndex = Integer.parseInt(text); //把讀到的值作為新的開始位置 startIndex = newStartIndex; fis.close();
-
三條線程都下載完畢之后芯咧,刪除緩存文件
RUNNING_THREAD--; if(RUNNING_THREAD == 0){ for(int i = 0; i <= 3; i++){ File f = new File(i + ".txt"); f.delete(); } }
手機(jī)版的斷點(diǎn)續(xù)傳多線程下載器
- 把剛才的代碼直接粘貼過來就能用,記得在訪問文件時(shí)的路徑要改成Android的目錄,添加訪問網(wǎng)絡(luò)和外部存儲的路徑
用進(jìn)度條顯示下載進(jìn)度(掌握)
-
拿到下載文件總長度時(shí)敬飒,設(shè)置進(jìn)度條的最大值
//設(shè)置進(jìn)度條的最大值 pb.setMax(length);
-
進(jìn)度條需要顯示三條線程的整體下載進(jìn)度邪铲,所以三條線程每下載一次,就要把新下載的長度加入進(jìn)度條
-
定義一個(gè)int全局變量无拗,記錄三條線程的總下載長度
int progress;
-
刷新進(jìn)度條
while((len = is.read(b)) != -1){ raf.write(b, 0, len); //把當(dāng)前線程本次下載的長度加到進(jìn)度條里 progress += len; pb.setProgress(progress);
-
-
每次斷點(diǎn)下載時(shí)带到,從新的開始位置開始下載,進(jìn)度條也要從新的位置開始顯示英染,在讀取緩存文件獲取新的下載開始位置時(shí)揽惹,也要處理進(jìn)度條進(jìn)度
FileInputStream fis = new FileInputStream(file); BufferedReader br = new BufferedReader(new InputStreamReader(fis)); String text = br.readLine(); int newStartIndex = Integer.parseInt(text); //新開始位置減去原本的開始位置,得到已經(jīng)下載的數(shù)據(jù)長度 int alreadyDownload = newStartIndex - startIndex; //把已經(jīng)下載的長度設(shè)置入進(jìn)度條 progress += alreadyDownload;
添加文本框顯示百分比進(jìn)度(熟悉)
tv.setText(progress * 100 / pb.getMax() + "%");
HttpUtils的使用(熟悉)
HttpUtils本身就支持多線程斷點(diǎn)續(xù)傳四康,使用起來非常的方便
-
創(chuàng)建HttpUtils對象
HttpUtils http = new HttpUtils();
-
下載文件
http.download(url, //下載請求的網(wǎng)址 target, //下載的數(shù)據(jù)保存路徑和文件名 true, //是否開啟斷點(diǎn)續(xù)傳 true, //如果服務(wù)器響應(yīng)頭中包含了文件名搪搏,那么下載完畢后自動重命名 new RequestCallBack<File>() {//偵聽下載狀態(tài) //下載成功此方法調(diào)用 @Override public void onSuccess(ResponseInfo<File> arg0) { tv.setText("下載成功" + arg0.result.getPath()); } //下載失敗此方法調(diào)用,比如文件已經(jīng)下載闪金、沒有網(wǎng)絡(luò)權(quán)限疯溺、文件訪問不到,方法傳入一個(gè)字符串參數(shù)告知失敗原因 @Override public void onFailure(HttpException arg0, String arg1) { tv.setText("下載失敗" + arg1); } //在下載過程中不斷的調(diào)用哎垦,用于刷新進(jìn)度條 @Override public void onLoading(long total, long current, boolean isUploading) { super.onLoading(total, current, isUploading); //設(shè)置進(jìn)度條總長度 pb.setMax((int) total); //設(shè)置進(jìn)度條當(dāng)前進(jìn)度 pb.setProgress((int) current); tv_progress.setText(current * 100 / total + "%"); } });