package com.igo.user.ui.trip import android.Manifest import android.content.Intent import android.content.pm.PackageManager import android.graphics.Bitmap import android.os.Bundle import android.os.Handler import android.os.Message import android.util.Log import android.view.View import android.widget.ImageView import android.widget.TextView import androidx.appcompat.widget.AppCompatTextView import androidx.core.app.ActivityCompat import androidx.core.os.bundleOf import androidx.core.view.isVisible import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import cn.sinata.rxnetty.LogHelper import cn.sinata.rxnetty.LogHelper.logRecord import cn.sinata.rxnetty.NettyClient import cn.sinata.xldutils.activity.BaseActivity import cn.sinata.xldutils.callPhone import cn.sinata.xldutils.gone import cn.sinata.xldutils.utils.LanguageUtil import cn.sinata.xldutils.utils.SpanBuilder import cn.sinata.xldutils.utils.myToast import cn.sinata.xldutils.utils.parserTime import cn.sinata.xldutils.view.TitleBar import cn.sinata.xldutils.visible import com.facebook.drawee.view.SimpleDraweeView import com.github.zackratos.ultimatebar.UltimateBar import com.google.android.gms.maps.CameraUpdateFactory import com.google.android.gms.maps.GoogleMap import com.google.android.gms.maps.model.BitmapDescriptorFactory import com.google.android.gms.maps.model.LatLng import com.google.android.gms.maps.model.Marker import com.google.android.gms.maps.model.MarkerOptions import com.google.android.gms.maps.model.Polyline import com.google.android.libraries.mapsplatform.transportation.consumer.ConsumerApi import com.google.android.libraries.mapsplatform.transportation.consumer.managers.TripModelCallback import com.google.android.libraries.mapsplatform.transportation.consumer.model.MarkerType import com.google.android.libraries.mapsplatform.transportation.consumer.model.TripInfo import com.google.android.libraries.mapsplatform.transportation.consumer.model.TripInfo.TripStatus import com.google.android.libraries.mapsplatform.transportation.consumer.model.TripModelOptions import com.google.android.libraries.mapsplatform.transportation.consumer.model.VehicleLocation import com.google.android.libraries.mapsplatform.transportation.consumer.sessions.JourneySharingSession import com.google.android.libraries.mapsplatform.transportation.consumer.view.ConsumerController import com.google.android.libraries.mapsplatform.transportation.consumer.view.ConsumerGoogleMap import com.google.android.libraries.mapsplatform.transportation.consumer.view.ConsumerMapFragment import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.igo.user.IGoApplication import com.igo.user.R import com.igo.user.dialog.TipDialog import com.igo.user.interfaces.OrderStateChangeListener import com.igo.user.network.HttpManager import com.igo.user.network.entity.Order import com.igo.user.network.entity.Point import com.igo.user.network.entity.TrippingInfo import com.igo.user.network.request import com.igo.user.ui.mine.TripOrderFragment import com.igo.user.ui.trip.adapter.ProgressAdapter import com.igo.user.utils.Const import com.igo.user.utils.Const.OrderType.TYPE_SPECIAL import com.igo.user.utils.google.AMapKit import com.igo.user.utils.google.JsonAuthTokenFactory import com.tbruyelle.rxpermissions2.RxPermissions import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.launch import org.jetbrains.anko.dip import org.jetbrains.anko.find import org.jetbrains.anko.imageResource import org.jetbrains.anko.sdk27.coroutines.onClick import org.jetbrains.anko.startActivity import org.jetbrains.anko.startActivityForResult class TripActivity : BaseActivity(), Handler.Callback, OrderStateChangeListener { var aMap: ConsumerGoogleMap? = null private val noticeCancelFlow = MutableSharedFlow() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_trip) initView() initClick() lifecycleScope.launch(Dispatchers.Main) { repeatOnLifecycle(Lifecycle.State.RESUMED) { noticeCancelFlow.collect { if (noResponseDialog.dialog?.isShowing != true) { noResponseDialog.show(supportFragmentManager, "noResponse") LogHelper.logRecord("显示超时无应答弹窗orderId:${id} orderType:${type}") } } } } } private val app by lazy { application as IGoApplication } private val handler by lazy { Handler(this) } private val gson by lazy { Gson() } //已行驶的路径,灰色 private var newDrivedRouteOverlay: Polyline? = null private var oldDrivedRouteOverlay: Polyline? = null private var consumerController: ConsumerController? = null private var vehicleLocation: VehicleLocation? = null //车辆位置 private val noResponseDialog by lazy { //无应答弹窗,不重复覆盖弹窗 val tipDialog = TipDialog() tipDialog.arguments = bundleOf( "msg" to getString(R.string.附近暂无司机接单), "ok" to getString(R.string.继续等待), "cancel" to getString(R.string.取消订单) ) tipDialog.setCallback(object : TipDialog.OnClickCallback { override fun onOk() { LogHelper.logRecord("继续等待订单接单orderId:${id} orderType:${type}") HttpManager.pushOrderTaxi(id, type).request(this@TripActivity, success = { _, _ -> LogHelper.logRecord("继续等待订单被接单成功orderId:${id} orderType:${type}") }) { code, msg -> LogHelper.logRecord("继续等待订单被接单失败orderId:${id} orderType:${type} code:${code} msg:${msg}") } } override fun onCancel() { cancelOrder() } }) tipDialog } private var id = 0 private var type: Int = 0 private var order: Order? = null var phoneEmergency = "" //报警电话 var phoneService = "" //客服电话 private val iv_shuaxing by lazy { find(R.id.iv_shuaxing) } private val titleBar by lazy { find(R.id.titleBar) } private val tv_action by lazy { find(R.id.tv_action) } private val tv_complain by lazy { find(R.id.tv_complain) } private val iv_call by lazy { find(R.id.iv_call) } private val tv_110 by lazy { find(R.id.tv_110) } private val tv_service by lazy { find(R.id.tv_service) } private val iv_location by lazy { find(R.id.iv_location) } private val tv_cancel by lazy { find(R.id.tv_cancel) } private val tv_change_destination by lazy { find(R.id.tv_change_destination) } private val fl_one_click by lazy { find(R.id.fl_one_click) } private val iv_header_home by lazy { find(R.id.iv_header_home) } private val tv_end by lazy { find(R.id.tv_end) } private val tv_start by lazy { find(R.id.tv_start) } private val tv_time by lazy { find(R.id.tv_time) } private val tv_passenger_num by lazy { find(R.id.tv_passenger_num) } private val tv_remark by lazy { find(R.id.tv_remark) } private val ll_receiver_goods_code by lazy { find(R.id.ll_receiver_goods_code) } private val tv_receiver_goods_code by lazy { find(R.id.tv_receiver_goods_code) } private val tv_state by lazy { find(R.id.tv_state) } private val cl_driver by lazy { find(R.id.cl_driver) } private val tv_name by lazy { find(R.id.tv_name) } private val tv_car by lazy { find(R.id.tv_car) } private val tv_car_info by lazy { find(R.id.tv_car_info) } private val tv_score by lazy { find(R.id.tv_score) } private val fl_reserve by lazy { find(R.id.fl_reserve) } private val tv_count by lazy { find(R.id.tv_count) } private val tv_progress by lazy { find(R.id.tv_progress) } private val line by lazy { find(R.id.line) } private val ll_progress by lazy { find(R.id.ll_progress) } private val rv_progress by lazy { find(R.id.rv_progress) } private val view_bg by lazy { find(R.id.view_bg) } private var consumerApi: ConsumerApi? = null //谷歌消费者sdk private var session: JourneySharingSession? = null private val progressList = arrayListOf() private val progressAdapter = ProgressAdapter(progressList) fun initClick() { iv_shuaxing.onClick { LogHelper.logRecord("刷新行驶数据orderId:${id} orderType:${type}") HttpManager.getOrderDrivingData(id, type) .request(this@TripActivity, false, { _, data -> LogHelper.logRecord("获取行驶数据成功orderId:${id} orderType:${type} data:${data}") data?.also { setTrippingUI(it) } }) { code, msg -> LogHelper.logRecord("获取行驶数据失败orderId:${id} orderType:${type} code:${code} msg:${msg}") } } tv_complain.onClick { order?.also { startActivity("id" to it.driverId) } } tv_action.setOnClickListener { if (order?.state == 1) { val tipDialog = TipDialog() tipDialog.arguments = bundleOf( "msg" to getString(R.string.取消订单吗), "ok" to getString( R.string.确定取消 ), "cancel" to getString(R.string.不取消) ) tipDialog.setCallback(object : TipDialog.OnClickCallback { override fun onOk() { showDialog() cancelOrder() } override fun onCancel() { } }) tipDialog.show(supportFragmentManager, "cancel") } } iv_call.setOnClickListener { order?.driverPhone?.takeIf { it.isNotEmpty() }?.also { callPhone(it) } } tv_110.setOnClickListener { phoneEmergency.takeIf { it.isNotEmpty() }?.also { callPhone(it) } } tv_service.setOnClickListener { phoneService.takeIf { it.isNotEmpty() }?.also { callPhone(it) } } iv_header_home.setOnClickListener { order?.also { startActivity("id" to it.driverId) } } iv_location.setOnClickListener { if (order?.state == 5 && vehicleLocation != null) { aMap?.animateCamera( CameraUpdateFactory.newLatLngZoom( LatLng( vehicleLocation!!.latLng.latitude, vehicleLocation!!.latLng.longitude ), 18f ) ) } else aMap?.animateCamera( CameraUpdateFactory.newLatLngZoom(IGoApplication.getCurrentLocation(), 18f) ) handler.removeMessages(4) consumerController?.isAutoCameraEnabled = false } tv_change_destination.setOnClickListener { startActivityForResult(2, "isModify" to true) } tv_cancel.setOnClickListener { order?.also { val tipDialog = TipDialog() tipDialog.arguments = bundleOf( "msg" to getString(R.string.未达取消), "ok" to getString(R.string.确认), "cancel" to getString(R.string.拒绝) ) tipDialog.setCallback(object : TipDialog.OnClickCallback { override fun onOk() { startActivityForResult( 1, "id" to id, "type" to type, "timeOut" to it.timeOutCancel, "driverTimeOut" to it.driverTimeOut, "state" to it.state ) } override fun onCancel() { } }) tipDialog.show(supportFragmentManager, "cancel") } } tv_progress.setOnClickListener { showDialog() HttpManager.queryTimeInfo(id).request(this) { _, data -> data?.apply { progressList.clear() progressList.add(getString(R.string.接单时间) + snatchOrderTime) progressList.add(getString(R.string.取件时间) + startServiceTime) progressList.add(getString(R.string.目前用时) + usedTime) progressList.add(getString(R.string.剩余时间) + remainingTime) progressList.add(getString(R.string.送达时间) + endServiceTime) progressList.add(getString(R.string.整体里程公里).format(allMileage)) progressList.add(getString(R.string.当前里程公里).format(mileage)) ll_progress.visible() } } } view_bg.setOnClickListener { ll_progress.gone() } } private fun cancelOrder() { var lat: Double var lon: Double if (vehicleLocation == null) { val currentLocation = IGoApplication.getCurrentLocation() lat = currentLocation.latitude lon = currentLocation.longitude } else { lat = vehicleLocation!!.latLng.latitude lon = vehicleLocation!!.latLng.longitude } LogHelper.logRecord("取消订单,不在继续等待订单被接单orderId:${id} orderType:${type}") HttpManager.cancelOrder(lat, lon, id, type).request(this, success = { _, _ -> myToast(getString(R.string.取消成功)) logRecord("取消订单成功orderId:${id} type:${type}") setResult(RESULT_OK) finish() }) { code, msg -> logRecord("取消订单失败orderId:${id} type:${type} code:${code} msg:${msg}") } } fun initView() { UltimateBar.with(this) .statusDark(true) .create().immersionBar() //沉浸状态栏 id = intent.getIntExtra("id", 0) type = intent.getIntExtra("type", Const.OrderType.TYPE_TAXI) logRecord("订单进行中orderId:${id} type:${type}") titleBar.addRightButton( getString(R.string.取消订单), onClickListener = View.OnClickListener { when (titleBar.getRightButton(0)?.text) { getString(R.string.取消订单) -> { order?.also { startActivityForResult( 1, "id" to id, "type" to type, "timeOut" to it.timeOutCancel, "driverTimeOut" to it.driverTimeOut, "state" to it.state ) } } getString(R.string.投诉司机) -> { tv_complain.callOnClick() } else -> startActivityForResult(2, "isModify" to true) } }) titleBar.getRightButton(0)?.gone() initConsumerSdk() enableMyLocation() app.addTripStateListener(this) getPhone() rv_progress.layoutManager = LinearLayoutManager(this) rv_progress.adapter = progressAdapter } private fun initConsumerSdk() { //谷歌乘客端api初始化 val consumerApiTask = ConsumerApi.initialize(this, Const.google_provider_id, JsonAuthTokenFactory()) consumerApiTask?.addOnSuccessListener { consumerApi: ConsumerApi -> Log.e(Const.GoogleTag, "ConsumerApi初始化成功") this.consumerApi = consumerApi } } private fun initMap() { val fragment = supportFragmentManager.findFragmentById(R.id.mMapView) as ConsumerMapFragment fragment.getConsumerGoogleMapAsync(object : ConsumerGoogleMap.ConsumerMapReadyCallback() { override fun onConsumerMapReady(consumerGoogleMap: ConsumerGoogleMap) { if (ActivityCompat.checkSelfPermission( this@TripActivity, Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission( this@TripActivity, Manifest.permission.ACCESS_COARSE_LOCATION ) != PackageManager.PERMISSION_GRANTED ) { logRecord("没有定位权限orderId:${id} type:${type}") return } consumerController = consumerGoogleMap.consumerController!! val markerOptions = MarkerOptions() markerOptions.icon(BitmapDescriptorFactory.fromResource(R.mipmap.location_car)) consumerController?.consumerMapStyle?.setMarkerStyleOptions( MarkerType.TRIP_VEHICLE, markerOptions ) // consumerController?.isAutoCameraEnabled = false aMap = consumerGoogleMap.apply { isMyLocationEnabled = true setPadding(0, dip(120), 0, dip(70)) uiSettings.isMyLocationButtonEnabled = false moveCamera(CameraUpdateFactory.newLatLng(IGoApplication.getCurrentLocation())) setOnCameraMoveStartedListener { if (it == GoogleMap.OnCameraMoveStartedListener.REASON_GESTURE) { handler.removeMessages(4) consumerController?.isAutoCameraEnabled = false } } //地图相机(视角)停止移动并变为空闲状态时触发回调 setOnCameraIdleListener { handler.sendEmptyMessageDelayed(4, 10000) } } getData() } }) } /** * Enables the My Location layer if the fine location permission has been granted. */ private fun enableMyLocation() { // 1. Check if permissions are granted, if so, enable the my location layer val subscribe = RxPermissions(this).request( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION ).subscribe { if (it) initMap() else { myToast(getString(R.string.没有权限)) logRecord("用户没有授予定位权限orderId:${id} type:${type}") } } } private fun getPhone() { val currentLocation = IGoApplication.getCurrentLocation() HttpManager.getPhone(currentLocation.latitude, currentLocation.longitude) .request(this, false) { _, data -> data?.forEach { if (it.type == 1) phoneEmergency = it.phone else if (it.type == 2) phoneService = it.phone } } } /** * 获取订单基础数据:起终点,订单状态等 */ private fun getData() { HttpManager.queryOrderInfo(id, type).request(this) { _, data -> order = data data?.let { if (session == null) { try { IGoApplication.tripId = it.tripId val tripName = "providers/i-go-odrd-testing/trips/${it.tripId}" val tripModelManager = consumerApi?.tripModelManager val tripModel = tripModelManager?.getTripModel(tripName) // Create a JourneySharingSession instance based on the TripModel. session = JourneySharingSession.createInstance(tripModel!!) // Add the JourneySharingSession instance on the map for updating the UI. consumerController?.showSession(session!!) tripModel.registerTripCallback(object : TripModelCallback() { override fun onTripStatusUpdate(p0: TripInfo, p1: Int) { super.onTripStatusUpdate(p0, p1) Log.e(Const.GoogleTag, "onTripStatusUpdate:${p1}") if (p1 == TripStatus.CANCELED || p1 == TripStatus.COMPLETE) { Log.e(Const.GoogleTag, "重置tripId") IGoApplication.tripId = "" } } override fun onTripUpdated(p0: TripInfo) { super.onTripUpdated(p0) Log.e( Const.GoogleTag, "onTripUpdated:${p0.vehicleLocation?.latLng}" ) vehicleLocation = p0.vehicleLocation } }) // Set refresh interval to 2 seconds. val tripOptions = TripModelOptions.builder().setRefreshIntervalMillis(2000).build() tripModel.tripModelOptions = tripOptions } catch (e: Exception) { e.printStackTrace() Log.e(Const.GoogleTag, e.message ?: "用户sdk初始化异常") } } if (type == Const.OrderType.TYPE_TAXI && it.endLat == 0.0) { tv_end.text = "——" fl_one_click.visible() } else tv_end.text = it.endAddress tv_start.text = it.startAddress tv_time.text = it.travelTime if (type == Const.OrderType.TYPE_CROSS_CITY) { tv_passenger_num.visible() tv_passenger_num.text = String.format("%d人 座位:%s号", it.peopleNumber, it.seatNumber) .replace(",", "号,") tv_remark.visibility = if (it.remark.isNotEmpty()) View.VISIBLE else View.GONE tv_remark.text = it.remark } if (type == Const.OrderType.TYPE_SAME_CITY) { tv_passenger_num.visible() tv_passenger_num.text = it.remark.ifEmpty { "——" } } if (it.state != 1) { //有司机 handler.removeMessages(0) handler.removeMessages(1) handler.removeMessages(2) titleBar.getRightButton(0)?.visible() tv_action.gone() if (type == TYPE_SPECIAL) tv_state.visible() else tv_state.gone() cl_driver.visible() order?.run { iv_header_home.setImageURI(driverAvatar) tv_name.text = driverName tv_car.text = licensePlate tv_car_info.text = "$brand·$carColor" tv_score.text = String.format("%.1f", score) tv_count.text = getString(R.string.单数, orderNum) } } setStateUI() } } } /** * 订单状态变化后的UI渲染,主要是起终点,标题等数据 */ private fun setStateUI() { iv_shuaxing.gone() ll_receiver_goods_code.isVisible = false order?.let { when (it.state) { 1 -> { logRecord("订单处于等待应答状态:${order}") titleBar.getRightButton(0)?.visible() titleBar.setTitle(getString(R.string.等待应答)) if (!handler.hasMessages(0)) handler.sendEmptyMessage(0) tv_action.visible() aMap?.animateCamera( CameraUpdateFactory.newLatLngZoom( LatLng(it.startLat, it.startLon), 18f ) ) queryEndPush() } 2 -> { logRecord( "订单处于等待${ if (type == TripOrderFragment.TYPE_LOGISTICS) { "取件" } else { "接驾" } }状态:${order}" ) if (type == TripOrderFragment.TYPE_LOGISTICS) titleBar.getRightButton(0)?.gone() titleBar.setTitle( getString( if (type == TripOrderFragment.TYPE_LOGISTICS) { ll_progress.gone() R.string.等待取件 } else R.string.等待接驾 ) ) fl_reserve.visibility = if (it.travelTime1.isNotEmpty() && it.travelTime1.parserTime() - System.currentTimeMillis() > (30L * 60 * 1000)) View.VISIBLE else View.GONE if (!handler.hasMessages(2)) handler.sendEmptyMessage(2) setMarker(LatLng(it.startLat, it.startLon), it.startAddress) getTrippingData() } 3 -> { logRecord( "订单处于司机前往${ if (type == TripOrderFragment.TYPE_LOGISTICS) { "取件点" } else { "接驾点" } }状态:${order}" ) titleBar.getRightButton(0)?.gone() titleBar.setTitle( getString( if (type == TripOrderFragment.TYPE_LOGISTICS) { ll_progress.gone() R.string.等待取件 } else R.string.等待接驾 ) ) if (!handler.hasMessages(2)) handler.sendEmptyMessage(2) setMarker(LatLng(it.startLat, it.startLon), it.startAddress) getTrippingData() } 4 -> { logRecord( "订单处于司机已到达${ if (type == TripOrderFragment.TYPE_LOGISTICS) { "取件点" } else { "接驾点" } }状态:${order}" ) titleBar.getRightButton(0)?.gone() println("隐藏取消订单") titleBar.setTitle(getString(R.string.司机已到达)) setMarker(LatLng(it.startLat, it.startLon), it.startAddress) if (!handler.hasMessages(1)) handler.sendEmptyMessage(1) getTrippingData() } 5 -> { logRecord( "订单处于司机${ if (type == TripOrderFragment.TYPE_LOGISTICS) { "送货中" } else { "服务中" } }状态:${order}" ) if (type == TYPE_SPECIAL) iv_shuaxing.visible() else iv_shuaxing.gone() titleBar.setTitle(getString(R.string.serving)) if (!handler.hasMessages(2)) handler.sendEmptyMessage(2) setMarker(LatLng(it.startLat, it.startLon)) setMarker(LatLng(it.endLat, it.endLon), isStart = false) getTrippingData() // tv_complain.visible() titleBar.getRightButton(0)?.visible() titleBar.getRightButton(0)?.text = getString(R.string.投诉司机) // if (type == Const.OrderType.TYPE_CROSS_CITY) //跨城行程中无法取消 //todo 原型没有修改终点 // titleBar.getRightButton(0)?.gone() // if (type == Const.OrderType.TYPE_CROSS_CITY||type == Const.OrderType.TYPE_SPECIAL) //专车行程中增加修改目的地 // titleBar.getRightButton(0)?.text = getString(R.string.修改终点) if (type == TYPE_SPECIAL) tv_change_destination.visible() else tv_change_destination.gone() if (type != Const.OrderType.TYPE_SAME_CITY) { tv_cancel.gone() } //客户反馈:快件单一旦司机开始行程后(取到快件送货途中)就不能再取消订单 titleBar.getRightButton(0)?.gone() aMap?.isMyLocationEnabled = false //行程中取消乘客定位 drawLine() ll_receiver_goods_code.isVisible = it.orderType == Const.OrderType.TYPE_SAME_CITY tv_receiver_goods_code.text = getString(R.string.取件码) + (it.code ?: "") } 10 -> { logRecord("订单处于已取消状态:${order}") if (it.cancelUserType != 1) { startActivity("id" to id, "type" to type) finish() } } else -> { logRecord("订单处于状态state=${it.state}:${order}") startActivity("id" to id, "type" to type) finish() } } } } private fun drawLine() { if (order?.orderType == 4) return // 快件订单不绘制 if (startMarker != null && endMarker != null) { LogHelper.logRecord("开始规划路线") AMapKit.initRouteLine( startMarker!!.position, endMarker!!.position, object : (MutableList, Float, Long) -> Unit { override fun invoke(p1: MutableList, p2: Float, p3: Long) { if (isFinishing || isDestroyed) { LogHelper.logRecord("订单行程页已经关闭") return } aMap?.also { markerLine?.remove() LogHelper.logRecord("开始绘制规划路线 ${p1.size}") markerLine = AMapKit.drawLine(this@TripActivity, it, p1) AMapKit.moveCamera(it, startMarker!!.position, endMarker!!.position) } } }) } } /** * 获取行程中的数据:主要是司机位置,订单状态变化,距离、时间等预算信息 */ private fun getTrippingData() { IGoApplication.intervalCount = 0 HttpManager.trippingInfo(id, type).request(this) { _, data -> data?.let { if (!it.lat.isNullOrEmpty()) setDriverMarker(LatLng(it.lat.toDouble(), it.lon?.toDoubleOrNull() ?: 0.0)) if (it.state != order?.state) //订单状态发生变化,重新拉取数据 getData() else { setTrippingUI(it) } } } } /** * 获取是否有司机接单 */ private fun queryEndPush() { IGoApplication.intervalCount = 0 HttpManager.queryEndPush(id, type).request(this) { _, data -> data?.let { if (it.state == 2) { //无人接单 noResponse(id) } } } } /** * 超时无应答 */ fun noResponse(id: Int) { if (isFinishing || isDestroyed || id != this.id) { return } lifecycleScope.launch { noticeCancelFlow.emit(true) } } /** * 行程中的UI,展示不同状态下的动态数据 * */ private fun setTrippingUI(it: TrippingInfo) { tv_state.isVisible = false //订单状态(1=待接单,2=待出发,3=待到达预约地点,4=待乘客上车,5=服务中,6=完成服务, // 7=待支付,8=待评价,9=已完成,10=已取消,11=改派中,12=取消待支付)加个15作为改派成功 when (order?.state) { 2, 3 -> { if (order?.orderType != 4) { // 非快件订单才显示订单状态 tv_state.isVisible = true if ((it.reservationMileage.isNullOrEmpty() || it.reservationMileage.toDouble() == 0.0) && (it.reservationTime.isNullOrEmpty() || it.reservationTime.toInt() == 0) ) { //无数据 tv_state.text = getString(R.string.司机接驾途中) } else { val time = getString(R.string.多少分钟, it.reservationTime) val distance = "%.2f".format(it.reservationMileage?.toDoubleOrNull() ?: 0.0) val s = getString(R.string.接驾中, distance, time) tv_state.text = SpanBuilder(s).color( this, s.indexOf(distance), s.indexOf(distance) + distance.length, R.color.colorPrimary ).color( this, s.indexOf(time), s.indexOf(time) + (it.reservationTime ?: "").length, R.color.colorPrimary ).build() } } } 4 -> { tv_state.isVisible = true } 5, 6 -> { if (order?.orderType != 4) { // 非快件订单才显示订单状态 tv_state.isVisible = true val mile2 = "%.2f".format(it.servedMileage?.toDoubleOrNull() ?: 0.0) val timeS = getString(R.string.多少分钟, it.laveTime) val s = getString(R.string.已服务时间, it.servedTime, mile2, it.laveMileage, timeS) tv_state.text = SpanBuilder(s).color( this, s.indexOf(it.servedTime ?: ""), s.indexOf(it.servedTime ?: "") + (it.servedTime ?: "").length, R.color.colorPrimary ) .color( this, s.indexOf(mile2), s.indexOf(mile2) + mile2.length, R.color.colorPrimary ) .color( this, s.indexOf(it.laveMileage ?: ""), s.indexOf(it.laveMileage ?: "") + (it.laveMileage ?: "").length, R.color.colorPrimary ) .color( this, s.lastIndexOf(timeS), s.lastIndexOf(timeS) + (it.laveTime ?: "").length, R.color.colorPrimary ) .build() } if (!it.orderPositionList.isNullOrEmpty()) { try { val list = gson.fromJson>( it.orderPositionList, object : TypeToken>() {}.type ) if (!list.isNullOrEmpty()) { aMap?.also { it -> oldDrivedRouteOverlay = newDrivedRouteOverlay val data = list.map { LatLng(it.lat, it.lon) }.toMutableList() if (driverMarker != null) { data.add(driverMarker!!.position) } newDrivedRouteOverlay = AMapKit.drawLine(this, it, data, cn.sinata.xldutils.R.color.textColor99) oldDrivedRouteOverlay?.remove() } } } catch (e: Exception) { e.printStackTrace() } } } } } private var startMarker: Marker? = null private var endMarker: Marker? = null var markerLine: Polyline? = null /** * @param isStart true:起点标记 false:终点标记 */ private fun setMarker(latLon: LatLng, content: CharSequence = "", isStart: Boolean = true) { val language = LanguageUtil.getLanguage() if (isStart) { val ic = when (language) { Const.Language.ENGLISH -> R.mipmap.starting_point_e Const.Language.CHINESE -> R.mipmap.starting_point else -> R.mipmap.starting_point_f } val icon = if (content.isEmpty()) BitmapDescriptorFactory.fromResource(ic) else { val view = layoutInflater.inflate(R.layout.marker_with_text_2, null, false) view.find(R.id.tv_content).text = content view.find(R.id.iv).imageResource = if (order?.state == 1) R.mipmap.icon_location else ic BitmapDescriptorFactory.fromBitmap(convertViewToBitmap(view)) } if (startMarker != null) { startMarker!!.position = latLon startMarker!!.setIcon(icon) } else { val options = MarkerOptions() options.position(latLon).icon(icon) startMarker = aMap?.addMarker(options) } } else { val ic = when (language) { Const.Language.ENGLISH -> R.mipmap.end_point_e Const.Language.CHINESE -> R.mipmap.end_point else -> R.mipmap.end_point_f } if (endMarker != null) { endMarker!!.position = latLon } else { val options = MarkerOptions() options.position(latLon).icon(BitmapDescriptorFactory.fromResource(ic)) endMarker = aMap?.addMarker(options) } } } private var driverMarker: Marker? = null //司机标记 private fun setDriverMarker(latLng: LatLng) { //现在使用谷歌套餐,不需要自己画司机位置 if (driverMarker == null) { val b = BitmapDescriptorFactory.fromResource(R.mipmap.location_car) val options = MarkerOptions() options.position(latLng) options.icon(b) driverMarker = aMap?.addMarker(options) } else { driverMarker?.position = latLng } } /** * handler定时器 * #what:0:等待应答 1:司机等待 2:其他状态时,判断socket是否在线,如果不在线就调仿socket接口 */ override fun handleMessage(msg: Message): Boolean { if (order == null) return true when (msg.what) { 0 -> { if (order?.state == 1) { val latLon = LatLng(order!!.startLat, order!!.startLon) val waittime = order!!.insertTime.parserTime() val s = System.currentTimeMillis() val i = (s - waittime).coerceAtLeast(0L) val c = getString(R.string.正在寻找车辆, i / 1000 / 60, i / 1000 % 60) setMarker( latLon, SpanBuilder(c).color(this, c.length - 6, c.length, R.color.colorRed).build() ) IGoApplication.intervalCount++ if (IGoApplication.intervalCount > 7) { queryEndPush() getTrippingData() } handler.sendEmptyMessageDelayed(0, 1000) } } 1 -> { if (order?.state == 4) { val waittime = order!!.arriveTime.parserTime() val s = System.currentTimeMillis() val i = Math.max(s - waittime, 0L) val c = getString(R.string.司机到达预约地点等待, i / 1000 / 60, i / 1000 % 60) tv_state.text = SpanBuilder(c).color(this, c.length - 5, c.length, R.color.colorPrimary) .build() IGoApplication.intervalCount++ if (IGoApplication.intervalCount > 7) { getTrippingData() } handler.sendEmptyMessageDelayed(1, 1000) } } 2 -> { IGoApplication.intervalCount++ if (IGoApplication.intervalCount > 7) { getTrippingData() } if (order?.state == 2) fl_reserve.visibility = if (order!!.travelTime1.isNotEmpty() && order!!.travelTime1.parserTime() - System.currentTimeMillis() > (30L * 60 * 1000)) View.VISIBLE else View.GONE handler.sendEmptyMessageDelayed(2, 1000) } 4 -> { consumerController?.isAutoCameraEnabled = true } } return true } override fun onStateChanged(id: Int, type: Int, state: Int) { //state if (id == order?.orderId && type == order?.orderType) { setResult(RESULT_OK) if (order?.driverId == 0 || order?.arriveTime.isNullOrEmpty() || state == 15 || state == 10) { //司机接单和到达预约点需要掉接口去获取司机信息以及等待开始时间 getData() } else { order?.state = state setStateUI() } } } override fun onTrippingChanged(info: TrippingInfo) { if (info.orderId == order?.orderId && info.orderType == order?.orderType) { setTrippingUI(info) } } override fun onAddressChanged(info: TrippingInfo) { Log.e("地址变更: ", (info.status == 2).toString()) if (info.orderId == order?.orderId && info.orderType == order?.orderType) { if (info.status == 2) { //司机同意修改目的地 LogHelper.logRecord("司机同意修改目的地:orderId:${id} orderType:${type}") getData() } if (info.status == 3) {//司机拒绝修改目的地 LogHelper.logRecord("司机拒绝修改目的地:orderId:${id} orderType:${type}") val tipDialog = TipDialog() tipDialog.arguments = bundleOf( "msg" to getString(R.string.拒绝变更), "ok" to getString(R.string.确认), "isAlert" to true ) tipDialog.setCallback(object : TipDialog.OnClickCallback { override fun onOk() { } override fun onCancel() { } }) tipDialog.show(supportFragmentManager, "refuse") } } } override fun onShuttleConfirm(id: Int, type: Int) { if (this.type == TYPE_SPECIAL && order?.state == 1) { this.type = type this.id = id getData() } } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (resultCode == RESULT_OK && data != null) { if (requestCode == 1) { setResult(RESULT_OK) finish() val money = data.getDoubleExtra("money", 0.0) if (money != 0.0) startActivity("id" to id, "type" to type) } else if (requestCode == 2) { //修改终点 LogHelper.logRecord("乘客变更目的地:orderId:${id} orderType:${type}") val lat = data.getDoubleExtra("lat", 0.0) val lon = data.getDoubleExtra("lon", 0.0) val address = data.getStringExtra("name") ?: "" val tipDialog = TipDialog() tipDialog.arguments = bundleOf( "msg" to getString(R.string.变更目的地提示), "ok" to getString(R.string.确认), "cancel" to getString(R.string.拒绝) ) tipDialog.setCallback(object : TipDialog.OnClickCallback { override fun onOk() { showDialog() HttpManager.updateEndAddress(address, lat, lon, id, type) .request(this@TripActivity, success = { _, _ -> LogHelper.logRecord("乘客变更目的地成功:orderId:${id} orderType:${type}") }) { code, msg -> LogHelper.logRecord("乘客变更目的地失败:orderId:${id} orderType:${type} code:${code} msg:${msg}") } } override fun onCancel() { } }) tipDialog.show(supportFragmentManager, "modify") } } } /** * 吧iew转化为bitmap * * @param view * @return */ fun convertViewToBitmap(view: View): Bitmap { view.isDrawingCacheEnabled = true view.measure( View.MeasureSpec.makeMeasureSpec( 0, View.MeasureSpec.UNSPECIFIED ), View.MeasureSpec.makeMeasureSpec( 0, View.MeasureSpec.UNSPECIFIED ) ) view.layout(0, 0, view.measuredWidth, view.measuredHeight) view.buildDrawingCache() val mCacheBitmap = view.drawingCache return Bitmap.createBitmap(mCacheBitmap) } override fun onResume() { super.onResume() getData() NettyClient.getInstance().checkNettyState() } override fun finish() { IGoApplication.tripId = "" super.finish() } override fun onDestroy() { handler.removeMessages(0) handler.removeMessages(1) handler.removeMessages(2) handler.removeMessages(3) app.removeTripStateListener(this) session?.stop() super.onDestroy() } override fun onBackPressHandle() { if (ll_progress.isVisible) ll_progress.gone() else super.onBackPressHandle() } }