Android服务器通信的几种方式详解
16lz
2021-01-24
来公司上班这么久,一直做的就是通信这块 - -! 好长时间没写博客了,现在把Android通信这块总结下,我会尽可能详细的讲解所有通信技能。
先列出通信的几种方式:
(1)webservice调用
一、Android通过WebService通信
这也是我们公司Android项目通信的架构,并且封装成一个模块了,具体来说就是:使用HttpURLConnection进行HTTP通信,采用xml数据格式交互。那么问题来了,HttpURLConnection+xml算是WebService通信吗?首先得知道什么是WebService。
WebService是一种跨编程语言和跨操作系统平台的远程调用技术。也就是一个应用程序向外界暴露出一个能通过Web进行调用的API,也就是说能用编程的方法通过Web来调用这个应用程序。XML+XSD,SOAP和WSDL就是构成WebService平台的三大技术。WebService采用http协议传输数据,采用xml封装数据。
XML+XSD:解决了数据的封装和数据类型格式的定义。
SOAP:SOAP协议 = HTTP协议 + XML数据格式。
WebService通过HTTP协议发送请求和接收结果时,发送的请求内容和结果内容都采用XML格式封装,并增加了一些特定的HTTP消息头,以说明HTTP消息的内容格式,这些特定的HTTP消息头和XML内容格式就是SOAP协议。SOAP提供了标准的RPC方法来调用Web Service。
上面说到,WebService采用HTTP协议传输数据,那么在Android如何实现HTTP传输呢,通常用的方式有两种:使用Java标准类库的HttpURLConnection和使用Apache的HttpClient接口。
1、使用HttpURLConnection(官方推荐使用此种方式)
HttpURLConnection的使用很简单,就是使用URL url = new URL("your service ur"),对象来打开一个Hppt连接(HttpURLConnection对象),即new HttpURLConnection() = url.openConnection();.然后使用该对象设置一系列参数,比如请求方法是get还是post,缓存等等。但是为了支持众多请求参数,以及文件传输,做一个比较好的封装是一个问题,如下:
先列出通信的几种方式:
(1)webservice调用
一、Android通过WebService通信
这也是我们公司Android项目通信的架构,并且封装成一个模块了,具体来说就是:使用HttpURLConnection进行HTTP通信,采用xml数据格式交互。那么问题来了,HttpURLConnection+xml算是WebService通信吗?首先得知道什么是WebService。
WebService是一种跨编程语言和跨操作系统平台的远程调用技术。也就是一个应用程序向外界暴露出一个能通过Web进行调用的API,也就是说能用编程的方法通过Web来调用这个应用程序。XML+XSD,SOAP和WSDL就是构成WebService平台的三大技术。WebService采用http协议传输数据,采用xml封装数据。
XML+XSD:解决了数据的封装和数据类型格式的定义。
SOAP:SOAP协议 = HTTP协议 + XML数据格式。
WebService通过HTTP协议发送请求和接收结果时,发送的请求内容和结果内容都采用XML格式封装,并增加了一些特定的HTTP消息头,以说明HTTP消息的内容格式,这些特定的HTTP消息头和XML内容格式就是SOAP协议。SOAP提供了标准的RPC方法来调用Web Service。
上面说到,WebService采用HTTP协议传输数据,那么在Android如何实现HTTP传输呢,通常用的方式有两种:使用Java标准类库的HttpURLConnection和使用Apache的HttpClient接口。
1、使用HttpURLConnection(官方推荐使用此种方式)
HttpURLConnection的使用很简单,就是使用URL url = new URL("your service ur"),对象来打开一个Hppt连接(HttpURLConnection对象),即new HttpURLConnection() = url.openConnection();.然后使用该对象设置一系列参数,比如请求方法是get还是post,缓存等等。但是为了支持众多请求参数,以及文件传输,做一个比较好的封装是一个问题,如下:
* 使用HttpUrlCollection进行Http通信,支持文件传输、post和get提交方式 * @param url 服务地址 * @param paras 参数列表 * @param files 文件列表 * @param authenticated * @param httpMethod 请求方式 * @return 返回InputStream输入流 * @throws IOException */ public InputStream httpRequest(String url, List<BasicNameValuePair> paras, ArrayList<File> files, boolean authenticated, String httpMethod) throws IOException { String end = "\r\n"; String twoHyphens = "--"; String boundary = "*****"; HttpURLConnection con = null; DataOutputStream ds = null; InputStream is = null; int responseCode = -1; String error = ""; try { if (httpMethod.equals("GET") && null != paras) { if (!url.contains("?")){ url += "?"; } for (BasicNameValuePair kv : paras) { url += ("&" + kv.key + "=" + kv.value); } } URL uri = new URL(url); con = (HttpURLConnection) uri.openConnection(); if (this.timeout > 0) { con.setConnectTimeout(this.timeout); } else { con.setConnectTimeout(30000); } // con.setReadTimeout(60000); /* 允许Input、Output,不使用Cache */ con.setDoInput(true); con.setDoOutput(true); con.setUseCaches(false); /* setRequestProperty */ con.setRequestProperty("Connection", "Keep-Alive"); con.setRequestProperty("Charset", "UTF-8"); if (httpMethod.equals("POST")) { /* 设定传送的method=POST */ con.setRequestMethod("POST"); con.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary); /* 设定DataOutputStream */ ds = new DataOutputStream(con.getOutputStream()); /* 添加键值 */ if (null != paras) { for (BasicNameValuePair kv : paras) { StringBuilder sb = new StringBuilder(); sb.append(end + twoHyphens + boundary + end); sb.append("Content-Disposition: form-data; " + "name=\"" + kv.key + "\"" + end + end); sb.append((null==kv.value)?"":kv.value); // sb.append(twoHyphens + boundary); byte[] bytes = sb.toString().getBytes("utf8"); ds.write(bytes); } ds.write((end + twoHyphens + boundary + end) .getBytes("utf8")); } /* 发送文件 */ if (null != files) { for (File file : files) { ds.writeBytes(twoHyphens + boundary + end); ds.writeBytes("Content-Disposition: form-data; " + "name=\"" + file.getName() + "\";filename=\"" + file.getName() + "\"" + end + end); FileInputStream fStream = new FileInputStream(file); String fileName = file.getName(); int bufferSize = 1024; byte[] buffer = new byte[bufferSize]; int length = -1; long total = 0; long fileLength = file.length(); while ((length = fStream.read(buffer)) != -1) { ds.write(buffer, 0, length); total += length; } ds.write((end + twoHyphens + boundary + end) .getBytes("utf8")); fStream.close(); } /* 所有文件上传完成后加上这一行 */ ds.writeBytes(twoHyphens + boundary + twoHyphens + end); ds.flush(); } } else if (httpMethod.equals("GET")) { //设置为get请求 con.setRequestMethod("GET"); } responseCode = con.getResponseCode(); /* 取得Response内容 */ is = con.getInputStream(); } catch (MalformedURLException e) { responseCode = -2; error = e.getMessage(); e.printStackTrace(); } catch (IOException e) { responseCode = -3; error = e.getMessage(); e.printStackTrace(); } catch (Exception e) { responseCode = -4; error = e.getMessage(); e.printStackTrace(); } finally { if (null != ds) { ds.close(); ds = null; } } return is; }
通过上面的Http连接就可以进行客户端服务器数据之间的传输,当从服务器请求获取数据时,返回的InputStream流,如果采用xml封装数据,下面以Pull解析为例,将InputStream流解析成ContentValues对象:
/** * 读取关键词下的节点数据, 以键值对的形式返回 * @param is Xml数据流 * @param key节点名 * @return 键值对 */public static ContentValues getAsContentValues(InputStream is, String key ){try{is.reset();}catch(Exception e){e.printStackTrace();}ContentValues ret = null;;XmlPullParserFactory factory;try {factory = XmlPullParserFactory.newInstance(); //生成一个Pull解析器 XmlPullParser parser = factory.newPullParser();parser.setInput(is, "utf-8"); // 解析器和xml节点值类解析xml ret = fromXmlContentValues(parser, key);} catch (XmlPullParserException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}if (null == ret){ret = new ContentValues();}return ret;} private static ContentValues fromXmlContentValues(XmlPullParser parser, String key) throws XmlPullParserException, IOException{ ContentValues ret = null; Boolean keyTag = false;//是否进入key节点 Boolean innerTag = false;//是否进入key的子节点 String subKey = ""; //当前key的子节点名称 int eventType = parser.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT) { String keyName = parser.getName(); if (eventType == XmlPullParser.END_TAG){ if (keyName.contentEquals(key) && !innerTag){ parser.next(); break;//退出key节点 }else if (keyName.contentEquals(subKey)){ innerTag = false; } } if (eventType == XmlPullParser.START_TAG) { if (keyName.contentEquals(key) && !keyTag){ keyTag = true; }else if (keyTag){ //开始读取key的子节点数据 eventType = parser.next(); if (!innerTag){ if (eventType == XmlPullParser.TEXT || eventType == XmlPullParser.CDSECT ){ if (null == ret){ ret = new ContentValues(); } String value = parser.getText(); ret.put(keyName, value); } subKey = keyName; innerTag = true;//进入key的子节点 if (eventType == XmlPullParser.END_TAG){//刚进入就退出的子节点, 说明值为空 if (null == ret){ ret = new ContentValues(); } String value = ""; ret.put(keyName, value); innerTag = false;////退出key的子节点 } } } } eventType = parser.next(); } return ret; }
2、使用HttpClient通信(在2.2之后官方就不推荐使用这种方式了,使用HttpURLConnection)
HttpClient通信就更简单了,直接上代码
/** * 根据给定的url地址访问网络,得到响应内容(这里为GET方式访问) * * @param url * 指定天气url地址 * * @param params 请求参数 * @return 返回结果数据,返回失败时是null */public String getWeatherFromServe(String url,List<String> parameters) {// 创建一个http请求对象HttpGet request = new HttpGet(url);// 创建HttpParams以用来设置HTTP参数HttpParams params = new BasicHttpParams();//设置布尔参数,//params.setBooleanParameter("boolean", false);//序列化对象参数//params.setParameter("string", "dsa");// 设置连接超时或响应超时HttpConnectionParams.setConnectionTimeout(params, 3000);HttpConnectionParams.setSoTimeout(params, 5000);// 创建一个网络访问处理对象HttpClient httpClient = new DefaultHttpClient(params);try {// 执行请求参数项HttpResponse response = httpClient.execute(request);// 判断是否请求成功if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {HttpEntity entity = response.getEntity();// 获得响应信息String content = EntityUtils.toString(response.getEntity());return content;} else {// 网连接失败,使用Toast显示提示信息Toast.makeText(mContext, "网络访问失败,请检查手机网络状态!",Toast.LENGTH_LONG).show();}} catch (Exception e) {e.printStackTrace();} finally {// 释放网络连接资源httpClient.getConnectionManager().shutdown();}return null;}上面的例子中使用的是HttpGet请求方式,也可以使用HttpPost请求。服务器响应的HttpResponse对象获取一个HTTPEntity对象通过getEntity()方法,通过HttpEntity对象就可以获取服务器返回的众多信息。
3、Socket通信
Socket是建立在TCP/IP协议的基础上,就是对TCp/IP的一种封装,Socket提供接口我们使用。关于Socket的文章恐怕一篇两篇也讲不清楚,先放着了,有时间了另开文章详细讲解。
更多相关文章
- android的looper,handler消息小结
- Android+SpringMVC通信
- android sp&wp
- Android(安卓)Acrchitecture Components( 架构组件)+热门框架(Re
- 你不知道的 Android(安卓)WebView 使用漏洞
- Shape Drawable的学习
- Android之组件详解
- Android中解析xml的几种方式
- Android(安卓)简单的Http框架