package com.example.tyxiong.myapplication;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.util.ArrayList;
/*
*
* Android 網絡應用.
* 3句概述:1 Android支持JDK的TCP/IP UDP的網絡通信API.即可用ServiceSocket Socket來建立基於TCP/IP協議的網絡通信;
* 也可以用DatagramSocket Dategrampacket MuliticastSocket來建立基於UDP協議的網絡通信.
* 2 Android支持JDK的URL URLConnection等網絡通信.
* 3 Android內置了HttpClient,方便的發送HTTP請求,簡化了與網站間的交互.(可惜沒有內置Web Service支持./有ksoap2-android項目)
*
* IP協議:實現計算機發送接收分組數據.
* TCP協議:提供可靠無差錯的通信服務. 端對端的協議(爲兩個通信實體之間通信起到了重要作用), 重發機制(接收方收到數據,有應答,若無則發送方重發數據)
* TCP IP功能互補,通常兩者結合使用,統稱TCP/IP協議.
* TCP/IP協議通信建立過程: 服務器端(主動)接收客戶端連接請求(accept()方法),當有客戶端(Socket)發送連接請求時,
* 方法返回與之對應的Socket;通信鏈路建立.主客消失,可通過Socket通信.
* 使用步驟4步:
* 1 服務器端創建ServiceSocket對象,指定端口(大於1024) 默認IP
* 2 對象的實例方法accept(),接收客戶端請求.阻塞線程,有請求時方法返回Socket對象
* 3 客戶端創建Socket對象,連接到指定的服務器端口 new Socket(remoteAddress,port)
* 4 兩個通信實體可通過Socket通信啦. 有方法getInputStream()/out.. 編碼的問題linux平臺用UTF-8字符集.
*
* 注意:android建立網絡連接不允許在UI線程中進行.
* 設置讀取數據超時(BufferReader readLine()阻塞):Socket有方法setSoTimeout(),超時可拋異常
* 設置連接服務器超時:步驟1 建無連接的Socket new Socket() 2 connect()方法設置
*
* 網絡通信中多線程:服務器端:由於readLine()會阻塞線程,則每個Socket建立一個線程負責.
* 客戶端: 同樣,需要一個線程讀取服務器數據+ 然後主線程負責界面,用戶輸入.
*
*
* URL,統一資源定位器,能打開URL指定網絡數據的輸入流(讀取) 2個實例方法openStream()/打開連接的輸入流 openURLConnection()/打開應用程序與URL資源間的連接對象
* URL組成:協議名,主機名,端口,資源.
* 讀取網絡資源2步驟:
* 1 創建URL對象 2openStream()打開資源輸入流,,讀取吧.>>>
*
* URLConnection提交請求:URL對象實例方法openURLConnection()方法->URLConnection對象-->發送請求,獲取數據.
* 6方法 2+4 設置請求頭字段 setRequestProperty(key,value)設置請求字段的值. addRequestProperty()爲指定key追加value值.
* 獲取響應 getContent()/獲取該URLConnection內容
* getHeaderField(string)獲取指定響應頭字段的值
* getInputStream()/URLConnection輸入流,讀取響應
* getOutputStram()/URLConnection輸出流,發送請求參數
* 使用分4步驟:
* 1 URL對象,方法 獲取URLConnection對象
* 2 設置URLConnection參數及請求字段屬性
* 3 若發送GET請求,直接connect()方法建立實際連接. Post請求則要打開URLConnection的輸出流,先發送請求參數.
* 4 遠程資源可用,用獲取響應方法讀取資源.
* 注意:*****若既要發送請求,又要讀取響應內容時,先發,再讀.POST請求
* ****若需發送POST請求,必須設置 setDoOutput(true) setDoInput(true)頭字段.
* ****用完關閉流.try/catch/final
*
* HttpURLConnection URLConnection子類,增強,爲Http訪問提供了不4個便捷方法
* 1 getResponseCode()//獲取服務器響應代碼
* 2 getResponseMessage()//響應消息
* 3 getRequestMethod()//獲取發送請求的方法
* 4 setRequestMethoe()//設置發送請求的方法.
*
* 多線程下載5步:
* 1 URL對象
* 2 獲取URL對象指定資源數據大小(getContentLength())
* 3 本地建立與資源相同大小空文件
* 4 平分資源計算每條線程下載的字節部分.
* 5 創建,啓動多條線程下載.
*
*
* HttpClient :1概述:Apache組織的項目,Android也內置了HttpClient支持.簡單的Http客戶端,用於發送HTTP請求
* 接收響應,增強版本的HttpURLConnection.使用5步: 3個對象 3個方法
* 1 創建HttpClient對象
* 2 若發送GET請求--HttpGet對象 POST請求--HttpPost對象
* 3 設置發送請求參數,,,可用setParams()/setEntity()
* 4 HttpClient對象execute()方法發送請求.該方法返回HttpResponse對象
* 5 HttpResponse對象 getEntity()方法,,獲取響應內容.
*
*
*
*
*
*
* HttpURLConnection URLConnection子類,增強,爲Http訪問提供了不4個便捷方法
* 1 getResponseCode()//獲取服務器響應代碼
* 2 getResponseMessage()//響應消息
* 3 getRequestMethod()//獲取發送請求的方法
* 4 setRequestMethoe()//設置發送請求的方法.
* */
public class MainActivity extends Activity {
EditText show;
Handler handler;
private Thread thread;
EditText fileName;
EditText threadCount;
ProgressDialog progressDialog;
private int progress;
private int MAX = 100;
DownUtils downUtils;
String url;
String path;
int count;
public void send(View view) {//向服務器發送數據....
url = show.getText().toString();
path = fileName.getText().toString();
count = Integer.parseInt(threadCount.getText().toString().trim());
progressDialog.show();
thread.start();
}//發送GET請求...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
show = (EditText) findViewById(R.id.show);
fileName = (EditText) findViewById(R.id.fileName);
threadCount = (EditText) findViewById(R.id.count);
progressDialog = new ProgressDialog(this);
progressDialog.setTitle("下載");
progressDialog.setIndeterminate(false);
progressDialog.setCancelable(false);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setMessage("正在下載...");
progressDialog.setMax(MAX);
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 0x11) {
progressDialog.setProgress(progress);
}
}
};
thread = new Thread() {
@Override
public void run() {
downUtils = new DownUtils(url, path, count);
downUtils.sendGet();
while (progress < MAX) {
float position = downUtils.getProgress();
progress = (int) (MAX * position);
try {
sleep(1 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.sendEmptyMessage(0x11);
}
progressDialog.dismiss();
}
};
}
}
class DownUtils {
String link;
/* "http://p.gdown.baidu.com/ab67d1f87dda5edd22d919fc5a33bad644220b671bb3bb17fd6f8849a61ed2c3c7e9c44f13348ef75f6bcbdb8cdc5c867bcf7dd31f353abeb47a285ab0b588c5c0df7dcdbcf395acd80b500258e99d064d92bac54af82bd95b7553bd86e2bc83ce217398cfb18bd8fd5e6a6f506db32f75cb5e965207230404b400a9fdd2fdc8e20c4215f9fde290e5b22eed14479ddd43a35e954f30c2e8ed119b7239a659fbf59390a45f51edaab818ef4eeb14a4011dd043f84f4b70f4d49f8a5b0571d5b1d8bdb84b2d49d3687d5b43e0fe513b59f3beef45c6121fd0088e20ad370cb22e02207716b95d8f627a5fe9d79f99b06852651f73c5d0e63476b8148506a88909fb0947b3e5510573632887aeee2e6b871dfe70d2ee93fc2fad2997f2a2845e1f40ac0b9ddbcf4e679cd8b0600f1a93af5774d530038d59a073d1e7f97ef1b488";*/
String path;
int COUNT;
public DownUtils(String link, String path, int COUNT) {
this.link = link;
this.path = "/mnt/sdcard/"+path;
this.COUNT = COUNT;
}
ArrayList<DownThread> list = new ArrayList<>();
int fileSize = 0;
int subSize = 0;
public float getProgress() {
int num = 0;
for (int i = 0; i < list.size(); i++) {
num += list.get(i).progress;
}
return 1.0f * num / fileSize;
}
public void sendGet() {
RandomAccessFile file = null;
try {
final HttpURLConnection urlConnection;
URL url = new URL(link);
urlConnection = (HttpURLConnection) url.openConnection();//1獲取與遠程資源的連接.
urlConnection.setConnectTimeout(10 * 1000);
urlConnection.setRequestProperty("accept", "*/*");
urlConnection.setRequestProperty("connection", "Keep-Alive");
urlConnection.setRequestProperty("charset", "utf-8");//設置請求字段屬性.
urlConnection.getRequestMethod();
urlConnection.setRequestMethod("GET"); //便捷方法設置發送請求方法
fileSize = urlConnection.getContentLength();
urlConnection.disconnect();
file = new RandomAccessFile(path, "rw");
file.setLength(fileSize);
Log.w("xxx", "sendGet: 需要下載文件大小" + fileSize);
subSize = fileSize / COUNT;
for (int i = 0; i < COUNT; i++) {
DownThread newThread = new DownThread(i * subSize, subSize);//// TODO: 11/11/2016
list.add(newThread);
newThread.start();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
assert file != null;
file.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class DownThread extends Thread {
public int position = 0;
int length = 0;
int progress = 0;
public DownThread(int position, int length) {
this.position = position;
this.length = length;
}
@Override
public void run() {
HttpURLConnection urlConnection;
URL url;
try {
RandomAccessFile randomAccessFile = new RandomAccessFile(path, "rw");
url = new URL(link);
urlConnection = (HttpURLConnection) url.openConnection();//1獲取與遠程資源的連接.
urlConnection.setConnectTimeout(10 * 1000);
urlConnection.setRequestProperty("accept", "*/*");
urlConnection.setRequestProperty("connection", "Keep-Alive");
urlConnection.setRequestProperty("charset", "utf-8");//設置請求字段屬性.
urlConnection.getRequestMethod();
urlConnection.setRequestMethod("GET"); //便捷方法設置發送請求方法
urlConnection.connect();
InputStream inputStream = urlConnection.getInputStream();
long j = 0;
while (j < position) {
j += inputStream.skip(position - j);
}
randomAccessFile.seek(position);
int read = 0;
byte[] buffer = new byte[1024];
while (progress < length && read != -1) {
read = inputStream.read(buffer, 0, buffer.length);
randomAccessFile.write(buffer, 0, read);
progress += read;
}
randomAccessFile.close();
inputStream.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (ProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
![運行效果](http://img.blog.csdn.net/20161112192835504)
HttpURLConnection實現多線程下載資源contentLength()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.