Android 开发中很多涉及网络通信,因为项目中涉及过一次,当时实现方式是 Http 请求,服务器端为 C# MVC 实现,所以这里想对这种方式进行一个总结。
Android 客户端:
首先封装一个 Http 请求帮助类
HttpHelper.java
package com.iflytek.leting.net; import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.util.List; import java.util.Map; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.CookieStore; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.AbstractHttpClient; import org.apache.http.impl.client.DefaultHttpClient; import android.util.Log; public abstract class HttpHelper { private final static String TAG = "HttpHelper"; private final static String SERVER_URL = "http://10.0.0.3/Test/"; private static CookieStore cookieStore; /** * @descrption 上传可变参数的Http请求方法 * @author xdwang * @create 2012-9-27下午8:06:28 * @param controllerName C# MVC中的controller * @param actionName C# MVC中的action * @param params 可变参数 * @return */ public static String invoke(String controllerName, String actionName, List<NameValuePair> params) { String result = null; try { String url = SERVER_URL + controllerName + "/" + actionName + "/"; Log.d(TAG, "url is" + url); HttpPost httpPost = new HttpPost(url); if (params != null && params.size() > 0) { HttpEntity entity = new UrlEncodedFormEntity(params, "UTF-8"); httpPost.setEntity(entity); } DefaultHttpClient httpClient = new DefaultHttpClient(); // 添加Cookie if (cookieStore != null) { httpClient.setCookieStore(cookieStore); } HttpResponse httpResponse = httpClient.execute(httpPost); StringBuilder builder = new StringBuilder(); BufferedReader reader = new BufferedReader(new InputStreamReader( httpResponse.getEntity().getContent())); for (String s = reader.readLine(); s != null; s = reader.readLine()) { builder.append(s); } result = builder.toString(); Log.d(TAG, "result is ( " + result + " )"); // 保存Cookie cookieStore = ((AbstractHttpClient) httpClient).getCookieStore(); } catch (Exception e) { Log.e(TAG, e.toString()); } Log.d(TAG, "over"); return result; } public static String invoke(String controllerName, String actionName) { return invoke(controllerName, actionName, null); } /** * @descrption 通过拼接的方式构造请求内容,实现参数传输以及文件传输 * @author xdwang * @create 2012-9-27下午7:06:20 * @param controllerName * .NETMVC中的controllerName * @param actionName * .NETMVC中的actionName * @param params * key:为C#方法接受的参数,value为参数值,支持多个参数 * @param files * key:为C#方法接受的参数,不要重复,value为参数值,支持上传多个附件 * @return * @throws IOException */ public static String httpPostByte(String controllerName, String actionName, Map<String, String> params, Map<String, byte[]> files) throws IOException { String BOUNDARY = java.util.UUID.randomUUID().toString(); String PREFIX = "--", LINEND = "\r\n"; String MULTIPART_FROM_DATA = "multipart/form-data"; String CHARSET = "UTF-8"; String url = SERVER_URL + controllerName + "/" + actionName + "/"; URL uri = new URL(url); HttpURLConnection conn = (HttpURLConnection) uri.openConnection(); conn.setReadTimeout(5 * 1000); // 缓存的最长时间 conn.setDoInput(true);// 允许输入 conn.setDoOutput(true);// 允许输出 conn.setUseCaches(false); // 不允许使用缓存 conn.setRequestMethod("POST"); conn.setRequestProperty("connection", "keep-alive"); conn.setRequestProperty("Charsert", "UTF-8"); conn.setRequestProperty("Content-Type", MULTIPART_FROM_DATA + ";boundary=" + BOUNDARY); // 首先组拼文本类型的参数 StringBuilder sb = new StringBuilder(); for (Map.Entry<String, String> entry : params.entrySet()) { sb.append(PREFIX); sb.append(BOUNDARY); sb.append(LINEND); sb.append("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"" + LINEND); sb.append("Content-Type: text/plain; charset=" + CHARSET + LINEND); sb.append("Content-Transfer-Encoding: 8bit" + LINEND); sb.append(LINEND); sb.append(entry.getValue()); sb.append(LINEND); } DataOutputStream outStream = new DataOutputStream( conn.getOutputStream()); outStream.write(sb.toString().getBytes()); // 发送文件数据 if (files != null) { for (Map.Entry<String, byte[]> file : files.entrySet()) { StringBuilder sb1 = new StringBuilder(); sb1.append(PREFIX); sb1.append(BOUNDARY); sb1.append(LINEND); sb1.append("Content-Disposition: form-data; name=\"" + file.getKey() + "\"; filename=\"" + file.getKey() + "\"" + LINEND); sb1.append("Content-Type: application/octet-stream; charset=" + CHARSET + LINEND); sb1.append(LINEND); outStream.write(sb1.toString().getBytes()); //这里如何是File对象,则写成这种形式 // InputStream is = new FileInputStream(file.getValue()); // byte[] buffer = new byte[1024]; // int len = 0; // while ((len = is.read(buffer)) != -1) { // outStream.write(buffer, 0, len); // } outStream.write(file.getValue()); // is.close(); outStream.write(LINEND.getBytes()); } } // 请求结束标志 byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINEND).getBytes(); outStream.write(end_data); outStream.flush(); // 得到响应码 int res = conn.getResponseCode(); InputStream in = null; if (res == 200) { in = conn.getInputStream(); int ch; StringBuilder sb2 = new StringBuilder(); while ((ch = in.read()) != -1) { sb2.append((char) ch); } } return in == null ? null : in.toString(); } }
Android 中的调用:
AsyncTask<Void, Void, String> task = new AsyncTask<Void, Void, String>() { /** * 服务器端的返回值处理 */ @Override protected void onPostExecute(String result) { Log.d(TAG, result); try { JSONObject json = new JSONObject(result); uuid = json.getString("Result"); String picName = ""; String picSrc = ""; JSONObject picMap = json.getJSONObject("Message"); if (json.getJSONObject("Message") != null) { picSrc = picMap.getString("Value"); picName = picMap.getString("Key"); } } catch (JSONException e) { Log.e(TAG, e.toString()); } } @Override protected void onPreExecute() { super.onPreExecute(); } /** * 调用Http方法请求服务器端 */ @Override protected String doInBackground(Void... arg0) { try { // 直接传普通参数; NameValuePair param = new BasicNameValuePair("uuid", uuid); List<NameValuePair> params = new ArrayList<NameValuePair>(); params.add(param); return HttpHelper.invoke("GuessPic", "GetNextPicture", params); // 直接传普通参数和附件; Map<String, String> params = new HashMap<String, String>(); params.put("content", contentTemp); params.put("usId", guessPicture.usId); Map<String, byte[]> files = new HashMap<String, byte[]>(); files.put("soundBytes", totalBytes); return HttpHelper.httpPostByte("GuessPic", "SaveAudio", params, files); } catch (Exception e) { Log.e(TAG, e.toString()); return null; } } }; task.execute();
服务器端(C#MVC实现):
/// <summary> /// 下一张图片 /// </summary> /// <returns></returns> public JsonResult GetNextPicture(string uuid) { ResultMessage<string, KeyValuePair<string, string>> rm = new ResultMessage<string, KeyValuePair<string, string>>(); //….TODO逻辑处理 return Json(rm, JsonRequestBehavior.AllowGet); }
/// <summary> /// 保存上传一个文件和内容 /// </summary> /// <param name="content">内容</param> /// <param name="soundBytes">音频文件对象</param> /// <returns></returns> public JsonResult SaveAudio(string content, HttpPostedFileBase soundBytes, string usId) { ResultMessage<bool, object> rm = new ResultMessage<bool, object>(); byte[] bytes = new byte[soundBytes.InputStream.Length]; soundBytes.InputStream.Read(bytes, 0, bytes.Length); //….TODO逻辑处理 return Json(rm, JsonRequestBehavior.AllowGet); }