package com.grkj.iscs.util import android.content.Context import android.util.Log import cn.zhxu.okhttps.HTTP import cn.zhxu.data.Mapper import cn.zhxu.okhttps.HttpResult import cn.zhxu.okhttps.HttpTask import cn.zhxu.okhttps.OkHttps import cn.zhxu.okhttps.gson.GsonMsgConvertor import cn.zhxu.okhttps.okhttp.OkHttpClientWrapper import com.grkj.iscs.MyApplication import com.grkj.iscs.R import com.grkj.iscs.model.Constants import com.grkj.iscs.model.Token import com.grkj.iscs.model.UrlConsts import com.grkj.iscs.model.UrlConsts.SIGN_IN import com.grkj.iscs.model.vo.BaseVO import com.grkj.iscs.util.log.LogUtil import okhttp3.logging.HttpLoggingInterceptor import java.io.IOException import java.net.SocketTimeoutException class NetHttpManager { lateinit var myHttp: HTTP var context: Context? = null var exceptionCount: Int = 0 companion object { fun getInstance() = InstanceHelper.sSingle val tagAuth = "Auth" } object InstanceHelper { val sSingle = NetHttpManager() } fun initCtx(ctx: Context) { context = ctx myHttp = HTTP.builder() .addMsgConvertor(GsonMsgConvertor()) .bodyType("application/json") .baseUrl(UrlConsts.BASE_URL) .responseListener { task: HttpTask<*>?, result: HttpResult? -> if (result?.status != 200) { LogUtil.d( "Api fail : Url : ${task?.url}, " + "Status : ${result?.status}, " + "Params : ${task?.urlParas ?: task?.bodyParas}" ) } true } .config { it.addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)) } .addSerialPreprocessor { itPreChain -> if (!itPreChain.task.isTagged(tagAuth)) { itPreChain.proceed() return@addSerialPreprocessor } requestTokenAndRefreshIfExpired { itPreChain.task.addHeader("Authorization", it) itPreChain.proceed() } } .build() } /** * 获取TOKEN,若过期则刷新(代码中的字符串可以替换为常量) */ fun requestTokenAndRefreshIfExpired(callback: (String?) -> Unit) { val token = Token.fromSp(context!!) if (token == null) { doLogin(callback) return } if (token.isValid()) { callback(token.token) return } // TODO 检查当前登录状态;临时注掉,方便调试 // if (SPUtils.getLoginUser(context!!) == null) { // ToastUtils.tip(context!!.resources.getString(R.string.please_login)) // return // } doLogin(callback) } private fun doLogin(callback: (String?) -> Unit) { val ctx = MyApplication.instance?.applicationContext // TODO 临时注掉,方便调试 // if (ctx == null || SPUtils.getLoginUser(ctx) == null) { // return // } // TODO 后续用SP数据替换 myHttp.async(SIGN_IN) .skipPreproc() .addBodyPara("username", "admin") .addBodyPara("password", "grkj8888") .nextOnIO() .setOnResponse { exceptionCount = 0 if (!it.isSuccessful) { callback(null) return@setOnResponse } try { val newToken = it.body.toBean(Token::class.java) newToken.saveToSp(context!!) callback(newToken.token) } catch (e: Exception) { callback(null) return@setOnResponse } } .setOnException { evictHttpConnectPool(it) callback(null) } .post() } fun doRequestNet( urlStr: String, isSkipPreproc: Boolean, bodyParas: Map, callback: (HttpResult.Body?, String?, Int) -> Unit, isGet: Boolean, isAuth: Boolean, mapperCallBack: ((Mapper) -> Unit)? = null ) { var httpTask = myHttp.async(urlStr).setOnException { evictHttpConnectPool(it) callback(null, context?.getString(R.string.common_net_dis), 0) } if (isAuth) httpTask.tag(tagAuth) if (isSkipPreproc) { httpTask.skipPreproc() } httpTask.nextOnIO() .setOnResponse { exceptionCount = 0 if (it.isSuccessful) { MyApplication.instance?.applicationContext?.let { itCtx -> Token.refresh(itCtx) } // TODO 待观察 try { it.body.cache() val baseVO = getBaseVO(it.body) if (baseVO?.code in 200 until 300) { callback(it.body, null, it.status) } else { baseVO?.msg?.let { itMsg -> ToastUtils.tip(itMsg) } val bobyStr = it.body.toString() callback( null, if (bobyStr.isEmpty()) { it.toString() } else { bobyStr }, it.status ) } } catch (e: Exception) { println("非标准返回数据,特殊处理:${e.message}") callback(it.body, null, it.status) } } else { var bobyStr = it.body.toString() callback( null, if (bobyStr.isNullOrEmpty()) { it.toString() } else { bobyStr }, it.status ) } } .setOnException { evictHttpConnectPool(it) callback(null, context?.getString(R.string.common_net_dis), 0) } mapperCallBack?.let { httpTask.setOnResMapper { mapperCallBack.invoke(it) } } // .setOnResMapper { // mapperCallBack?.invoke(it) // } if (isGet) { httpTask.addUrlPara(bodyParas) httpTask.get() } else { httpTask.addBodyPara(bodyParas) httpTask.post() } } fun downloadFileWithProcess( url: String, downloadCallBack: DownloadCallBack, filePath: String? = null, folderPath: String? = null ) { try { if (filePath.isNullOrBlank() && folderPath.isNullOrBlank()) { downloadCallBack.onResult( false, errorMsg = context?.getString(R.string.common_download_erro_notag) ) return } OkHttps.async(url).setOnResponse { exceptionCount = 0 if (it.isSuccessful) { if (filePath != null && filePath.isNotEmpty()) { it.body .stepRate(0.01) .setOnProcess { downloadCallBack.onProcess(it) } .toFile(filePath) .setOnSuccess { downloadCallBack.onResult(true, file = it) } .setOnFailure { downloadCallBack.onResult(false, errorMsg = it.exception.toString()) }.start() } else if (folderPath != null && folderPath.isNotEmpty()) { it.body .stepRate(0.01) .setOnProcess { downloadCallBack.onProcess(it) } .toFolder(folderPath) .setOnSuccess { downloadCallBack.onResult(true, file = it) } .setOnFailure { downloadCallBack.onResult(false, errorMsg = it.exception.toString()) }.start() } } else { downloadCallBack.onResult( false, it.status, errorMsg = context?.getString(R.string.common_net_download) ) } }.setOnException { evictHttpConnectPool(it) downloadCallBack.onResult( false, errorMsg = context?.getString(R.string.common_net_download) ) }.get() } catch (e: Exception) { downloadCallBack.onResult(false, errorMsg = e.message) } } private fun evictHttpConnectPool(e: Exception) { try { if (e is SocketTimeoutException) { exceptionCount += 1 if (exceptionCount >= 5) { exceptionCount = 0 (myHttp as OkHttpClientWrapper).okClient().connectionPool().evictAll() } } else { exceptionCount = 0 } } catch (e: Exception) { } } }