Android开发请求网络方式详解

来源:互联网 发布:php薪资待遇 编辑:程序博客网 时间:2024/05/20 09:43

转载请注明出处:http://blog.csdn.net/allen315410/article/details/42643401

        大家知道Google支持和发布的Android移动操作系统,主要是为了使其迅速占领移动互联网的市场份额,所谓移动互联网当然也是互联网了,凡是涉及互联网的任何软件任何程序都少不了联网模块的开发,诚然Android联网开发也是我们开发中至关重要的一部分,那么Android是怎么样进行联网操作的呢?这篇博客就简单的介绍一下Android常用的联网方式,包括JDK支持的HttpUrlConnection,Apache支持的HttpClient,以及开源的一些联网框架(譬如AsyncHttpClient)的介绍。本篇博客只讲实现过程和方式,不讲解原理,否则原理用文字很难以讲清,其实我们知道怎么去用,就可以解决一些基本开发需要了。

        绝大多数的Android应用联网都是基于Http协议的,也有很少是基于Socket的,我们这里主要讲解基于Http协议的联网方式。讲解实例是建立在一个模拟的登录小模块中进行,登录请求数据仅仅只有username和password两个简单字段。


HttpUrlConnection

         HttpUrlConnection是JDK里提供的联网API,我们知道Android SDK是基于Java的,所以当然优先考虑HttpUrlConnection这种最原始最基本的API,其实大多数开源的联网框架基本上也是基于JDK的HttpUrlConnection进行的封装罢了,掌握HttpUrlConnection需要以下几个步骤:

1将访问的路径转换成URL。

URL url = new URL(path);  

2,通过URL获取连接。

HttpURLConnection conn = (HttpURLConnection) url.openConnection();  

3,设置请求方式。

conn.setRequestMethod("GET");  

4,设置连接超时时间。

conn.setConnectTimeout(5000);  

5,设置请求头的信息。

conn.setRequestProperty("User-Agent""Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)");  

6,获取响应码

int code = conn.getResponseCode();  

7,针对不同的响应码,做不同的操作

      7.1,请求码200,表明请求成功,获取返回内容的输入流

InputStream is = conn.getInputStream();  

      7.2,将输入流转换成字符串信息

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. public class StreamTools {  
  2.     /** 
  3.      * 将输入流转换成字符串 
  4.      *  
  5.      * @param is 
  6.      *            从网络获取的输入流 
  7.      * @return 
  8.      */  
  9.     public static String streamToString(InputStream is) {  
  10.         try {  
  11.             ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  12.             byte[] buffer = new byte[1024];  
  13.             int len = 0;  
  14.             while ((len = is.read(buffer)) != -1) {  
  15.                 baos.write(buffer, 0, len);  
  16.             }  
  17.             baos.close();  
  18.             is.close();  
  19.             byte[] byteArray = baos.toByteArray();  
  20.             return new String(byteArray);  
  21.         } catch (Exception e) {  
  22.             Log.e("tag", e.toString());  
  23.             return null;  
  24.         }  
  25.     }  
  26. }  

      7.3,若返回值400,则是返回网络异常,做出响应的处理。


HttpUrlConnection发送GET请求

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. /** 
  2.      * 通过HttpUrlConnection发送GET请求 
  3.      *  
  4.      * @param username 
  5.      * @param password 
  6.      * @return 
  7.      */  
  8.     public static String loginByGet(String username, String password) {  
  9.         String path = "http://192.168.0.107:8080/WebTest/LoginServerlet?username=" + username + "&password=" + password;  
  10.         try {  
  11.             URL url = new URL(path);  
  12.             HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
  13.             conn.setConnectTimeout(5000);  
  14.             conn.setRequestMethod("GET");  
  15.             int code = conn.getResponseCode();  
  16.             if (code == 200) {  
  17.                 InputStream is = conn.getInputStream(); // 字节流转换成字符串  
  18.                 return StreamTools.streamToString(is);  
  19.             } else {  
  20.                 return "网络访问失败";  
  21.             }  
  22.         } catch (Exception e) {  
  23.             e.printStackTrace();  
  24.             return "网络访问失败";  
  25.         }  
  26.     }  

