xamarin android网络请求总结
xamarin android中网络请求的框架非常多,在项目中使用的是第三方的一个网络请求框架restsharp,应该是github上.net网络请求最多star的框架,没有之一。这里就简单汇总了其他的一些网络请求的例子,主要还是分为android和.net两种平台。
下面就用.net中的httpwebrequest、httpclient、restsharp和android中的httpURLConnection、okhttp实现一个get方式获取图片、post方式提交表单,适合新手入门看看总结一下。
效果图如下:
1.HttpWebRquest、HttpWebResponse
命名空间: System.Net;程序集: System(位于 System.dll)
1 public class HttpWebRequestUtil 2 { 3 //发送get请求获取bytes 4 public static async System.Threading.Tasks.Task<byte[]> GetBytes(string path) 5 { 6 try 7 { 8 HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(path); 9 request.Method = "get"; 10 request.Timeout = 500; 11 //request.Proxy设置代理 12 //path 中可添加querystring参数 13 //request.UserAgent 请求的代理 14 HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync(); 15 if (response.StatusCode == HttpStatusCode.OK) 16 { 17 Stream responseStream = response.GetResponseStream(); 18 //将流转成字节 19 byte[] bytes = StreamUtil.StreamToBytes(responseStream); 20 return bytes; 21 } 22 else 23 return null; 24 } 25 catch (Exception ex) 26 { 27 return null; 28 } 29 } 30 31 public static async System.Threading.Tasks.Task<bool> PostForm(string path, string name, string pwd) 32 { 33 try 34 { 35 string formData = "name=" + name +"&pwd=" +pwd ; 36 byte[] bytes = Encoding.UTF8.GetBytes(formData); 37 StringBuilder strBuilder = new StringBuilder(); 38 HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(path); 39 request.Method = "get"; 40 request.Timeout = 500; 41 request.ContentType = "application/x-www-form-urlencoded; charset=UTF-8"; 42 request.ContentLength = bytes.Length; 43 request.Method = "Post"; 44 Stream requestStream = request.GetRequestStream(); 45 requestStream.Write(bytes, 0, bytes.Length); 46 requestStream.Close(); 47 48 HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync(); 49 if (response.StatusCode == HttpStatusCode.OK) 50 { 51 StreamReader streamReader = new StreamReader(response.GetResponseStream(), Encoding.UTF8); 52 string content = JsonConvert.DeserializeObject<string>(streamReader.ReadToEnd()); 53 streamReader.Close(); 54 if (content == "success") 55 { 56 return true; 57 } 58 else 59 return false; 60 } 61 return false; 62 } 63 catch (Exception ex) 64 { 65 return false; 66 } 67 } 68 }
2.RestSharp .net常用的http网络请求库
当然重点还是说一下这个的。restsharp在github上的star应该是.net网络请求库最多的,(和第二名的差距比较大)。可以在nuget上直接添加引用restsharp。
github地址:https://github.com/restsharp/RestSharp
restSharp官网:http://restsharp.org/
stackoverflow上restsharp的相关问题汇总: https://stackoverflow.com/questions/tagged/RestSharp
restsharp有一下这么几个重要的有点:
- 轻量级的、基于HttpWebRequest的封装(不依赖任何第三方组件、支持.net 任何平台上)
- 支持异步操作、支持http的get、post、put、delete等操作
- 使用简单、易调试、request和response的类型齐全
- 功能齐全,支持oAuth 1, oAuth 2, Basic等授权验证、可上传文件
- 自定义序列化和反序列化、自动检测返回的内容类型
1 public class RestSharpUtil 2 { 3 internal static RestClient Instance(string url) 4 { 5 var restClient = new RestClient(url) 6 { 7 Timeout = 5000, 8 ReadWriteTimeout = 5000 9 }; 10 return restClient; 11 } 12 public static async System.Threading.Tasks.Task<bool> Post(string url, User user) 13 { 14 RestClient restClient = Instance(url); 15 RestRequest request = new RestRequest(); 16 //request.AddQueryParameter("id","") 添加url的参数(AddUrlSegment) 17 //request.AddHeader("Authorization","token");添加请求头参数 18 // request.AddHeader("content-type", "application/x-www-form-urlencoded; charset=UTF-8"); 19 request.AddJsonBody(user); 20 //request.AddParameter("application/x-www-form-urlencoded; charset=UTF-8", user, ParameterType.RequestBody); 21 var response = await restClient.ExecutePostTaskAsync(request); 22 //var response = await restClient.ExecutePostTaskAsync<string>(request); 自动序列化 23 if (response.StatusCode == System.Net.HttpStatusCode.OK) 24 { 25 var result = JsonConvert.DeserializeObject<string>(response.Content); 26 if (result == "success") 27 { 28 return true; 29 } 30 return false; 31 } 32 else 33 { 34 return false; 35 } 36 } 37 public static async System.Threading.Tasks.Task<byte[]> Get(string url) 38 { 39 RestClient restClient = Instance(url); 40 RestRequest request = new RestRequest(); 41 var response = await restClient.ExecuteGetTaskAsync(request); 42 if (response.StatusCode == System.Net.HttpStatusCode.OK) 43 { 44 var bytes = response.RawBytes; 45 return bytes; 46 } 47 return null; 48 } 49 }
post请求和get请求在编码类型不同,get:仅一种 application/x-www-form-urlencoded,post:application/x-www-form-urlencoded 或 multipart/form-data……等多种编码方式。
restsharp在发送post请求方式时必须设置header的content-type解码方式。
request.AddJsonBody(user);等同于:
request.AddParameter(“application/x-www-form-urlencoded; charset=UTF-8”, user, ParameterType.RequestBody);等同于:
request.RequestFormat =DataFormat.Json;
request.AddBody(user);
这里备注一下以前犯的一个错误,用了AddBody方法必须添加 request.RequestFormat =DataFormat.Json; ,不然会出异常
我们看看下面的AddBody的源码可以知道,除restsharp,.net第三方的网络请求框架还有flurl.http。
1 /// <summary> 2 /// Serializes obj to format specified by RequestFormat, but passes xmlNamespace if using the default XmlSerializer 3 /// The default format is XML. Change RequestFormat if you wish to use a different serialization format. 4 /// </summary> 5 /// <param name="obj">The object to serialize</param> 6 /// <param name="xmlNamespace">The XML namespace to use when serializing</param> 7 /// <returns>This request</returns> 8 public IRestRequest AddBody(object obj, string xmlNamespace) 9 { 10 string serialized; 11 string contentType; 12 13 // TODO: Make it possible to change the serialiser 14 switch (RequestFormat) 15 { 16 case DataFormat.Json: 17 serialized = JsonSerializer.Serialize(obj); 18 contentType = JsonSerializer.ContentType; 19 break; 20 21 case DataFormat.Xml: 22 XmlSerializer.Namespace = xmlNamespace; 23 serialized = XmlSerializer.Serialize(obj); 24 contentType = XmlSerializer.ContentType; 25 break; 26 27 default: 28 serialized = ""; 29 contentType = ""; 30 break; 31 } 32 33 // passing the content type as the parameter name because there can only be 34 // one parameter with ParameterType.RequestBody so name isn't used otherwise 35 // it's a hack, but it works :) 36 return AddParameter(contentType, serialized, ParameterType.RequestBody); 37 } 38 39 /// <summary> 40 /// Serializes obj to data format specified by RequestFormat and adds it to the request body. 41 /// The default format is XML. Change RequestFormat if you wish to use a different serialization format. 42 /// </summary> 43 /// <param name="obj">The object to serialize</param> 44 /// <returns>This request</returns> 45 public IRestRequest AddBody(object obj) 46 { 47 return AddBody(obj, ""); 48 } 49 50 /// <summary> 51 /// Serializes obj to JSON format and adds it to the request body. 52 /// </summary> 53 /// <param name="obj">The object to serialize</param> 54 /// <returns>This request</returns> 55 public IRestRequest AddJsonBody(object obj) 56 { 57 RequestFormat = DataFormat.Json; 58 59 return AddBody(obj, ""); 60 }
3.HttpClient
性能上不如httpwebrequest,用的非常少,据说使用的时候要注意不少,这里只是写一个简单的例子,不喜勿喷。
需要添加引用System.Http.Http
1 public class HttpClientUtil 2 { 3 public static async System.Threading.Tasks.Task<byte[]> GetBytes(string path) 4 { 5 HttpClient client = new HttpClient(); 6 try 7 { 8 HttpResponseMessage response = await client.GetAsync(path); 9 if (response.StatusCode == System.Net.HttpStatusCode.OK) 10 { 11 byte[] bytes = await response.Content.ReadAsByteArrayAsync(); 12 return bytes; 13 } 14 return null; 15 } 16 catch (Exception ex) 17 { 18 return null; 19 } 20 finally 21 { 22 client.Dispose(); 23 } 24 } 25 26 public static async System.Threading.Tasks.Task<bool> PostForm(string path, Dictionary<string,string> _params) 27 { 28 29 var handler = new HttpClientHandler() { AutomaticDecompression = System.Net.DecompressionMethods.GZip }; 30 HttpClient client = new HttpClient(); 31 try 32 { 33 client.Timeout = TimeSpan.FromSeconds(5); 34 //HttpContent httpContent = new StringContent(postData); 35 //httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/x-www-form-urlencoded"); 36 HttpContent httpContent = new FormUrlEncodedContent(_params); 37 var response = await client.PostAsync(path, httpContent); 38 if (response.StatusCode == System.Net.HttpStatusCode.OK) 39 { 40 string result = await response.Content.ReadAsStringAsync(); 41 result = JsonConvert.DeserializeObject<string>(result); 42 if (result == "success") 43 return true; 44 return false; 45 } 46 return false; 47 } 48 catch (Exception ex) 49 { 50 return false; 51 } 52 finally 53 { 54 client.Dispose(); 55 } 56 } 57 }
上面介绍了三种.net方面的网络请求的方法,下面就来说说android方面的网络请求HttpUrlConnection、第三方okhttp。
4.HttpURLConnection
httpURLConnection和HttpWebRequest很相似,是java平台上的一种多用途、轻量级的http客户端,提供的api都非常简单,这一点也是好处,可以使得我们非常方便去拓展他。下面我们简单看下如何使用HttpURLConnection。
引用来自:Java.Net
- HttpURLConnection conn = (HttpURLConnection)url.OpenConnection();创建一个URL对象
- conn.ConnectTimeout = 5000; conn.RequestMethod = “get”;设置请求方式和连接超时的时间
- inputStream = conn.InputStream;获取服务器返回的输入流
- conn.Disconnect();最后调用disconnect方法将http连接关掉
public class HttpUrlConnecUtil { /// <summary> /// get方式获取byte 数组 /// </summary> /// <param name="path"></param> /// <returns></returns> public static byte[] getImage(string path) { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection)url.OpenConnection(); conn.ConnectTimeout = 5000; conn.RequestMethod = "GET";//小写会报错 System.IO.Stream inputStream=null; try { if (conn.ResponseCode == HttpStatus.Ok) { inputStream = conn.InputStream; return StreamUtil.StreamToBytes(inputStream); } return null; } catch (Exception ex) { return null; } finally { inputStream.Close(); conn.Disconnect(); } } public static string post(string path,string name,string pwd) { string result = string.Empty; HttpURLConnection conn = (HttpURLConnection)new URL(path).OpenConnection(); conn.RequestMethod = "POST"; conn.ReadTimeout = 5000; conn.ConnectTimeout = 5000; //设置运行输入、输出 conn.DoOutput = true; conn.DoInput = true; //post 方式不能缓存,需要手动设置false conn.UseCaches = false; string data = "name=" + URLEncoder.Encode(name, "UTF-8") + "&pwd=" + URLEncoder.Encode(pwd,"UTF-8"); Stream outSteam=null; //获取输出流 try { outSteam = conn.OutputStream; outSteam.Write(Encoding.UTF8.GetBytes(data), 0, data.Length); outSteam.Flush(); if (conn.ResponseCode == HttpStatus.Ok) { Stream input = conn.InputStream; byte[] bytes = StreamUtil.StreamToBytes(input); result = bytes.ToString(); } return result; } catch (Exception ex) { return ""; } finally { outSteam.Close(); conn.Disconnect(); } } } /// <summary> /// 将流转成byte数组 /// </summary> /// <param name="stream"></param> /// <param name="bytes"></param> public static byte[] StreamToBytes(Stream stream) { MemoryStream memoryStream = new MemoryStream(); byte[] buffer = new byte[64 * 1024]; int i; try { while ((i = stream.Read(buffer, 0, buffer.Length)) > 0) { memoryStream.Write(buffer, 0, i); } var bytes = memoryStream.ToArray(); return bytes; } catch (Exception ex) { return null; } finally { memoryStream.Close(); stream.Close(); } }
5.OkHttp 最火的android网络请求框架
okhttp是一个第三方的网络请求框架,被广泛适用于android中请求网络数据,是一个一个轻量级的框架,有移动支付Square公司贡献(Picasso和LeakCanary),和HttpURLConnection和api是一致的。在xamarin android中使用的时候需要在nuget中添加引用OkHttp,命名空间:using Square.OkHttp3;
okhttp官网:http://square.github.io/okhttp/
github地址:https://github.com/square/okhttp
除了okhttp外,android中比较流行的网络请求框架还有
retrofit,retrofit2依赖于okhttp;github地址:http://square.github.io/retrofit/,拓展性比较强
volley:google在2013年推出的android异步网络请求框架和图片加载框架
下面看看,如何在xamarin android中使用okhttp发送get,post请求吧。
public class OkHttpClientUtil { private OkHttpClient httpClient; public OkHttpClientUtil() { httpClient = new OkHttpClient.Builder() .ConnectTimeout(5, TimeUnit.Seconds)//连接超时5秒 .WriteTimeout(5, TimeUnit.Seconds)//写入数据超时5秒 .ReadTimeout(5, TimeUnit.Seconds)//读取数据超时5秒 .Build(); } public static OkHttpClientUtil Instance() { return new OkHttpClientUtil(); } public async System.Threading.Tasks.Task<bool> Post(string url, User user) { FormBody.Builder formBody = new FormBody.Builder(); //创建表单请求体 formBody.Add("name", user.Name); formBody.Add("pwd", user.Pwd); Request request = new Request.Builder().AddHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8").Url(url).Post(formBody.Build()).Build(); var response = await httpClient.NewCall(request).ExecuteAsync(); if (response.Code() == 200) { var result =JsonConvert.DeserializeObject<string>(response.Body().String()); if (result == "success") { return true; } return false; } return false; } public async System.Threading.Tasks.Task<byte[]> Get(string url) { Request request = new Request.Builder().Url(url).Build(); Response response = await httpClient.NewCall(request).ExecuteAsync(); if (response.Code() == 200) { var stream = response.Body().ByteStream(); var bytes = StreamUtil.StreamToBytes(stream); return bytes; } return null; } }