注:本文翻譯自Google官方的Android Developers Training文檔,譯者技術(shù)一般,由于喜愛安卓而產(chǎn)生了翻譯的念頭,純屬個(gè)人興趣愛好。
原文鏈接: http://developer.android.com/training/basics/network-ops/connecting.html
這節(jié)課將會(huì)向你展示如何實(shí)現(xiàn)一個(gè)簡單地連接網(wǎng)絡(luò)的應(yīng)用。這當(dāng)中包含了一些創(chuàng)建哪怕是最簡單的網(wǎng)絡(luò)連接應(yīng)用時(shí)需要遵循的最佳實(shí)踐規(guī)范。
注意,要執(zhí)行這節(jié)課中所講的網(wǎng)絡(luò)操作,你的應(yīng)用清單必須包含如下的權(quán)限:
< uses-permission android:name ="android.permission.INTERNET" /> < uses-permission android:name ="android.permission.ACCESS_NETWORK_STATE" />
一). 選擇一個(gè)HTTP客戶端
大多數(shù)帶有網(wǎng)絡(luò)連接的Android應(yīng)用使用HTTP來發(fā)送和接收數(shù)據(jù)。Android包含了兩個(gè)HTTP客戶端: HttpURLConnection ,以及 Apache? HttpClient 。兩者都支持HTTPS,數(shù)據(jù)流的上傳和下載,可配置的超時(shí)限定,IPv6,以及連接池。對于適用于 Gingerbread及更高系統(tǒng)的應(yīng)用,我們推薦使用 HttpURLConnection 。更多關(guān)于這方面的信息,可以閱讀 Android's HTTP Clients 。
二). 檢查網(wǎng)絡(luò)連接
當(dāng)你的應(yīng)用嘗試連接到網(wǎng)絡(luò)時(shí),它應(yīng)該使用 getActiveNetworkInfo() 和 isConnected() 來檢查當(dāng)前是否有一個(gè)可獲取的網(wǎng)絡(luò)連接。這是因?yàn)椋撛O(shè)備可能會(huì)超出網(wǎng)絡(luò)的覆蓋范圍,或者用戶將Wi-Fi和移動(dòng)數(shù)據(jù)連接都禁用的。更多關(guān)于該方面的知識,可以閱讀 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 } ... }
三). 在另一個(gè)線程上執(zhí)行網(wǎng)絡(luò)操作?
網(wǎng)絡(luò)操作會(huì)包含不可預(yù)期的延遲。要避免它引起糟糕的用戶體驗(yàn),一般是將網(wǎng)絡(luò)操作在UI線程之外的另一個(gè)線程上執(zhí)行。 AsyncTask 類提供了一個(gè)最簡單的方法來啟動(dòng)一個(gè)UI線程之外的新線程。想知道有關(guān)這方面的內(nèi)容,可以閱讀: Multithreading For Performance 。
在下面的代碼中, myClickHandler()方法調(diào)用 new DownloadWebpageTask().execute(stringUrl)。 DownloadWebpageTask類是 AsyncTask 的子類,它實(shí)現(xiàn)下列 AsyncTask 中的方法:
- doInBackground() ?- 執(zhí)行 downloadUrl()方法。它接受網(wǎng)頁的URL作為一個(gè)參數(shù)。該方法獲取并處理網(wǎng)頁內(nèi)容。當(dāng)它結(jié)束后,它會(huì)返回一個(gè)結(jié)果字符串。
- onPostExecute() ?- 接收返回的字符串并將結(jié)果顯示在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); } } ... }
在上述代碼中,事件的發(fā)生流程如下:
當(dāng)用戶點(diǎn)擊按鈕激活 myClickHandler()后,應(yīng)用會(huì)將指定的URL傳遞給 AsyncTask 的子類 DownloadWebpageTask。
AsyncTask 中的方法 doInBackground() 調(diào)用 downloadUrl()方法。
downloadUrl()方法接收一個(gè)URL字符串作為參數(shù)并使用它來創(chuàng)建一個(gè) URL 對象。
URL 對象用來建立一個(gè) HttpURLConnection 。
一旦連接建立完成, HttpURLConnection 對象取回網(wǎng)頁內(nèi)容,并將其作為一個(gè) InputStream 。
InputStream 傳遞給 readIt()方法,它將其轉(zhuǎn)換為String。
最后 AsyncTask 的 onPostExecute() 方法將結(jié)果顯示在主activity的UI上。
四). 連接并下載數(shù)據(jù)
在你的執(zhí)行網(wǎng)絡(luò)交互的線程中,你可以使用 HttpURLConnection 來執(zhí)行一個(gè) GET,并下載你的數(shù)據(jù)。在你調(diào)用了 connect()之后,你可以通過調(diào)用 getInputStream()來 獲得數(shù)據(jù)的 InputStream 。
在下面的代碼中,
doInBackground()
方法調(diào)用
downloadUrl()。后者接收URL參數(shù),并使用URL通過
HttpURLConnection
連接網(wǎng)絡(luò)。一旦一個(gè)連接建立了,應(yīng)用將使用
getInputStream()方法來獲取
InputStream
形式的數(shù)據(jù)。
// 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()返回的是連接的狀態(tài)碼( status code )。這是一個(gè)非常有用的方法來獲得關(guān)于連接的額外信息。狀態(tài)碼200意味著連接成功。
五). 將InputStream轉(zhuǎn)換為String
一個(gè) InputStream 是一個(gè)可讀的字節(jié)源。一旦你獲得了一個(gè) InputStream ,通常都需要將它解碼或轉(zhuǎn)換成你需要的數(shù)據(jù)類型。例如,如果你正在下載圖像數(shù)據(jù),你可能會(huì)這樣對它進(jìn)行解碼:
InputStream is = null ; ... Bitmap bitmap = BitmapFactory.decodeStream(is); ImageView imageView = (ImageView) findViewById(R.id.image_view); imageView.setImageBitmap(bitmap);
在上面的例子中, InputStream 代表了一個(gè)網(wǎng)頁的文本。下面的例子是將 InputStream 轉(zhuǎn)換為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); }
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
