okhttp3 示例 及 HttpUtil
implementation 'com.squareup.okhttp3:okhttp:4.9.0'
1.GET请求
1 private fun httpGetDemo() { 2 //1.请求参数 3 val url = httpHost + "/api/test?arg1=xxx" 4 5 //2.构造 OkHttpClient : 设置连接超时、读取超时、写出超时、cookie等 6 var okhttp3 = OkHttpClient.Builder() 7 .retryOnConnectionFailure(true) //失败重连 8 .connectTimeout(connectTimeout, TimeUnit.SECONDS) //设置连接超时时间 9 .readTimeout(readTimeout, TimeUnit.SECONDS) //设置读取超时时间 10 .writeTimeout(writeTimeout,TimeUnit.SECONDS) //设置写出超时时间 11 .cookieJar(cookieJar) //设置cookie 12 .build() 13 14 //3.构造 Request ,设置请求方法,请求头参数 15 var rb = Request.Builder() 16 .url(url) //指定请求地址 17 .get() //指定请求的方法 18 19 //设置header的3种方法: 20 //a, 添加 key - value 21 rb.addHeader("header1","value1") //添加自定义的header1 22 rb.addHeader("header2","value2") //添加自定义的header2 23 24 //b, 按key修改value 25 rb.header("Cookie","df") //指定某个header的值 26 27 //c,完全替换headers,注意它会把Request.Builder里设置的都删除,然后按自己添加的key-value重新设置当前builder的headers 28 var hb = Headers.Builder() 29 hb.add("header1","value1") 30 hb.add("header2","value2") 31 var headers = hb.build() 32 rb.headers(headers) //指定headers 33 34 var request = rb.build() 35 36 //4.发起请求 37 okhttp3.newCall(request).enqueue(object : Callback { 38 override fun onFailure(call: Call, e: IOException) { 39 40 //5.处理请求失败 41 Log.e("DailyFrgmt","rollOverData onFailure error = " + e.message) 42 activity?.runOnUiThread { 43 Toast.makeText(getContext(),"查询翻身数据失败",Toast.LENGTH_SHORT).show() 44 } 45 } 46 override fun onResponse(call: Call, response: Response) { 47 //6.请求成功 48 var json = "" 49 //6.1 从response里可取得cookie 50 var url = request.url 51 var headers = response.headers 52 var cookies = Cookie.parseAll(url,headers) 53 for (cookie in cookies){ 54 Log.e("Cookies ", "cookie : name = " + cookie.name + " value = " + cookie.value) 55 } 56 //6.2 得到2进制流,一般下载用,保存成文件。 57 var stream = response.body?.byteStream() 58 var br = BufferedInputStream(stream) 59 var len = 0 60 var buf = ByteArray(1024 * 8) 61 do { 62 len = br.read(buf) 63 if (len > 0){ 64 json += String(buf,0,len) 65 } 66 }while (len != -1) 67 Log.e("DailyFrgmt","rollOverData onResponse = " + json) 68 if (LogUtil.TO_FILE){ 69 try { 70 var js = context?.getExternalFilesDir("")?.absolutePath.toString() + "/rollover.json" 71 var fw = FileWriter(js) 72 fw.write(json) 73 fw.close() 74 }catch (e : java.lang.Exception){ 75 e.printStackTrace() 76 Log.e("DailyFrgmt","exception = " + e.message) 77 } 78 } 79 //7.业务方法 80 } 81 }) 82 }
2.POST请求
1 fun login( uname : String,pwd : String,failed : (reason : String?) -> Unit,succeed : () -> Unit){ 2 val url = httpHost + "/api/login/" 3 4 //1.构造post的json 5 var jsObj = JSONObject() 6 jsObj.put("userName",uname) 7 jsObj.put("password", Encrypt.md5(pwd)) 8 var body = RequestBody.create("application/json; charset=utf-8".toMediaType(), jsObj.toString()) 9 10 //2.构造 OkHttpClient 11 var okhttp3 = OkHttpClient.Builder() 12 .retryOnConnectionFailure(true) //失败重连 13 .connectTimeout(connectTimeout, TimeUnit.SECONDS) //设置连接超时时间 14 .readTimeout(readTimeout, TimeUnit.SECONDS) //设置读取超时时间 15 .writeTimeout(writeTimeout,TimeUnit.SECONDS) 16 .cookieJar(cookieJar) //设置cookie 17 .build() 18 19 //3.构造post请求 20 var rb = Request.Builder() 21 .url(url) 22 .post(body) 23 24 //设置header的3种方法: 25 //a, 添加 key - value 26 rb.addHeader("header1","value1") //添加自定义的header1 27 rb.addHeader("header2","value2") //添加自定义的header2 28 29 //b, 按key修改value 30 rb.header("Cookie","df") //指定某个header的值 31 32 //c,完全替换headers,注意它会把Request.Builder里设置的都删除,然后按自己添加的key-value重新设置当前builder的headers 33 var hb = Headers.Builder() 34 hb.add("header1","value1") 35 hb.add("header2","value2") 36 var headers = hb.build() 37 rb.headers(headers) //指定headers 38 39 var request = rb.build() 40 41 //4.发送请求 42 okhttp3.newCall(request).enqueue(object : Callback{ 43 override fun onFailure(call: Call, e: IOException) { 44 //5.处理失败 45 Log.e("Login","error = " + e.message) 46 failed("请求失败") 47 } 48 override fun onResponse(call: Call, response: Response) { 49 //6.请求成功 50 var json = "" 51 //6.1 从response里可取得cookie 52 var url = request.url 53 var headers = response.headers 54 var cookies = Cookie.parseAll(url,headers) 55 for (cookie in cookies){ 56 Log.e("Cookies ", "cookie : name = " + cookie.name + " value = " + cookie.value) 57 } 58 //6.2 得到2进制流,一般下载用,保存成文件。 59 var stream = response.body?.byteStream() 60 var br = BufferedInputStream(stream) 61 var len = 0 62 var buf = ByteArray(1024 * 8) 63 do { 64 len = br.read(buf) 65 if (len > 0){ 66 json += String(buf,0,len) 67 } 68 }while (len != -1) 69 //7.业务方法 70 onSomeFunction(json) 71 } 72 }) 73 }
3.关于Cookie
3.1 解析cookie
1 //4.发送请求 2 okhttp3.newCall(request).enqueue(object : Callback{ 3 override fun onFailure(call: Call, e: IOException) { 4 //5.处理失败 5 Log.e("Login","error = " + e.message) 6 failed("请求失败") 7 } 8 override fun onResponse(call: Call, response: Response) { 9 //6.请求成功 10 var json = "" 11 //6.1 从response里可取得cookie 12 var url = request.url 13 var headers = response.headers 14 var cookies = Cookie.parseAll(url,headers) 15 for (cookie in cookies){ 16 Log.e("Cookies ", "cookie : name = " + cookie.name + " value = " + cookie.value) 17 } 18 ... 19 } 20 })
3.2 使用CookieJar操作cookie(保存、上报、共享)
1 var cm = HashMap<String,List<Cookie> >() 2 var cookieJar = object : CookieJar{ 3 override fun loadForRequest(url: HttpUrl): List<Cookie> { 4 var cookies = java.util.ArrayList<Cookie>() 5 var cks = cm.get(url.host) 6 if (cks != null){ 7 cookies.addAll(cks) 8 } 9 for(cookie in cookies){ 10 Log.i("cookieJar","loadForRequest cookie = ${cookie}") 11 } 12 return cookies 13 } 14 15 override fun saveFromResponse(url: HttpUrl, cookies: List<Cookie>) { 16 cm.put(url.host,cookies) 17 } 18 } 19 20 private fun testCookie() { 21 //1.请求参数 22 val url = httpHost + "/api/test?arg1=xxx" 23 24 //2.构造 OkHttpClient : 设置连接超时、读取超时、写出超时、cookie等 25 var okhttp3 = OkHttpClient.Builder() 26 .retryOnConnectionFailure(true) //失败重连 27 .connectTimeout(connectTimeout, TimeUnit.SECONDS) //设置连接超时时间 28 .readTimeout(readTimeout, TimeUnit.SECONDS) //设置读取超时时间 29 .writeTimeout(writeTimeout,TimeUnit.SECONDS) //设置写出超时时间 30 .cookieJar(cookieJar) //设置cookie处理对象 31 .build() 32 33 ... 34 }
- loadForRequest 是请求时加载本地cookie 的调用
- saveFromResponse 是保存cookie时的调用
- 每个 OkHttpClient 可以指定一个 cookie处理对象,一般一个url可返回一个cookie,同一个主机所有子url可以使用相同的CookieJar对象。
4.HttpUtil
1 import android.util.Log 2 import okhttp3.* 3 import okhttp3.MediaType.Companion.toMediaType 4 import java.io.IOException 5 import java.io.InputStream 6 import java.util.ArrayList 7 import java.util.HashMap 8 import java.util.concurrent.TimeUnit 9 10 object HttpUtil { 11 val okhttp3 : OkHttpClient by lazy { initClient() } 12 val cookieMap = HashMap<String,List<Cookie> >() 13 val cookieJar : CookieJar by lazy { initCookieJar() } 14 15 fun initClient() : OkHttpClient{ 16 val timeout = 1000 * 15L 17 val builder = OkHttpClient.Builder().apply { 18 retryOnConnectionFailure(true) 19 connectTimeout(timeout, TimeUnit.SECONDS) //设置连接超时时间 20 readTimeout(timeout , TimeUnit.SECONDS) //设置读取超时时间 21 writeTimeout(timeout, TimeUnit.SECONDS) 22 cookieJar(cookieJar) 23 } 24 return builder.build() 25 } 26 fun initCookieJar() : CookieJar{ 27 var host = "__none" 28 return object : CookieJar{ 29 override fun loadForRequest(url: HttpUrl): List<Cookie> { 30 Log.i("cookieJar","loadForRequest url = $url") 31 val cookies = ArrayList<Cookie>() 32 val cks = cookieMap.get(url.host) 33 if (cks != null){ 34 cookies.addAll(cks) 35 } 36 return cookies 37 } 38 39 override fun saveFromResponse(url: HttpUrl, cookies: List<Cookie>) { 40 Log.i("cookieJar","saveFromResponse url = $url") 41 host = url.host 42 cookieMap.put(url.host,cookies) 43 } 44 45 override fun toString(): String { 46 val cookies = cookieMap.get(host) as List<Cookie> 47 var ret = "" 48 for(cookie in cookies){ 49 ret += " , $cookie" 50 } 51 return ret 52 } 53 } 54 } 55 fun get(url : String, callback : (result : Int, response : String?)->Unit){ 56 val builder = Request.Builder().apply { 57 url(url) 58 get() 59 } 60 val request = builder.build() 61 okhttp3.newCall(request).enqueue(object : Callback{ 62 override fun onFailure(call: Call, e: IOException) { 63 callback.invoke(-1,e.message.toString()) 64 } 65 override fun onResponse(call: Call, response: Response) { 66 val res = response.body?.string() 67 callback.invoke(0,res) 68 } 69 }) 70 } 71 fun post(url: String, body : String, callback: (result: Int, response: String?) -> Unit){ 72 val rb = RequestBody.create("application/json; charset=utf-8".toMediaType(), body) 73 74 val request = Request.Builder().run { 75 url(url) 76 post(rb) 77 build() 78 } 79 80 okhttp3.newCall(request).enqueue(object : Callback{ 81 override fun onFailure(call: Call, e: IOException) { 82 callback.invoke(-1,e.message.toString()) 83 } 84 override fun onResponse(call: Call, response: Response) { 85 val res = response.body?.string() 86 callback.invoke(0,res) 87 } 88 }) 89 } 90 fun getWithHeader(url : String,headerMap : Map<String,String>, callback : (result : Int, response : String?)->Unit){ 91 val headers = Headers.Builder().run { 92 val iterator = headerMap.iterator() 93 while (iterator.hasNext()){ 94 val header = iterator.next() 95 add(header.key,header.value) 96 } 97 build() 98 } 99 val builder = Request.Builder().apply { 100 url(url) 101 get() 102 headers(headers) 103 } 104 val request = builder.build() 105 okhttp3.newCall(request).enqueue(object : Callback{ 106 override fun onFailure(call: Call, e: IOException) { 107 callback.invoke(-1,e.message.toString()) 108 } 109 override fun onResponse(call: Call, response: Response) { 110 val res = response.body?.string() 111 callback.invoke(0,res) 112 } 113 }) 114 } 115 fun postWithHeader(url: String, body : String, hm : Map<String,String>,callback: (result: Int, response: String?) -> Unit){ 116 val rb = RequestBody.create("application/json; charset=utf-8".toMediaType(), body) 117 118 val headers = Headers.Builder().run { 119 val keys = hm.keys 120 for (key in keys){ 121 val value = hm[key] 122 if (value != null){ 123 add(key,value) 124 } 125 } 126 build() 127 } 128 val request = Request.Builder().run { 129 url(url) 130 headers(headers) 131 post(rb) 132 build() 133 } 134 135 okhttp3.newCall(request).enqueue(object : Callback{ 136 override fun onFailure(call: Call, e: IOException) { 137 callback.invoke(-1,e.message.toString()) 138 } 139 override fun onResponse(call: Call, response: Response) { 140 val res = response.body?.string() 141 callback.invoke(0,res) 142 } 143 }) 144 } 145 fun getStream(url : String, callback : (result : Int, stream : InputStream?)->Int){ 146 val builder = Request.Builder().apply { 147 url(url) 148 get() 149 } 150 val request = builder.build() 151 okhttp3.newCall(request).enqueue(object : Callback{ 152 override fun onFailure(call: Call, e: IOException) { 153 callback.invoke(-1,null) 154 } 155 override fun onResponse(call: Call, response: Response) { 156 val res = response.body?.byteStream() 157 callback.invoke(0,res) 158 } 159 }) 160 } 161 fun getBody(url : String,callback : (result : Int,body : ResponseBody?)->Unit){ 162 val builder = Request.Builder().apply { 163 url(url) 164 get() 165 } 166 val request = builder.build() 167 okhttp3.newCall(request).enqueue(object : Callback{ 168 override fun onFailure(call: Call, e: IOException) { 169 callback.invoke(-1,null) 170 } 171 override fun onResponse(call: Call, response: Response) { 172 callback.invoke(0,response.body) 173 } 174 }) 175 } 176 177 }