HttpUrlConnection发送POST请求

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. /** 
  2.      * 通过HttpUrlConnection发送POST请求 
  3.      *  
  4.      * @param username 
  5.      * @param password 
  6.      * @return 
  7.      */  
  8.     public static String loginByPost(String username, String password) {  
  9.         String path = "http://192.168.0.107:8080/WebTest/LoginServerlet";  
  10.         try {  
  11.             URL url = new URL(path);  
  12.             HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
  13.             conn.setConnectTimeout(5000);  
  14.             conn.setRequestMethod("POST");  
  15.             conn.setRequestProperty("Content-Type""application/x-www-form-urlencoded");  
  16.             String data = "username=" + username + "&password=" + password;  
  17.             conn.setRequestProperty("Content-Length", data.length() + "");  
  18.             // POST方式,其实就是浏览器把数据写给服务器  
  19.             conn.setDoOutput(true); // 设置可输出流  
  20.             OutputStream os = conn.getOutputStream(); // 获取输出流  
  21.             os.write(data.getBytes()); // 将数据写给服务器  
  22.             int code = conn.getResponseCode();  
  23.             if (code == 200) {  
  24.                 InputStream is = conn.getInputStream();  
  25.                 return StreamTools.streamToString(is);  
  26.             } else {  
  27.                 return "网络访问失败";  
  28.             }  
  29.         } catch (Exception e) {  
  30.             e.printStackTrace();  
  31.             return "网络访问失败";  
  32.         }  
  33.     }  

HttpClient

        HttpClient是开源组织Apache提供的Java请求网络框架,其最早是为了方便Java服务器开发而诞生的,是对JDK中的HttpUrlConnection各API进行了封装和简化,提高了性能并且降低了调用API的繁琐,Android因此也引进了这个联网框架,我们再不需要导入任何jar或者类库就可以直接使用,值得注意的是Android官方已经宣布不建议使用HttpClient了,我们再开发的时候尽量少用吧,但是用了也无妨!

HttpClient发送GET请求

1, 创建HttpClient对象

2,创建HttpGet对象,指定请求地址(带参数)

3,使用HttpClient的execute(),方法执行HttpGet请求,得到HttpResponse对象

4,调用HttpResponse的getStatusLine().getStatusCode()方法得到响应码

5,调用的HttpResponse的getEntity().getContent()得到输入流,获取服务端写回的数据

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. /** 
  2.      * 通过HttpClient发送GET请求 
  3.      *  
  4.      * @param username 
  5.      * @param password 
  6.      * @return 
  7.      */  
  8.     public static String loginByHttpClientGet(String username, String password) {  
  9.         String path = "http://192.168.0.107:8080/WebTest/LoginServerlet?username="  
  10.                 + username + "&password=" + password;  
  11.         HttpClient client = new DefaultHttpClient(); // 开启网络访问客户端  
  12.         HttpGet httpGet = new HttpGet(path); // 包装一个GET请求  
  13.         try {  
  14.             HttpResponse response = client.execute(httpGet); // 客户端执行请求  
  15.             int code = response.getStatusLine().getStatusCode(); // 获取响应码  
  16.             if (code == 200) {  
  17.                 InputStream is = response.getEntity().getContent(); // 获取实体内容  
  18.                 String result = StreamTools.streamToString(is); // 字节流转字符串  
  19.                 return result;  
  20.             } else {  
  21.                 return "网络访问失败";  
  22.             }  
  23.         } catch (Exception e) {  
  24.             e.printStackTrace();  
  25.             return "网络访问失败";  
  26.         }  
  27.     }  

HttpClient发送POST请求

1,创建HttpClient对象

2,创建HttpPost对象,指定请求地址

3,创建List<NameValuePair>,用来装载参数

4,调用HttpPost对象的setEntity()方法,装入一个UrlEncodedFormEntity对象,携带之前封装好的参数

5,使用HttpClient的execute()方法执行HttpPost请求,得到HttpResponse对象

6, 调用HttpResponse的getStatusLine().getStatusCode()方法得到响应码

7, 调用的HttpResponse的getEntity().getContent()得到输入流,获取服务端写回的数据

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. /** 
  2.      * 通过HttpClient发送POST请求 
  3.      *  
  4.      * @param username 
  5.      * @param password 
  6.      * @return 
  7.      */  
  8.     public static String loginByHttpClientPOST(String username, String password) {  
  9.         String path = "http://192.168.0.107:8080/WebTest/LoginServerlet";  
  10.         try {  
  11.             HttpClient client = new DefaultHttpClient(); // 建立一个客户端  
  12.             HttpPost httpPost = new HttpPost(path); // 包装POST请求  
  13.             // 设置发送的实体参数  
  14.             List<NameValuePair> parameters = new ArrayList<NameValuePair>();  
  15.             parameters.add(new BasicNameValuePair("username", username));  
  16.             parameters.add(new BasicNameValuePair("password", password));  
  17.             httpPost.setEntity(new UrlEncodedFormEntity(parameters, "UTF-8"));  
  18.             HttpResponse response = client.execute(httpPost); // 执行POST请求  
  19.             int code = response.getStatusLine().getStatusCode();  
  20.             if (code == 200) {  
  21.                 InputStream is = response.getEntity().getContent();  
  22.                 String result = StreamTools.streamToString(is);  
  23.                 return result;  
  24.             } else {  
  25.                 return "网络访问失败";  
  26.             }  
  27.         } catch (Exception e) {  
  28.             e.printStackTrace();  
  29.             return "访问网络失败";  
  30.         }  
  31.     }  

