Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android初級教程理論知識(第八章網絡編程二)

Android初級教程理論知識(第八章網絡編程二)

編輯:關於Android編程

HttpClient

發送get請求

創建一個客戶端對象

HttpClient client = new DefaultHttpClient();

創建一個get請求對象

HttpGet hg = new HttpGet(path);

發送get請求,建立連接,返回響應頭對象

HttpResponse hr = hc.execute(hg);

獲取狀態行對象,獲取狀態碼,如果為200則說明請求成功

if(hr.getStatusLine().getStatusCode() == 200){
    //拿到服務器返回的輸入流
    InputStream is = hr.getEntity().getContent();
    String text = Utils.getTextFromStream(is);
}

發送post請求

    //創建一個客戶端對象
    HttpClient client = new DefaultHttpClient();
    //創建一個post請求對象
    HttpPost hp = new HttpPost(path);

往post對象裡放入要提交給服務器的數據

//要提交的數據以鍵值對的形式存在BasicNameValuePair對象中
List parameters = new ArrayList();
BasicNameValuePair bnvp = new BasicNameValuePair("name", name);
BasicNameValuePair bnvp2 = new BasicNameValuePair("pass", pass);
//BasicNameValuePair是NameValuePair的實現類
parameters.add(bnvp);
parameters.add(bnvp2);
//創建實體對象,指定進行URL編碼的碼表
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(parameters, "utf-8");
//為post請求設置實體
hp.setEntity(entity);

異步HttpClient框架

發送get請求

    //創建異步的httpclient對象
    AsyncHttpClient ahc = new AsyncHttpClient();
    //發送get請求
    ahc.get(path, new MyHandler());

注意AsyncHttpResponseHandler兩個方法的調用時機

class MyHandler extends AsyncHttpResponseHandler{

    //http請求成功,返回碼為200,系統回調此方法
    @Override
    public void onSuccess(int statusCode, Header[] headers,
            //responseBody的內容就是服務器返回的數據
            byte[] responseBody) {
        Toast.makeText(MainActivity.this, new String(responseBody), 0).show();

    }

    //http請求失敗,返回碼不為200,系統回調此方法
    @Override
    public void onFailure(int statusCode, Header[] headers,
            byte[] responseBody, Throwable error) {
        Toast.makeText(MainActivity.this, "返回碼不為200", 0).show();

    }

}

發送post請求

使用RequestParams對象封裝要攜帶的數據

//創建異步httpclient對象
AsyncHttpClient ahc = new AsyncHttpClient();
//創建RequestParams封裝要攜帶的數據
RequestParams rp = new RequestParams();
rp.add("name", name);
rp.add("pass", pass);
//發送post請求
ahc.post(path, rp, new MyHandler());

多線程下載

原理:服務器CPU分配給每條線程的時間片相同,服務器帶寬平均分配給每條線程,所以客戶端開啟的線程越多,就能搶占到更多的服務器資源

確定每條線程下載多少數據

發送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");                   

獲取文件總長度,然後創建長度一致的臨時文件

if(conn.getResponseCode() == 200){
    //獲得服務器流中數據的長度
    int length = conn.getContentLength();
    //創建一個臨時文件存儲下載的數據
    RandomAccessFile raf = new RandomAccessFile(getFileName(path), "rwd");
    //設置臨時文件的大小
    raf.setLength(length);
    raf.close();

確定線程下載多少數據

    //計算每個線程下載多少數據
    int blockSize = length / THREAD_COUNT;

計算每條線程下載數據的開始位置和結束位置

    for(int id = 1; id <= 3; id++){
        //計算每個線程下載數據的開始位置和結束位置
        int startIndex = (id - 1) * blockSize;
        int endIndex = id * blockSize - 1;
        if(id == THREAD_COUNT){
            endIndex = length;
        }

        //開啟線程,按照計算出來的開始結束位置開始下載數據
        new DownLoadThread(startIndex, endIndex, id).start();
    }

再次發送請求至下載地址,請求開始位置至結束位置的數據

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

    //向服務器請求部分數據
    conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
    conn.connect();

下載請求到的數據,存放至臨時文件中

if(conn.getResponseCode() == 206){
    InputStream is = conn.getInputStream();
    RandomAccessFile raf = new RandomAccessFile(getFileName(path), "rwd");
    //指定從哪個位置開始存放數據
    raf.seek(startIndex);
    byte[] b = new byte[1024];
    int len;
    while((len = is.read(b)) != -1){
        raf.write(b, 0, len);
    }
    raf.close();
}

帶斷點續傳的多線程下載

定義一個int變量記錄每條線程下載的數據總長度,然後加上該線程的下載開始位置,得到的結果就是下次下載時,該線程的開始位置,把得到的結果存入緩存文件

//用來記錄當前線程總的下載長度
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();
}

下次下載開始時,先讀取緩存文件中的值,得到的值就是該線程新的開始位置

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

手機版的斷點續傳多線程下載器

把剛才的代碼直接粘貼過來就能用,記得在訪問文件時的路徑要改成Android的目錄,添加訪問網絡和外部存儲的路徑

用進度條顯示下載進度

拿到下載文件總長度時,設置進度條的最大值

//設置進度條的最大值
pb.setMax(length);

進度條需要顯示三條線程的整體下載進度,所以三條線程每下載一次,就要把新下載的長度加入進度條

定義一個int全局變量,記錄三條線程的總下載長度

int progress;

刷新進度條

while((len = is.read(b)) != -1){
    raf.write(b, 0, len);


    //把當前線程本次下載的長度加到進度條裡
    progress += len;
    pb.setProgress(progress);

每次斷點下載時,從新的開始位置開始下載,進度條也要從新的位置開始顯示,在讀取緩存文件獲取新的下載開始位置時,也要處理進度條進度

FileInputStream fis = new FileInputStream(file);
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
String text = br.readLine();
int newStartIndex = Integer.parseInt(text);

//新開始位置減去原本的開始位置,得到已經下載的數據長度
int alreadyDownload = newStartIndex - startIndex;
//把已經下載的長度設置入進度條
progress += alreadyDownload;

添加文本框顯示百分比進度

    tv.setText(progress * 100 / pb.getMax() + "%");

HttpUtils的使用

HttpUtils本身就支持多線程斷點續傳,使用起來非常的方便

創建HttpUtils對象

HttpUtils http = new HttpUtils();

下載文件

http.download(url, //下載請求的網址
        target, //下載的數據保存路徑和文件名
        true, //是否開啟斷點續傳
        true, //如果服務器響應頭中包含了文件名,那麼下載完畢後自動重命名
        new RequestCallBack() {//偵聽下載狀態

    //下載成功此方法調用
    @Override
    public void onSuccess(ResponseInfo arg0) {
        tv.setText("下載成功" + arg0.result.getPath());
    }

    //下載失敗此方法調用,比如文件已經下載、沒有網絡權限、文件訪問不到,方法傳入一個字符串參數告知失敗原因
    @Override
    public void onFailure(HttpException arg0, String arg1) {
        tv.setText("下載失敗" + arg1);
    }

    //在下載過程中不斷的調用,用於刷新進度條
    @Override
    public void onLoading(long total, long current, boolean isUploading) {
        super.onLoading(total, current, isUploading);
        //設置進度條總長度
        pb.setMax((int) total);
        //設置進度條當前進度
        pb.setProgress((int) current);
        tv_progress.setText(current * 100 / total + "%");
    }
});

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved