Connecting to the Network

翻译自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" />

Choose an HTTP Client

大部分需要网络连接的Android应用使用HTTP来发送和接收数据。安卓平台包括HttpURLConnection 客户端,支持了HTTPS,流上传和下载,配置超时,IPv6,和连接池。

Check the Network COnnection

在你的应用准备连接网络之前,需要检查是否有一个网络连接,可以使用getActiveNetworkInfo()isConnected(), 记住,设备可能超出网络的范围,或者使用者禁止了Wi-Fi和移动数据。

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
    }
    ...
}

Perform Network Operations on a Separate Thread

网络操作会包含不可预测的延迟。为了避免不好的用户体验,经常在一个单独的非UI线程里面执行网络操作.AsyncTask提供了最简答的方法从主UI线程启动一个新任务。
在下面的片段中,myClickHandler()方法包含了
new DownloadWebpageTask().execute(stringUrl)DownloadWebpageTaskAsyncTask的子类,DownloadWebpageTask实现了AsyncTask以下的方法:

  • doInBackground()运行了downloadUrl()方法,它传递了页面地址作为一个参数。downloadUrl()方法获取和处理网页的内容,当它完成时,它返回一个结果。
  • 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);
       }
    }
    ...
}

代码段对应的事件流程如下所示:

  1. 当用户点击按钮,触发myClickHandler(), 应用传递特定的URL到AsyncTask的子类DownloadWebpageTask
  2. AsyncTask的方法doInBackground()使用downloadUrl()方法
  3. downloadUrl()方法取到一个URL字符串,来建立一个URL对象
  4. 这个URL对象用来建立HttpURLConnection
  5. 连接一旦建立,HttpURLConnection对象就以流的方式抓取网页内容
  6. 流内容通过readIt()方法,这个方法可以将流对象转换为字符串对象
  7. 最后,AsyncTaskonPostExecute()方法在UI进程中展示字符串

Connect and Download Data

如果你的进程执行网络事务,你可以使用HttpURLConnection来执行GET和下载数据,在你使用connect()之后,你可以通过getInputStream()得到数据的流对象

在下面的代码段里,doInBackground()方法使用了downloadUrl()方法,这个downloadUrl()方法获取到特定的URL,通过HttpURLConnection连接到网络,连接一旦被建立,应用使用getInputStream()获取到流对象。

// 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()方法返回的状态码,这是一个有效的方法获取到连接的额外信息。200状态码表示成功。

Convert the InputStream to a String

一个InputStream是位的可读数据,你拿到InputStream之后,将它解码并转换为一个目标数据类型是很正常的事情。比如,如果你在下载图像数据,你可能解码并如下展示:

InputStream is = null;
...
Bitmap bitmap = BitmapFactory.decodeStream(is);
ImageView imageView = (ImageView) findViewById(R.id.image_view);
imageView.setImageBitmap(bitmap);

如上面的例子展示的,InputStream代表网页的文字内容,如下是展现如何将InputStream转换为字符串,并在主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);
}

你可能感兴趣的:(android,网络)