【Android Developers Training】 79. 连接到网

系统 3370 0

注:本文翻译自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);

}
      
    

【Android Developers Training】 79. 连接到网络


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】元

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论