W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
編寫:kesenhoo - 原文:http://developer.android.com/training/basics/network-ops/connecting.html
這一課會演示如何實現(xiàn)一個簡單的連接到網(wǎng)絡(luò)的程序。它提供了一些我們在創(chuàng)建即使最簡單的網(wǎng)絡(luò)連接程序時也應(yīng)該遵循的最佳示例。
請注意,想要執(zhí)行本課的網(wǎng)絡(luò)操作首先需要在程序的 manifest 文件中添加以下權(quán)限:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
大多數(shù)連接網(wǎng)絡(luò)的 Android app 會使用 HTTP 來發(fā)送與接收數(shù)據(jù)。Android 提供了兩種 HTTP clients:HttpURLConnection 與 Apache HttpClient。二者均支持 HTTPS、流媒體上傳和下載、可配置的超時、IPv6 與連接池(connection pooling)。對于 Android 2.3 Gingerbread 或更高的版本,推薦使用 HttpURLConnection。關(guān)于這部分的更多詳情,請參考 Android's HTTP Clients。
在我們的 app 嘗試連接網(wǎng)絡(luò)之前,應(yīng)通過函數(shù) getActiveNetworkInfo() 和 isConnected() 檢測當(dāng)前網(wǎng)絡(luò)是否可用。請注意,設(shè)備可能不在網(wǎng)絡(luò)覆蓋范圍內(nèi),或者用戶可能關(guān)閉 Wi-Fi 與移動網(wǎng)絡(luò)連接。關(guān)于這部分的更多詳情,請參考管理網(wǎng)絡(luò)的使用情況
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
}
...
}
網(wǎng)絡(luò)操作會遇到不可預(yù)期的延遲。為了避免造成不好的用戶體驗,總是在 UI 線程之外單獨的線程中執(zhí)行網(wǎng)絡(luò)操作。AsyncTask 類提供了一種簡單的方式來處理這個問題。這部分的詳情,請參考 Multithreading For Performance。
在下面的代碼示例中,myClickHandler()
方法會執(zhí)行 new DownloadWebpageTask().execute(stringUrl)
。DownloadWebpageTask
是 AsyncTask
的子類,它實現(xiàn)了下面兩個方法:
downloadUrl()
方法。它以網(wǎng)頁的 URL 作為參數(shù),方法 downloadUrl()
獲取并處理網(wǎng)頁返回的數(shù)據(jù)。執(zhí)行完畢后,返回一個結(jié)果字符串。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 DownloadWebpageText().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 DownloadWebpageText extends AsyncTask {
@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()
,app 將指定的 URL 傳給 AsyncTask 的子類 DownloadWebpageTask
。downloadUrl()
方法。downloadUrl()
方法以一個 URL 字符串作為參數(shù),并用它創(chuàng)建一個 URL 對象。readIt()
方法,該方法將流轉(zhuǎn)換成字符串。在執(zhí)行網(wǎng)絡(luò)交互的線程里面,我們可以使用 HttpURLConnection 來執(zhí)行一個 GET 類型的操作并下載數(shù)據(jù)。在調(diào)用 connect()
之后,我們可以通過調(diào)用 getInputStream()
來得到一個包含數(shù)據(jù)的 InputStream 對象。
在下面的代碼示例中,doInBackground() 方法會調(diào)用 downloadUrl()
。這個 downloadUrl()
方法使用給予的 URL,通過 HttpURLConnection 連接到網(wǎng)絡(luò)。一旦建立連接后,app 就會使用 getInputStream()
來獲取包含數(shù)據(jù)的 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()
會返回連接的狀態(tài)碼(status code)。這是一種獲知額外網(wǎng)絡(luò)連接信息的有效方式。其中,狀態(tài)碼是 200 則意味著連接成功。
InputStream 是一種可讀的 byte 數(shù)據(jù)源。如果我們獲得了一個 InputStream,通常會進(jìn)行解碼(decode)或者轉(zhuǎn)換為目標(biāo)數(shù)據(jù)類型。例如,如果我們是在下載圖片數(shù)據(jù),那么可能需要像下面這樣解碼并展示它:
InputStream is = null;
...
Bitmap bitmap = BitmapFactory.decodeStream(is);
ImageView imageView = (ImageView) findViewById(R.id.image_view);
imageView.setImageBitmap(bitmap);
在上面演示的示例中,InputStream 包含的是網(wǎng)頁的文本內(nèi)容。下面會演示如何把 InputStream 轉(zhuǎn)換為字符串,以便顯示在 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);
}
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: