来公司上班这么久,一直做的就是通信这块 - -! 好长时间没写博客了,现在把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,缓存等等。但是为了支持众多请求参数,以及文件传输,做一个比较好的封装是一个问题,如下:

     * 使用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的文章恐怕一篇两篇也讲不清楚,先放着了,有时间了另开文章详细讲解。



更多相关文章

  1. android的looper,handler消息小结
  2. Android+SpringMVC通信
  3. android sp&wp
  4. Android(安卓)Acrchitecture Components( 架构组件)+热门框架(Re
  5. 你不知道的 Android(安卓)WebView 使用漏洞
  6. Shape Drawable的学习
  7. Android之组件详解
  8. Android中解析xml的几种方式
  9. Android(安卓)简单的Http框架

随机推荐

  1. android设置activity全屏 | 无标题
  2. android EditText使用指南
  3. Android(安卓)Camera使用小结
  4. 【30篇突击 android】源码统计四
  5. android操作系统默认的图片
  6. 第十周智能手机开发学习笔记
  7. android EditText 全面阐述
  8. Android(安卓)对话框【Dialog】去除白色
  9. Activity去除标题栏和状态栏
  10. Android开发如何正确使用WebView