其他开源联网框架

AsyncHttpClient

         除了上述Android官方推荐的联网框架以外,在开源世界里关于联网框架真是太多太多了,例如afinal,xutils等等,都是一些开源大牛自己封装的联网框架,并且在GitHub开源社区中可以下载到,其实类似的开源联网框架基本上也是基于HttpUrlConnection的进一步封装,大大提高了性能,同时更加简化了使用方法,这里使用AsyncHttpClient作为案例,其他的联网框架大家可以去网上找,下载使用试试便可。
        AsyncHttpClient是一个非常优秀的联网框架,不仅支持所有Http请求的方式,而且还支持文件的上传和下载,要知道用HttpUrlConnection写一个文件上传和下载健全功能是很需要花费一定时间和精力的,因为请求头实在是太多了,稍有不慎就会写错。但是AsyncHttpClient已经封装好了这些“麻烦”,我们只需要下载到AsyncHttpClient的jar包或者源码导入项目中,Http,上传,下载等等,只需要几个简单的api即可搞定。
        AsyncHttpClient的GitHub主页:https://github.com/AsyncHttpClient/async-http-client/
        

AsyncHttpClient发送GET请求

1,将下载好的源码拷贝到src目录下

2,创建一个AsyncHttpClient的对象

3,调用该类的get方法发送GET请求,传入请求资源地址URL,创建AsyncHttpResponseHandler对象

4,重写AsyncHttpResponseHandler下的两个方法,onSuccess和onFailure方法

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. /** 
  2.      * 通过AsyncHttpClient发送GET请求 
  3.      */  
  4.     public void loginByAsyncHttpGet() {  
  5.         String path = "http://192.168.0.107:8080/WebTest/LoginServerlet?username=zhangsan&password=123";  
  6.         AsyncHttpClient client = new AsyncHttpClient();  
  7.         client.get(path, new AsyncHttpResponseHandler() {  
  8.   
  9.             @Override  
  10.             public void onFailure(int arg0, Header[] arg1, byte[] arg2,  
  11.                     Throwable arg3) {  
  12.                 // TODO Auto-generated method stub  
  13.                 Log.i("TAG""请求失败:" + new String(arg2));  
  14.             }  
  15.   
  16.             @Override  
  17.             public void onSuccess(int arg0, Header[] arg1, byte[] arg2) {  
  18.                 // TODO Auto-generated method stub  
  19.                 Log.i("TAG""请求成功:" + new String(arg2));  
  20.             }  
  21.         });  
  22.     }  

AsyncHttpClient发送POST请求

1,将下载好的源码拷贝到src目录下

2,创建一个AsyncHttpClient的对象

3,创建请求参数,RequestParams对象

4,调用该类的post方法发POST,传入请求资源地址URL,请求参数RequestParams,创建AsyncHttpResponseHandler对象

5,重写AsyncHttpResponseHandler下的两个方法,onSuccess和onFailure方法

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. /** 
  2.      * 通过AsyncHttpClient发送POST请求 
  3.      */  
  4.     public void loginByAsyncHttpPost() {  
  5.         String path = "http://192.168.0.107:8080/WebTest/LoginServerlet";  
  6.         AsyncHttpClient client = new AsyncHttpClient();  
  7.         RequestParams params = new RequestParams();  
  8.         params.put("username""zhangsan");  
  9.         params.put("password""123");  
  10.         client.post(path, params, new AsyncHttpResponseHandler() {  
  11.   
  12.             @Override  
  13.             public void onFailure(int arg0, Header[] arg1, byte[] arg2,  
  14.                     Throwable arg3) {  
  15.                 // TODO Auto-generated method stub  
  16.                 Log.i("TAG""请求失败:" + new String(arg2));  
  17.             }  
  18.   
  19.             @Override  
  20.             public void onSuccess(int arg0, Header[] arg1, byte[] arg2) {  
  21.                 // TODO Auto-generated method stub  
  22.                 Log.i("TAG""请求成功:" + new String(arg2));  
  23.             }  
  24.         });  
  25.     }  

