注:本文翻譯自Google官方的Android Developers Training文檔,譯者技術一般,由于喜愛安卓而產生了翻譯的念頭,純屬個人興趣愛好。
原文鏈接: http://developer.android.com/training/basics/network-ops/connecting.html
這節課將會向你展示如何實現一個簡單地連接網絡的應用。這當中包含了一些創建哪怕是最簡單的網絡連接應用時需要遵循的最佳實踐規范。
注意,要執行這節課中所講的網絡操作,你的應用清單必須包含如下的權限:
<
uses-permission
android:name
="android.permission.INTERNET"
/>
<
uses-permission
android:name
="android.permission.ACCESS_NETWORK_STATE"
/>
一). 選擇一個HTTP客戶端
大多數帶有網絡連接的Android應用使用HTTP來發送和接收數據。Android包含了兩個HTTP客戶端: HttpURLConnection ,以及 Apache? HttpClient 。兩者都支持HTTPS,數據流的上傳和下載,可配置的超時限定,IPv6,以及連接池。對于適用于 Gingerbread及更高系統的應用,我們推薦使用 HttpURLConnection 。更多關于這方面的信息,可以閱讀 Android's HTTP Clients 。
二). 檢查網絡連接
當你的應用嘗試連接到網絡時,它應該使用 getActiveNetworkInfo() 和 isConnected() 來檢查當前是否有一個可獲取的網絡連接。這是因為,該設備可能會超出網絡的覆蓋范圍,或者用戶將Wi-Fi和移動數據連接都禁用的。更多關于該方面的知識,可以閱讀 Managing Network Usage :
public
void
myClickHandler(View view) {
...
ConnectivityManager connMgr
=
(ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo
=
connMgr.getActiveNetworkInfo();
if
(networkInfo !=
null
&&
networkInfo.isConnected()) {
//
fetch data
}
else
{
//
display error
}
...
}
三). 在另一個線程上執行網絡操作?
網絡操作會包含不可預期的延遲。要避免它引起糟糕的用戶體驗,一般是將網絡操作在UI線程之外的另一個線程上執行。 AsyncTask 類提供了一個最簡單的方法來啟動一個UI線程之外的新線程。想知道有關這方面的內容,可以閱讀: Multithreading For Performance 。
在下面的代碼中, myClickHandler()方法調用 new DownloadWebpageTask().execute(stringUrl)。 DownloadWebpageTask類是 AsyncTask 的子類,它實現下列 AsyncTask 中的方法:
- doInBackground() ?- 執行 downloadUrl()方法。它接受網頁的URL作為一個參數。該方法獲取并處理網頁內容。當它結束后,它會返回一個結果字符串。
- onPostExecute() ?- 接收返回的字符串并將結果顯示在UI上。
public
class
HttpExampleActivity
extends
Activity {
private
static
final
String DEBUG_TAG = "HttpExample"
;
private
EditText urlText;
private
TextView textView;
@Override
public
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.main);
urlText
=
(EditText) findViewById(R.id.myUrl);
textView
=
(TextView) findViewById(R.id.myText);
}
//
When user clicks button, calls AsyncTask.
//
Before attempting to fetch the URL, makes sure that there is a network connection.
public
void
myClickHandler(View view) {
//
Gets the URL from the UI's text field.
String stringUrl =
urlText.getText().toString();
ConnectivityManager connMgr
=
(ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo
=
connMgr.getActiveNetworkInfo();
if
(networkInfo !=
null
&&
networkInfo.isConnected()) {
new
DownloadWebpageTask().execute(stringUrl);
}
else
{
textView.setText(
"No network connection available."
);
}
}
//
Uses AsyncTask to create a task away from the main UI thread. This task takes a
//
URL string and uses it to create an HttpUrlConnection. Once the connection
//
has been established, the AsyncTask downloads the contents of the webpage as
//
an InputStream. Finally, the InputStream is converted into a string, which is
//
displayed in the UI by the AsyncTask's onPostExecute method.
private
class
DownloadWebpageTask
extends
AsyncTask<String, Void, String>
{
@Override
protected
String doInBackground(String... urls) {
//
params comes from the execute() call: params[0] is the url.
try
{
return
downloadUrl(urls[0
]);
}
catch
(IOException e) {
return
"Unable to retrieve web page. URL may be invalid."
;
}
}
//
onPostExecute displays the results of the AsyncTask.
@Override
protected
void
onPostExecute(String result) {
textView.setText(result);
}
}
...
}
在上述代碼中,事件的發生流程如下:
當用戶點擊按鈕激活 myClickHandler()后,應用會將指定的URL傳遞給 AsyncTask 的子類 DownloadWebpageTask。
AsyncTask 中的方法 doInBackground() 調用 downloadUrl()方法。
downloadUrl()方法接收一個URL字符串作為參數并使用它來創建一個 URL 對象。
URL 對象用來建立一個 HttpURLConnection 。
一旦連接建立完成, HttpURLConnection 對象取回網頁內容,并將其作為一個 InputStream 。
InputStream 傳遞給 readIt()方法,它將其轉換為String。
最后 AsyncTask 的 onPostExecute() 方法將結果顯示在主activity的UI上。
四). 連接并下載數據
在你的執行網絡交互的線程中,你可以使用 HttpURLConnection 來執行一個 GET,并下載你的數據。在你調用了 connect()之后,你可以通過調用 getInputStream()來 獲得數據的 InputStream 。
在下面的代碼中,
doInBackground()
方法調用
downloadUrl()。后者接收URL參數,并使用URL通過
HttpURLConnection
連接網絡。一旦一個連接建立了,應用將使用
getInputStream()方法來獲取
InputStream
形式的數據。
//
Given a URL, establishes an HttpUrlConnection and retrieves
//
the web page content as a InputStream, which it returns as
//
a string.
private
String downloadUrl(String myurl)
throws
IOException {
InputStream is
=
null
;
//
Only display the first 500 characters of the retrieved
//
web page content.
int
len = 500
;
try
{
URL url
=
new
URL(myurl);
HttpURLConnection conn
=
(HttpURLConnection) url.openConnection();
conn.setReadTimeout(
10000
/*
milliseconds
*/
);
conn.setConnectTimeout(
15000
/*
milliseconds
*/
);
conn.setRequestMethod(
"GET"
);
conn.setDoInput(
true
);
//
Starts the query
conn.connect();
int
response =
conn.getResponseCode();
Log.d(DEBUG_TAG,
"The response is: " +
response);
is
=
conn.getInputStream();
//
Convert the InputStream into a string
String contentAsString =
readIt(is, len);
return
contentAsString;
//
Makes sure that the InputStream is closed after the app is
//
finished using it.
}
finally
{
if
(is !=
null
) {
is.close();
}
}
}
注意方法getResponseCode()返回的是連接的狀態碼( status code )。這是一個非常有用的方法來獲得關于連接的額外信息。狀態碼200意味著連接成功。
五). 將InputStream轉換為String
一個 InputStream 是一個可讀的字節源。一旦你獲得了一個 InputStream ,通常都需要將它解碼或轉換成你需要的數據類型。例如,如果你正在下載圖像數據,你可能會這樣對它進行解碼:
InputStream is =
null
;
...
Bitmap bitmap
=
BitmapFactory.decodeStream(is);
ImageView imageView
=
(ImageView) findViewById(R.id.image_view);
imageView.setImageBitmap(bitmap);
在上面的例子中, InputStream 代表了一個網頁的文本。下面的例子是將 InputStream 轉換為String,這樣activity可以在UI中顯示它:
//
Reads an InputStream and converts it to a String.
public
String readIt(InputStream stream,
int
len)
throws
IOException, UnsupportedEncodingException {
Reader reader
=
null
;
reader
=
new
InputStreamReader(stream, "UTF-8"
);
char
[] buffer =
new
char
[len];
reader.read(buffer);
return
new
String(buffer);
}
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

