package com.driver.igotrip.base import android.annotation.SuppressLint import android.app.Activity import android.app.Application import android.content.Context import android.content.Intent import android.os.* import android.util.Log import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import cn.jpush.android.api.JPushInterface import cn.jpush.android.api.TagAliasCallback import cn.sinata.rxnetty.LogHelper.initLogs import cn.sinata.rxnetty.LogHelper.logRecord import cn.sinata.rxnetty.NettyClient import cn.sinata.xldutils.BaseApplication import cn.sinata.xldutils.utils.SPUtils import cn.sinata.xldutils.utils.sysErr import com.driver.igotrip.R import com.driver.igotrip.bean.OrderBean import com.driver.igotrip.bean.OrderResData import com.driver.igotrip.bean.OrderSimpleData import com.driver.igotrip.bean.websocket.HeartBean import com.driver.igotrip.netUtls.* import com.driver.igotrip.ui.main.TripActivity import com.driver.igotrip.ui.main.small_cargo.SmallCargoActivity import com.driver.igotrip.ui.pub.LoginActivity import com.driver.igotrip.utils.AudioRecoderUtils import com.driver.igotrip.utils.Cache.CacheKey import com.driver.igotrip.utils.Cache.CacheUtil import com.driver.igotrip.utils.LanguageManager import com.driver.igotrip.utils.LogUtils import com.google.android.gms.maps.model.LatLng import com.google.cloud.texttospeech.v1.* import com.google.gson.Gson import com.google.protobuf.ByteString import com.tencent.bugly.crashreport.CrashReport //import com.umeng.commonsdk.UMConfigure //import com.umeng.socialize.PlatformConfig import com.xuexiang.xui.XUI import org.greenrobot.eventbus.EventBus import org.jetbrains.anko.startActivity import org.jetbrains.anko.toast import org.json.JSONObject import java.io.FileOutputStream import java.security.SecureRandom import java.security.cert.X509Certificate import java.util.* import javax.net.ssl.HttpsURLConnection import javax.net.ssl.SSLContext import javax.net.ssl.TrustManager import javax.net.ssl.X509TrustManager //MD5: A6:19:B7:92:10:27:61:22:BC:37:1B:98:9B:9E:1A:82 //SHA1: B9:D3:9B:10:B1:25:77:FF:62:D2:56:83:CC:14:1B:EA:DB:BC:97:74 /** * Created by Administrator on 2018/1/17. */ open class MyApplication : BaseApplication(), Application.ActivityLifecycleCallbacks { //设置debug模式 var isDebug = false var heartHandler: Handler? = null var currentTime = System.currentTimeMillis() override fun setSharedPreferencesName(): String { return "MyApplication" } override fun onCreate() { super.onCreate() appContext = this // Places.initialize(applicationContext, Const.google_key) // handleSSLHandshake() //如果是主进程 XUI.init(this) // UMConfigure.init( // this, // "62da14bc88ccdf4b7edb89cc", // "gaode", // UMConfigure.DEVICE_TYPE_PHONE, // "" // ) registerActivityLifecycleCallbacks(this) // PlatformConfig.setWeixin("wx6cbdae945b602b64", "f1c4a7d85118b5b841ef65349bd045dd") // PlatformConfig.setQQZone("1111276329", "JuAotVjQcUiesxgp") //qq互联 CrashReport.initCrashReport(this, "163c95c374", true); LogUtils.OpenLog(true) initLogs() initSocket() JPushInterface.setDebugMode(true) JPushInterface.init(this) setAlisa() } override fun attachBaseContext(base: Context?) { var language = SPUtils.getString("language") // super.attachBaseContext(LanguageUtil.changeAppLanguage(base, language, "")) super.attachBaseContext(LanguageManager.wrapContext(base)) } public fun setAlisa() { if (CacheKey.getUserId().isNotEmpty()) { var alisa = "DRIVER" + CacheKey.getUserId() sysErr(alisa) mHandler.sendMessage(mHandler.obtainMessage(MSG_SET_ALIAS, alisa)) } } private val MSG_SET_ALIAS = 1001 private val MSG_ORDER_CANCEL = 1002 @SuppressLint("HandlerLeak") private val mHandler: Handler = object : Handler() { override fun handleMessage(msg: Message) { super.handleMessage(msg) when (msg.what) { MSG_SET_ALIAS -> { Log.d(TAG, "Set alias in handler.") // 调用 JPush 接口来设置别名。 JPushInterface.setAliasAndTags( applicationContext, msg.obj as String, null, mAliasCallback ) } MSG_ORDER_CANCEL -> { val pair = msg.obj as Pair val orderBean = Gson().fromJson(pair.first, OrderBean::class.java) val act = activities[activities.size - 1] if (orderBean.data.cancelMidway == 1) { (act as PublicServiceActivity).cancelOrder( pair.second.audioUrl, pair.second.orderId.toString(), pair.second.orderType.toString(), orderBean.data.cancelReason, "${orderBean.data.cancelPayMoney}" ) if (act is PublicServiceDialogActivity) act.finish() } else if (pair.second.status == 12) { //取消待乘客支付弹窗 (act as PublicServiceActivity).cancelOrder( pair.second.audioUrl, "${orderBean.data.cancelPayMoney}" ) if (act is PublicServiceDialogActivity) act.finish() } else { if (pair.second.status == 10 && orderBean.data.cancelPayMoney != 0.0) { //乘客已支付的取消,不做处理 } else if (orderBean.data.timeOutCancel < System.currentTimeMillis()) { //已超时弹窗 (act as PublicServiceActivity).cancelOrder( pair.second.from, pair.second.audioUrl, pair.second.orderId.toString(), pair.second.orderType.toString(), orderBean.data.timeOutCancel, "${orderBean.data.cancelPayMoney}" ) if (act is PublicServiceDialogActivity) act.finish() } else { //司机没超时,用户也无取消费用,只播语音 不做处理 // act?.startActivity( // "orderId" to pair.second.orderId.toString(), // "orderType" to pair.second.orderType.toString() // ) Handler(mainLooper).post { getTTsManager().setVideoText(pair.second.audioUrl) } } } } else -> Log.i(TAG, "Unhandled msg - " + msg.what) } } } private val mAliasCallback = TagAliasCallback { code, alias, tags -> val logs: String when (code) { 0 -> { logs = "Set tag and alias success" Log.i("TAG", logs) } 6002 -> { logs = "Failed to set alias and tags due to timeout. Try again after 60s." Log.i("TAG", logs) // 延迟 60 秒来调用 Handler 设置别名 var alisa = "DRIVER" + CacheKey.getUserId() Handler().postDelayed({ JPushInterface.setAliasAndTags(this, alisa, null, null) }, 60 * 1000) } else -> { logs = "Failed with errorCode = $code" Log.e("TAG", logs) } } } private fun initSocket() { Log.e("sendLocation: ", "开始链接") NettyClient.getInstance().init(this, Api.SOCKET_SERVER, Api.SOCKET_PORT, true) NettyClient.getInstance().addOnMessageListener { message: String -> initnetdata(message) } NettyClient.getInstance().setOnConnectListener { sendHeart() } if (frist) { /* MainScope().launch { while (true){ delay(5000) var map = getMapByAny() if (getDriverOrderMessage.startsWith("api")) { map["appid"] = getAppId() var sign = DES.getSign(map) map["sign"] = sign } HttpManager.getInstance().post(getDriverOrderMessage, map, object : MyNoMsgObserver(this@MyApplication) { override fun success(responseString: String?) { Log.e("长连接接口消息: ",responseString.toString() ) initnetdata(responseString.toString()) } }) } }*/ frist = false } } fun initnetdata(message: String, isnet: Boolean? = false) { try { if (!isLogin && isnet == false) { return } currentTime = System.currentTimeMillis() val json = JSONObject(message) val method = json.optString("method") if (method != "OK") { Log.d("zmc-socket", message) } val data = json.optString("data") val code = json.optInt("code", -1) if (code == 200) { Log.e(" 订单: ", method) when (method) { Const.SOCKET_METHOD.OK -> { testReceiveNum++ } Const.SOCKET_METHOD.OFFLINE -> { val simpleData = Gson().fromJson( data, OrderSimpleData::class.java ) CacheUtil.get().clear() CacheKey.putKeyStr("isAgreen", "1") NettyClient.getInstance().stopService() isLogin = false val intent = Intent() intent.setClass(this, LoginActivity::class.java) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) startActivity(intent) toast(getString(R.string.您的账号已在其他平台登录)) } Const.SOCKET_METHOD.AFTER_WORK -> { val simpleData = Gson().fromJson( data, OrderSimpleData::class.java ) EventBus.getDefault().post(BaseEvent(BaseEvent.FORCED_OFFLINE)) val act = activities[activities.size - 1] (act as PublicServiceActivity).forceOffline( simpleData.audioUrl, simpleData.msg ) if (act is PublicServiceDialogActivity) act.finish() } Const.SOCKET_METHOD.ORDER_STATUS -> { val orderSimpleData = Gson().fromJson( data, OrderSimpleData::class.java ) OrderTimeOutManager.instance.checkOrderManager( "${orderSimpleData.orderId}", "${orderSimpleData.orderType}", orderSimpleData.status ) for (view in orderStatueViews.asReversed().indices) { orderStatueViews[view].orderInfo(orderSimpleData) } if (orderSimpleData.status == 1) { val act = activities[activities.size - 1] // MyApplication.getTTsManager().setVideoText("收到新的订单") Log.e(" 订单: ", "showOrder") when (orderSimpleData.orderType) { 1, 2 -> { (act as PublicServiceActivity).showOrder( orderSimpleData.audioUrl, orderSimpleData.orderId.toString(), orderSimpleData.orderType.toString(), orderSimpleData.time, 1 ) if (act is PublicServiceDialogActivity) act.finish() } 4, 5 -> { (act as PublicServiceActivity).showOrder( orderSimpleData.audioUrl, orderSimpleData.orderId.toString(), orderSimpleData.orderType.toString(), orderSimpleData.time, 1 ) if (act is PublicServiceDialogActivity) act.finish() } } } if (orderSimpleData.status == 2) { val act = activities[activities.size - 1] when (orderSimpleData.orderType) { 1, 2 -> { (act as PublicServiceActivity).toDorderAct( orderSimpleData.orderId.toString(), orderSimpleData.orderType.toString() ) if (act is PublicServiceDialogActivity) act.finish() } 4, 5 -> { act?.startActivity( "orderId" to orderSimpleData.orderId.toString(), "orderType" to orderSimpleData.orderType.toString() ) } 3 -> { } } } if (orderSimpleData.status == 10 || orderSimpleData.status == 12) { val map = getMapByAny() map["orderId"] = orderSimpleData.orderId map["orderType"] = orderSimpleData.orderType EventBus.getDefault().post(BaseEvent(BaseEvent.ORDER_CANCEL)) callNet(this, Api.queryOrderInfo, map) { val message = Message().apply { what = MSG_ORDER_CANCEL obj = Pair(it, orderSimpleData) } mHandler.sendMessage(message) } } } Const.SOCKET_METHOD.OFFLINE_PAYMENT -> { val orderSimpleData = Gson().fromJson( data, OrderResData::class.java ) val act = activities[activities.size - 1] (act as PublicServiceActivity).showDriverPayDialog( orderSimpleData.audioUrl, orderSimpleData.orderId.toString(), orderSimpleData.orderType.toString(), orderSimpleData.money ) if (act is PublicServiceDialogActivity) act.finish() } Const.SOCKET_METHOD.FROZEN_ORDER -> { EventBus.getDefault().post(BaseEvent(BaseEvent.MODIFY_ADDRESS_SUC)) } Const.SOCKET_METHOD.REASSIGN -> { Log.e( "zmc-socket", "EventBus.getDefault().post(BaseEvent(BaseEvent.REFREASH_MAIN))" ) EventBus.getDefault().post(BaseEvent(BaseEvent.REFREASH_MAIN)) // val orderSimpleData = // Gson().fromJson( // data, // OrderResData::class.java // ) // val act = activities[activities.size - 1] // when (orderSimpleData.orderType) { //// 1, 2, 4 -> { //// (act as PublicServiceActivity).showOrder( //// orderSimpleData.audioUrl, //// orderSimpleData.orderId.toString(), //// orderSimpleData.orderType.toString(), //// 30, //// 2 //// ) //// if (act is PublicServiceDialogActivity) act.finish() //// } // 4, 5 -> { // act?.startActivity( // "orderId" to orderSimpleData.orderId.toString(), // "orderType" to orderSimpleData.orderType.toString() // ) // } // // else -> { // act?.startActivity( // "orderId" to orderSimpleData.orderId.toString(), // "orderType" to orderSimpleData.orderType.toString() // ) // } // } } Const.SOCKET_METHOD.MODIFY_ADDRESS -> { val jsob = JSONObject(data) // if (jsob.optString("status") == "1") { // 只处理 申请订单消息 val act = activities[activities.size - 1] (act as PublicServiceActivity).modifyAddress( jsob.optString("audioUrl"), jsob.optString("orderId"), jsob.optString("orderType") ) // } if (act is PublicServiceDialogActivity) act.finish() } Const.SOCKET_METHOD.ORDER_TIME_OUT -> { val jsob = JSONObject(data) val act = activities[activities.size - 1] /** * 司机超时推送 * @param timeOutType 超时类型(1=用户可免费取消提醒,2=预约单接单提醒,3=超时循环提醒) * @param orderId 订单id * @param orderType 订单类型(1=打车,4=包裹) * @param describe 展示内容 * @param audioUrl 语音播报音频地址 */ val timeOutType = jsob.optString("timeOutType") val orderId = jsob.optString("orderId") val orderType = jsob.optString("orderType") val describe = jsob.optString("describe") val audioUrl = jsob.optString("audioUrl") if (timeOutType == "1" || timeOutType == "3") { // 仅提示 (act as PublicServiceActivity).onlyTips(audioUrl, describe) if (act is PublicServiceDialogActivity) act.finish() } else if (timeOutType == "2") { // 提示并查看订单详情 (act as PublicServiceActivity).goOrderTips( orderId, orderType, audioUrl, describe ) if (act is PublicServiceDialogActivity) act.finish() } } Const.SOCKET_METHOD.DIFFERENCE -> { val jsob = JSONObject(data) when (jsob.optString("status")) { // status 1=申请,2=同意,3=拒绝 "1" -> {} "2" -> { EventBus.getDefault() .post(BaseEvent(BaseEvent.DIFF_PRICE_AGREE)) } "3" -> { val act = activities[activities.size - 1] val tips = "${act!!.getString(R.string.您的包裹订单)}${ jsob.optString("orderId") }\n${ act.getString(R.string.申请补差价) } ${act.getString(R.string.money)} ${jsob.optString("money")} ${ act.getString(R.string.补差价被拒) }" EventBus.getDefault() .post(BaseEvent(BaseEvent.DIFF_PRICE_REFUSE)) (act as PublicServiceActivity).onlyTips( jsob.optString("audioUrl"), tips ) if (act is PublicServiceDialogActivity) act.finish() } } } } } else { sysErr("socket return code ===$code") } } catch (e: Exception) { e.printStackTrace() } } private fun getOrderWhenNoSocket(){ Log.e("sendLocation: ", "定时获取司机订单数据" + (getUserId() != -1).toString()) if (getUserId() != -1) { val map = getMapByAny() callNet1(this, Api.getDriverOrderMessage, map, clickAction = { logRecord(TAG, "getOrderWhenNoSocket 获取订单成功 $it") initnetdata(it ?: "") }, { logRecord(TAG, "getOrderWhenNoSocket 获取订单失败") }, false) } } private fun sendLocation() { Log.e("sendLocation: ", "发送定位 userId = ${getUserId()}, aMapLocation = ${Gson().toJson(aMapLocation)}") if (getUserId() != -1 && aMapLocation != null) { val map = getMapByAny() map["orderId"] = currentOrderId map["orderType"] = currentOrderType map["driverId"] = getUserId() map["lon"] = aMapLocation!!.longitude map["lat"] = aMapLocation!!.latitude logRecord(TAG, "sendLocation 发送定位参数" + Gson().toJson(map)) callNet1(this, Api.saveOrderPosition, map, clickAction = { logRecord(TAG, "sendLocation 发送定位成功") }, { logRecord(TAG, "sendLocation 发送定位失败") }, false) val map1 = getMapByAny() map1["orderId"] = currentOrderId map1["orderType"] = currentOrderType map1["driverId"] = getUserId() map1["lon"] = aMapLocation!!.longitude map1["lat"] = aMapLocation!!.latitude map1["altitude"] = 0 map1["directionAngle"] = 0 callNet1(this, Api.positionSocket, map1, clickAction = { logRecord(TAG, "positionSocket 发送定位成功") }, { logRecord(TAG, "positionSocket 发送定位失败") }, false) } } val TAG = "MyApplication" private fun sendHeart() { if (getUserId() != -1) { logRecord(TAG, "sendHeart: userId = " + getUserId()) val bean = HeartBean() bean.data = HeartBean.DataBean() NettyClient.getInstance().sendMessage(Gson().toJson(bean)) sendLocation() if (heartHandler == null) { heartHandler = Handler(mainLooper) } heartHandler!!.removeCallbacksAndMessages(null) testHeartNunm++ // if ((System.currentTimeMillis() - currentTime) / 1000 > 3) { // sysErr("sendHeart_websocket 重新连接") logRecord(TAG, "sendHeart check socket status") currentTime = System.currentTimeMillis() val nettyState = NettyClient.getInstance().checkNettyState() if (!nettyState) { getOrderWhenNoSocket() } // } else { // sysErr("sendHeart_websocket 发送心跳") // } } heartHandler!!.postDelayed({ sendHeart() }, 5000) } interface OrderStatueView { fun orderInfo(data: OrderSimpleData?) } companion object { var frist = true private const val TAG = "MyApplication" public var appContext: MyApplication? = null var mTtsManager: AudioRecoderUtils? = null var isPlayVoice = true var lastPlayTime = 0L //上次提示播放时间 var hasAutoGoTripping = false //true 本次启动已经自动跳转过 public var isLogin: Boolean = true fun getInstance(): MyApplication? { if (appContext == null) { appContext = MyApplication() } return appContext } fun getTTsManager(): AudioRecoderUtils { if (null == mTtsManager) { mTtsManager = AudioRecoderUtils(appContext) } return mTtsManager!! } fun getLocation(): LatLng? { if (aMapLocation == null) { return null } else { return aMapLocation!! } } fun tts(content: String) { Thread { TextToSpeechClient.create().use { textToSpeechClient -> // Set the text input to be synthesized val input: SynthesisInput = SynthesisInput.newBuilder().setText(content).build() // Build the voice request, select the language code ("en-US") and the ssml voice gender // ("neutral") val voice: VoiceSelectionParams = VoiceSelectionParams.newBuilder() .setLanguageCode("en-US") .setSsmlGender(SsmlVoiceGender.NEUTRAL) .build() // Select the type of audio file you want returned val audioConfig: AudioConfig = AudioConfig.newBuilder().setAudioEncoding(AudioEncoding.MP3).build() // Perform the text-to-speech request on the text input with the selected voice parameters and // audio file type val response: SynthesizeSpeechResponse = textToSpeechClient.synthesizeSpeech(input, voice, audioConfig) // Get the audio contents from the response val audioContents: ByteString = response.getAudioContent() FileOutputStream("output.mp3").use { out -> out.write(audioContents.toByteArray()) println("Audio content written to file \"output.mp3\"") } } }.start() } var aMapLocation: LatLng? = null var currentOrderId: String = "" var currentOrderType: String = "" var orderStatueViews: MutableList = mutableListOf() var testHeartNunm = 0 var testReceiveNum = 0 fun handleSSLHandshake() { try { val trustAllCerts = arrayOf(object : X509TrustManager { override fun getAcceptedIssuers(): Array { return arrayOfNulls(0) } override fun checkClientTrusted( certs: Array, authType: String, ) { } override fun checkServerTrusted( certs: Array, authType: String, ) { } }) val sc = SSLContext.getInstance("TLS") // trustAllCerts信任所有的证书 sc.init(null, trustAllCerts, SecureRandom()) HttpsURLConnection.setDefaultSSLSocketFactory(sc.socketFactory) HttpsURLConnection.setDefaultHostnameVerifier { hostname, session -> true } } catch (ignored: Exception) { } } fun addOrderView(view: OrderStatueView) { if (!orderStatueViews.contains(view)) { orderStatueViews.add(view) } } fun removeOrderView(view: OrderStatueView?) { orderStatueViews.remove(view) } } val activities = ArrayList() private var showNum = 0 fun finishAll() { for (item in activities) { item?.finish() } } fun getCurrentActivity(): Activity? { var act: Activity? = try { activities[activities.size - 1] } catch (e: Exception) { null } return act } override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { activities.add(activity) Log.i("zmc-pageA", "onActivityCreated: " + activity.javaClass.name) if (activity is MyBaseActivity) { activity.supportFragmentManager.registerFragmentLifecycleCallbacks(object : FragmentManager.FragmentLifecycleCallbacks() { override fun onFragmentCreated( fm: FragmentManager, f: Fragment, savedInstanceState: Bundle? ) { super.onFragmentCreated(fm, f, savedInstanceState) Log.i("zmc-pageF", "onFragmentCreated: " + f.javaClass.name) } override fun onFragmentDestroyed(fm: FragmentManager, f: Fragment) { super.onFragmentDestroyed(fm, f) Log.e("zmc-pageF", "onFragmentDestroyed: " + f.javaClass.name) } }, true) } } override fun onActivityStarted(activity: Activity) { showNum++ Log.d("zmc-pageA", "onActivityStarted: " + activity.javaClass.name) } override fun onActivityResumed(activity: Activity) { // Log.i("zmc-pageA", "onActivityResumed: " + activity.javaClass.name) } override fun onActivityPaused(activity: Activity) { // Log.e("zmc-pageA", "onActivityPaused: " + activity.javaClass.name) } override fun onActivityStopped(activity: Activity) { Log.e("zmc-pageA", "onActivityStopped: " + activity.javaClass.name) showNum-- Handler(Looper.getMainLooper()).postDelayed({ if (showNum == 0 && isPlayVoice) { if (System.currentTimeMillis() - lastPlayTime > 20000) { // getTTsManager().setVideoText(activity!!.getString(R.string.请勿切换)) lastPlayTime = System.currentTimeMillis() } } isPlayVoice = true }, 600) } override fun onActivityDestroyed(activity: Activity) { Log.d("zmc-pageA", "onActivityDestroyed: " + activity.javaClass.name) activities.remove(activity) } override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) { // Log.d("zmc-pageA", "onActivitySaveInstanceState: " + activity.javaClass.name) } }