AsyncHttpClient上传文件

1,将下载好的源码拷贝到src目录下

2,创建一个AsyncHttpClient的对象

3,创建请求参数,RequestParams对象,请求参数仅仅包含文件对象即可,例如:

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. params.put("profile_picture"new File("/sdcard/pictures/pic.jpg"));  

4,调用该类的post方法发POST,传入请求资源地址URL,请求参数RequestParams,创建AsyncHttpResponseHandler对象

5,重写AsyncHttpResponseHandler下的两个方法,onSuccess和onFailure方法


判断网络连接状态

        很多时候对于手机或者平板电脑这样的手持设备,我们是不知道它们的网络连接状态的,在联网的时候我们必须得保证设备的网路是否正常,是否可以连接上互联网,或者我们在进行大量数据上传或者下载,例如下载网路视频,看网路电视等等,我们必须得为用户省钱,这样大数据的传输显然是不能使用用户昂贵的数据流量的,而是判断当前网络是不是在wifi下,使用WiFi来进行大数据的传输,会给用户更好的体验,那么下面这个工具类就是用来判断设备网络连接状态的,不仅判断了当前设置手机网络下还是WiFi环境下,而且如果手机网络下还需要设置运营商的代理IP和端口。

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. /** 
  2.  * 判断网络状态的工具类 
  3.  *  
  4.  */  
  5. public class NetworkUtil {  
  6.   
  7.     /* 代码IP */  
  8.     private static String PROXY_IP = null;  
  9.     /* 代理端口 */  
  10.     private static int PROXY_PORT = 0;  
  11.     /** 
  12.      * 判断当前是否有网络连接 
  13.      *  
  14.      * @param context 
  15.      * @return 
  16.      */  
  17.     public static boolean isNetwork(Context context) {  
  18.         boolean network = isWifi(context);  
  19.         boolean mobilework = isMobile(context);  
  20.         if (!network && !mobilework) { // 无网络连接  
  21.             Log.i("NetworkUtil""无网路链接!");  
  22.             return false;  
  23.         } else if (network == true && mobilework == false) { // wifi连接  
  24.             Log.i("NetworkUtil""wifi连接!");  
  25.         } else { // 网络连接  
  26.             Log.i("NetworkUtil""手机网路连接,读取代理信息!");  
  27.             readProxy(context); // 读取代理信息  
  28.             return true;  
  29.         }  
  30.         return true;  
  31.     }  
  32.   
  33.     /** 
  34.      * 读取网络代理 
  35.      *  
  36.      * @param context 
  37.      */  
  38.     private static void readProxy(Context context) {  
  39.         Uri uri = Uri.parse("content://telephony/carriers/preferapn");  
  40.         ContentResolver resolver = context.getContentResolver();  
  41.         Cursor cursor = resolver.query(uri, nullnullnullnull);  
  42.         if (cursor != null && cursor.moveToFirst()) {  
  43.             PROXY_IP = cursor.getString(cursor.getColumnIndex("proxy"));  
  44.             PROXY_PORT = cursor.getInt(cursor.getColumnIndex("port"));  
  45.         }  
  46.         cursor.close();  
  47.     }  
  48.   
  49.     /** 
  50.      * 判断当前网络是否是wifi局域网 
  51.      *  
  52.      * @param context 
  53.      * @return 
  54.      */  
  55.     public static boolean isWifi(Context context) {  
  56.         ConnectivityManager manager = (ConnectivityManager) context  
  57.                 .getSystemService(Context.CONNECTIVITY_SERVICE);  
  58.         NetworkInfo info = manager  
  59.                 .getNetworkInfo(ConnectivityManager.TYPE_WIFI);  
  60.         if (info != null) {  
  61.             return info.isConnected(); // 返回网络连接状态  
  62.         }  
  63.         return false;  
  64.     }  
  65.   
  66.     /** 
  67.      * 判断当前网络是否是手机网络 
  68.      *  
  69.      * @param context 
  70.      * @return 
  71.      */  
  72.     public static boolean isMobile(Context context) {  
  73.         ConnectivityManager manager = (ConnectivityManager) context  
  74.                 .getSystemService(Context.CONNECTIVITY_SERVICE);  
  75.         NetworkInfo info = manager  
  76.                 .getNetworkInfo(ConnectivityManager.TYPE_MOBILE);  
  77.         if (info != null) {  
  78.             return info.isConnected(); // 返回网络连接状态  
  79.         }  
  80.         return false;  
  81.     }  
  82. }  

0 0
原创粉丝点击