package com.za.offline import android.content.Intent import android.provider.Settings import androidx.appcompat.app.AlertDialog import androidx.core.net.toUri import com.alibaba.fastjson.JSONObject import com.amap.api.services.core.LatLonPoint import com.amap.api.services.geocoder.GeocodeResult import com.amap.api.services.geocoder.GeocodeSearch import com.amap.api.services.geocoder.GeocodeSearch.OnGeocodeSearchListener import com.amap.api.services.geocoder.RegeocodeQuery import com.amap.api.services.geocoder.RegeocodeResult import com.blankj.utilcode.util.ActivityUtils import com.blankj.utilcode.util.ToastUtils import com.za.bean.request.SaveEleOrderRequest import com.za.bean.request.TaskFinishRequest import com.za.bean.request.TaskFinishResponse import com.za.bean.request.UpdateTaskBean import com.za.bean.request.UpdateTaskRequest import com.za.common.GlobalData import com.za.common.log.LogUtil import com.za.ext.toJson import com.za.net.BaseObserver import com.za.net.CommonMethod import com.za.net.RetrofitHelper import com.za.room.RoomHelper import com.za.water_marker.PhotoMarkerManager import com.za.water_marker.bean.PhotoMarkerInfo import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.core.Observable import io.reactivex.rxjava3.disposables.Disposable import io.reactivex.rxjava3.schedulers.Schedulers import java.io.File interface IOfflineListener { fun start() fun stop() fun uploadSuccess() fun uploadFailure(msg : String?) fun currentTask(offlineUpdateTaskBean : OfflineUpdateTaskBean) } object OfflineManager { private var isUploading = false private var uploadDispose : Disposable? = null private var offlineListener : IOfflineListener? = null private var currentTaskId : Int? = null fun addOfflineListener(offlineListener : IOfflineListener) { this.offlineListener = offlineListener } fun start(taskId : Int?) { if (checkOfflineIsComplete(taskId)) { return } if (currentTaskId != null && taskId == currentTaskId && isUploading) { return } if (! Settings.canDrawOverlays(GlobalData.application)) { openSystemAlertPermissionDialog() return } stop() OfflineService.addListener() offlineListener?.start() uploadDispose = Observable.interval(0, 5, java.util.concurrent.TimeUnit.SECONDS) .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe { if (! isUploading) { val list = RoomHelper.db?.offlineTaskDao()?.getOfflineTaskFromTaskId(taskId ?: 0) if (list.isNullOrEmpty()) { LogUtil.print("离线任务", "离线任务为空!!") stop() ToastUtils.showLong("离线任务上传完成") return@subscribe } doUpload(list[0]) } } } private fun stop() { uploadDispose?.dispose() uploadDispose = null isUploading = false currentTaskId = null offlineListener?.stop() offlineListener = null } private fun checkOfflineIsComplete(taskId : Int?) : Boolean { val list = RoomHelper.db?.offlineTaskDao()?.getOfflineTaskFromTaskId(taskId ?: 0) LogUtil.print("离线任务列表", "${list.toJson()}") return list.isNullOrEmpty() } private fun doUpload(offlineUpdateTaskBean : OfflineUpdateTaskBean) { offlineListener?.currentTask(offlineUpdateTaskBean) currentTaskId = offlineUpdateTaskBean.taskId when (offlineUpdateTaskBean.offlineType) { 1 -> uploadTask(offlineUpdateTaskBean) 2 -> uploadOrderImage(offlineUpdateTaskBean) 3 -> uploadEleWorkOrder(offlineUpdateTaskBean) 4 -> uploadEleDamageImage(offlineUpdateTaskBean) 5 -> uploadCustomerSignImage(offlineUpdateTaskBean) 6 -> uploadAcceptPeopleSignImage(offlineUpdateTaskBean) 7 -> uploadServicePeopleSignImage(offlineUpdateTaskBean) 8 -> taskFinish(offlineUpdateTaskBean) } } private fun uploadTask(offlineUpdateTaskBean : OfflineUpdateTaskBean) { isUploading = true val updateTaskRequest = UpdateTaskRequest(type = offlineUpdateTaskBean.type, taskId = offlineUpdateTaskBean.taskId, userId = offlineUpdateTaskBean.userId, vehicleId = offlineUpdateTaskBean.vehicleId, currentState = offlineUpdateTaskBean.currentState, operateTime = offlineUpdateTaskBean.operateTime, lat = offlineUpdateTaskBean.updateTaskLat, lng = offlineUpdateTaskBean.updateTaskLng, address = offlineUpdateTaskBean.updateTaskAddress, offlineMode = offlineUpdateTaskBean.offlineMode, flowType = offlineUpdateTaskBean.flowType, success = offlineUpdateTaskBean.success, templatePhotoInfoList = offlineUpdateTaskBean.templatePhotoInfoList) RetrofitHelper.getDefaultService().updateTask(updateTaskRequest) .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()) .subscribe(object : BaseObserver() { override fun doSuccess(it : UpdateTaskBean?) { RoomHelper.db?.offlineTaskDao() ?.deleteOfflineTaskFromId(offlineUpdateTaskBean.primaryId ?: 0) isUploading = false offlineListener?.uploadSuccess() LogUtil.print("离线任务", "success=$it request=${updateTaskRequest.toJson()}") } override fun doFailure(code : Int, msg : String?) { isUploading = false offlineListener?.uploadFailure(msg) LogUtil.print("离线任务", "uploadTask failed==${offlineUpdateTaskBean.toJson()}") } }) } private fun uploadOrderImage(offlineUpdateTaskBean : OfflineUpdateTaskBean) { isUploading = true var file = File(offlineUpdateTaskBean.photoLocalWaterMarkerPath ?: "") if (! file.exists()) { offlineListener?.uploadFailure("图片未找到!") LogUtil.print("离线任务 uploadOrderImage", "uploadTask failed==${offlineUpdateTaskBean.toJson()}") RoomHelper.db?.offlineTaskDao() ?.deleteOfflineTaskFromId(offlineUpdateTaskBean.primaryId ?: 0) isUploading = false return } if (offlineUpdateTaskBean.imageAddress.isNullOrBlank() && (offlineUpdateTaskBean.imageLat != null && offlineUpdateTaskBean.imageLat != 0f && offlineUpdateTaskBean.imageLng != null && offlineUpdateTaskBean.imageLng != 0f)) { geoCoder(offlineUpdateTaskBean.imageLat.toDouble(), offlineUpdateTaskBean.imageLng.toDouble(), success = { it -> val photoMarkerInfo = PhotoMarkerInfo(offlineUpdateTaskBean.needWater, needShowPhoneBrand = offlineUpdateTaskBean.needPhoneBrand, path = offlineUpdateTaskBean.photoLocalWaterMarkerPath, from = "(离线)", lat = offlineUpdateTaskBean.imageLat.toDouble(), lng = offlineUpdateTaskBean.imageLng.toDouble(), address = it, time = offlineUpdateTaskBean.time, driverName = GlobalData.driverInfo?.userName, taskCode = offlineUpdateTaskBean.taskCode) val offlineTemp = offlineUpdateTaskBean.copy(imageAddress = it) file = File(PhotoMarkerManager.addPhotoMarker(ActivityUtils.getTopActivity(), photoMarkerInfo)) CommonMethod.uploadImage(file = file, success = { val item = RoomHelper.db?.offlineTaskDao() ?.getRecentOfflineTask(offlineTemp.taskId ?: 0)?.get(0) if (item == null) { offlineListener?.uploadFailure(it) isUploading = false return@uploadImage } LogUtil.print("离线任务 getRecentOfflineTask", "success=${item.toJson()}") val list = item.templatePhotoInfoList?.toMutableList() val jsonObject = JSONObject() jsonObject["realTakePhotoTime"] = offlineTemp.realTakePhotoTime ?: "" jsonObject["photoSource"] = offlineTemp.photoSource jsonObject["path"] = it jsonObject["time"] = offlineTemp.time jsonObject["lat"] = offlineTemp.imageLat jsonObject["lng"] = offlineTemp.imageLng jsonObject["address"] = offlineTemp.imageAddress list?.set(offlineTemp.imageIndex ?: 0, jsonObject.toJSONString()) val temp = item.copy(templatePhotoInfoList = list?.toList()) RoomHelper.db?.offlineTaskDao()?.update(temp) RoomHelper.db?.offlineTaskDao() ?.deleteOfflineTaskFromId(offlineTemp.primaryId ?: 0) isUploading = false offlineListener?.uploadSuccess() LogUtil.print("离线任务 逆地理 uploadOrderImage", "success=$it request=${offlineUpdateTaskBean.toJson()}") }, failed = { RoomHelper.db?.offlineTaskDao()?.update(offlineTemp) offlineListener?.uploadFailure(it) isUploading = false }) }, failed = { offlineListener?.uploadFailure(it) isUploading = false }) } else { CommonMethod.uploadImage(file = file, success = { val item = RoomHelper.db?.offlineTaskDao() ?.getRecentOfflineTask(offlineUpdateTaskBean.taskId ?: 0)?.get(0) if (item == null) { offlineListener?.uploadFailure(it) isUploading = false return@uploadImage } LogUtil.print("离线任务 getRecentOfflineTask", "success=${item.toJson()}") val list = item.templatePhotoInfoList?.toMutableList() val jsonObject = JSONObject() jsonObject["realTakePhotoTime"] = offlineUpdateTaskBean.realTakePhotoTime ?: "" jsonObject["photoSource"] = offlineUpdateTaskBean.photoSource jsonObject["path"] = it jsonObject["time"] = offlineUpdateTaskBean.time jsonObject["lat"] = offlineUpdateTaskBean.imageLat jsonObject["lng"] = offlineUpdateTaskBean.imageLng jsonObject["address"] = offlineUpdateTaskBean.imageAddress list?.set(offlineUpdateTaskBean.imageIndex ?: 0, jsonObject.toJSONString()) val temp = item.copy(templatePhotoInfoList = list?.toList()) RoomHelper.db?.offlineTaskDao()?.update(temp) RoomHelper.db?.offlineTaskDao() ?.deleteOfflineTaskFromId(offlineUpdateTaskBean.primaryId ?: 0) isUploading = false offlineListener?.uploadSuccess() LogUtil.print("离线任务 uploadOrderImage", "success=$it request=${offlineUpdateTaskBean.toJson()}") }, failed = { offlineListener?.uploadFailure(it) isUploading = false }) } } private fun uploadEleDamageImage(offlineUpdateTaskBean : OfflineUpdateTaskBean) { isUploading = true val file = File(offlineUpdateTaskBean.imageLocalPath ?: "") if (! file.exists()) { offlineListener?.uploadFailure("图片未找到!") LogUtil.print("离线任务 uploadEleDamageImage", "failed==${offlineUpdateTaskBean.toJson()}") RoomHelper.db?.offlineTaskDao() ?.deleteOfflineTaskFromId(offlineUpdateTaskBean.primaryId ?: 0) isUploading = false return } CommonMethod.uploadImage(file = file, success = { val item = RoomHelper.db?.offlineTaskDao() ?.getRecentOfflineEle(offlineUpdateTaskBean.taskId ?: 0)?.get(0) if (item == null) { offlineListener?.uploadFailure(it) isUploading = false return@uploadImage } LogUtil.print("离线任务 getRecentOfflineEle", "success=${item.toJson()}") val list = item.damageFileList?.toMutableList() list?.set(offlineUpdateTaskBean.imageIndex ?: 0, it) val temp = item.copy(templatePhotoInfoList = list?.toList()) RoomHelper.db?.offlineTaskDao()?.update(temp) RoomHelper.db?.offlineTaskDao() ?.deleteOfflineTaskFromId(offlineUpdateTaskBean.primaryId ?: 0) isUploading = false offlineListener?.uploadSuccess() LogUtil.print("离线任务 uploadEleDamageImage", "success=$it request=${offlineUpdateTaskBean.toJson()}") }, failed = { offlineListener?.uploadFailure(it) isUploading = false }) } private fun uploadEleWorkOrder(offlineUpdateTaskBean : OfflineUpdateTaskBean) { val saveEleOrderRequest = SaveEleOrderRequest(state = offlineUpdateTaskBean.eleState, userOrderId = offlineUpdateTaskBean.userOrderId, taskOrderId = offlineUpdateTaskBean.taskId, damageFileList = offlineUpdateTaskBean.damageFileList, hasDamage = offlineUpdateTaskBean.hasDamage, hasSuccess = offlineUpdateTaskBean.hasSuccess, customerSignPath = offlineUpdateTaskBean.customerSignPath, recipientSignPath = offlineUpdateTaskBean.recipientSignPath, waitstaffSignPath = offlineUpdateTaskBean.waitstaffSignPath, offlineMode = 1, userOrderCode = offlineUpdateTaskBean.userOrderCode, lat = offlineUpdateTaskBean.eleLat, lng = offlineUpdateTaskBean.eleLng, tyreNumber = offlineUpdateTaskBean.tyreNumber, isFinish = offlineUpdateTaskBean.isFinish) LogUtil.print("离线数据 eleSign_check request", saveEleOrderRequest.toJson() ?: "") RetrofitHelper.getDefaultService().saveElectronOrder(saveEleOrderRequest) .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()) .subscribe(object : BaseObserver() { override fun doSuccess(it : String?) { RoomHelper.db?.offlineTaskDao() ?.deleteOfflineTaskFromId(offlineUpdateTaskBean.primaryId ?: 0) isUploading = false offlineListener?.uploadSuccess() LogUtil.print("离线任务 uploadEleWorkOrder", "success=$it request=${offlineUpdateTaskBean.toJson()}") } override fun doFailure(code : Int, msg : String?) { offlineListener?.uploadFailure(msg) isUploading = false } }) } private fun uploadCustomerSignImage(offlineUpdateTaskBean : OfflineUpdateTaskBean) { isUploading = true val file = File(offlineUpdateTaskBean.imageLocalPath ?: "") if (! file.exists()) { offlineListener?.uploadFailure("图片未找到!") LogUtil.print("离线任务 uploadCustomerSignImage", "failed==${offlineUpdateTaskBean.toJson()}") RoomHelper.db?.offlineTaskDao() ?.deleteOfflineTaskFromId(offlineUpdateTaskBean.primaryId ?: 0) isUploading = false return } CommonMethod.uploadImage(file = file, success = { it -> val item = RoomHelper.db?.offlineTaskDao() ?.getRecentOfflineEle(offlineUpdateTaskBean.taskId ?: 0)?.get(0) if (item == null) { offlineListener?.uploadFailure(it) isUploading = false return@uploadImage } LogUtil.print("离线任务 uploadCustomerSignImage getRecentOfflineEle", "success=${item.toJson()}") RoomHelper.db?.offlineTaskDao()?.update(item.copy(customerSignPath = it)) RoomHelper.db?.offlineTaskDao() ?.deleteOfflineTaskFromId(offlineUpdateTaskBean.primaryId ?: 0) RoomHelper.db?.eleWorkOrderDao()?.getEleWorkOrder(offlineUpdateTaskBean.taskId ?: 0) ?.copy(serverCustomSignPath = it)?.let { RoomHelper.db?.eleWorkOrderDao()?.update(it) } isUploading = false offlineListener?.uploadSuccess() LogUtil.print("离线任务 uploadCustomerSignImage", "success=$it request=${offlineUpdateTaskBean.toJson()}") }, failed = { offlineListener?.uploadFailure(it) isUploading = false }) } private fun uploadAcceptPeopleSignImage(offlineUpdateTaskBean : OfflineUpdateTaskBean) { isUploading = true val file = File(offlineUpdateTaskBean.imageLocalPath ?: "") if (! file.exists()) { offlineListener?.uploadFailure("图片未找到!") LogUtil.print("离线任务 uploadCustomerSignImage", "failed==${offlineUpdateTaskBean.toJson()}") RoomHelper.db?.offlineTaskDao() ?.deleteOfflineTaskFromId(offlineUpdateTaskBean.primaryId ?: 0) isUploading = false return } CommonMethod.uploadImage(file = file, success = { it -> val item = RoomHelper.db?.offlineTaskDao() ?.getRecentOfflineEle(offlineUpdateTaskBean.taskId ?: 0)?.get(0) if (item == null) { offlineListener?.uploadFailure(it) isUploading = false return@uploadImage } LogUtil.print("离线任务 uploadAcceptPeopleSignImage getRecentOfflineEle", "success=${item.toJson()}") RoomHelper.db?.offlineTaskDao()?.update(item.copy(recipientSignPath = it)) RoomHelper.db?.offlineTaskDao() ?.deleteOfflineTaskFromId(offlineUpdateTaskBean.primaryId ?: 0) RoomHelper.db?.eleWorkOrderDao()?.getEleWorkOrder(offlineUpdateTaskBean.taskId ?: 0) ?.copy(serverAcceptCarSignPath = it)?.let { RoomHelper.db?.eleWorkOrderDao()?.update(it) } isUploading = false offlineListener?.uploadSuccess() LogUtil.print("离线任务 uploadAcceptPeopleSignImage", "success=$it request=${offlineUpdateTaskBean.toJson()}") }, failed = { offlineListener?.uploadFailure(it) isUploading = false }) } private fun uploadServicePeopleSignImage(offlineUpdateTaskBean : OfflineUpdateTaskBean) { isUploading = true val file = File(offlineUpdateTaskBean.imageLocalPath ?: "") if (! file.exists()) { offlineListener?.uploadFailure("图片未找到!") LogUtil.print("离线任务 uploadCustomerSignImage", "failed==${offlineUpdateTaskBean.toJson()}") RoomHelper.db?.offlineTaskDao() ?.deleteOfflineTaskFromId(offlineUpdateTaskBean.primaryId ?: 0) isUploading = false return } CommonMethod.uploadImage(file = file, success = { it -> val item = RoomHelper.db?.offlineTaskDao() ?.getRecentOfflineEle(offlineUpdateTaskBean.taskId ?: 0)?.get(0) if (item == null) { offlineListener?.uploadFailure(it) isUploading = false return@uploadImage } LogUtil.print("离线任务 uploadCustomerSignImage getRecentOfflineEle", "success=${item.toJson()}") RoomHelper.db?.offlineTaskDao()?.update(item.copy(waitstaffSignPath = it)) RoomHelper.db?.offlineTaskDao() ?.deleteOfflineTaskFromId(offlineUpdateTaskBean.primaryId ?: 0) RoomHelper.db?.eleWorkOrderDao()?.getEleWorkOrder(offlineUpdateTaskBean.taskId ?: 0) ?.copy(serverServicePeopleSignPath = it)?.let { RoomHelper.db?.eleWorkOrderDao()?.update(it) } isUploading = false offlineListener?.uploadSuccess() LogUtil.print("离线任务 uploadCustomerSignImage", "success=$it request=${offlineUpdateTaskBean.toJson()}") }, failed = { offlineListener?.uploadFailure(it) isUploading = false }) } private fun taskFinish(offlineUpdateTaskBean : OfflineUpdateTaskBean) { isUploading = true val taskFinishRequest = TaskFinishRequest( operateTime = offlineUpdateTaskBean.operateTime?.toLong(), lat = offlineUpdateTaskBean.updateTaskLat, userOrderId = offlineUpdateTaskBean.userOrderId, lng = offlineUpdateTaskBean.updateTaskLng, ) RetrofitHelper.getDefaultService().taskFinish(taskFinishRequest) .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()) .subscribe(object : BaseObserver() { override fun doSuccess(it : TaskFinishResponse?) { RoomHelper.db?.offlineTaskDao() ?.deleteOfflineTaskFromId(offlineUpdateTaskBean.primaryId ?: 0) isUploading = false offlineListener?.uploadSuccess() LogUtil.print("离线任务", "success=$it request=${taskFinishRequest.toJson()}") } override fun doFailure(code : Int, msg : String?) { isUploading = false offlineListener?.uploadFailure(msg) LogUtil.print("离线任务", "uploadTask failed==${offlineUpdateTaskBean.toJson()}") } }) } } //打开系统悬浮窗权限 private fun openSystemAlertPermissionDialog() { val context = ActivityUtils.getTopActivity() val alertdialog = AlertDialog.Builder(ActivityUtils.getTopActivity()).setTitle("提示") .setMessage("当前应用缺少【悬浮窗】必要权限。\n\n请点击\"设置\"-\"权限\"-打开所需权限。") .setCancelable(false).setPositiveButton("设置") { _, _ -> val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, "package:${context.packageName}".toUri()) intent.data = ("package:" + ActivityUtils.getTopActivity().packageName).toUri() ActivityUtils.getTopActivity().startActivity(intent) } alertdialog.show() } //逆地址编码 private fun geoCoder(lat : Double, lng : Double, success : (String) -> Unit, failed : (String) -> Unit = {}) { val geocoderSearch = GeocodeSearch(ActivityUtils.getTopActivity().application) val query = RegeocodeQuery(LatLonPoint(lat, lng), 200f, GeocodeSearch.AMAP) geocoderSearch.getFromLocationAsyn(query) geocoderSearch.setOnGeocodeSearchListener(object : OnGeocodeSearchListener { override fun onRegeocodeSearched(regeocodeResult : RegeocodeResult, i : Int) { if (i == 1000) { success(regeocodeResult.regeocodeAddress.formatAddress) LogUtil.print("离线任务 singleLocation 逆地理编码", regeocodeResult.regeocodeAddress.formatAddress) } else { failed("地址获取失败") LogUtil.print("singleLocation 逆地理失败 ", regeocodeResult.toString()) } } override fun onGeocodeSearched(geocodeResult : GeocodeResult, i : Int) {} }) }