diff --git a/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt new file mode 100644 index 0000000..40b3660 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt @@ -0,0 +1,28 @@ +package com.casic.br.ktd.extensions + +import com.amap.api.maps.model.LatLng +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.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.listener.OnGeocodeSearchListener + +private val geocoderSearch by lazy { GeocodeSearch(BaseApplication.get()) } + +fun LatLng.toChineseAddress(listener: OnGeocodeSearchListener) { + val queryParam = RegeocodeQuery( + LatLonPoint(this.latitude, this.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + listener.onRegionCodeSearched(regeocodeResult.regeocodeAddress.formatAddress) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt new file mode 100644 index 0000000..40b3660 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt @@ -0,0 +1,28 @@ +package com.casic.br.ktd.extensions + +import com.amap.api.maps.model.LatLng +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.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.listener.OnGeocodeSearchListener + +private val geocoderSearch by lazy { GeocodeSearch(BaseApplication.get()) } + +fun LatLng.toChineseAddress(listener: OnGeocodeSearchListener) { + val queryParam = RegeocodeQuery( + LatLonPoint(this.latitude, this.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + listener.onRegionCodeSearched(regeocodeResult.regeocodeAddress.formatAddress) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index 36af820..e090122 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -1,9 +1,9 @@ package com.casic.br.ktd.extensions import android.content.Context +import com.casic.br.ktd.listener.OnImageCompressListener import com.casic.br.ktd.model.ErrorMessageModel import com.casic.br.ktd.utils.LocaleConstant -import com.casic.br.ktd.utils.OnImageCompressListener import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.createCompressImageDir @@ -14,7 +14,8 @@ import top.zibin.luban.OnCompressListener import java.io.File import java.text.SimpleDateFormat -import java.util.* +import java.util.Date +import java.util.Locale import java.util.regex.Pattern diff --git a/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt new file mode 100644 index 0000000..40b3660 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt @@ -0,0 +1,28 @@ +package com.casic.br.ktd.extensions + +import com.amap.api.maps.model.LatLng +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.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.listener.OnGeocodeSearchListener + +private val geocoderSearch by lazy { GeocodeSearch(BaseApplication.get()) } + +fun LatLng.toChineseAddress(listener: OnGeocodeSearchListener) { + val queryParam = RegeocodeQuery( + LatLonPoint(this.latitude, this.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + listener.onRegionCodeSearched(regeocodeResult.regeocodeAddress.formatAddress) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index 36af820..e090122 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -1,9 +1,9 @@ package com.casic.br.ktd.extensions import android.content.Context +import com.casic.br.ktd.listener.OnImageCompressListener import com.casic.br.ktd.model.ErrorMessageModel import com.casic.br.ktd.utils.LocaleConstant -import com.casic.br.ktd.utils.OnImageCompressListener import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.createCompressImageDir @@ -14,7 +14,8 @@ import top.zibin.luban.OnCompressListener import java.io.File import java.text.SimpleDateFormat -import java.util.* +import java.util.Date +import java.util.Locale import java.util.regex.Pattern diff --git a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt index 40b27b1..a8d1e7a 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt @@ -2,31 +2,55 @@ import android.graphics.Color import android.os.Bundle +import android.os.Handler +import android.os.Message import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.model.BitmapDescriptorFactory import com.amap.api.maps.model.CameraPosition import com.amap.api.maps.model.LatLng +import com.amap.api.maps.model.Marker import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.PolylineOptions import com.casic.br.ktd.R import com.casic.br.ktd.databinding.FragmentHomeBinding +import com.casic.br.ktd.extensions.toChineseAddress +import com.casic.br.ktd.listener.OnGeocodeSearchListener +import com.casic.br.ktd.model.DeviceListModel +import com.casic.br.ktd.model.VehicleListModel +import com.casic.br.ktd.utils.LocaleConstant +import com.casic.br.ktd.vm.DeviceViewModel +import com.casic.br.ktd.vm.VehicleViewModel import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.utils.SaveKeyValues +import com.pengxh.kt.lite.utils.WeakReferenceHandler +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton -class HomePageFragment : KotlinBaseFragment() { +class HomePageFragment : KotlinBaseFragment(), AMap.OnMarkerClickListener, + AMap.InfoWindowAdapter, Handler.Callback { + + private val kTag = "HomePageFragment" + private lateinit var vehicleViewModel: VehicleViewModel + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private lateinit var weakReferenceHandler: WeakReferenceHandler + private var isInfoWindowShow = false + private val handlerVehicleCode = 2023082501 + private val handlerDeviceCode = 2023082502 override fun initViewBinding( - inflater: LayoutInflater, - container: ViewGroup? + inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { return FragmentHomeBinding.inflate(inflater, container, false) } - private lateinit var aMap: AMap - override fun initOnCreate(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -36,6 +60,143 @@ uiSettings.isScaleControlsEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isRotateGesturesEnabled = false//不许地图随手势旋转角度 + // 点击marker弹出自定义popup + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) + + weakReferenceHandler = WeakReferenceHandler(this) + + vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] + vehicleViewModel.getVehicles() + vehicleViewModel.vehicleList.observe(this) { + if (it.code == 200) { + if (it.data.rows.isNotEmpty()) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerVehicleCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + deviceViewModel.deviceList.observe(this) { + if (it.code == 200) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerDeviceCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + handlerVehicleCode -> { + val vehicleModel = msg.obj as VehicleListModel.DataModel.RowsModel + + SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, vehicleModel.carPlate) + SaveKeyValues.putValue(LocaleConstant.CAR_ID, vehicleModel.id) + + val marker = if (vehicleModel.status == "1") { + //在线 + R.mipmap.vehicle_on + } else { + //离线 + R.mipmap.vehicle_on + } + + val latLng = LatLng( + vehicleModel.latitude.toDouble(), vehicleModel.longitude.toDouble() + ) + addMarker(latLng, "Car", marker) + + /** + * 地图PopupWindow数据绑定 + * ****/ + if (isInfoWindowShow) { + windowTitleView.text = vehicleModel.carPlate + val state = if (vehicleModel.status == "1") { + "状态:在线" + } else { + "状态:离线" + } + carStateView.text = state + + timeView.text = "时间:${vehicleModel.ts}" + latLng.toChineseAddress(object : OnGeocodeSearchListener { + override fun onRegionCodeSearched(address: String) { + locationView.text = "位置:$address" + } + }) + } + } + + handlerDeviceCode -> { + if (isInfoWindowShow) { + val deviceModel = msg.obj as DeviceListModel.DataModel.RowsModel + + deviceModelView.text = "云台型号:${deviceModel.deviceModel}" + } + } + } + return true + } + + override fun onMarkerClick(marker: Marker?): Boolean { + //点击Marker显示自定义Popup + marker?.showInfoWindow() + return true + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + + private lateinit var windowTitleView: TextView + private lateinit var taskStateView: QMUIRoundButton + private lateinit var carStateView: TextView + private lateinit var deviceModelView: TextView + private lateinit var timeView: TextView + private lateinit var locationView: TextView + + override fun getInfoWindow(marker: Marker?): View { + isInfoWindowShow = true + + val v = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_car_window, null) + + windowTitleView = v.findViewById(R.id.windowTitleView) + taskStateView = v.findViewById(R.id.taskStateView) + val closeView = v.findViewById(R.id.closeView) + carStateView = v.findViewById(R.id.carStateView) + deviceModelView = v.findViewById(R.id.deviceModelView) + timeView = v.findViewById(R.id.timeView) + locationView = v.findViewById(R.id.locationView) + val routeView = v.findViewById(R.id.routeView) + + if (marker?.title == "Car") { + taskStateView.visibility = View.GONE + routeView.visibility = View.GONE + + vehicleViewModel.getVehicles() + + deviceViewModel.getDevices() + } else { + taskStateView.visibility = View.VISIBLE + routeView.visibility = View.VISIBLE + + routeView.setOnClickListener { + + } + } + + closeView.setOnClickListener { + marker?.hideInfoWindow() + isInfoWindowShow = false + } + return v } override fun initEvent() { @@ -44,9 +205,9 @@ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 1500, null) //设置起点 - addMarker(LatLng(39.914885, 116.272312), R.mipmap.start) + addMarker(LatLng(39.914885, 116.272312), "", R.mipmap.start) //设置终点 - addMarker(LatLng(39.914716, 116.265097), R.mipmap.end) + addMarker(LatLng(39.914716, 116.265097), "", R.mipmap.end) //瞄点画线 val latLngPoints = ArrayList() latLngPoints.add(LatLng(39.914885, 116.272312)) @@ -78,9 +239,10 @@ } - private fun addMarker(point: LatLng, res: Int) { + private fun addMarker(point: LatLng, type: String, res: Int) { val markerOption = MarkerOptions() markerOption.position(point) + markerOption.title(type) markerOption.icon(BitmapDescriptorFactory.fromResource(res)) aMap.addMarker(markerOption) } diff --git a/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt new file mode 100644 index 0000000..40b3660 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt @@ -0,0 +1,28 @@ +package com.casic.br.ktd.extensions + +import com.amap.api.maps.model.LatLng +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.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.listener.OnGeocodeSearchListener + +private val geocoderSearch by lazy { GeocodeSearch(BaseApplication.get()) } + +fun LatLng.toChineseAddress(listener: OnGeocodeSearchListener) { + val queryParam = RegeocodeQuery( + LatLonPoint(this.latitude, this.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + listener.onRegionCodeSearched(regeocodeResult.regeocodeAddress.formatAddress) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index 36af820..e090122 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -1,9 +1,9 @@ package com.casic.br.ktd.extensions import android.content.Context +import com.casic.br.ktd.listener.OnImageCompressListener import com.casic.br.ktd.model.ErrorMessageModel import com.casic.br.ktd.utils.LocaleConstant -import com.casic.br.ktd.utils.OnImageCompressListener import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.createCompressImageDir @@ -14,7 +14,8 @@ import top.zibin.luban.OnCompressListener import java.io.File import java.text.SimpleDateFormat -import java.util.* +import java.util.Date +import java.util.Locale import java.util.regex.Pattern diff --git a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt index 40b27b1..a8d1e7a 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt @@ -2,31 +2,55 @@ import android.graphics.Color import android.os.Bundle +import android.os.Handler +import android.os.Message import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.model.BitmapDescriptorFactory import com.amap.api.maps.model.CameraPosition import com.amap.api.maps.model.LatLng +import com.amap.api.maps.model.Marker import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.PolylineOptions import com.casic.br.ktd.R import com.casic.br.ktd.databinding.FragmentHomeBinding +import com.casic.br.ktd.extensions.toChineseAddress +import com.casic.br.ktd.listener.OnGeocodeSearchListener +import com.casic.br.ktd.model.DeviceListModel +import com.casic.br.ktd.model.VehicleListModel +import com.casic.br.ktd.utils.LocaleConstant +import com.casic.br.ktd.vm.DeviceViewModel +import com.casic.br.ktd.vm.VehicleViewModel import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.utils.SaveKeyValues +import com.pengxh.kt.lite.utils.WeakReferenceHandler +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton -class HomePageFragment : KotlinBaseFragment() { +class HomePageFragment : KotlinBaseFragment(), AMap.OnMarkerClickListener, + AMap.InfoWindowAdapter, Handler.Callback { + + private val kTag = "HomePageFragment" + private lateinit var vehicleViewModel: VehicleViewModel + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private lateinit var weakReferenceHandler: WeakReferenceHandler + private var isInfoWindowShow = false + private val handlerVehicleCode = 2023082501 + private val handlerDeviceCode = 2023082502 override fun initViewBinding( - inflater: LayoutInflater, - container: ViewGroup? + inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { return FragmentHomeBinding.inflate(inflater, container, false) } - private lateinit var aMap: AMap - override fun initOnCreate(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -36,6 +60,143 @@ uiSettings.isScaleControlsEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isRotateGesturesEnabled = false//不许地图随手势旋转角度 + // 点击marker弹出自定义popup + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) + + weakReferenceHandler = WeakReferenceHandler(this) + + vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] + vehicleViewModel.getVehicles() + vehicleViewModel.vehicleList.observe(this) { + if (it.code == 200) { + if (it.data.rows.isNotEmpty()) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerVehicleCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + deviceViewModel.deviceList.observe(this) { + if (it.code == 200) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerDeviceCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + handlerVehicleCode -> { + val vehicleModel = msg.obj as VehicleListModel.DataModel.RowsModel + + SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, vehicleModel.carPlate) + SaveKeyValues.putValue(LocaleConstant.CAR_ID, vehicleModel.id) + + val marker = if (vehicleModel.status == "1") { + //在线 + R.mipmap.vehicle_on + } else { + //离线 + R.mipmap.vehicle_on + } + + val latLng = LatLng( + vehicleModel.latitude.toDouble(), vehicleModel.longitude.toDouble() + ) + addMarker(latLng, "Car", marker) + + /** + * 地图PopupWindow数据绑定 + * ****/ + if (isInfoWindowShow) { + windowTitleView.text = vehicleModel.carPlate + val state = if (vehicleModel.status == "1") { + "状态:在线" + } else { + "状态:离线" + } + carStateView.text = state + + timeView.text = "时间:${vehicleModel.ts}" + latLng.toChineseAddress(object : OnGeocodeSearchListener { + override fun onRegionCodeSearched(address: String) { + locationView.text = "位置:$address" + } + }) + } + } + + handlerDeviceCode -> { + if (isInfoWindowShow) { + val deviceModel = msg.obj as DeviceListModel.DataModel.RowsModel + + deviceModelView.text = "云台型号:${deviceModel.deviceModel}" + } + } + } + return true + } + + override fun onMarkerClick(marker: Marker?): Boolean { + //点击Marker显示自定义Popup + marker?.showInfoWindow() + return true + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + + private lateinit var windowTitleView: TextView + private lateinit var taskStateView: QMUIRoundButton + private lateinit var carStateView: TextView + private lateinit var deviceModelView: TextView + private lateinit var timeView: TextView + private lateinit var locationView: TextView + + override fun getInfoWindow(marker: Marker?): View { + isInfoWindowShow = true + + val v = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_car_window, null) + + windowTitleView = v.findViewById(R.id.windowTitleView) + taskStateView = v.findViewById(R.id.taskStateView) + val closeView = v.findViewById(R.id.closeView) + carStateView = v.findViewById(R.id.carStateView) + deviceModelView = v.findViewById(R.id.deviceModelView) + timeView = v.findViewById(R.id.timeView) + locationView = v.findViewById(R.id.locationView) + val routeView = v.findViewById(R.id.routeView) + + if (marker?.title == "Car") { + taskStateView.visibility = View.GONE + routeView.visibility = View.GONE + + vehicleViewModel.getVehicles() + + deviceViewModel.getDevices() + } else { + taskStateView.visibility = View.VISIBLE + routeView.visibility = View.VISIBLE + + routeView.setOnClickListener { + + } + } + + closeView.setOnClickListener { + marker?.hideInfoWindow() + isInfoWindowShow = false + } + return v } override fun initEvent() { @@ -44,9 +205,9 @@ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 1500, null) //设置起点 - addMarker(LatLng(39.914885, 116.272312), R.mipmap.start) + addMarker(LatLng(39.914885, 116.272312), "", R.mipmap.start) //设置终点 - addMarker(LatLng(39.914716, 116.265097), R.mipmap.end) + addMarker(LatLng(39.914716, 116.265097), "", R.mipmap.end) //瞄点画线 val latLngPoints = ArrayList() latLngPoints.add(LatLng(39.914885, 116.272312)) @@ -78,9 +239,10 @@ } - private fun addMarker(point: LatLng, res: Int) { + private fun addMarker(point: LatLng, type: String, res: Int) { val markerOption = MarkerOptions() markerOption.position(point) + markerOption.title(type) markerOption.icon(BitmapDescriptorFactory.fromResource(res)) aMap.addMarker(markerOption) } diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt new file mode 100644 index 0000000..ad16496 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt @@ -0,0 +1,5 @@ +package com.casic.br.ktd.listener + +interface OnGeocodeSearchListener { + fun onRegionCodeSearched(address: String) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt new file mode 100644 index 0000000..40b3660 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt @@ -0,0 +1,28 @@ +package com.casic.br.ktd.extensions + +import com.amap.api.maps.model.LatLng +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.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.listener.OnGeocodeSearchListener + +private val geocoderSearch by lazy { GeocodeSearch(BaseApplication.get()) } + +fun LatLng.toChineseAddress(listener: OnGeocodeSearchListener) { + val queryParam = RegeocodeQuery( + LatLonPoint(this.latitude, this.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + listener.onRegionCodeSearched(regeocodeResult.regeocodeAddress.formatAddress) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index 36af820..e090122 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -1,9 +1,9 @@ package com.casic.br.ktd.extensions import android.content.Context +import com.casic.br.ktd.listener.OnImageCompressListener import com.casic.br.ktd.model.ErrorMessageModel import com.casic.br.ktd.utils.LocaleConstant -import com.casic.br.ktd.utils.OnImageCompressListener import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.createCompressImageDir @@ -14,7 +14,8 @@ import top.zibin.luban.OnCompressListener import java.io.File import java.text.SimpleDateFormat -import java.util.* +import java.util.Date +import java.util.Locale import java.util.regex.Pattern diff --git a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt index 40b27b1..a8d1e7a 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt @@ -2,31 +2,55 @@ import android.graphics.Color import android.os.Bundle +import android.os.Handler +import android.os.Message import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.model.BitmapDescriptorFactory import com.amap.api.maps.model.CameraPosition import com.amap.api.maps.model.LatLng +import com.amap.api.maps.model.Marker import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.PolylineOptions import com.casic.br.ktd.R import com.casic.br.ktd.databinding.FragmentHomeBinding +import com.casic.br.ktd.extensions.toChineseAddress +import com.casic.br.ktd.listener.OnGeocodeSearchListener +import com.casic.br.ktd.model.DeviceListModel +import com.casic.br.ktd.model.VehicleListModel +import com.casic.br.ktd.utils.LocaleConstant +import com.casic.br.ktd.vm.DeviceViewModel +import com.casic.br.ktd.vm.VehicleViewModel import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.utils.SaveKeyValues +import com.pengxh.kt.lite.utils.WeakReferenceHandler +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton -class HomePageFragment : KotlinBaseFragment() { +class HomePageFragment : KotlinBaseFragment(), AMap.OnMarkerClickListener, + AMap.InfoWindowAdapter, Handler.Callback { + + private val kTag = "HomePageFragment" + private lateinit var vehicleViewModel: VehicleViewModel + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private lateinit var weakReferenceHandler: WeakReferenceHandler + private var isInfoWindowShow = false + private val handlerVehicleCode = 2023082501 + private val handlerDeviceCode = 2023082502 override fun initViewBinding( - inflater: LayoutInflater, - container: ViewGroup? + inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { return FragmentHomeBinding.inflate(inflater, container, false) } - private lateinit var aMap: AMap - override fun initOnCreate(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -36,6 +60,143 @@ uiSettings.isScaleControlsEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isRotateGesturesEnabled = false//不许地图随手势旋转角度 + // 点击marker弹出自定义popup + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) + + weakReferenceHandler = WeakReferenceHandler(this) + + vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] + vehicleViewModel.getVehicles() + vehicleViewModel.vehicleList.observe(this) { + if (it.code == 200) { + if (it.data.rows.isNotEmpty()) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerVehicleCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + deviceViewModel.deviceList.observe(this) { + if (it.code == 200) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerDeviceCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + handlerVehicleCode -> { + val vehicleModel = msg.obj as VehicleListModel.DataModel.RowsModel + + SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, vehicleModel.carPlate) + SaveKeyValues.putValue(LocaleConstant.CAR_ID, vehicleModel.id) + + val marker = if (vehicleModel.status == "1") { + //在线 + R.mipmap.vehicle_on + } else { + //离线 + R.mipmap.vehicle_on + } + + val latLng = LatLng( + vehicleModel.latitude.toDouble(), vehicleModel.longitude.toDouble() + ) + addMarker(latLng, "Car", marker) + + /** + * 地图PopupWindow数据绑定 + * ****/ + if (isInfoWindowShow) { + windowTitleView.text = vehicleModel.carPlate + val state = if (vehicleModel.status == "1") { + "状态:在线" + } else { + "状态:离线" + } + carStateView.text = state + + timeView.text = "时间:${vehicleModel.ts}" + latLng.toChineseAddress(object : OnGeocodeSearchListener { + override fun onRegionCodeSearched(address: String) { + locationView.text = "位置:$address" + } + }) + } + } + + handlerDeviceCode -> { + if (isInfoWindowShow) { + val deviceModel = msg.obj as DeviceListModel.DataModel.RowsModel + + deviceModelView.text = "云台型号:${deviceModel.deviceModel}" + } + } + } + return true + } + + override fun onMarkerClick(marker: Marker?): Boolean { + //点击Marker显示自定义Popup + marker?.showInfoWindow() + return true + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + + private lateinit var windowTitleView: TextView + private lateinit var taskStateView: QMUIRoundButton + private lateinit var carStateView: TextView + private lateinit var deviceModelView: TextView + private lateinit var timeView: TextView + private lateinit var locationView: TextView + + override fun getInfoWindow(marker: Marker?): View { + isInfoWindowShow = true + + val v = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_car_window, null) + + windowTitleView = v.findViewById(R.id.windowTitleView) + taskStateView = v.findViewById(R.id.taskStateView) + val closeView = v.findViewById(R.id.closeView) + carStateView = v.findViewById(R.id.carStateView) + deviceModelView = v.findViewById(R.id.deviceModelView) + timeView = v.findViewById(R.id.timeView) + locationView = v.findViewById(R.id.locationView) + val routeView = v.findViewById(R.id.routeView) + + if (marker?.title == "Car") { + taskStateView.visibility = View.GONE + routeView.visibility = View.GONE + + vehicleViewModel.getVehicles() + + deviceViewModel.getDevices() + } else { + taskStateView.visibility = View.VISIBLE + routeView.visibility = View.VISIBLE + + routeView.setOnClickListener { + + } + } + + closeView.setOnClickListener { + marker?.hideInfoWindow() + isInfoWindowShow = false + } + return v } override fun initEvent() { @@ -44,9 +205,9 @@ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 1500, null) //设置起点 - addMarker(LatLng(39.914885, 116.272312), R.mipmap.start) + addMarker(LatLng(39.914885, 116.272312), "", R.mipmap.start) //设置终点 - addMarker(LatLng(39.914716, 116.265097), R.mipmap.end) + addMarker(LatLng(39.914716, 116.265097), "", R.mipmap.end) //瞄点画线 val latLngPoints = ArrayList() latLngPoints.add(LatLng(39.914885, 116.272312)) @@ -78,9 +239,10 @@ } - private fun addMarker(point: LatLng, res: Int) { + private fun addMarker(point: LatLng, type: String, res: Int) { val markerOption = MarkerOptions() markerOption.position(point) + markerOption.title(type) markerOption.icon(BitmapDescriptorFactory.fromResource(res)) aMap.addMarker(markerOption) } diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt new file mode 100644 index 0000000..ad16496 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt @@ -0,0 +1,5 @@ +package com.casic.br.ktd.listener + +interface OnGeocodeSearchListener { + fun onRegionCodeSearched(address: String) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt new file mode 100644 index 0000000..61104eb --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt @@ -0,0 +1,15 @@ +package com.casic.br.ktd.listener + +import java.io.File + +interface OnImageCompressListener { + /** + * Fired when a compression returns successfully, override to handle in your own code + */ + fun onSuccess(file: File) + + /** + * Fired when a compression fails to complete, override to handle in your own code + */ + fun onError(e: Throwable) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt new file mode 100644 index 0000000..40b3660 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt @@ -0,0 +1,28 @@ +package com.casic.br.ktd.extensions + +import com.amap.api.maps.model.LatLng +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.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.listener.OnGeocodeSearchListener + +private val geocoderSearch by lazy { GeocodeSearch(BaseApplication.get()) } + +fun LatLng.toChineseAddress(listener: OnGeocodeSearchListener) { + val queryParam = RegeocodeQuery( + LatLonPoint(this.latitude, this.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + listener.onRegionCodeSearched(regeocodeResult.regeocodeAddress.formatAddress) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index 36af820..e090122 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -1,9 +1,9 @@ package com.casic.br.ktd.extensions import android.content.Context +import com.casic.br.ktd.listener.OnImageCompressListener import com.casic.br.ktd.model.ErrorMessageModel import com.casic.br.ktd.utils.LocaleConstant -import com.casic.br.ktd.utils.OnImageCompressListener import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.createCompressImageDir @@ -14,7 +14,8 @@ import top.zibin.luban.OnCompressListener import java.io.File import java.text.SimpleDateFormat -import java.util.* +import java.util.Date +import java.util.Locale import java.util.regex.Pattern diff --git a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt index 40b27b1..a8d1e7a 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt @@ -2,31 +2,55 @@ import android.graphics.Color import android.os.Bundle +import android.os.Handler +import android.os.Message import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.model.BitmapDescriptorFactory import com.amap.api.maps.model.CameraPosition import com.amap.api.maps.model.LatLng +import com.amap.api.maps.model.Marker import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.PolylineOptions import com.casic.br.ktd.R import com.casic.br.ktd.databinding.FragmentHomeBinding +import com.casic.br.ktd.extensions.toChineseAddress +import com.casic.br.ktd.listener.OnGeocodeSearchListener +import com.casic.br.ktd.model.DeviceListModel +import com.casic.br.ktd.model.VehicleListModel +import com.casic.br.ktd.utils.LocaleConstant +import com.casic.br.ktd.vm.DeviceViewModel +import com.casic.br.ktd.vm.VehicleViewModel import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.utils.SaveKeyValues +import com.pengxh.kt.lite.utils.WeakReferenceHandler +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton -class HomePageFragment : KotlinBaseFragment() { +class HomePageFragment : KotlinBaseFragment(), AMap.OnMarkerClickListener, + AMap.InfoWindowAdapter, Handler.Callback { + + private val kTag = "HomePageFragment" + private lateinit var vehicleViewModel: VehicleViewModel + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private lateinit var weakReferenceHandler: WeakReferenceHandler + private var isInfoWindowShow = false + private val handlerVehicleCode = 2023082501 + private val handlerDeviceCode = 2023082502 override fun initViewBinding( - inflater: LayoutInflater, - container: ViewGroup? + inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { return FragmentHomeBinding.inflate(inflater, container, false) } - private lateinit var aMap: AMap - override fun initOnCreate(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -36,6 +60,143 @@ uiSettings.isScaleControlsEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isRotateGesturesEnabled = false//不许地图随手势旋转角度 + // 点击marker弹出自定义popup + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) + + weakReferenceHandler = WeakReferenceHandler(this) + + vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] + vehicleViewModel.getVehicles() + vehicleViewModel.vehicleList.observe(this) { + if (it.code == 200) { + if (it.data.rows.isNotEmpty()) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerVehicleCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + deviceViewModel.deviceList.observe(this) { + if (it.code == 200) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerDeviceCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + handlerVehicleCode -> { + val vehicleModel = msg.obj as VehicleListModel.DataModel.RowsModel + + SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, vehicleModel.carPlate) + SaveKeyValues.putValue(LocaleConstant.CAR_ID, vehicleModel.id) + + val marker = if (vehicleModel.status == "1") { + //在线 + R.mipmap.vehicle_on + } else { + //离线 + R.mipmap.vehicle_on + } + + val latLng = LatLng( + vehicleModel.latitude.toDouble(), vehicleModel.longitude.toDouble() + ) + addMarker(latLng, "Car", marker) + + /** + * 地图PopupWindow数据绑定 + * ****/ + if (isInfoWindowShow) { + windowTitleView.text = vehicleModel.carPlate + val state = if (vehicleModel.status == "1") { + "状态:在线" + } else { + "状态:离线" + } + carStateView.text = state + + timeView.text = "时间:${vehicleModel.ts}" + latLng.toChineseAddress(object : OnGeocodeSearchListener { + override fun onRegionCodeSearched(address: String) { + locationView.text = "位置:$address" + } + }) + } + } + + handlerDeviceCode -> { + if (isInfoWindowShow) { + val deviceModel = msg.obj as DeviceListModel.DataModel.RowsModel + + deviceModelView.text = "云台型号:${deviceModel.deviceModel}" + } + } + } + return true + } + + override fun onMarkerClick(marker: Marker?): Boolean { + //点击Marker显示自定义Popup + marker?.showInfoWindow() + return true + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + + private lateinit var windowTitleView: TextView + private lateinit var taskStateView: QMUIRoundButton + private lateinit var carStateView: TextView + private lateinit var deviceModelView: TextView + private lateinit var timeView: TextView + private lateinit var locationView: TextView + + override fun getInfoWindow(marker: Marker?): View { + isInfoWindowShow = true + + val v = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_car_window, null) + + windowTitleView = v.findViewById(R.id.windowTitleView) + taskStateView = v.findViewById(R.id.taskStateView) + val closeView = v.findViewById(R.id.closeView) + carStateView = v.findViewById(R.id.carStateView) + deviceModelView = v.findViewById(R.id.deviceModelView) + timeView = v.findViewById(R.id.timeView) + locationView = v.findViewById(R.id.locationView) + val routeView = v.findViewById(R.id.routeView) + + if (marker?.title == "Car") { + taskStateView.visibility = View.GONE + routeView.visibility = View.GONE + + vehicleViewModel.getVehicles() + + deviceViewModel.getDevices() + } else { + taskStateView.visibility = View.VISIBLE + routeView.visibility = View.VISIBLE + + routeView.setOnClickListener { + + } + } + + closeView.setOnClickListener { + marker?.hideInfoWindow() + isInfoWindowShow = false + } + return v } override fun initEvent() { @@ -44,9 +205,9 @@ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 1500, null) //设置起点 - addMarker(LatLng(39.914885, 116.272312), R.mipmap.start) + addMarker(LatLng(39.914885, 116.272312), "", R.mipmap.start) //设置终点 - addMarker(LatLng(39.914716, 116.265097), R.mipmap.end) + addMarker(LatLng(39.914716, 116.265097), "", R.mipmap.end) //瞄点画线 val latLngPoints = ArrayList() latLngPoints.add(LatLng(39.914885, 116.272312)) @@ -78,9 +239,10 @@ } - private fun addMarker(point: LatLng, res: Int) { + private fun addMarker(point: LatLng, type: String, res: Int) { val markerOption = MarkerOptions() markerOption.position(point) + markerOption.title(type) markerOption.icon(BitmapDescriptorFactory.fromResource(res)) aMap.addMarker(markerOption) } diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt new file mode 100644 index 0000000..ad16496 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt @@ -0,0 +1,5 @@ +package com.casic.br.ktd.listener + +interface OnGeocodeSearchListener { + fun onRegionCodeSearched(address: String) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt new file mode 100644 index 0000000..61104eb --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt @@ -0,0 +1,15 @@ +package com.casic.br.ktd.listener + +import java.io.File + +interface OnImageCompressListener { + /** + * Fired when a compression returns successfully, override to handle in your own code + */ + fun onSuccess(file: File) + + /** + * Fired when a compression fails to complete, override to handle in your own code + */ + fun onError(e: Throwable) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/model/PointModel.kt b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt new file mode 100644 index 0000000..ec2065d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt @@ -0,0 +1,3 @@ +package com.casic.br.ktd.model + +data class PointModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt new file mode 100644 index 0000000..40b3660 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt @@ -0,0 +1,28 @@ +package com.casic.br.ktd.extensions + +import com.amap.api.maps.model.LatLng +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.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.listener.OnGeocodeSearchListener + +private val geocoderSearch by lazy { GeocodeSearch(BaseApplication.get()) } + +fun LatLng.toChineseAddress(listener: OnGeocodeSearchListener) { + val queryParam = RegeocodeQuery( + LatLonPoint(this.latitude, this.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + listener.onRegionCodeSearched(regeocodeResult.regeocodeAddress.formatAddress) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index 36af820..e090122 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -1,9 +1,9 @@ package com.casic.br.ktd.extensions import android.content.Context +import com.casic.br.ktd.listener.OnImageCompressListener import com.casic.br.ktd.model.ErrorMessageModel import com.casic.br.ktd.utils.LocaleConstant -import com.casic.br.ktd.utils.OnImageCompressListener import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.createCompressImageDir @@ -14,7 +14,8 @@ import top.zibin.luban.OnCompressListener import java.io.File import java.text.SimpleDateFormat -import java.util.* +import java.util.Date +import java.util.Locale import java.util.regex.Pattern diff --git a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt index 40b27b1..a8d1e7a 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt @@ -2,31 +2,55 @@ import android.graphics.Color import android.os.Bundle +import android.os.Handler +import android.os.Message import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.model.BitmapDescriptorFactory import com.amap.api.maps.model.CameraPosition import com.amap.api.maps.model.LatLng +import com.amap.api.maps.model.Marker import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.PolylineOptions import com.casic.br.ktd.R import com.casic.br.ktd.databinding.FragmentHomeBinding +import com.casic.br.ktd.extensions.toChineseAddress +import com.casic.br.ktd.listener.OnGeocodeSearchListener +import com.casic.br.ktd.model.DeviceListModel +import com.casic.br.ktd.model.VehicleListModel +import com.casic.br.ktd.utils.LocaleConstant +import com.casic.br.ktd.vm.DeviceViewModel +import com.casic.br.ktd.vm.VehicleViewModel import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.utils.SaveKeyValues +import com.pengxh.kt.lite.utils.WeakReferenceHandler +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton -class HomePageFragment : KotlinBaseFragment() { +class HomePageFragment : KotlinBaseFragment(), AMap.OnMarkerClickListener, + AMap.InfoWindowAdapter, Handler.Callback { + + private val kTag = "HomePageFragment" + private lateinit var vehicleViewModel: VehicleViewModel + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private lateinit var weakReferenceHandler: WeakReferenceHandler + private var isInfoWindowShow = false + private val handlerVehicleCode = 2023082501 + private val handlerDeviceCode = 2023082502 override fun initViewBinding( - inflater: LayoutInflater, - container: ViewGroup? + inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { return FragmentHomeBinding.inflate(inflater, container, false) } - private lateinit var aMap: AMap - override fun initOnCreate(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -36,6 +60,143 @@ uiSettings.isScaleControlsEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isRotateGesturesEnabled = false//不许地图随手势旋转角度 + // 点击marker弹出自定义popup + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) + + weakReferenceHandler = WeakReferenceHandler(this) + + vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] + vehicleViewModel.getVehicles() + vehicleViewModel.vehicleList.observe(this) { + if (it.code == 200) { + if (it.data.rows.isNotEmpty()) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerVehicleCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + deviceViewModel.deviceList.observe(this) { + if (it.code == 200) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerDeviceCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + handlerVehicleCode -> { + val vehicleModel = msg.obj as VehicleListModel.DataModel.RowsModel + + SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, vehicleModel.carPlate) + SaveKeyValues.putValue(LocaleConstant.CAR_ID, vehicleModel.id) + + val marker = if (vehicleModel.status == "1") { + //在线 + R.mipmap.vehicle_on + } else { + //离线 + R.mipmap.vehicle_on + } + + val latLng = LatLng( + vehicleModel.latitude.toDouble(), vehicleModel.longitude.toDouble() + ) + addMarker(latLng, "Car", marker) + + /** + * 地图PopupWindow数据绑定 + * ****/ + if (isInfoWindowShow) { + windowTitleView.text = vehicleModel.carPlate + val state = if (vehicleModel.status == "1") { + "状态:在线" + } else { + "状态:离线" + } + carStateView.text = state + + timeView.text = "时间:${vehicleModel.ts}" + latLng.toChineseAddress(object : OnGeocodeSearchListener { + override fun onRegionCodeSearched(address: String) { + locationView.text = "位置:$address" + } + }) + } + } + + handlerDeviceCode -> { + if (isInfoWindowShow) { + val deviceModel = msg.obj as DeviceListModel.DataModel.RowsModel + + deviceModelView.text = "云台型号:${deviceModel.deviceModel}" + } + } + } + return true + } + + override fun onMarkerClick(marker: Marker?): Boolean { + //点击Marker显示自定义Popup + marker?.showInfoWindow() + return true + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + + private lateinit var windowTitleView: TextView + private lateinit var taskStateView: QMUIRoundButton + private lateinit var carStateView: TextView + private lateinit var deviceModelView: TextView + private lateinit var timeView: TextView + private lateinit var locationView: TextView + + override fun getInfoWindow(marker: Marker?): View { + isInfoWindowShow = true + + val v = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_car_window, null) + + windowTitleView = v.findViewById(R.id.windowTitleView) + taskStateView = v.findViewById(R.id.taskStateView) + val closeView = v.findViewById(R.id.closeView) + carStateView = v.findViewById(R.id.carStateView) + deviceModelView = v.findViewById(R.id.deviceModelView) + timeView = v.findViewById(R.id.timeView) + locationView = v.findViewById(R.id.locationView) + val routeView = v.findViewById(R.id.routeView) + + if (marker?.title == "Car") { + taskStateView.visibility = View.GONE + routeView.visibility = View.GONE + + vehicleViewModel.getVehicles() + + deviceViewModel.getDevices() + } else { + taskStateView.visibility = View.VISIBLE + routeView.visibility = View.VISIBLE + + routeView.setOnClickListener { + + } + } + + closeView.setOnClickListener { + marker?.hideInfoWindow() + isInfoWindowShow = false + } + return v } override fun initEvent() { @@ -44,9 +205,9 @@ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 1500, null) //设置起点 - addMarker(LatLng(39.914885, 116.272312), R.mipmap.start) + addMarker(LatLng(39.914885, 116.272312), "", R.mipmap.start) //设置终点 - addMarker(LatLng(39.914716, 116.265097), R.mipmap.end) + addMarker(LatLng(39.914716, 116.265097), "", R.mipmap.end) //瞄点画线 val latLngPoints = ArrayList() latLngPoints.add(LatLng(39.914885, 116.272312)) @@ -78,9 +239,10 @@ } - private fun addMarker(point: LatLng, res: Int) { + private fun addMarker(point: LatLng, type: String, res: Int) { val markerOption = MarkerOptions() markerOption.position(point) + markerOption.title(type) markerOption.icon(BitmapDescriptorFactory.fromResource(res)) aMap.addMarker(markerOption) } diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt new file mode 100644 index 0000000..ad16496 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt @@ -0,0 +1,5 @@ +package com.casic.br.ktd.listener + +interface OnGeocodeSearchListener { + fun onRegionCodeSearched(address: String) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt new file mode 100644 index 0000000..61104eb --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt @@ -0,0 +1,15 @@ +package com.casic.br.ktd.listener + +import java.io.File + +interface OnImageCompressListener { + /** + * Fired when a compression returns successfully, override to handle in your own code + */ + fun onSuccess(file: File) + + /** + * Fired when a compression fails to complete, override to handle in your own code + */ + fun onError(e: Throwable) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/model/PointModel.kt b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt new file mode 100644 index 0000000..ec2065d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt @@ -0,0 +1,3 @@ +package com.casic.br.ktd.model + +data class PointModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt b/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt deleted file mode 100644 index c45d645..0000000 --- a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.casic.br.ktd.model - -data class RouteModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt new file mode 100644 index 0000000..40b3660 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt @@ -0,0 +1,28 @@ +package com.casic.br.ktd.extensions + +import com.amap.api.maps.model.LatLng +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.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.listener.OnGeocodeSearchListener + +private val geocoderSearch by lazy { GeocodeSearch(BaseApplication.get()) } + +fun LatLng.toChineseAddress(listener: OnGeocodeSearchListener) { + val queryParam = RegeocodeQuery( + LatLonPoint(this.latitude, this.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + listener.onRegionCodeSearched(regeocodeResult.regeocodeAddress.formatAddress) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index 36af820..e090122 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -1,9 +1,9 @@ package com.casic.br.ktd.extensions import android.content.Context +import com.casic.br.ktd.listener.OnImageCompressListener import com.casic.br.ktd.model.ErrorMessageModel import com.casic.br.ktd.utils.LocaleConstant -import com.casic.br.ktd.utils.OnImageCompressListener import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.createCompressImageDir @@ -14,7 +14,8 @@ import top.zibin.luban.OnCompressListener import java.io.File import java.text.SimpleDateFormat -import java.util.* +import java.util.Date +import java.util.Locale import java.util.regex.Pattern diff --git a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt index 40b27b1..a8d1e7a 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt @@ -2,31 +2,55 @@ import android.graphics.Color import android.os.Bundle +import android.os.Handler +import android.os.Message import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.model.BitmapDescriptorFactory import com.amap.api.maps.model.CameraPosition import com.amap.api.maps.model.LatLng +import com.amap.api.maps.model.Marker import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.PolylineOptions import com.casic.br.ktd.R import com.casic.br.ktd.databinding.FragmentHomeBinding +import com.casic.br.ktd.extensions.toChineseAddress +import com.casic.br.ktd.listener.OnGeocodeSearchListener +import com.casic.br.ktd.model.DeviceListModel +import com.casic.br.ktd.model.VehicleListModel +import com.casic.br.ktd.utils.LocaleConstant +import com.casic.br.ktd.vm.DeviceViewModel +import com.casic.br.ktd.vm.VehicleViewModel import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.utils.SaveKeyValues +import com.pengxh.kt.lite.utils.WeakReferenceHandler +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton -class HomePageFragment : KotlinBaseFragment() { +class HomePageFragment : KotlinBaseFragment(), AMap.OnMarkerClickListener, + AMap.InfoWindowAdapter, Handler.Callback { + + private val kTag = "HomePageFragment" + private lateinit var vehicleViewModel: VehicleViewModel + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private lateinit var weakReferenceHandler: WeakReferenceHandler + private var isInfoWindowShow = false + private val handlerVehicleCode = 2023082501 + private val handlerDeviceCode = 2023082502 override fun initViewBinding( - inflater: LayoutInflater, - container: ViewGroup? + inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { return FragmentHomeBinding.inflate(inflater, container, false) } - private lateinit var aMap: AMap - override fun initOnCreate(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -36,6 +60,143 @@ uiSettings.isScaleControlsEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isRotateGesturesEnabled = false//不许地图随手势旋转角度 + // 点击marker弹出自定义popup + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) + + weakReferenceHandler = WeakReferenceHandler(this) + + vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] + vehicleViewModel.getVehicles() + vehicleViewModel.vehicleList.observe(this) { + if (it.code == 200) { + if (it.data.rows.isNotEmpty()) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerVehicleCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + deviceViewModel.deviceList.observe(this) { + if (it.code == 200) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerDeviceCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + handlerVehicleCode -> { + val vehicleModel = msg.obj as VehicleListModel.DataModel.RowsModel + + SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, vehicleModel.carPlate) + SaveKeyValues.putValue(LocaleConstant.CAR_ID, vehicleModel.id) + + val marker = if (vehicleModel.status == "1") { + //在线 + R.mipmap.vehicle_on + } else { + //离线 + R.mipmap.vehicle_on + } + + val latLng = LatLng( + vehicleModel.latitude.toDouble(), vehicleModel.longitude.toDouble() + ) + addMarker(latLng, "Car", marker) + + /** + * 地图PopupWindow数据绑定 + * ****/ + if (isInfoWindowShow) { + windowTitleView.text = vehicleModel.carPlate + val state = if (vehicleModel.status == "1") { + "状态:在线" + } else { + "状态:离线" + } + carStateView.text = state + + timeView.text = "时间:${vehicleModel.ts}" + latLng.toChineseAddress(object : OnGeocodeSearchListener { + override fun onRegionCodeSearched(address: String) { + locationView.text = "位置:$address" + } + }) + } + } + + handlerDeviceCode -> { + if (isInfoWindowShow) { + val deviceModel = msg.obj as DeviceListModel.DataModel.RowsModel + + deviceModelView.text = "云台型号:${deviceModel.deviceModel}" + } + } + } + return true + } + + override fun onMarkerClick(marker: Marker?): Boolean { + //点击Marker显示自定义Popup + marker?.showInfoWindow() + return true + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + + private lateinit var windowTitleView: TextView + private lateinit var taskStateView: QMUIRoundButton + private lateinit var carStateView: TextView + private lateinit var deviceModelView: TextView + private lateinit var timeView: TextView + private lateinit var locationView: TextView + + override fun getInfoWindow(marker: Marker?): View { + isInfoWindowShow = true + + val v = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_car_window, null) + + windowTitleView = v.findViewById(R.id.windowTitleView) + taskStateView = v.findViewById(R.id.taskStateView) + val closeView = v.findViewById(R.id.closeView) + carStateView = v.findViewById(R.id.carStateView) + deviceModelView = v.findViewById(R.id.deviceModelView) + timeView = v.findViewById(R.id.timeView) + locationView = v.findViewById(R.id.locationView) + val routeView = v.findViewById(R.id.routeView) + + if (marker?.title == "Car") { + taskStateView.visibility = View.GONE + routeView.visibility = View.GONE + + vehicleViewModel.getVehicles() + + deviceViewModel.getDevices() + } else { + taskStateView.visibility = View.VISIBLE + routeView.visibility = View.VISIBLE + + routeView.setOnClickListener { + + } + } + + closeView.setOnClickListener { + marker?.hideInfoWindow() + isInfoWindowShow = false + } + return v } override fun initEvent() { @@ -44,9 +205,9 @@ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 1500, null) //设置起点 - addMarker(LatLng(39.914885, 116.272312), R.mipmap.start) + addMarker(LatLng(39.914885, 116.272312), "", R.mipmap.start) //设置终点 - addMarker(LatLng(39.914716, 116.265097), R.mipmap.end) + addMarker(LatLng(39.914716, 116.265097), "", R.mipmap.end) //瞄点画线 val latLngPoints = ArrayList() latLngPoints.add(LatLng(39.914885, 116.272312)) @@ -78,9 +239,10 @@ } - private fun addMarker(point: LatLng, res: Int) { + private fun addMarker(point: LatLng, type: String, res: Int) { val markerOption = MarkerOptions() markerOption.position(point) + markerOption.title(type) markerOption.icon(BitmapDescriptorFactory.fromResource(res)) aMap.addMarker(markerOption) } diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt new file mode 100644 index 0000000..ad16496 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt @@ -0,0 +1,5 @@ +package com.casic.br.ktd.listener + +interface OnGeocodeSearchListener { + fun onRegionCodeSearched(address: String) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt new file mode 100644 index 0000000..61104eb --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt @@ -0,0 +1,15 @@ +package com.casic.br.ktd.listener + +import java.io.File + +interface OnImageCompressListener { + /** + * Fired when a compression returns successfully, override to handle in your own code + */ + fun onSuccess(file: File) + + /** + * Fired when a compression fails to complete, override to handle in your own code + */ + fun onError(e: Throwable) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/model/PointModel.kt b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt new file mode 100644 index 0000000..ec2065d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt @@ -0,0 +1,3 @@ +package com.casic.br.ktd.model + +data class PointModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt b/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt deleted file mode 100644 index c45d645..0000000 --- a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.casic.br.ktd.model - -data class RouteModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java new file mode 100644 index 0000000..e813075 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java @@ -0,0 +1,166 @@ +package com.casic.br.ktd.model; + +import java.util.List; + +public class VehicleRouteModel { + + private Integer code; + private DataModel data; + private String message; + + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } + + public DataModel getData() { + return data; + } + + public void setData(DataModel data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public static class DataModel { + private List rows; + private Integer total; + + public List getRows() { + return rows; + } + + public void setRows(List rows) { + this.rows = rows; + } + + public Integer getTotal() { + return total; + } + + public void setTotal(Integer total) { + this.total = total; + } + + public static class RowsModel { + private String deviceStatus; + private String direction; + private String gas; + private String id; + private String isAlarm; + private String lagitude; + private String longitude; + private String pitch; + private String position; + private String speed; + private String taskId; + private String ts; + + public String getDeviceStatus() { + return deviceStatus; + } + + public void setDeviceStatus(String deviceStatus) { + this.deviceStatus = deviceStatus; + } + + public String getDirection() { + return direction; + } + + public void setDirection(String direction) { + this.direction = direction; + } + + public String getGas() { + return gas; + } + + public void setGas(String gas) { + this.gas = gas; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getIsAlarm() { + return isAlarm; + } + + public void setIsAlarm(String isAlarm) { + this.isAlarm = isAlarm; + } + + public String getLagitude() { + return lagitude; + } + + public void setLagitude(String lagitude) { + this.lagitude = lagitude; + } + + public String getLongitude() { + return longitude; + } + + public void setLongitude(String longitude) { + this.longitude = longitude; + } + + public String getPitch() { + return pitch; + } + + public void setPitch(String pitch) { + this.pitch = pitch; + } + + public String getPosition() { + return position; + } + + public void setPosition(String position) { + this.position = position; + } + + public String getSpeed() { + return speed; + } + + public void setSpeed(String speed) { + this.speed = speed; + } + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public String getTs() { + return ts; + } + + public void setTs(String ts) { + this.ts = ts; + } + } + } +} diff --git a/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt new file mode 100644 index 0000000..40b3660 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt @@ -0,0 +1,28 @@ +package com.casic.br.ktd.extensions + +import com.amap.api.maps.model.LatLng +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.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.listener.OnGeocodeSearchListener + +private val geocoderSearch by lazy { GeocodeSearch(BaseApplication.get()) } + +fun LatLng.toChineseAddress(listener: OnGeocodeSearchListener) { + val queryParam = RegeocodeQuery( + LatLonPoint(this.latitude, this.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + listener.onRegionCodeSearched(regeocodeResult.regeocodeAddress.formatAddress) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index 36af820..e090122 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -1,9 +1,9 @@ package com.casic.br.ktd.extensions import android.content.Context +import com.casic.br.ktd.listener.OnImageCompressListener import com.casic.br.ktd.model.ErrorMessageModel import com.casic.br.ktd.utils.LocaleConstant -import com.casic.br.ktd.utils.OnImageCompressListener import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.createCompressImageDir @@ -14,7 +14,8 @@ import top.zibin.luban.OnCompressListener import java.io.File import java.text.SimpleDateFormat -import java.util.* +import java.util.Date +import java.util.Locale import java.util.regex.Pattern diff --git a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt index 40b27b1..a8d1e7a 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt @@ -2,31 +2,55 @@ import android.graphics.Color import android.os.Bundle +import android.os.Handler +import android.os.Message import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.model.BitmapDescriptorFactory import com.amap.api.maps.model.CameraPosition import com.amap.api.maps.model.LatLng +import com.amap.api.maps.model.Marker import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.PolylineOptions import com.casic.br.ktd.R import com.casic.br.ktd.databinding.FragmentHomeBinding +import com.casic.br.ktd.extensions.toChineseAddress +import com.casic.br.ktd.listener.OnGeocodeSearchListener +import com.casic.br.ktd.model.DeviceListModel +import com.casic.br.ktd.model.VehicleListModel +import com.casic.br.ktd.utils.LocaleConstant +import com.casic.br.ktd.vm.DeviceViewModel +import com.casic.br.ktd.vm.VehicleViewModel import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.utils.SaveKeyValues +import com.pengxh.kt.lite.utils.WeakReferenceHandler +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton -class HomePageFragment : KotlinBaseFragment() { +class HomePageFragment : KotlinBaseFragment(), AMap.OnMarkerClickListener, + AMap.InfoWindowAdapter, Handler.Callback { + + private val kTag = "HomePageFragment" + private lateinit var vehicleViewModel: VehicleViewModel + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private lateinit var weakReferenceHandler: WeakReferenceHandler + private var isInfoWindowShow = false + private val handlerVehicleCode = 2023082501 + private val handlerDeviceCode = 2023082502 override fun initViewBinding( - inflater: LayoutInflater, - container: ViewGroup? + inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { return FragmentHomeBinding.inflate(inflater, container, false) } - private lateinit var aMap: AMap - override fun initOnCreate(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -36,6 +60,143 @@ uiSettings.isScaleControlsEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isRotateGesturesEnabled = false//不许地图随手势旋转角度 + // 点击marker弹出自定义popup + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) + + weakReferenceHandler = WeakReferenceHandler(this) + + vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] + vehicleViewModel.getVehicles() + vehicleViewModel.vehicleList.observe(this) { + if (it.code == 200) { + if (it.data.rows.isNotEmpty()) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerVehicleCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + deviceViewModel.deviceList.observe(this) { + if (it.code == 200) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerDeviceCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + handlerVehicleCode -> { + val vehicleModel = msg.obj as VehicleListModel.DataModel.RowsModel + + SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, vehicleModel.carPlate) + SaveKeyValues.putValue(LocaleConstant.CAR_ID, vehicleModel.id) + + val marker = if (vehicleModel.status == "1") { + //在线 + R.mipmap.vehicle_on + } else { + //离线 + R.mipmap.vehicle_on + } + + val latLng = LatLng( + vehicleModel.latitude.toDouble(), vehicleModel.longitude.toDouble() + ) + addMarker(latLng, "Car", marker) + + /** + * 地图PopupWindow数据绑定 + * ****/ + if (isInfoWindowShow) { + windowTitleView.text = vehicleModel.carPlate + val state = if (vehicleModel.status == "1") { + "状态:在线" + } else { + "状态:离线" + } + carStateView.text = state + + timeView.text = "时间:${vehicleModel.ts}" + latLng.toChineseAddress(object : OnGeocodeSearchListener { + override fun onRegionCodeSearched(address: String) { + locationView.text = "位置:$address" + } + }) + } + } + + handlerDeviceCode -> { + if (isInfoWindowShow) { + val deviceModel = msg.obj as DeviceListModel.DataModel.RowsModel + + deviceModelView.text = "云台型号:${deviceModel.deviceModel}" + } + } + } + return true + } + + override fun onMarkerClick(marker: Marker?): Boolean { + //点击Marker显示自定义Popup + marker?.showInfoWindow() + return true + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + + private lateinit var windowTitleView: TextView + private lateinit var taskStateView: QMUIRoundButton + private lateinit var carStateView: TextView + private lateinit var deviceModelView: TextView + private lateinit var timeView: TextView + private lateinit var locationView: TextView + + override fun getInfoWindow(marker: Marker?): View { + isInfoWindowShow = true + + val v = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_car_window, null) + + windowTitleView = v.findViewById(R.id.windowTitleView) + taskStateView = v.findViewById(R.id.taskStateView) + val closeView = v.findViewById(R.id.closeView) + carStateView = v.findViewById(R.id.carStateView) + deviceModelView = v.findViewById(R.id.deviceModelView) + timeView = v.findViewById(R.id.timeView) + locationView = v.findViewById(R.id.locationView) + val routeView = v.findViewById(R.id.routeView) + + if (marker?.title == "Car") { + taskStateView.visibility = View.GONE + routeView.visibility = View.GONE + + vehicleViewModel.getVehicles() + + deviceViewModel.getDevices() + } else { + taskStateView.visibility = View.VISIBLE + routeView.visibility = View.VISIBLE + + routeView.setOnClickListener { + + } + } + + closeView.setOnClickListener { + marker?.hideInfoWindow() + isInfoWindowShow = false + } + return v } override fun initEvent() { @@ -44,9 +205,9 @@ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 1500, null) //设置起点 - addMarker(LatLng(39.914885, 116.272312), R.mipmap.start) + addMarker(LatLng(39.914885, 116.272312), "", R.mipmap.start) //设置终点 - addMarker(LatLng(39.914716, 116.265097), R.mipmap.end) + addMarker(LatLng(39.914716, 116.265097), "", R.mipmap.end) //瞄点画线 val latLngPoints = ArrayList() latLngPoints.add(LatLng(39.914885, 116.272312)) @@ -78,9 +239,10 @@ } - private fun addMarker(point: LatLng, res: Int) { + private fun addMarker(point: LatLng, type: String, res: Int) { val markerOption = MarkerOptions() markerOption.position(point) + markerOption.title(type) markerOption.icon(BitmapDescriptorFactory.fromResource(res)) aMap.addMarker(markerOption) } diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt new file mode 100644 index 0000000..ad16496 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt @@ -0,0 +1,5 @@ +package com.casic.br.ktd.listener + +interface OnGeocodeSearchListener { + fun onRegionCodeSearched(address: String) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt new file mode 100644 index 0000000..61104eb --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt @@ -0,0 +1,15 @@ +package com.casic.br.ktd.listener + +import java.io.File + +interface OnImageCompressListener { + /** + * Fired when a compression returns successfully, override to handle in your own code + */ + fun onSuccess(file: File) + + /** + * Fired when a compression fails to complete, override to handle in your own code + */ + fun onError(e: Throwable) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/model/PointModel.kt b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt new file mode 100644 index 0000000..ec2065d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt @@ -0,0 +1,3 @@ +package com.casic.br.ktd.model + +data class PointModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt b/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt deleted file mode 100644 index c45d645..0000000 --- a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.casic.br.ktd.model - -data class RouteModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java new file mode 100644 index 0000000..e813075 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java @@ -0,0 +1,166 @@ +package com.casic.br.ktd.model; + +import java.util.List; + +public class VehicleRouteModel { + + private Integer code; + private DataModel data; + private String message; + + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } + + public DataModel getData() { + return data; + } + + public void setData(DataModel data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public static class DataModel { + private List rows; + private Integer total; + + public List getRows() { + return rows; + } + + public void setRows(List rows) { + this.rows = rows; + } + + public Integer getTotal() { + return total; + } + + public void setTotal(Integer total) { + this.total = total; + } + + public static class RowsModel { + private String deviceStatus; + private String direction; + private String gas; + private String id; + private String isAlarm; + private String lagitude; + private String longitude; + private String pitch; + private String position; + private String speed; + private String taskId; + private String ts; + + public String getDeviceStatus() { + return deviceStatus; + } + + public void setDeviceStatus(String deviceStatus) { + this.deviceStatus = deviceStatus; + } + + public String getDirection() { + return direction; + } + + public void setDirection(String direction) { + this.direction = direction; + } + + public String getGas() { + return gas; + } + + public void setGas(String gas) { + this.gas = gas; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getIsAlarm() { + return isAlarm; + } + + public void setIsAlarm(String isAlarm) { + this.isAlarm = isAlarm; + } + + public String getLagitude() { + return lagitude; + } + + public void setLagitude(String lagitude) { + this.lagitude = lagitude; + } + + public String getLongitude() { + return longitude; + } + + public void setLongitude(String longitude) { + this.longitude = longitude; + } + + public String getPitch() { + return pitch; + } + + public void setPitch(String pitch) { + this.pitch = pitch; + } + + public String getPosition() { + return position; + } + + public void setPosition(String position) { + this.position = position; + } + + public String getSpeed() { + return speed; + } + + public void setSpeed(String speed) { + this.speed = speed; + } + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public String getTs() { + return ts; + } + + public void setTs(String ts) { + this.ts = ts; + } + } + } +} diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt index 9211b3a..519ab45 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt @@ -49,7 +49,7 @@ @Header("token") token: String, @Body requestBody: RequestBody, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -78,7 +78,7 @@ suspend fun getVehicles( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -88,7 +88,7 @@ suspend fun getDevices( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -101,6 +101,16 @@ ): String /** + * 巡检路径 + */ + @POST("/system/busPatrolTrack/listPage") + suspend fun busTrackRoute( + @Header("token") token: String, + @QueryMap limit: Map, + @QueryMap offset: Map + ): String + + /** * 新增报警规则,主要是阈值 */ @POST("/system/alarmRule/add") @@ -116,7 +126,7 @@ suspend fun getAlarmRules( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -146,6 +156,6 @@ @Header("token") token: String, @Body requestBody: RequestBody, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt new file mode 100644 index 0000000..40b3660 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt @@ -0,0 +1,28 @@ +package com.casic.br.ktd.extensions + +import com.amap.api.maps.model.LatLng +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.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.listener.OnGeocodeSearchListener + +private val geocoderSearch by lazy { GeocodeSearch(BaseApplication.get()) } + +fun LatLng.toChineseAddress(listener: OnGeocodeSearchListener) { + val queryParam = RegeocodeQuery( + LatLonPoint(this.latitude, this.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + listener.onRegionCodeSearched(regeocodeResult.regeocodeAddress.formatAddress) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index 36af820..e090122 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -1,9 +1,9 @@ package com.casic.br.ktd.extensions import android.content.Context +import com.casic.br.ktd.listener.OnImageCompressListener import com.casic.br.ktd.model.ErrorMessageModel import com.casic.br.ktd.utils.LocaleConstant -import com.casic.br.ktd.utils.OnImageCompressListener import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.createCompressImageDir @@ -14,7 +14,8 @@ import top.zibin.luban.OnCompressListener import java.io.File import java.text.SimpleDateFormat -import java.util.* +import java.util.Date +import java.util.Locale import java.util.regex.Pattern diff --git a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt index 40b27b1..a8d1e7a 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt @@ -2,31 +2,55 @@ import android.graphics.Color import android.os.Bundle +import android.os.Handler +import android.os.Message import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.model.BitmapDescriptorFactory import com.amap.api.maps.model.CameraPosition import com.amap.api.maps.model.LatLng +import com.amap.api.maps.model.Marker import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.PolylineOptions import com.casic.br.ktd.R import com.casic.br.ktd.databinding.FragmentHomeBinding +import com.casic.br.ktd.extensions.toChineseAddress +import com.casic.br.ktd.listener.OnGeocodeSearchListener +import com.casic.br.ktd.model.DeviceListModel +import com.casic.br.ktd.model.VehicleListModel +import com.casic.br.ktd.utils.LocaleConstant +import com.casic.br.ktd.vm.DeviceViewModel +import com.casic.br.ktd.vm.VehicleViewModel import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.utils.SaveKeyValues +import com.pengxh.kt.lite.utils.WeakReferenceHandler +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton -class HomePageFragment : KotlinBaseFragment() { +class HomePageFragment : KotlinBaseFragment(), AMap.OnMarkerClickListener, + AMap.InfoWindowAdapter, Handler.Callback { + + private val kTag = "HomePageFragment" + private lateinit var vehicleViewModel: VehicleViewModel + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private lateinit var weakReferenceHandler: WeakReferenceHandler + private var isInfoWindowShow = false + private val handlerVehicleCode = 2023082501 + private val handlerDeviceCode = 2023082502 override fun initViewBinding( - inflater: LayoutInflater, - container: ViewGroup? + inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { return FragmentHomeBinding.inflate(inflater, container, false) } - private lateinit var aMap: AMap - override fun initOnCreate(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -36,6 +60,143 @@ uiSettings.isScaleControlsEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isRotateGesturesEnabled = false//不许地图随手势旋转角度 + // 点击marker弹出自定义popup + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) + + weakReferenceHandler = WeakReferenceHandler(this) + + vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] + vehicleViewModel.getVehicles() + vehicleViewModel.vehicleList.observe(this) { + if (it.code == 200) { + if (it.data.rows.isNotEmpty()) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerVehicleCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + deviceViewModel.deviceList.observe(this) { + if (it.code == 200) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerDeviceCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + handlerVehicleCode -> { + val vehicleModel = msg.obj as VehicleListModel.DataModel.RowsModel + + SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, vehicleModel.carPlate) + SaveKeyValues.putValue(LocaleConstant.CAR_ID, vehicleModel.id) + + val marker = if (vehicleModel.status == "1") { + //在线 + R.mipmap.vehicle_on + } else { + //离线 + R.mipmap.vehicle_on + } + + val latLng = LatLng( + vehicleModel.latitude.toDouble(), vehicleModel.longitude.toDouble() + ) + addMarker(latLng, "Car", marker) + + /** + * 地图PopupWindow数据绑定 + * ****/ + if (isInfoWindowShow) { + windowTitleView.text = vehicleModel.carPlate + val state = if (vehicleModel.status == "1") { + "状态:在线" + } else { + "状态:离线" + } + carStateView.text = state + + timeView.text = "时间:${vehicleModel.ts}" + latLng.toChineseAddress(object : OnGeocodeSearchListener { + override fun onRegionCodeSearched(address: String) { + locationView.text = "位置:$address" + } + }) + } + } + + handlerDeviceCode -> { + if (isInfoWindowShow) { + val deviceModel = msg.obj as DeviceListModel.DataModel.RowsModel + + deviceModelView.text = "云台型号:${deviceModel.deviceModel}" + } + } + } + return true + } + + override fun onMarkerClick(marker: Marker?): Boolean { + //点击Marker显示自定义Popup + marker?.showInfoWindow() + return true + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + + private lateinit var windowTitleView: TextView + private lateinit var taskStateView: QMUIRoundButton + private lateinit var carStateView: TextView + private lateinit var deviceModelView: TextView + private lateinit var timeView: TextView + private lateinit var locationView: TextView + + override fun getInfoWindow(marker: Marker?): View { + isInfoWindowShow = true + + val v = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_car_window, null) + + windowTitleView = v.findViewById(R.id.windowTitleView) + taskStateView = v.findViewById(R.id.taskStateView) + val closeView = v.findViewById(R.id.closeView) + carStateView = v.findViewById(R.id.carStateView) + deviceModelView = v.findViewById(R.id.deviceModelView) + timeView = v.findViewById(R.id.timeView) + locationView = v.findViewById(R.id.locationView) + val routeView = v.findViewById(R.id.routeView) + + if (marker?.title == "Car") { + taskStateView.visibility = View.GONE + routeView.visibility = View.GONE + + vehicleViewModel.getVehicles() + + deviceViewModel.getDevices() + } else { + taskStateView.visibility = View.VISIBLE + routeView.visibility = View.VISIBLE + + routeView.setOnClickListener { + + } + } + + closeView.setOnClickListener { + marker?.hideInfoWindow() + isInfoWindowShow = false + } + return v } override fun initEvent() { @@ -44,9 +205,9 @@ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 1500, null) //设置起点 - addMarker(LatLng(39.914885, 116.272312), R.mipmap.start) + addMarker(LatLng(39.914885, 116.272312), "", R.mipmap.start) //设置终点 - addMarker(LatLng(39.914716, 116.265097), R.mipmap.end) + addMarker(LatLng(39.914716, 116.265097), "", R.mipmap.end) //瞄点画线 val latLngPoints = ArrayList() latLngPoints.add(LatLng(39.914885, 116.272312)) @@ -78,9 +239,10 @@ } - private fun addMarker(point: LatLng, res: Int) { + private fun addMarker(point: LatLng, type: String, res: Int) { val markerOption = MarkerOptions() markerOption.position(point) + markerOption.title(type) markerOption.icon(BitmapDescriptorFactory.fromResource(res)) aMap.addMarker(markerOption) } diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt new file mode 100644 index 0000000..ad16496 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt @@ -0,0 +1,5 @@ +package com.casic.br.ktd.listener + +interface OnGeocodeSearchListener { + fun onRegionCodeSearched(address: String) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt new file mode 100644 index 0000000..61104eb --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt @@ -0,0 +1,15 @@ +package com.casic.br.ktd.listener + +import java.io.File + +interface OnImageCompressListener { + /** + * Fired when a compression returns successfully, override to handle in your own code + */ + fun onSuccess(file: File) + + /** + * Fired when a compression fails to complete, override to handle in your own code + */ + fun onError(e: Throwable) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/model/PointModel.kt b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt new file mode 100644 index 0000000..ec2065d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt @@ -0,0 +1,3 @@ +package com.casic.br.ktd.model + +data class PointModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt b/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt deleted file mode 100644 index c45d645..0000000 --- a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.casic.br.ktd.model - -data class RouteModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java new file mode 100644 index 0000000..e813075 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java @@ -0,0 +1,166 @@ +package com.casic.br.ktd.model; + +import java.util.List; + +public class VehicleRouteModel { + + private Integer code; + private DataModel data; + private String message; + + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } + + public DataModel getData() { + return data; + } + + public void setData(DataModel data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public static class DataModel { + private List rows; + private Integer total; + + public List getRows() { + return rows; + } + + public void setRows(List rows) { + this.rows = rows; + } + + public Integer getTotal() { + return total; + } + + public void setTotal(Integer total) { + this.total = total; + } + + public static class RowsModel { + private String deviceStatus; + private String direction; + private String gas; + private String id; + private String isAlarm; + private String lagitude; + private String longitude; + private String pitch; + private String position; + private String speed; + private String taskId; + private String ts; + + public String getDeviceStatus() { + return deviceStatus; + } + + public void setDeviceStatus(String deviceStatus) { + this.deviceStatus = deviceStatus; + } + + public String getDirection() { + return direction; + } + + public void setDirection(String direction) { + this.direction = direction; + } + + public String getGas() { + return gas; + } + + public void setGas(String gas) { + this.gas = gas; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getIsAlarm() { + return isAlarm; + } + + public void setIsAlarm(String isAlarm) { + this.isAlarm = isAlarm; + } + + public String getLagitude() { + return lagitude; + } + + public void setLagitude(String lagitude) { + this.lagitude = lagitude; + } + + public String getLongitude() { + return longitude; + } + + public void setLongitude(String longitude) { + this.longitude = longitude; + } + + public String getPitch() { + return pitch; + } + + public void setPitch(String pitch) { + this.pitch = pitch; + } + + public String getPosition() { + return position; + } + + public void setPosition(String position) { + this.position = position; + } + + public String getSpeed() { + return speed; + } + + public void setSpeed(String speed) { + this.speed = speed; + } + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public String getTs() { + return ts; + } + + public void setTs(String ts) { + this.ts = ts; + } + } + } +} diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt index 9211b3a..519ab45 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt @@ -49,7 +49,7 @@ @Header("token") token: String, @Body requestBody: RequestBody, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -78,7 +78,7 @@ suspend fun getVehicles( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -88,7 +88,7 @@ suspend fun getDevices( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -101,6 +101,16 @@ ): String /** + * 巡检路径 + */ + @POST("/system/busPatrolTrack/listPage") + suspend fun busTrackRoute( + @Header("token") token: String, + @QueryMap limit: Map, + @QueryMap offset: Map + ): String + + /** * 新增报警规则,主要是阈值 */ @POST("/system/alarmRule/add") @@ -116,7 +126,7 @@ suspend fun getAlarmRules( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -146,6 +156,6 @@ @Header("token") token: String, @Body requestBody: RequestBody, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt index 0f109db..fd9624c 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt @@ -186,6 +186,18 @@ } /** + * 巡检路径 + */ + suspend fun busTrackRoute(): String { + val limitMap = HashMap() + limitMap["limit"] = LocaleConstant.PAGE_LIMIT + + val offsetMap = HashMap() + offsetMap["offset"] = 1 + return api.busTrackRoute(AuthenticationHelper.token, limitMap, offsetMap) + } + + /** * 新增报警规则,主要是阈值 */ suspend fun addAlarmRule(high: String, deviceId: String, ts: String): String { diff --git a/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt new file mode 100644 index 0000000..40b3660 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt @@ -0,0 +1,28 @@ +package com.casic.br.ktd.extensions + +import com.amap.api.maps.model.LatLng +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.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.listener.OnGeocodeSearchListener + +private val geocoderSearch by lazy { GeocodeSearch(BaseApplication.get()) } + +fun LatLng.toChineseAddress(listener: OnGeocodeSearchListener) { + val queryParam = RegeocodeQuery( + LatLonPoint(this.latitude, this.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + listener.onRegionCodeSearched(regeocodeResult.regeocodeAddress.formatAddress) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index 36af820..e090122 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -1,9 +1,9 @@ package com.casic.br.ktd.extensions import android.content.Context +import com.casic.br.ktd.listener.OnImageCompressListener import com.casic.br.ktd.model.ErrorMessageModel import com.casic.br.ktd.utils.LocaleConstant -import com.casic.br.ktd.utils.OnImageCompressListener import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.createCompressImageDir @@ -14,7 +14,8 @@ import top.zibin.luban.OnCompressListener import java.io.File import java.text.SimpleDateFormat -import java.util.* +import java.util.Date +import java.util.Locale import java.util.regex.Pattern diff --git a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt index 40b27b1..a8d1e7a 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt @@ -2,31 +2,55 @@ import android.graphics.Color import android.os.Bundle +import android.os.Handler +import android.os.Message import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.model.BitmapDescriptorFactory import com.amap.api.maps.model.CameraPosition import com.amap.api.maps.model.LatLng +import com.amap.api.maps.model.Marker import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.PolylineOptions import com.casic.br.ktd.R import com.casic.br.ktd.databinding.FragmentHomeBinding +import com.casic.br.ktd.extensions.toChineseAddress +import com.casic.br.ktd.listener.OnGeocodeSearchListener +import com.casic.br.ktd.model.DeviceListModel +import com.casic.br.ktd.model.VehicleListModel +import com.casic.br.ktd.utils.LocaleConstant +import com.casic.br.ktd.vm.DeviceViewModel +import com.casic.br.ktd.vm.VehicleViewModel import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.utils.SaveKeyValues +import com.pengxh.kt.lite.utils.WeakReferenceHandler +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton -class HomePageFragment : KotlinBaseFragment() { +class HomePageFragment : KotlinBaseFragment(), AMap.OnMarkerClickListener, + AMap.InfoWindowAdapter, Handler.Callback { + + private val kTag = "HomePageFragment" + private lateinit var vehicleViewModel: VehicleViewModel + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private lateinit var weakReferenceHandler: WeakReferenceHandler + private var isInfoWindowShow = false + private val handlerVehicleCode = 2023082501 + private val handlerDeviceCode = 2023082502 override fun initViewBinding( - inflater: LayoutInflater, - container: ViewGroup? + inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { return FragmentHomeBinding.inflate(inflater, container, false) } - private lateinit var aMap: AMap - override fun initOnCreate(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -36,6 +60,143 @@ uiSettings.isScaleControlsEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isRotateGesturesEnabled = false//不许地图随手势旋转角度 + // 点击marker弹出自定义popup + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) + + weakReferenceHandler = WeakReferenceHandler(this) + + vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] + vehicleViewModel.getVehicles() + vehicleViewModel.vehicleList.observe(this) { + if (it.code == 200) { + if (it.data.rows.isNotEmpty()) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerVehicleCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + deviceViewModel.deviceList.observe(this) { + if (it.code == 200) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerDeviceCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + handlerVehicleCode -> { + val vehicleModel = msg.obj as VehicleListModel.DataModel.RowsModel + + SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, vehicleModel.carPlate) + SaveKeyValues.putValue(LocaleConstant.CAR_ID, vehicleModel.id) + + val marker = if (vehicleModel.status == "1") { + //在线 + R.mipmap.vehicle_on + } else { + //离线 + R.mipmap.vehicle_on + } + + val latLng = LatLng( + vehicleModel.latitude.toDouble(), vehicleModel.longitude.toDouble() + ) + addMarker(latLng, "Car", marker) + + /** + * 地图PopupWindow数据绑定 + * ****/ + if (isInfoWindowShow) { + windowTitleView.text = vehicleModel.carPlate + val state = if (vehicleModel.status == "1") { + "状态:在线" + } else { + "状态:离线" + } + carStateView.text = state + + timeView.text = "时间:${vehicleModel.ts}" + latLng.toChineseAddress(object : OnGeocodeSearchListener { + override fun onRegionCodeSearched(address: String) { + locationView.text = "位置:$address" + } + }) + } + } + + handlerDeviceCode -> { + if (isInfoWindowShow) { + val deviceModel = msg.obj as DeviceListModel.DataModel.RowsModel + + deviceModelView.text = "云台型号:${deviceModel.deviceModel}" + } + } + } + return true + } + + override fun onMarkerClick(marker: Marker?): Boolean { + //点击Marker显示自定义Popup + marker?.showInfoWindow() + return true + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + + private lateinit var windowTitleView: TextView + private lateinit var taskStateView: QMUIRoundButton + private lateinit var carStateView: TextView + private lateinit var deviceModelView: TextView + private lateinit var timeView: TextView + private lateinit var locationView: TextView + + override fun getInfoWindow(marker: Marker?): View { + isInfoWindowShow = true + + val v = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_car_window, null) + + windowTitleView = v.findViewById(R.id.windowTitleView) + taskStateView = v.findViewById(R.id.taskStateView) + val closeView = v.findViewById(R.id.closeView) + carStateView = v.findViewById(R.id.carStateView) + deviceModelView = v.findViewById(R.id.deviceModelView) + timeView = v.findViewById(R.id.timeView) + locationView = v.findViewById(R.id.locationView) + val routeView = v.findViewById(R.id.routeView) + + if (marker?.title == "Car") { + taskStateView.visibility = View.GONE + routeView.visibility = View.GONE + + vehicleViewModel.getVehicles() + + deviceViewModel.getDevices() + } else { + taskStateView.visibility = View.VISIBLE + routeView.visibility = View.VISIBLE + + routeView.setOnClickListener { + + } + } + + closeView.setOnClickListener { + marker?.hideInfoWindow() + isInfoWindowShow = false + } + return v } override fun initEvent() { @@ -44,9 +205,9 @@ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 1500, null) //设置起点 - addMarker(LatLng(39.914885, 116.272312), R.mipmap.start) + addMarker(LatLng(39.914885, 116.272312), "", R.mipmap.start) //设置终点 - addMarker(LatLng(39.914716, 116.265097), R.mipmap.end) + addMarker(LatLng(39.914716, 116.265097), "", R.mipmap.end) //瞄点画线 val latLngPoints = ArrayList() latLngPoints.add(LatLng(39.914885, 116.272312)) @@ -78,9 +239,10 @@ } - private fun addMarker(point: LatLng, res: Int) { + private fun addMarker(point: LatLng, type: String, res: Int) { val markerOption = MarkerOptions() markerOption.position(point) + markerOption.title(type) markerOption.icon(BitmapDescriptorFactory.fromResource(res)) aMap.addMarker(markerOption) } diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt new file mode 100644 index 0000000..ad16496 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt @@ -0,0 +1,5 @@ +package com.casic.br.ktd.listener + +interface OnGeocodeSearchListener { + fun onRegionCodeSearched(address: String) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt new file mode 100644 index 0000000..61104eb --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt @@ -0,0 +1,15 @@ +package com.casic.br.ktd.listener + +import java.io.File + +interface OnImageCompressListener { + /** + * Fired when a compression returns successfully, override to handle in your own code + */ + fun onSuccess(file: File) + + /** + * Fired when a compression fails to complete, override to handle in your own code + */ + fun onError(e: Throwable) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/model/PointModel.kt b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt new file mode 100644 index 0000000..ec2065d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt @@ -0,0 +1,3 @@ +package com.casic.br.ktd.model + +data class PointModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt b/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt deleted file mode 100644 index c45d645..0000000 --- a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.casic.br.ktd.model - -data class RouteModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java new file mode 100644 index 0000000..e813075 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java @@ -0,0 +1,166 @@ +package com.casic.br.ktd.model; + +import java.util.List; + +public class VehicleRouteModel { + + private Integer code; + private DataModel data; + private String message; + + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } + + public DataModel getData() { + return data; + } + + public void setData(DataModel data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public static class DataModel { + private List rows; + private Integer total; + + public List getRows() { + return rows; + } + + public void setRows(List rows) { + this.rows = rows; + } + + public Integer getTotal() { + return total; + } + + public void setTotal(Integer total) { + this.total = total; + } + + public static class RowsModel { + private String deviceStatus; + private String direction; + private String gas; + private String id; + private String isAlarm; + private String lagitude; + private String longitude; + private String pitch; + private String position; + private String speed; + private String taskId; + private String ts; + + public String getDeviceStatus() { + return deviceStatus; + } + + public void setDeviceStatus(String deviceStatus) { + this.deviceStatus = deviceStatus; + } + + public String getDirection() { + return direction; + } + + public void setDirection(String direction) { + this.direction = direction; + } + + public String getGas() { + return gas; + } + + public void setGas(String gas) { + this.gas = gas; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getIsAlarm() { + return isAlarm; + } + + public void setIsAlarm(String isAlarm) { + this.isAlarm = isAlarm; + } + + public String getLagitude() { + return lagitude; + } + + public void setLagitude(String lagitude) { + this.lagitude = lagitude; + } + + public String getLongitude() { + return longitude; + } + + public void setLongitude(String longitude) { + this.longitude = longitude; + } + + public String getPitch() { + return pitch; + } + + public void setPitch(String pitch) { + this.pitch = pitch; + } + + public String getPosition() { + return position; + } + + public void setPosition(String position) { + this.position = position; + } + + public String getSpeed() { + return speed; + } + + public void setSpeed(String speed) { + this.speed = speed; + } + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public String getTs() { + return ts; + } + + public void setTs(String ts) { + this.ts = ts; + } + } + } +} diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt index 9211b3a..519ab45 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt @@ -49,7 +49,7 @@ @Header("token") token: String, @Body requestBody: RequestBody, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -78,7 +78,7 @@ suspend fun getVehicles( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -88,7 +88,7 @@ suspend fun getDevices( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -101,6 +101,16 @@ ): String /** + * 巡检路径 + */ + @POST("/system/busPatrolTrack/listPage") + suspend fun busTrackRoute( + @Header("token") token: String, + @QueryMap limit: Map, + @QueryMap offset: Map + ): String + + /** * 新增报警规则,主要是阈值 */ @POST("/system/alarmRule/add") @@ -116,7 +126,7 @@ suspend fun getAlarmRules( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -146,6 +156,6 @@ @Header("token") token: String, @Body requestBody: RequestBody, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt index 0f109db..fd9624c 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt @@ -186,6 +186,18 @@ } /** + * 巡检路径 + */ + suspend fun busTrackRoute(): String { + val limitMap = HashMap() + limitMap["limit"] = LocaleConstant.PAGE_LIMIT + + val offsetMap = HashMap() + offsetMap["offset"] = 1 + return api.busTrackRoute(AuthenticationHelper.token, limitMap, offsetMap) + } + + /** * 新增报警规则,主要是阈值 */ suspend fun addAlarmRule(high: String, deviceId: String, ts: String): String { diff --git a/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt deleted file mode 100644 index 92286ad..0000000 --- a/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.br.ktd.utils - -import java.io.File - -interface OnImageCompressListener { - /** - * Fired when a compression returns successfully, override to handle in your own code - */ - fun onSuccess(file: File) - - /** - * Fired when a compression fails to complete, override to handle in your own code - */ - fun onError(e: Throwable) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt new file mode 100644 index 0000000..40b3660 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt @@ -0,0 +1,28 @@ +package com.casic.br.ktd.extensions + +import com.amap.api.maps.model.LatLng +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.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.listener.OnGeocodeSearchListener + +private val geocoderSearch by lazy { GeocodeSearch(BaseApplication.get()) } + +fun LatLng.toChineseAddress(listener: OnGeocodeSearchListener) { + val queryParam = RegeocodeQuery( + LatLonPoint(this.latitude, this.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + listener.onRegionCodeSearched(regeocodeResult.regeocodeAddress.formatAddress) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index 36af820..e090122 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -1,9 +1,9 @@ package com.casic.br.ktd.extensions import android.content.Context +import com.casic.br.ktd.listener.OnImageCompressListener import com.casic.br.ktd.model.ErrorMessageModel import com.casic.br.ktd.utils.LocaleConstant -import com.casic.br.ktd.utils.OnImageCompressListener import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.createCompressImageDir @@ -14,7 +14,8 @@ import top.zibin.luban.OnCompressListener import java.io.File import java.text.SimpleDateFormat -import java.util.* +import java.util.Date +import java.util.Locale import java.util.regex.Pattern diff --git a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt index 40b27b1..a8d1e7a 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt @@ -2,31 +2,55 @@ import android.graphics.Color import android.os.Bundle +import android.os.Handler +import android.os.Message import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.model.BitmapDescriptorFactory import com.amap.api.maps.model.CameraPosition import com.amap.api.maps.model.LatLng +import com.amap.api.maps.model.Marker import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.PolylineOptions import com.casic.br.ktd.R import com.casic.br.ktd.databinding.FragmentHomeBinding +import com.casic.br.ktd.extensions.toChineseAddress +import com.casic.br.ktd.listener.OnGeocodeSearchListener +import com.casic.br.ktd.model.DeviceListModel +import com.casic.br.ktd.model.VehicleListModel +import com.casic.br.ktd.utils.LocaleConstant +import com.casic.br.ktd.vm.DeviceViewModel +import com.casic.br.ktd.vm.VehicleViewModel import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.utils.SaveKeyValues +import com.pengxh.kt.lite.utils.WeakReferenceHandler +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton -class HomePageFragment : KotlinBaseFragment() { +class HomePageFragment : KotlinBaseFragment(), AMap.OnMarkerClickListener, + AMap.InfoWindowAdapter, Handler.Callback { + + private val kTag = "HomePageFragment" + private lateinit var vehicleViewModel: VehicleViewModel + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private lateinit var weakReferenceHandler: WeakReferenceHandler + private var isInfoWindowShow = false + private val handlerVehicleCode = 2023082501 + private val handlerDeviceCode = 2023082502 override fun initViewBinding( - inflater: LayoutInflater, - container: ViewGroup? + inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { return FragmentHomeBinding.inflate(inflater, container, false) } - private lateinit var aMap: AMap - override fun initOnCreate(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -36,6 +60,143 @@ uiSettings.isScaleControlsEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isRotateGesturesEnabled = false//不许地图随手势旋转角度 + // 点击marker弹出自定义popup + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) + + weakReferenceHandler = WeakReferenceHandler(this) + + vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] + vehicleViewModel.getVehicles() + vehicleViewModel.vehicleList.observe(this) { + if (it.code == 200) { + if (it.data.rows.isNotEmpty()) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerVehicleCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + deviceViewModel.deviceList.observe(this) { + if (it.code == 200) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerDeviceCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + handlerVehicleCode -> { + val vehicleModel = msg.obj as VehicleListModel.DataModel.RowsModel + + SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, vehicleModel.carPlate) + SaveKeyValues.putValue(LocaleConstant.CAR_ID, vehicleModel.id) + + val marker = if (vehicleModel.status == "1") { + //在线 + R.mipmap.vehicle_on + } else { + //离线 + R.mipmap.vehicle_on + } + + val latLng = LatLng( + vehicleModel.latitude.toDouble(), vehicleModel.longitude.toDouble() + ) + addMarker(latLng, "Car", marker) + + /** + * 地图PopupWindow数据绑定 + * ****/ + if (isInfoWindowShow) { + windowTitleView.text = vehicleModel.carPlate + val state = if (vehicleModel.status == "1") { + "状态:在线" + } else { + "状态:离线" + } + carStateView.text = state + + timeView.text = "时间:${vehicleModel.ts}" + latLng.toChineseAddress(object : OnGeocodeSearchListener { + override fun onRegionCodeSearched(address: String) { + locationView.text = "位置:$address" + } + }) + } + } + + handlerDeviceCode -> { + if (isInfoWindowShow) { + val deviceModel = msg.obj as DeviceListModel.DataModel.RowsModel + + deviceModelView.text = "云台型号:${deviceModel.deviceModel}" + } + } + } + return true + } + + override fun onMarkerClick(marker: Marker?): Boolean { + //点击Marker显示自定义Popup + marker?.showInfoWindow() + return true + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + + private lateinit var windowTitleView: TextView + private lateinit var taskStateView: QMUIRoundButton + private lateinit var carStateView: TextView + private lateinit var deviceModelView: TextView + private lateinit var timeView: TextView + private lateinit var locationView: TextView + + override fun getInfoWindow(marker: Marker?): View { + isInfoWindowShow = true + + val v = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_car_window, null) + + windowTitleView = v.findViewById(R.id.windowTitleView) + taskStateView = v.findViewById(R.id.taskStateView) + val closeView = v.findViewById(R.id.closeView) + carStateView = v.findViewById(R.id.carStateView) + deviceModelView = v.findViewById(R.id.deviceModelView) + timeView = v.findViewById(R.id.timeView) + locationView = v.findViewById(R.id.locationView) + val routeView = v.findViewById(R.id.routeView) + + if (marker?.title == "Car") { + taskStateView.visibility = View.GONE + routeView.visibility = View.GONE + + vehicleViewModel.getVehicles() + + deviceViewModel.getDevices() + } else { + taskStateView.visibility = View.VISIBLE + routeView.visibility = View.VISIBLE + + routeView.setOnClickListener { + + } + } + + closeView.setOnClickListener { + marker?.hideInfoWindow() + isInfoWindowShow = false + } + return v } override fun initEvent() { @@ -44,9 +205,9 @@ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 1500, null) //设置起点 - addMarker(LatLng(39.914885, 116.272312), R.mipmap.start) + addMarker(LatLng(39.914885, 116.272312), "", R.mipmap.start) //设置终点 - addMarker(LatLng(39.914716, 116.265097), R.mipmap.end) + addMarker(LatLng(39.914716, 116.265097), "", R.mipmap.end) //瞄点画线 val latLngPoints = ArrayList() latLngPoints.add(LatLng(39.914885, 116.272312)) @@ -78,9 +239,10 @@ } - private fun addMarker(point: LatLng, res: Int) { + private fun addMarker(point: LatLng, type: String, res: Int) { val markerOption = MarkerOptions() markerOption.position(point) + markerOption.title(type) markerOption.icon(BitmapDescriptorFactory.fromResource(res)) aMap.addMarker(markerOption) } diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt new file mode 100644 index 0000000..ad16496 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt @@ -0,0 +1,5 @@ +package com.casic.br.ktd.listener + +interface OnGeocodeSearchListener { + fun onRegionCodeSearched(address: String) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt new file mode 100644 index 0000000..61104eb --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt @@ -0,0 +1,15 @@ +package com.casic.br.ktd.listener + +import java.io.File + +interface OnImageCompressListener { + /** + * Fired when a compression returns successfully, override to handle in your own code + */ + fun onSuccess(file: File) + + /** + * Fired when a compression fails to complete, override to handle in your own code + */ + fun onError(e: Throwable) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/model/PointModel.kt b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt new file mode 100644 index 0000000..ec2065d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt @@ -0,0 +1,3 @@ +package com.casic.br.ktd.model + +data class PointModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt b/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt deleted file mode 100644 index c45d645..0000000 --- a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.casic.br.ktd.model - -data class RouteModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java new file mode 100644 index 0000000..e813075 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java @@ -0,0 +1,166 @@ +package com.casic.br.ktd.model; + +import java.util.List; + +public class VehicleRouteModel { + + private Integer code; + private DataModel data; + private String message; + + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } + + public DataModel getData() { + return data; + } + + public void setData(DataModel data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public static class DataModel { + private List rows; + private Integer total; + + public List getRows() { + return rows; + } + + public void setRows(List rows) { + this.rows = rows; + } + + public Integer getTotal() { + return total; + } + + public void setTotal(Integer total) { + this.total = total; + } + + public static class RowsModel { + private String deviceStatus; + private String direction; + private String gas; + private String id; + private String isAlarm; + private String lagitude; + private String longitude; + private String pitch; + private String position; + private String speed; + private String taskId; + private String ts; + + public String getDeviceStatus() { + return deviceStatus; + } + + public void setDeviceStatus(String deviceStatus) { + this.deviceStatus = deviceStatus; + } + + public String getDirection() { + return direction; + } + + public void setDirection(String direction) { + this.direction = direction; + } + + public String getGas() { + return gas; + } + + public void setGas(String gas) { + this.gas = gas; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getIsAlarm() { + return isAlarm; + } + + public void setIsAlarm(String isAlarm) { + this.isAlarm = isAlarm; + } + + public String getLagitude() { + return lagitude; + } + + public void setLagitude(String lagitude) { + this.lagitude = lagitude; + } + + public String getLongitude() { + return longitude; + } + + public void setLongitude(String longitude) { + this.longitude = longitude; + } + + public String getPitch() { + return pitch; + } + + public void setPitch(String pitch) { + this.pitch = pitch; + } + + public String getPosition() { + return position; + } + + public void setPosition(String position) { + this.position = position; + } + + public String getSpeed() { + return speed; + } + + public void setSpeed(String speed) { + this.speed = speed; + } + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public String getTs() { + return ts; + } + + public void setTs(String ts) { + this.ts = ts; + } + } + } +} diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt index 9211b3a..519ab45 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt @@ -49,7 +49,7 @@ @Header("token") token: String, @Body requestBody: RequestBody, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -78,7 +78,7 @@ suspend fun getVehicles( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -88,7 +88,7 @@ suspend fun getDevices( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -101,6 +101,16 @@ ): String /** + * 巡检路径 + */ + @POST("/system/busPatrolTrack/listPage") + suspend fun busTrackRoute( + @Header("token") token: String, + @QueryMap limit: Map, + @QueryMap offset: Map + ): String + + /** * 新增报警规则,主要是阈值 */ @POST("/system/alarmRule/add") @@ -116,7 +126,7 @@ suspend fun getAlarmRules( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -146,6 +156,6 @@ @Header("token") token: String, @Body requestBody: RequestBody, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt index 0f109db..fd9624c 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt @@ -186,6 +186,18 @@ } /** + * 巡检路径 + */ + suspend fun busTrackRoute(): String { + val limitMap = HashMap() + limitMap["limit"] = LocaleConstant.PAGE_LIMIT + + val offsetMap = HashMap() + offsetMap["offset"] = 1 + return api.busTrackRoute(AuthenticationHelper.token, limitMap, offsetMap) + } + + /** * 新增报警规则,主要是阈值 */ suspend fun addAlarmRule(high: String, deviceId: String, ts: String): String { diff --git a/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt deleted file mode 100644 index 92286ad..0000000 --- a/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.br.ktd.utils - -import java.io.File - -interface OnImageCompressListener { - /** - * Fired when a compression returns successfully, override to handle in your own code - */ - fun onSuccess(file: File) - - /** - * Fired when a compression fails to complete, override to handle in your own code - */ - fun onError(e: Throwable) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt b/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt index b3146e7..7d6e558 100644 --- a/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt +++ b/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt @@ -29,7 +29,7 @@ import com.casic.br.ktd.extensions.* import com.casic.br.ktd.model.AlarmParam import com.casic.br.ktd.model.ChartPointModel -import com.casic.br.ktd.model.RouteModel +import com.casic.br.ktd.model.PointModel import com.casic.br.ktd.model.SensorDataModel import com.casic.br.ktd.netty.tcp.SocketManager import com.casic.br.ktd.netty.udp.UdpClient @@ -273,9 +273,9 @@ ) if (isStartInspect) { - val route = LinkedList() + val route = LinkedList() latlngs.forEach { - route.add(RouteModel(it.latitude, it.longitude)) + route.add(PointModel(it.latitude, it.longitude)) } } } diff --git a/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt new file mode 100644 index 0000000..40b3660 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt @@ -0,0 +1,28 @@ +package com.casic.br.ktd.extensions + +import com.amap.api.maps.model.LatLng +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.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.listener.OnGeocodeSearchListener + +private val geocoderSearch by lazy { GeocodeSearch(BaseApplication.get()) } + +fun LatLng.toChineseAddress(listener: OnGeocodeSearchListener) { + val queryParam = RegeocodeQuery( + LatLonPoint(this.latitude, this.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + listener.onRegionCodeSearched(regeocodeResult.regeocodeAddress.formatAddress) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index 36af820..e090122 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -1,9 +1,9 @@ package com.casic.br.ktd.extensions import android.content.Context +import com.casic.br.ktd.listener.OnImageCompressListener import com.casic.br.ktd.model.ErrorMessageModel import com.casic.br.ktd.utils.LocaleConstant -import com.casic.br.ktd.utils.OnImageCompressListener import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.createCompressImageDir @@ -14,7 +14,8 @@ import top.zibin.luban.OnCompressListener import java.io.File import java.text.SimpleDateFormat -import java.util.* +import java.util.Date +import java.util.Locale import java.util.regex.Pattern diff --git a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt index 40b27b1..a8d1e7a 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt @@ -2,31 +2,55 @@ import android.graphics.Color import android.os.Bundle +import android.os.Handler +import android.os.Message import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.model.BitmapDescriptorFactory import com.amap.api.maps.model.CameraPosition import com.amap.api.maps.model.LatLng +import com.amap.api.maps.model.Marker import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.PolylineOptions import com.casic.br.ktd.R import com.casic.br.ktd.databinding.FragmentHomeBinding +import com.casic.br.ktd.extensions.toChineseAddress +import com.casic.br.ktd.listener.OnGeocodeSearchListener +import com.casic.br.ktd.model.DeviceListModel +import com.casic.br.ktd.model.VehicleListModel +import com.casic.br.ktd.utils.LocaleConstant +import com.casic.br.ktd.vm.DeviceViewModel +import com.casic.br.ktd.vm.VehicleViewModel import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.utils.SaveKeyValues +import com.pengxh.kt.lite.utils.WeakReferenceHandler +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton -class HomePageFragment : KotlinBaseFragment() { +class HomePageFragment : KotlinBaseFragment(), AMap.OnMarkerClickListener, + AMap.InfoWindowAdapter, Handler.Callback { + + private val kTag = "HomePageFragment" + private lateinit var vehicleViewModel: VehicleViewModel + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private lateinit var weakReferenceHandler: WeakReferenceHandler + private var isInfoWindowShow = false + private val handlerVehicleCode = 2023082501 + private val handlerDeviceCode = 2023082502 override fun initViewBinding( - inflater: LayoutInflater, - container: ViewGroup? + inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { return FragmentHomeBinding.inflate(inflater, container, false) } - private lateinit var aMap: AMap - override fun initOnCreate(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -36,6 +60,143 @@ uiSettings.isScaleControlsEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isRotateGesturesEnabled = false//不许地图随手势旋转角度 + // 点击marker弹出自定义popup + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) + + weakReferenceHandler = WeakReferenceHandler(this) + + vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] + vehicleViewModel.getVehicles() + vehicleViewModel.vehicleList.observe(this) { + if (it.code == 200) { + if (it.data.rows.isNotEmpty()) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerVehicleCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + deviceViewModel.deviceList.observe(this) { + if (it.code == 200) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerDeviceCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + handlerVehicleCode -> { + val vehicleModel = msg.obj as VehicleListModel.DataModel.RowsModel + + SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, vehicleModel.carPlate) + SaveKeyValues.putValue(LocaleConstant.CAR_ID, vehicleModel.id) + + val marker = if (vehicleModel.status == "1") { + //在线 + R.mipmap.vehicle_on + } else { + //离线 + R.mipmap.vehicle_on + } + + val latLng = LatLng( + vehicleModel.latitude.toDouble(), vehicleModel.longitude.toDouble() + ) + addMarker(latLng, "Car", marker) + + /** + * 地图PopupWindow数据绑定 + * ****/ + if (isInfoWindowShow) { + windowTitleView.text = vehicleModel.carPlate + val state = if (vehicleModel.status == "1") { + "状态:在线" + } else { + "状态:离线" + } + carStateView.text = state + + timeView.text = "时间:${vehicleModel.ts}" + latLng.toChineseAddress(object : OnGeocodeSearchListener { + override fun onRegionCodeSearched(address: String) { + locationView.text = "位置:$address" + } + }) + } + } + + handlerDeviceCode -> { + if (isInfoWindowShow) { + val deviceModel = msg.obj as DeviceListModel.DataModel.RowsModel + + deviceModelView.text = "云台型号:${deviceModel.deviceModel}" + } + } + } + return true + } + + override fun onMarkerClick(marker: Marker?): Boolean { + //点击Marker显示自定义Popup + marker?.showInfoWindow() + return true + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + + private lateinit var windowTitleView: TextView + private lateinit var taskStateView: QMUIRoundButton + private lateinit var carStateView: TextView + private lateinit var deviceModelView: TextView + private lateinit var timeView: TextView + private lateinit var locationView: TextView + + override fun getInfoWindow(marker: Marker?): View { + isInfoWindowShow = true + + val v = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_car_window, null) + + windowTitleView = v.findViewById(R.id.windowTitleView) + taskStateView = v.findViewById(R.id.taskStateView) + val closeView = v.findViewById(R.id.closeView) + carStateView = v.findViewById(R.id.carStateView) + deviceModelView = v.findViewById(R.id.deviceModelView) + timeView = v.findViewById(R.id.timeView) + locationView = v.findViewById(R.id.locationView) + val routeView = v.findViewById(R.id.routeView) + + if (marker?.title == "Car") { + taskStateView.visibility = View.GONE + routeView.visibility = View.GONE + + vehicleViewModel.getVehicles() + + deviceViewModel.getDevices() + } else { + taskStateView.visibility = View.VISIBLE + routeView.visibility = View.VISIBLE + + routeView.setOnClickListener { + + } + } + + closeView.setOnClickListener { + marker?.hideInfoWindow() + isInfoWindowShow = false + } + return v } override fun initEvent() { @@ -44,9 +205,9 @@ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 1500, null) //设置起点 - addMarker(LatLng(39.914885, 116.272312), R.mipmap.start) + addMarker(LatLng(39.914885, 116.272312), "", R.mipmap.start) //设置终点 - addMarker(LatLng(39.914716, 116.265097), R.mipmap.end) + addMarker(LatLng(39.914716, 116.265097), "", R.mipmap.end) //瞄点画线 val latLngPoints = ArrayList() latLngPoints.add(LatLng(39.914885, 116.272312)) @@ -78,9 +239,10 @@ } - private fun addMarker(point: LatLng, res: Int) { + private fun addMarker(point: LatLng, type: String, res: Int) { val markerOption = MarkerOptions() markerOption.position(point) + markerOption.title(type) markerOption.icon(BitmapDescriptorFactory.fromResource(res)) aMap.addMarker(markerOption) } diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt new file mode 100644 index 0000000..ad16496 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt @@ -0,0 +1,5 @@ +package com.casic.br.ktd.listener + +interface OnGeocodeSearchListener { + fun onRegionCodeSearched(address: String) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt new file mode 100644 index 0000000..61104eb --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt @@ -0,0 +1,15 @@ +package com.casic.br.ktd.listener + +import java.io.File + +interface OnImageCompressListener { + /** + * Fired when a compression returns successfully, override to handle in your own code + */ + fun onSuccess(file: File) + + /** + * Fired when a compression fails to complete, override to handle in your own code + */ + fun onError(e: Throwable) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/model/PointModel.kt b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt new file mode 100644 index 0000000..ec2065d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt @@ -0,0 +1,3 @@ +package com.casic.br.ktd.model + +data class PointModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt b/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt deleted file mode 100644 index c45d645..0000000 --- a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.casic.br.ktd.model - -data class RouteModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java new file mode 100644 index 0000000..e813075 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java @@ -0,0 +1,166 @@ +package com.casic.br.ktd.model; + +import java.util.List; + +public class VehicleRouteModel { + + private Integer code; + private DataModel data; + private String message; + + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } + + public DataModel getData() { + return data; + } + + public void setData(DataModel data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public static class DataModel { + private List rows; + private Integer total; + + public List getRows() { + return rows; + } + + public void setRows(List rows) { + this.rows = rows; + } + + public Integer getTotal() { + return total; + } + + public void setTotal(Integer total) { + this.total = total; + } + + public static class RowsModel { + private String deviceStatus; + private String direction; + private String gas; + private String id; + private String isAlarm; + private String lagitude; + private String longitude; + private String pitch; + private String position; + private String speed; + private String taskId; + private String ts; + + public String getDeviceStatus() { + return deviceStatus; + } + + public void setDeviceStatus(String deviceStatus) { + this.deviceStatus = deviceStatus; + } + + public String getDirection() { + return direction; + } + + public void setDirection(String direction) { + this.direction = direction; + } + + public String getGas() { + return gas; + } + + public void setGas(String gas) { + this.gas = gas; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getIsAlarm() { + return isAlarm; + } + + public void setIsAlarm(String isAlarm) { + this.isAlarm = isAlarm; + } + + public String getLagitude() { + return lagitude; + } + + public void setLagitude(String lagitude) { + this.lagitude = lagitude; + } + + public String getLongitude() { + return longitude; + } + + public void setLongitude(String longitude) { + this.longitude = longitude; + } + + public String getPitch() { + return pitch; + } + + public void setPitch(String pitch) { + this.pitch = pitch; + } + + public String getPosition() { + return position; + } + + public void setPosition(String position) { + this.position = position; + } + + public String getSpeed() { + return speed; + } + + public void setSpeed(String speed) { + this.speed = speed; + } + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public String getTs() { + return ts; + } + + public void setTs(String ts) { + this.ts = ts; + } + } + } +} diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt index 9211b3a..519ab45 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt @@ -49,7 +49,7 @@ @Header("token") token: String, @Body requestBody: RequestBody, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -78,7 +78,7 @@ suspend fun getVehicles( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -88,7 +88,7 @@ suspend fun getDevices( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -101,6 +101,16 @@ ): String /** + * 巡检路径 + */ + @POST("/system/busPatrolTrack/listPage") + suspend fun busTrackRoute( + @Header("token") token: String, + @QueryMap limit: Map, + @QueryMap offset: Map + ): String + + /** * 新增报警规则,主要是阈值 */ @POST("/system/alarmRule/add") @@ -116,7 +126,7 @@ suspend fun getAlarmRules( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -146,6 +156,6 @@ @Header("token") token: String, @Body requestBody: RequestBody, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt index 0f109db..fd9624c 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt @@ -186,6 +186,18 @@ } /** + * 巡检路径 + */ + suspend fun busTrackRoute(): String { + val limitMap = HashMap() + limitMap["limit"] = LocaleConstant.PAGE_LIMIT + + val offsetMap = HashMap() + offsetMap["offset"] = 1 + return api.busTrackRoute(AuthenticationHelper.token, limitMap, offsetMap) + } + + /** * 新增报警规则,主要是阈值 */ suspend fun addAlarmRule(high: String, deviceId: String, ts: String): String { diff --git a/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt deleted file mode 100644 index 92286ad..0000000 --- a/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.br.ktd.utils - -import java.io.File - -interface OnImageCompressListener { - /** - * Fired when a compression returns successfully, override to handle in your own code - */ - fun onSuccess(file: File) - - /** - * Fired when a compression fails to complete, override to handle in your own code - */ - fun onError(e: Throwable) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt b/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt index b3146e7..7d6e558 100644 --- a/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt +++ b/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt @@ -29,7 +29,7 @@ import com.casic.br.ktd.extensions.* import com.casic.br.ktd.model.AlarmParam import com.casic.br.ktd.model.ChartPointModel -import com.casic.br.ktd.model.RouteModel +import com.casic.br.ktd.model.PointModel import com.casic.br.ktd.model.SensorDataModel import com.casic.br.ktd.netty.tcp.SocketManager import com.casic.br.ktd.netty.udp.UdpClient @@ -273,9 +273,9 @@ ) if (isStartInspect) { - val route = LinkedList() + val route = LinkedList() latlngs.forEach { - route.add(RouteModel(it.latitude, it.longitude)) + route.add(PointModel(it.latitude, it.longitude)) } } } diff --git a/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt b/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt index bce4c24..b3c519a 100644 --- a/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt +++ b/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt @@ -21,7 +21,6 @@ import com.casic.br.ktd.fragment.TaskPageFragment import com.casic.br.ktd.utils.LocaleConstant import com.casic.br.ktd.vm.AlarmViewModel -import com.casic.br.ktd.vm.VehicleViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.show @@ -36,7 +35,6 @@ private val fragmentPages = ArrayList() private val slideAdapter by lazy { SlideAdapter(this) } private var clickTime: Long = 0 - private lateinit var vehicleViewModel: VehicleViewModel private lateinit var alarmViewModel: AlarmViewModel init { @@ -71,20 +69,6 @@ //显示首页 switchPage(fragmentPages[0]) - vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] - vehicleViewModel.getVehicles() - vehicleViewModel.vehicleList.observe(this) { - if (it.code == 200) { - if (it.data.rows.isNotEmpty()) { - val model = it.data.rows[0] - SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, model.carPlate) - SaveKeyValues.putValue(LocaleConstant.CAR_ID, model.id) - } else { - Log.d(kTag, "initData => 无可用巡检车") - } - } - } - alarmViewModel = ViewModelProvider(this)[AlarmViewModel::class.java] alarmViewModel.getAlarmRules() alarmViewModel.alarmRuleList.observe(this) { diff --git a/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt new file mode 100644 index 0000000..40b3660 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt @@ -0,0 +1,28 @@ +package com.casic.br.ktd.extensions + +import com.amap.api.maps.model.LatLng +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.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.listener.OnGeocodeSearchListener + +private val geocoderSearch by lazy { GeocodeSearch(BaseApplication.get()) } + +fun LatLng.toChineseAddress(listener: OnGeocodeSearchListener) { + val queryParam = RegeocodeQuery( + LatLonPoint(this.latitude, this.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + listener.onRegionCodeSearched(regeocodeResult.regeocodeAddress.formatAddress) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index 36af820..e090122 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -1,9 +1,9 @@ package com.casic.br.ktd.extensions import android.content.Context +import com.casic.br.ktd.listener.OnImageCompressListener import com.casic.br.ktd.model.ErrorMessageModel import com.casic.br.ktd.utils.LocaleConstant -import com.casic.br.ktd.utils.OnImageCompressListener import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.createCompressImageDir @@ -14,7 +14,8 @@ import top.zibin.luban.OnCompressListener import java.io.File import java.text.SimpleDateFormat -import java.util.* +import java.util.Date +import java.util.Locale import java.util.regex.Pattern diff --git a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt index 40b27b1..a8d1e7a 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt @@ -2,31 +2,55 @@ import android.graphics.Color import android.os.Bundle +import android.os.Handler +import android.os.Message import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.model.BitmapDescriptorFactory import com.amap.api.maps.model.CameraPosition import com.amap.api.maps.model.LatLng +import com.amap.api.maps.model.Marker import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.PolylineOptions import com.casic.br.ktd.R import com.casic.br.ktd.databinding.FragmentHomeBinding +import com.casic.br.ktd.extensions.toChineseAddress +import com.casic.br.ktd.listener.OnGeocodeSearchListener +import com.casic.br.ktd.model.DeviceListModel +import com.casic.br.ktd.model.VehicleListModel +import com.casic.br.ktd.utils.LocaleConstant +import com.casic.br.ktd.vm.DeviceViewModel +import com.casic.br.ktd.vm.VehicleViewModel import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.utils.SaveKeyValues +import com.pengxh.kt.lite.utils.WeakReferenceHandler +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton -class HomePageFragment : KotlinBaseFragment() { +class HomePageFragment : KotlinBaseFragment(), AMap.OnMarkerClickListener, + AMap.InfoWindowAdapter, Handler.Callback { + + private val kTag = "HomePageFragment" + private lateinit var vehicleViewModel: VehicleViewModel + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private lateinit var weakReferenceHandler: WeakReferenceHandler + private var isInfoWindowShow = false + private val handlerVehicleCode = 2023082501 + private val handlerDeviceCode = 2023082502 override fun initViewBinding( - inflater: LayoutInflater, - container: ViewGroup? + inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { return FragmentHomeBinding.inflate(inflater, container, false) } - private lateinit var aMap: AMap - override fun initOnCreate(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -36,6 +60,143 @@ uiSettings.isScaleControlsEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isRotateGesturesEnabled = false//不许地图随手势旋转角度 + // 点击marker弹出自定义popup + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) + + weakReferenceHandler = WeakReferenceHandler(this) + + vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] + vehicleViewModel.getVehicles() + vehicleViewModel.vehicleList.observe(this) { + if (it.code == 200) { + if (it.data.rows.isNotEmpty()) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerVehicleCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + deviceViewModel.deviceList.observe(this) { + if (it.code == 200) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerDeviceCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + handlerVehicleCode -> { + val vehicleModel = msg.obj as VehicleListModel.DataModel.RowsModel + + SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, vehicleModel.carPlate) + SaveKeyValues.putValue(LocaleConstant.CAR_ID, vehicleModel.id) + + val marker = if (vehicleModel.status == "1") { + //在线 + R.mipmap.vehicle_on + } else { + //离线 + R.mipmap.vehicle_on + } + + val latLng = LatLng( + vehicleModel.latitude.toDouble(), vehicleModel.longitude.toDouble() + ) + addMarker(latLng, "Car", marker) + + /** + * 地图PopupWindow数据绑定 + * ****/ + if (isInfoWindowShow) { + windowTitleView.text = vehicleModel.carPlate + val state = if (vehicleModel.status == "1") { + "状态:在线" + } else { + "状态:离线" + } + carStateView.text = state + + timeView.text = "时间:${vehicleModel.ts}" + latLng.toChineseAddress(object : OnGeocodeSearchListener { + override fun onRegionCodeSearched(address: String) { + locationView.text = "位置:$address" + } + }) + } + } + + handlerDeviceCode -> { + if (isInfoWindowShow) { + val deviceModel = msg.obj as DeviceListModel.DataModel.RowsModel + + deviceModelView.text = "云台型号:${deviceModel.deviceModel}" + } + } + } + return true + } + + override fun onMarkerClick(marker: Marker?): Boolean { + //点击Marker显示自定义Popup + marker?.showInfoWindow() + return true + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + + private lateinit var windowTitleView: TextView + private lateinit var taskStateView: QMUIRoundButton + private lateinit var carStateView: TextView + private lateinit var deviceModelView: TextView + private lateinit var timeView: TextView + private lateinit var locationView: TextView + + override fun getInfoWindow(marker: Marker?): View { + isInfoWindowShow = true + + val v = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_car_window, null) + + windowTitleView = v.findViewById(R.id.windowTitleView) + taskStateView = v.findViewById(R.id.taskStateView) + val closeView = v.findViewById(R.id.closeView) + carStateView = v.findViewById(R.id.carStateView) + deviceModelView = v.findViewById(R.id.deviceModelView) + timeView = v.findViewById(R.id.timeView) + locationView = v.findViewById(R.id.locationView) + val routeView = v.findViewById(R.id.routeView) + + if (marker?.title == "Car") { + taskStateView.visibility = View.GONE + routeView.visibility = View.GONE + + vehicleViewModel.getVehicles() + + deviceViewModel.getDevices() + } else { + taskStateView.visibility = View.VISIBLE + routeView.visibility = View.VISIBLE + + routeView.setOnClickListener { + + } + } + + closeView.setOnClickListener { + marker?.hideInfoWindow() + isInfoWindowShow = false + } + return v } override fun initEvent() { @@ -44,9 +205,9 @@ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 1500, null) //设置起点 - addMarker(LatLng(39.914885, 116.272312), R.mipmap.start) + addMarker(LatLng(39.914885, 116.272312), "", R.mipmap.start) //设置终点 - addMarker(LatLng(39.914716, 116.265097), R.mipmap.end) + addMarker(LatLng(39.914716, 116.265097), "", R.mipmap.end) //瞄点画线 val latLngPoints = ArrayList() latLngPoints.add(LatLng(39.914885, 116.272312)) @@ -78,9 +239,10 @@ } - private fun addMarker(point: LatLng, res: Int) { + private fun addMarker(point: LatLng, type: String, res: Int) { val markerOption = MarkerOptions() markerOption.position(point) + markerOption.title(type) markerOption.icon(BitmapDescriptorFactory.fromResource(res)) aMap.addMarker(markerOption) } diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt new file mode 100644 index 0000000..ad16496 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt @@ -0,0 +1,5 @@ +package com.casic.br.ktd.listener + +interface OnGeocodeSearchListener { + fun onRegionCodeSearched(address: String) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt new file mode 100644 index 0000000..61104eb --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt @@ -0,0 +1,15 @@ +package com.casic.br.ktd.listener + +import java.io.File + +interface OnImageCompressListener { + /** + * Fired when a compression returns successfully, override to handle in your own code + */ + fun onSuccess(file: File) + + /** + * Fired when a compression fails to complete, override to handle in your own code + */ + fun onError(e: Throwable) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/model/PointModel.kt b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt new file mode 100644 index 0000000..ec2065d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt @@ -0,0 +1,3 @@ +package com.casic.br.ktd.model + +data class PointModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt b/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt deleted file mode 100644 index c45d645..0000000 --- a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.casic.br.ktd.model - -data class RouteModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java new file mode 100644 index 0000000..e813075 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java @@ -0,0 +1,166 @@ +package com.casic.br.ktd.model; + +import java.util.List; + +public class VehicleRouteModel { + + private Integer code; + private DataModel data; + private String message; + + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } + + public DataModel getData() { + return data; + } + + public void setData(DataModel data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public static class DataModel { + private List rows; + private Integer total; + + public List getRows() { + return rows; + } + + public void setRows(List rows) { + this.rows = rows; + } + + public Integer getTotal() { + return total; + } + + public void setTotal(Integer total) { + this.total = total; + } + + public static class RowsModel { + private String deviceStatus; + private String direction; + private String gas; + private String id; + private String isAlarm; + private String lagitude; + private String longitude; + private String pitch; + private String position; + private String speed; + private String taskId; + private String ts; + + public String getDeviceStatus() { + return deviceStatus; + } + + public void setDeviceStatus(String deviceStatus) { + this.deviceStatus = deviceStatus; + } + + public String getDirection() { + return direction; + } + + public void setDirection(String direction) { + this.direction = direction; + } + + public String getGas() { + return gas; + } + + public void setGas(String gas) { + this.gas = gas; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getIsAlarm() { + return isAlarm; + } + + public void setIsAlarm(String isAlarm) { + this.isAlarm = isAlarm; + } + + public String getLagitude() { + return lagitude; + } + + public void setLagitude(String lagitude) { + this.lagitude = lagitude; + } + + public String getLongitude() { + return longitude; + } + + public void setLongitude(String longitude) { + this.longitude = longitude; + } + + public String getPitch() { + return pitch; + } + + public void setPitch(String pitch) { + this.pitch = pitch; + } + + public String getPosition() { + return position; + } + + public void setPosition(String position) { + this.position = position; + } + + public String getSpeed() { + return speed; + } + + public void setSpeed(String speed) { + this.speed = speed; + } + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public String getTs() { + return ts; + } + + public void setTs(String ts) { + this.ts = ts; + } + } + } +} diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt index 9211b3a..519ab45 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt @@ -49,7 +49,7 @@ @Header("token") token: String, @Body requestBody: RequestBody, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -78,7 +78,7 @@ suspend fun getVehicles( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -88,7 +88,7 @@ suspend fun getDevices( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -101,6 +101,16 @@ ): String /** + * 巡检路径 + */ + @POST("/system/busPatrolTrack/listPage") + suspend fun busTrackRoute( + @Header("token") token: String, + @QueryMap limit: Map, + @QueryMap offset: Map + ): String + + /** * 新增报警规则,主要是阈值 */ @POST("/system/alarmRule/add") @@ -116,7 +126,7 @@ suspend fun getAlarmRules( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -146,6 +156,6 @@ @Header("token") token: String, @Body requestBody: RequestBody, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt index 0f109db..fd9624c 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt @@ -186,6 +186,18 @@ } /** + * 巡检路径 + */ + suspend fun busTrackRoute(): String { + val limitMap = HashMap() + limitMap["limit"] = LocaleConstant.PAGE_LIMIT + + val offsetMap = HashMap() + offsetMap["offset"] = 1 + return api.busTrackRoute(AuthenticationHelper.token, limitMap, offsetMap) + } + + /** * 新增报警规则,主要是阈值 */ suspend fun addAlarmRule(high: String, deviceId: String, ts: String): String { diff --git a/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt deleted file mode 100644 index 92286ad..0000000 --- a/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.br.ktd.utils - -import java.io.File - -interface OnImageCompressListener { - /** - * Fired when a compression returns successfully, override to handle in your own code - */ - fun onSuccess(file: File) - - /** - * Fired when a compression fails to complete, override to handle in your own code - */ - fun onError(e: Throwable) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt b/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt index b3146e7..7d6e558 100644 --- a/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt +++ b/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt @@ -29,7 +29,7 @@ import com.casic.br.ktd.extensions.* import com.casic.br.ktd.model.AlarmParam import com.casic.br.ktd.model.ChartPointModel -import com.casic.br.ktd.model.RouteModel +import com.casic.br.ktd.model.PointModel import com.casic.br.ktd.model.SensorDataModel import com.casic.br.ktd.netty.tcp.SocketManager import com.casic.br.ktd.netty.udp.UdpClient @@ -273,9 +273,9 @@ ) if (isStartInspect) { - val route = LinkedList() + val route = LinkedList() latlngs.forEach { - route.add(RouteModel(it.latitude, it.longitude)) + route.add(PointModel(it.latitude, it.longitude)) } } } diff --git a/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt b/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt index bce4c24..b3c519a 100644 --- a/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt +++ b/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt @@ -21,7 +21,6 @@ import com.casic.br.ktd.fragment.TaskPageFragment import com.casic.br.ktd.utils.LocaleConstant import com.casic.br.ktd.vm.AlarmViewModel -import com.casic.br.ktd.vm.VehicleViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.show @@ -36,7 +35,6 @@ private val fragmentPages = ArrayList() private val slideAdapter by lazy { SlideAdapter(this) } private var clickTime: Long = 0 - private lateinit var vehicleViewModel: VehicleViewModel private lateinit var alarmViewModel: AlarmViewModel init { @@ -71,20 +69,6 @@ //显示首页 switchPage(fragmentPages[0]) - vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] - vehicleViewModel.getVehicles() - vehicleViewModel.vehicleList.observe(this) { - if (it.code == 200) { - if (it.data.rows.isNotEmpty()) { - val model = it.data.rows[0] - SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, model.carPlate) - SaveKeyValues.putValue(LocaleConstant.CAR_ID, model.id) - } else { - Log.d(kTag, "initData => 无可用巡检车") - } - } - } - alarmViewModel = ViewModelProvider(this)[AlarmViewModel::class.java] alarmViewModel.getAlarmRules() alarmViewModel.alarmRuleList.observe(this) { diff --git a/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt b/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt index d81e7d6..c869ed8 100644 --- a/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt +++ b/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt @@ -1,7 +1,15 @@ package com.casic.br.ktd.vm +import androidx.lifecycle.MutableLiveData +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.extensions.separateResponseCode +import com.casic.br.ktd.extensions.toErrorMessage +import com.casic.br.ktd.model.VehicleRouteModel import com.casic.br.ktd.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.launch +import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.vm.BaseViewModel /** @@ -9,6 +17,9 @@ * */ class PointViewModel : BaseViewModel() { + private val gson by lazy { Gson() } + val vehicleRoute = MutableLiveData() + fun uploadPointDetail( isAlarm: String, lagitude: String, @@ -36,4 +47,18 @@ }, { it.printStackTrace() }) + + fun busTrackRoute() = launch({ + val response = RetrofitServiceManager.busTrackRoute() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + vehicleRoute.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + }) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt new file mode 100644 index 0000000..40b3660 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt @@ -0,0 +1,28 @@ +package com.casic.br.ktd.extensions + +import com.amap.api.maps.model.LatLng +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.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.listener.OnGeocodeSearchListener + +private val geocoderSearch by lazy { GeocodeSearch(BaseApplication.get()) } + +fun LatLng.toChineseAddress(listener: OnGeocodeSearchListener) { + val queryParam = RegeocodeQuery( + LatLonPoint(this.latitude, this.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + listener.onRegionCodeSearched(regeocodeResult.regeocodeAddress.formatAddress) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index 36af820..e090122 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -1,9 +1,9 @@ package com.casic.br.ktd.extensions import android.content.Context +import com.casic.br.ktd.listener.OnImageCompressListener import com.casic.br.ktd.model.ErrorMessageModel import com.casic.br.ktd.utils.LocaleConstant -import com.casic.br.ktd.utils.OnImageCompressListener import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.createCompressImageDir @@ -14,7 +14,8 @@ import top.zibin.luban.OnCompressListener import java.io.File import java.text.SimpleDateFormat -import java.util.* +import java.util.Date +import java.util.Locale import java.util.regex.Pattern diff --git a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt index 40b27b1..a8d1e7a 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt @@ -2,31 +2,55 @@ import android.graphics.Color import android.os.Bundle +import android.os.Handler +import android.os.Message import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.model.BitmapDescriptorFactory import com.amap.api.maps.model.CameraPosition import com.amap.api.maps.model.LatLng +import com.amap.api.maps.model.Marker import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.PolylineOptions import com.casic.br.ktd.R import com.casic.br.ktd.databinding.FragmentHomeBinding +import com.casic.br.ktd.extensions.toChineseAddress +import com.casic.br.ktd.listener.OnGeocodeSearchListener +import com.casic.br.ktd.model.DeviceListModel +import com.casic.br.ktd.model.VehicleListModel +import com.casic.br.ktd.utils.LocaleConstant +import com.casic.br.ktd.vm.DeviceViewModel +import com.casic.br.ktd.vm.VehicleViewModel import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.utils.SaveKeyValues +import com.pengxh.kt.lite.utils.WeakReferenceHandler +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton -class HomePageFragment : KotlinBaseFragment() { +class HomePageFragment : KotlinBaseFragment(), AMap.OnMarkerClickListener, + AMap.InfoWindowAdapter, Handler.Callback { + + private val kTag = "HomePageFragment" + private lateinit var vehicleViewModel: VehicleViewModel + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private lateinit var weakReferenceHandler: WeakReferenceHandler + private var isInfoWindowShow = false + private val handlerVehicleCode = 2023082501 + private val handlerDeviceCode = 2023082502 override fun initViewBinding( - inflater: LayoutInflater, - container: ViewGroup? + inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { return FragmentHomeBinding.inflate(inflater, container, false) } - private lateinit var aMap: AMap - override fun initOnCreate(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -36,6 +60,143 @@ uiSettings.isScaleControlsEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isRotateGesturesEnabled = false//不许地图随手势旋转角度 + // 点击marker弹出自定义popup + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) + + weakReferenceHandler = WeakReferenceHandler(this) + + vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] + vehicleViewModel.getVehicles() + vehicleViewModel.vehicleList.observe(this) { + if (it.code == 200) { + if (it.data.rows.isNotEmpty()) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerVehicleCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + deviceViewModel.deviceList.observe(this) { + if (it.code == 200) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerDeviceCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + handlerVehicleCode -> { + val vehicleModel = msg.obj as VehicleListModel.DataModel.RowsModel + + SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, vehicleModel.carPlate) + SaveKeyValues.putValue(LocaleConstant.CAR_ID, vehicleModel.id) + + val marker = if (vehicleModel.status == "1") { + //在线 + R.mipmap.vehicle_on + } else { + //离线 + R.mipmap.vehicle_on + } + + val latLng = LatLng( + vehicleModel.latitude.toDouble(), vehicleModel.longitude.toDouble() + ) + addMarker(latLng, "Car", marker) + + /** + * 地图PopupWindow数据绑定 + * ****/ + if (isInfoWindowShow) { + windowTitleView.text = vehicleModel.carPlate + val state = if (vehicleModel.status == "1") { + "状态:在线" + } else { + "状态:离线" + } + carStateView.text = state + + timeView.text = "时间:${vehicleModel.ts}" + latLng.toChineseAddress(object : OnGeocodeSearchListener { + override fun onRegionCodeSearched(address: String) { + locationView.text = "位置:$address" + } + }) + } + } + + handlerDeviceCode -> { + if (isInfoWindowShow) { + val deviceModel = msg.obj as DeviceListModel.DataModel.RowsModel + + deviceModelView.text = "云台型号:${deviceModel.deviceModel}" + } + } + } + return true + } + + override fun onMarkerClick(marker: Marker?): Boolean { + //点击Marker显示自定义Popup + marker?.showInfoWindow() + return true + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + + private lateinit var windowTitleView: TextView + private lateinit var taskStateView: QMUIRoundButton + private lateinit var carStateView: TextView + private lateinit var deviceModelView: TextView + private lateinit var timeView: TextView + private lateinit var locationView: TextView + + override fun getInfoWindow(marker: Marker?): View { + isInfoWindowShow = true + + val v = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_car_window, null) + + windowTitleView = v.findViewById(R.id.windowTitleView) + taskStateView = v.findViewById(R.id.taskStateView) + val closeView = v.findViewById(R.id.closeView) + carStateView = v.findViewById(R.id.carStateView) + deviceModelView = v.findViewById(R.id.deviceModelView) + timeView = v.findViewById(R.id.timeView) + locationView = v.findViewById(R.id.locationView) + val routeView = v.findViewById(R.id.routeView) + + if (marker?.title == "Car") { + taskStateView.visibility = View.GONE + routeView.visibility = View.GONE + + vehicleViewModel.getVehicles() + + deviceViewModel.getDevices() + } else { + taskStateView.visibility = View.VISIBLE + routeView.visibility = View.VISIBLE + + routeView.setOnClickListener { + + } + } + + closeView.setOnClickListener { + marker?.hideInfoWindow() + isInfoWindowShow = false + } + return v } override fun initEvent() { @@ -44,9 +205,9 @@ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 1500, null) //设置起点 - addMarker(LatLng(39.914885, 116.272312), R.mipmap.start) + addMarker(LatLng(39.914885, 116.272312), "", R.mipmap.start) //设置终点 - addMarker(LatLng(39.914716, 116.265097), R.mipmap.end) + addMarker(LatLng(39.914716, 116.265097), "", R.mipmap.end) //瞄点画线 val latLngPoints = ArrayList() latLngPoints.add(LatLng(39.914885, 116.272312)) @@ -78,9 +239,10 @@ } - private fun addMarker(point: LatLng, res: Int) { + private fun addMarker(point: LatLng, type: String, res: Int) { val markerOption = MarkerOptions() markerOption.position(point) + markerOption.title(type) markerOption.icon(BitmapDescriptorFactory.fromResource(res)) aMap.addMarker(markerOption) } diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt new file mode 100644 index 0000000..ad16496 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt @@ -0,0 +1,5 @@ +package com.casic.br.ktd.listener + +interface OnGeocodeSearchListener { + fun onRegionCodeSearched(address: String) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt new file mode 100644 index 0000000..61104eb --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt @@ -0,0 +1,15 @@ +package com.casic.br.ktd.listener + +import java.io.File + +interface OnImageCompressListener { + /** + * Fired when a compression returns successfully, override to handle in your own code + */ + fun onSuccess(file: File) + + /** + * Fired when a compression fails to complete, override to handle in your own code + */ + fun onError(e: Throwable) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/model/PointModel.kt b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt new file mode 100644 index 0000000..ec2065d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt @@ -0,0 +1,3 @@ +package com.casic.br.ktd.model + +data class PointModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt b/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt deleted file mode 100644 index c45d645..0000000 --- a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.casic.br.ktd.model - -data class RouteModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java new file mode 100644 index 0000000..e813075 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java @@ -0,0 +1,166 @@ +package com.casic.br.ktd.model; + +import java.util.List; + +public class VehicleRouteModel { + + private Integer code; + private DataModel data; + private String message; + + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } + + public DataModel getData() { + return data; + } + + public void setData(DataModel data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public static class DataModel { + private List rows; + private Integer total; + + public List getRows() { + return rows; + } + + public void setRows(List rows) { + this.rows = rows; + } + + public Integer getTotal() { + return total; + } + + public void setTotal(Integer total) { + this.total = total; + } + + public static class RowsModel { + private String deviceStatus; + private String direction; + private String gas; + private String id; + private String isAlarm; + private String lagitude; + private String longitude; + private String pitch; + private String position; + private String speed; + private String taskId; + private String ts; + + public String getDeviceStatus() { + return deviceStatus; + } + + public void setDeviceStatus(String deviceStatus) { + this.deviceStatus = deviceStatus; + } + + public String getDirection() { + return direction; + } + + public void setDirection(String direction) { + this.direction = direction; + } + + public String getGas() { + return gas; + } + + public void setGas(String gas) { + this.gas = gas; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getIsAlarm() { + return isAlarm; + } + + public void setIsAlarm(String isAlarm) { + this.isAlarm = isAlarm; + } + + public String getLagitude() { + return lagitude; + } + + public void setLagitude(String lagitude) { + this.lagitude = lagitude; + } + + public String getLongitude() { + return longitude; + } + + public void setLongitude(String longitude) { + this.longitude = longitude; + } + + public String getPitch() { + return pitch; + } + + public void setPitch(String pitch) { + this.pitch = pitch; + } + + public String getPosition() { + return position; + } + + public void setPosition(String position) { + this.position = position; + } + + public String getSpeed() { + return speed; + } + + public void setSpeed(String speed) { + this.speed = speed; + } + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public String getTs() { + return ts; + } + + public void setTs(String ts) { + this.ts = ts; + } + } + } +} diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt index 9211b3a..519ab45 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt @@ -49,7 +49,7 @@ @Header("token") token: String, @Body requestBody: RequestBody, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -78,7 +78,7 @@ suspend fun getVehicles( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -88,7 +88,7 @@ suspend fun getDevices( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -101,6 +101,16 @@ ): String /** + * 巡检路径 + */ + @POST("/system/busPatrolTrack/listPage") + suspend fun busTrackRoute( + @Header("token") token: String, + @QueryMap limit: Map, + @QueryMap offset: Map + ): String + + /** * 新增报警规则,主要是阈值 */ @POST("/system/alarmRule/add") @@ -116,7 +126,7 @@ suspend fun getAlarmRules( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -146,6 +156,6 @@ @Header("token") token: String, @Body requestBody: RequestBody, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt index 0f109db..fd9624c 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt @@ -186,6 +186,18 @@ } /** + * 巡检路径 + */ + suspend fun busTrackRoute(): String { + val limitMap = HashMap() + limitMap["limit"] = LocaleConstant.PAGE_LIMIT + + val offsetMap = HashMap() + offsetMap["offset"] = 1 + return api.busTrackRoute(AuthenticationHelper.token, limitMap, offsetMap) + } + + /** * 新增报警规则,主要是阈值 */ suspend fun addAlarmRule(high: String, deviceId: String, ts: String): String { diff --git a/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt deleted file mode 100644 index 92286ad..0000000 --- a/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.br.ktd.utils - -import java.io.File - -interface OnImageCompressListener { - /** - * Fired when a compression returns successfully, override to handle in your own code - */ - fun onSuccess(file: File) - - /** - * Fired when a compression fails to complete, override to handle in your own code - */ - fun onError(e: Throwable) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt b/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt index b3146e7..7d6e558 100644 --- a/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt +++ b/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt @@ -29,7 +29,7 @@ import com.casic.br.ktd.extensions.* import com.casic.br.ktd.model.AlarmParam import com.casic.br.ktd.model.ChartPointModel -import com.casic.br.ktd.model.RouteModel +import com.casic.br.ktd.model.PointModel import com.casic.br.ktd.model.SensorDataModel import com.casic.br.ktd.netty.tcp.SocketManager import com.casic.br.ktd.netty.udp.UdpClient @@ -273,9 +273,9 @@ ) if (isStartInspect) { - val route = LinkedList() + val route = LinkedList() latlngs.forEach { - route.add(RouteModel(it.latitude, it.longitude)) + route.add(PointModel(it.latitude, it.longitude)) } } } diff --git a/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt b/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt index bce4c24..b3c519a 100644 --- a/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt +++ b/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt @@ -21,7 +21,6 @@ import com.casic.br.ktd.fragment.TaskPageFragment import com.casic.br.ktd.utils.LocaleConstant import com.casic.br.ktd.vm.AlarmViewModel -import com.casic.br.ktd.vm.VehicleViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.show @@ -36,7 +35,6 @@ private val fragmentPages = ArrayList() private val slideAdapter by lazy { SlideAdapter(this) } private var clickTime: Long = 0 - private lateinit var vehicleViewModel: VehicleViewModel private lateinit var alarmViewModel: AlarmViewModel init { @@ -71,20 +69,6 @@ //显示首页 switchPage(fragmentPages[0]) - vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] - vehicleViewModel.getVehicles() - vehicleViewModel.vehicleList.observe(this) { - if (it.code == 200) { - if (it.data.rows.isNotEmpty()) { - val model = it.data.rows[0] - SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, model.carPlate) - SaveKeyValues.putValue(LocaleConstant.CAR_ID, model.id) - } else { - Log.d(kTag, "initData => 无可用巡检车") - } - } - } - alarmViewModel = ViewModelProvider(this)[AlarmViewModel::class.java] alarmViewModel.getAlarmRules() alarmViewModel.alarmRuleList.observe(this) { diff --git a/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt b/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt index d81e7d6..c869ed8 100644 --- a/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt +++ b/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt @@ -1,7 +1,15 @@ package com.casic.br.ktd.vm +import androidx.lifecycle.MutableLiveData +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.extensions.separateResponseCode +import com.casic.br.ktd.extensions.toErrorMessage +import com.casic.br.ktd.model.VehicleRouteModel import com.casic.br.ktd.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.launch +import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.vm.BaseViewModel /** @@ -9,6 +17,9 @@ * */ class PointViewModel : BaseViewModel() { + private val gson by lazy { Gson() } + val vehicleRoute = MutableLiveData() + fun uploadPointDetail( isAlarm: String, lagitude: String, @@ -36,4 +47,18 @@ }, { it.printStackTrace() }) + + fun busTrackRoute() = launch({ + val response = RetrofitServiceManager.busTrackRoute() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + vehicleRoute.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + }) } \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml new file mode 100644 index 0000000..aeae610 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt new file mode 100644 index 0000000..40b3660 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt @@ -0,0 +1,28 @@ +package com.casic.br.ktd.extensions + +import com.amap.api.maps.model.LatLng +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.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.listener.OnGeocodeSearchListener + +private val geocoderSearch by lazy { GeocodeSearch(BaseApplication.get()) } + +fun LatLng.toChineseAddress(listener: OnGeocodeSearchListener) { + val queryParam = RegeocodeQuery( + LatLonPoint(this.latitude, this.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + listener.onRegionCodeSearched(regeocodeResult.regeocodeAddress.formatAddress) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index 36af820..e090122 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -1,9 +1,9 @@ package com.casic.br.ktd.extensions import android.content.Context +import com.casic.br.ktd.listener.OnImageCompressListener import com.casic.br.ktd.model.ErrorMessageModel import com.casic.br.ktd.utils.LocaleConstant -import com.casic.br.ktd.utils.OnImageCompressListener import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.createCompressImageDir @@ -14,7 +14,8 @@ import top.zibin.luban.OnCompressListener import java.io.File import java.text.SimpleDateFormat -import java.util.* +import java.util.Date +import java.util.Locale import java.util.regex.Pattern diff --git a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt index 40b27b1..a8d1e7a 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt @@ -2,31 +2,55 @@ import android.graphics.Color import android.os.Bundle +import android.os.Handler +import android.os.Message import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.model.BitmapDescriptorFactory import com.amap.api.maps.model.CameraPosition import com.amap.api.maps.model.LatLng +import com.amap.api.maps.model.Marker import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.PolylineOptions import com.casic.br.ktd.R import com.casic.br.ktd.databinding.FragmentHomeBinding +import com.casic.br.ktd.extensions.toChineseAddress +import com.casic.br.ktd.listener.OnGeocodeSearchListener +import com.casic.br.ktd.model.DeviceListModel +import com.casic.br.ktd.model.VehicleListModel +import com.casic.br.ktd.utils.LocaleConstant +import com.casic.br.ktd.vm.DeviceViewModel +import com.casic.br.ktd.vm.VehicleViewModel import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.utils.SaveKeyValues +import com.pengxh.kt.lite.utils.WeakReferenceHandler +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton -class HomePageFragment : KotlinBaseFragment() { +class HomePageFragment : KotlinBaseFragment(), AMap.OnMarkerClickListener, + AMap.InfoWindowAdapter, Handler.Callback { + + private val kTag = "HomePageFragment" + private lateinit var vehicleViewModel: VehicleViewModel + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private lateinit var weakReferenceHandler: WeakReferenceHandler + private var isInfoWindowShow = false + private val handlerVehicleCode = 2023082501 + private val handlerDeviceCode = 2023082502 override fun initViewBinding( - inflater: LayoutInflater, - container: ViewGroup? + inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { return FragmentHomeBinding.inflate(inflater, container, false) } - private lateinit var aMap: AMap - override fun initOnCreate(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -36,6 +60,143 @@ uiSettings.isScaleControlsEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isRotateGesturesEnabled = false//不许地图随手势旋转角度 + // 点击marker弹出自定义popup + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) + + weakReferenceHandler = WeakReferenceHandler(this) + + vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] + vehicleViewModel.getVehicles() + vehicleViewModel.vehicleList.observe(this) { + if (it.code == 200) { + if (it.data.rows.isNotEmpty()) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerVehicleCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + deviceViewModel.deviceList.observe(this) { + if (it.code == 200) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerDeviceCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + handlerVehicleCode -> { + val vehicleModel = msg.obj as VehicleListModel.DataModel.RowsModel + + SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, vehicleModel.carPlate) + SaveKeyValues.putValue(LocaleConstant.CAR_ID, vehicleModel.id) + + val marker = if (vehicleModel.status == "1") { + //在线 + R.mipmap.vehicle_on + } else { + //离线 + R.mipmap.vehicle_on + } + + val latLng = LatLng( + vehicleModel.latitude.toDouble(), vehicleModel.longitude.toDouble() + ) + addMarker(latLng, "Car", marker) + + /** + * 地图PopupWindow数据绑定 + * ****/ + if (isInfoWindowShow) { + windowTitleView.text = vehicleModel.carPlate + val state = if (vehicleModel.status == "1") { + "状态:在线" + } else { + "状态:离线" + } + carStateView.text = state + + timeView.text = "时间:${vehicleModel.ts}" + latLng.toChineseAddress(object : OnGeocodeSearchListener { + override fun onRegionCodeSearched(address: String) { + locationView.text = "位置:$address" + } + }) + } + } + + handlerDeviceCode -> { + if (isInfoWindowShow) { + val deviceModel = msg.obj as DeviceListModel.DataModel.RowsModel + + deviceModelView.text = "云台型号:${deviceModel.deviceModel}" + } + } + } + return true + } + + override fun onMarkerClick(marker: Marker?): Boolean { + //点击Marker显示自定义Popup + marker?.showInfoWindow() + return true + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + + private lateinit var windowTitleView: TextView + private lateinit var taskStateView: QMUIRoundButton + private lateinit var carStateView: TextView + private lateinit var deviceModelView: TextView + private lateinit var timeView: TextView + private lateinit var locationView: TextView + + override fun getInfoWindow(marker: Marker?): View { + isInfoWindowShow = true + + val v = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_car_window, null) + + windowTitleView = v.findViewById(R.id.windowTitleView) + taskStateView = v.findViewById(R.id.taskStateView) + val closeView = v.findViewById(R.id.closeView) + carStateView = v.findViewById(R.id.carStateView) + deviceModelView = v.findViewById(R.id.deviceModelView) + timeView = v.findViewById(R.id.timeView) + locationView = v.findViewById(R.id.locationView) + val routeView = v.findViewById(R.id.routeView) + + if (marker?.title == "Car") { + taskStateView.visibility = View.GONE + routeView.visibility = View.GONE + + vehicleViewModel.getVehicles() + + deviceViewModel.getDevices() + } else { + taskStateView.visibility = View.VISIBLE + routeView.visibility = View.VISIBLE + + routeView.setOnClickListener { + + } + } + + closeView.setOnClickListener { + marker?.hideInfoWindow() + isInfoWindowShow = false + } + return v } override fun initEvent() { @@ -44,9 +205,9 @@ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 1500, null) //设置起点 - addMarker(LatLng(39.914885, 116.272312), R.mipmap.start) + addMarker(LatLng(39.914885, 116.272312), "", R.mipmap.start) //设置终点 - addMarker(LatLng(39.914716, 116.265097), R.mipmap.end) + addMarker(LatLng(39.914716, 116.265097), "", R.mipmap.end) //瞄点画线 val latLngPoints = ArrayList() latLngPoints.add(LatLng(39.914885, 116.272312)) @@ -78,9 +239,10 @@ } - private fun addMarker(point: LatLng, res: Int) { + private fun addMarker(point: LatLng, type: String, res: Int) { val markerOption = MarkerOptions() markerOption.position(point) + markerOption.title(type) markerOption.icon(BitmapDescriptorFactory.fromResource(res)) aMap.addMarker(markerOption) } diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt new file mode 100644 index 0000000..ad16496 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt @@ -0,0 +1,5 @@ +package com.casic.br.ktd.listener + +interface OnGeocodeSearchListener { + fun onRegionCodeSearched(address: String) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt new file mode 100644 index 0000000..61104eb --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt @@ -0,0 +1,15 @@ +package com.casic.br.ktd.listener + +import java.io.File + +interface OnImageCompressListener { + /** + * Fired when a compression returns successfully, override to handle in your own code + */ + fun onSuccess(file: File) + + /** + * Fired when a compression fails to complete, override to handle in your own code + */ + fun onError(e: Throwable) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/model/PointModel.kt b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt new file mode 100644 index 0000000..ec2065d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt @@ -0,0 +1,3 @@ +package com.casic.br.ktd.model + +data class PointModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt b/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt deleted file mode 100644 index c45d645..0000000 --- a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.casic.br.ktd.model - -data class RouteModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java new file mode 100644 index 0000000..e813075 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java @@ -0,0 +1,166 @@ +package com.casic.br.ktd.model; + +import java.util.List; + +public class VehicleRouteModel { + + private Integer code; + private DataModel data; + private String message; + + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } + + public DataModel getData() { + return data; + } + + public void setData(DataModel data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public static class DataModel { + private List rows; + private Integer total; + + public List getRows() { + return rows; + } + + public void setRows(List rows) { + this.rows = rows; + } + + public Integer getTotal() { + return total; + } + + public void setTotal(Integer total) { + this.total = total; + } + + public static class RowsModel { + private String deviceStatus; + private String direction; + private String gas; + private String id; + private String isAlarm; + private String lagitude; + private String longitude; + private String pitch; + private String position; + private String speed; + private String taskId; + private String ts; + + public String getDeviceStatus() { + return deviceStatus; + } + + public void setDeviceStatus(String deviceStatus) { + this.deviceStatus = deviceStatus; + } + + public String getDirection() { + return direction; + } + + public void setDirection(String direction) { + this.direction = direction; + } + + public String getGas() { + return gas; + } + + public void setGas(String gas) { + this.gas = gas; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getIsAlarm() { + return isAlarm; + } + + public void setIsAlarm(String isAlarm) { + this.isAlarm = isAlarm; + } + + public String getLagitude() { + return lagitude; + } + + public void setLagitude(String lagitude) { + this.lagitude = lagitude; + } + + public String getLongitude() { + return longitude; + } + + public void setLongitude(String longitude) { + this.longitude = longitude; + } + + public String getPitch() { + return pitch; + } + + public void setPitch(String pitch) { + this.pitch = pitch; + } + + public String getPosition() { + return position; + } + + public void setPosition(String position) { + this.position = position; + } + + public String getSpeed() { + return speed; + } + + public void setSpeed(String speed) { + this.speed = speed; + } + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public String getTs() { + return ts; + } + + public void setTs(String ts) { + this.ts = ts; + } + } + } +} diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt index 9211b3a..519ab45 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt @@ -49,7 +49,7 @@ @Header("token") token: String, @Body requestBody: RequestBody, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -78,7 +78,7 @@ suspend fun getVehicles( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -88,7 +88,7 @@ suspend fun getDevices( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -101,6 +101,16 @@ ): String /** + * 巡检路径 + */ + @POST("/system/busPatrolTrack/listPage") + suspend fun busTrackRoute( + @Header("token") token: String, + @QueryMap limit: Map, + @QueryMap offset: Map + ): String + + /** * 新增报警规则,主要是阈值 */ @POST("/system/alarmRule/add") @@ -116,7 +126,7 @@ suspend fun getAlarmRules( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -146,6 +156,6 @@ @Header("token") token: String, @Body requestBody: RequestBody, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt index 0f109db..fd9624c 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt @@ -186,6 +186,18 @@ } /** + * 巡检路径 + */ + suspend fun busTrackRoute(): String { + val limitMap = HashMap() + limitMap["limit"] = LocaleConstant.PAGE_LIMIT + + val offsetMap = HashMap() + offsetMap["offset"] = 1 + return api.busTrackRoute(AuthenticationHelper.token, limitMap, offsetMap) + } + + /** * 新增报警规则,主要是阈值 */ suspend fun addAlarmRule(high: String, deviceId: String, ts: String): String { diff --git a/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt deleted file mode 100644 index 92286ad..0000000 --- a/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.br.ktd.utils - -import java.io.File - -interface OnImageCompressListener { - /** - * Fired when a compression returns successfully, override to handle in your own code - */ - fun onSuccess(file: File) - - /** - * Fired when a compression fails to complete, override to handle in your own code - */ - fun onError(e: Throwable) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt b/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt index b3146e7..7d6e558 100644 --- a/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt +++ b/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt @@ -29,7 +29,7 @@ import com.casic.br.ktd.extensions.* import com.casic.br.ktd.model.AlarmParam import com.casic.br.ktd.model.ChartPointModel -import com.casic.br.ktd.model.RouteModel +import com.casic.br.ktd.model.PointModel import com.casic.br.ktd.model.SensorDataModel import com.casic.br.ktd.netty.tcp.SocketManager import com.casic.br.ktd.netty.udp.UdpClient @@ -273,9 +273,9 @@ ) if (isStartInspect) { - val route = LinkedList() + val route = LinkedList() latlngs.forEach { - route.add(RouteModel(it.latitude, it.longitude)) + route.add(PointModel(it.latitude, it.longitude)) } } } diff --git a/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt b/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt index bce4c24..b3c519a 100644 --- a/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt +++ b/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt @@ -21,7 +21,6 @@ import com.casic.br.ktd.fragment.TaskPageFragment import com.casic.br.ktd.utils.LocaleConstant import com.casic.br.ktd.vm.AlarmViewModel -import com.casic.br.ktd.vm.VehicleViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.show @@ -36,7 +35,6 @@ private val fragmentPages = ArrayList() private val slideAdapter by lazy { SlideAdapter(this) } private var clickTime: Long = 0 - private lateinit var vehicleViewModel: VehicleViewModel private lateinit var alarmViewModel: AlarmViewModel init { @@ -71,20 +69,6 @@ //显示首页 switchPage(fragmentPages[0]) - vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] - vehicleViewModel.getVehicles() - vehicleViewModel.vehicleList.observe(this) { - if (it.code == 200) { - if (it.data.rows.isNotEmpty()) { - val model = it.data.rows[0] - SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, model.carPlate) - SaveKeyValues.putValue(LocaleConstant.CAR_ID, model.id) - } else { - Log.d(kTag, "initData => 无可用巡检车") - } - } - } - alarmViewModel = ViewModelProvider(this)[AlarmViewModel::class.java] alarmViewModel.getAlarmRules() alarmViewModel.alarmRuleList.observe(this) { diff --git a/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt b/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt index d81e7d6..c869ed8 100644 --- a/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt +++ b/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt @@ -1,7 +1,15 @@ package com.casic.br.ktd.vm +import androidx.lifecycle.MutableLiveData +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.extensions.separateResponseCode +import com.casic.br.ktd.extensions.toErrorMessage +import com.casic.br.ktd.model.VehicleRouteModel import com.casic.br.ktd.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.launch +import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.vm.BaseViewModel /** @@ -9,6 +17,9 @@ * */ class PointViewModel : BaseViewModel() { + private val gson by lazy { Gson() } + val vehicleRoute = MutableLiveData() + fun uploadPointDetail( isAlarm: String, lagitude: String, @@ -36,4 +47,18 @@ }, { it.printStackTrace() }) + + fun busTrackRoute() = launch({ + val response = RetrofitServiceManager.busTrackRoute() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + vehicleRoute.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + }) } \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml new file mode 100644 index 0000000..aeae610 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/error.xml b/app/src/main/res/drawable/error.xml new file mode 100644 index 0000000..41b3c96 --- /dev/null +++ b/app/src/main/res/drawable/error.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt new file mode 100644 index 0000000..40b3660 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt @@ -0,0 +1,28 @@ +package com.casic.br.ktd.extensions + +import com.amap.api.maps.model.LatLng +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.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.listener.OnGeocodeSearchListener + +private val geocoderSearch by lazy { GeocodeSearch(BaseApplication.get()) } + +fun LatLng.toChineseAddress(listener: OnGeocodeSearchListener) { + val queryParam = RegeocodeQuery( + LatLonPoint(this.latitude, this.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + listener.onRegionCodeSearched(regeocodeResult.regeocodeAddress.formatAddress) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index 36af820..e090122 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -1,9 +1,9 @@ package com.casic.br.ktd.extensions import android.content.Context +import com.casic.br.ktd.listener.OnImageCompressListener import com.casic.br.ktd.model.ErrorMessageModel import com.casic.br.ktd.utils.LocaleConstant -import com.casic.br.ktd.utils.OnImageCompressListener import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.createCompressImageDir @@ -14,7 +14,8 @@ import top.zibin.luban.OnCompressListener import java.io.File import java.text.SimpleDateFormat -import java.util.* +import java.util.Date +import java.util.Locale import java.util.regex.Pattern diff --git a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt index 40b27b1..a8d1e7a 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt @@ -2,31 +2,55 @@ import android.graphics.Color import android.os.Bundle +import android.os.Handler +import android.os.Message import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.model.BitmapDescriptorFactory import com.amap.api.maps.model.CameraPosition import com.amap.api.maps.model.LatLng +import com.amap.api.maps.model.Marker import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.PolylineOptions import com.casic.br.ktd.R import com.casic.br.ktd.databinding.FragmentHomeBinding +import com.casic.br.ktd.extensions.toChineseAddress +import com.casic.br.ktd.listener.OnGeocodeSearchListener +import com.casic.br.ktd.model.DeviceListModel +import com.casic.br.ktd.model.VehicleListModel +import com.casic.br.ktd.utils.LocaleConstant +import com.casic.br.ktd.vm.DeviceViewModel +import com.casic.br.ktd.vm.VehicleViewModel import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.utils.SaveKeyValues +import com.pengxh.kt.lite.utils.WeakReferenceHandler +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton -class HomePageFragment : KotlinBaseFragment() { +class HomePageFragment : KotlinBaseFragment(), AMap.OnMarkerClickListener, + AMap.InfoWindowAdapter, Handler.Callback { + + private val kTag = "HomePageFragment" + private lateinit var vehicleViewModel: VehicleViewModel + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private lateinit var weakReferenceHandler: WeakReferenceHandler + private var isInfoWindowShow = false + private val handlerVehicleCode = 2023082501 + private val handlerDeviceCode = 2023082502 override fun initViewBinding( - inflater: LayoutInflater, - container: ViewGroup? + inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { return FragmentHomeBinding.inflate(inflater, container, false) } - private lateinit var aMap: AMap - override fun initOnCreate(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -36,6 +60,143 @@ uiSettings.isScaleControlsEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isRotateGesturesEnabled = false//不许地图随手势旋转角度 + // 点击marker弹出自定义popup + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) + + weakReferenceHandler = WeakReferenceHandler(this) + + vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] + vehicleViewModel.getVehicles() + vehicleViewModel.vehicleList.observe(this) { + if (it.code == 200) { + if (it.data.rows.isNotEmpty()) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerVehicleCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + deviceViewModel.deviceList.observe(this) { + if (it.code == 200) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerDeviceCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + handlerVehicleCode -> { + val vehicleModel = msg.obj as VehicleListModel.DataModel.RowsModel + + SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, vehicleModel.carPlate) + SaveKeyValues.putValue(LocaleConstant.CAR_ID, vehicleModel.id) + + val marker = if (vehicleModel.status == "1") { + //在线 + R.mipmap.vehicle_on + } else { + //离线 + R.mipmap.vehicle_on + } + + val latLng = LatLng( + vehicleModel.latitude.toDouble(), vehicleModel.longitude.toDouble() + ) + addMarker(latLng, "Car", marker) + + /** + * 地图PopupWindow数据绑定 + * ****/ + if (isInfoWindowShow) { + windowTitleView.text = vehicleModel.carPlate + val state = if (vehicleModel.status == "1") { + "状态:在线" + } else { + "状态:离线" + } + carStateView.text = state + + timeView.text = "时间:${vehicleModel.ts}" + latLng.toChineseAddress(object : OnGeocodeSearchListener { + override fun onRegionCodeSearched(address: String) { + locationView.text = "位置:$address" + } + }) + } + } + + handlerDeviceCode -> { + if (isInfoWindowShow) { + val deviceModel = msg.obj as DeviceListModel.DataModel.RowsModel + + deviceModelView.text = "云台型号:${deviceModel.deviceModel}" + } + } + } + return true + } + + override fun onMarkerClick(marker: Marker?): Boolean { + //点击Marker显示自定义Popup + marker?.showInfoWindow() + return true + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + + private lateinit var windowTitleView: TextView + private lateinit var taskStateView: QMUIRoundButton + private lateinit var carStateView: TextView + private lateinit var deviceModelView: TextView + private lateinit var timeView: TextView + private lateinit var locationView: TextView + + override fun getInfoWindow(marker: Marker?): View { + isInfoWindowShow = true + + val v = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_car_window, null) + + windowTitleView = v.findViewById(R.id.windowTitleView) + taskStateView = v.findViewById(R.id.taskStateView) + val closeView = v.findViewById(R.id.closeView) + carStateView = v.findViewById(R.id.carStateView) + deviceModelView = v.findViewById(R.id.deviceModelView) + timeView = v.findViewById(R.id.timeView) + locationView = v.findViewById(R.id.locationView) + val routeView = v.findViewById(R.id.routeView) + + if (marker?.title == "Car") { + taskStateView.visibility = View.GONE + routeView.visibility = View.GONE + + vehicleViewModel.getVehicles() + + deviceViewModel.getDevices() + } else { + taskStateView.visibility = View.VISIBLE + routeView.visibility = View.VISIBLE + + routeView.setOnClickListener { + + } + } + + closeView.setOnClickListener { + marker?.hideInfoWindow() + isInfoWindowShow = false + } + return v } override fun initEvent() { @@ -44,9 +205,9 @@ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 1500, null) //设置起点 - addMarker(LatLng(39.914885, 116.272312), R.mipmap.start) + addMarker(LatLng(39.914885, 116.272312), "", R.mipmap.start) //设置终点 - addMarker(LatLng(39.914716, 116.265097), R.mipmap.end) + addMarker(LatLng(39.914716, 116.265097), "", R.mipmap.end) //瞄点画线 val latLngPoints = ArrayList() latLngPoints.add(LatLng(39.914885, 116.272312)) @@ -78,9 +239,10 @@ } - private fun addMarker(point: LatLng, res: Int) { + private fun addMarker(point: LatLng, type: String, res: Int) { val markerOption = MarkerOptions() markerOption.position(point) + markerOption.title(type) markerOption.icon(BitmapDescriptorFactory.fromResource(res)) aMap.addMarker(markerOption) } diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt new file mode 100644 index 0000000..ad16496 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt @@ -0,0 +1,5 @@ +package com.casic.br.ktd.listener + +interface OnGeocodeSearchListener { + fun onRegionCodeSearched(address: String) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt new file mode 100644 index 0000000..61104eb --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt @@ -0,0 +1,15 @@ +package com.casic.br.ktd.listener + +import java.io.File + +interface OnImageCompressListener { + /** + * Fired when a compression returns successfully, override to handle in your own code + */ + fun onSuccess(file: File) + + /** + * Fired when a compression fails to complete, override to handle in your own code + */ + fun onError(e: Throwable) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/model/PointModel.kt b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt new file mode 100644 index 0000000..ec2065d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt @@ -0,0 +1,3 @@ +package com.casic.br.ktd.model + +data class PointModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt b/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt deleted file mode 100644 index c45d645..0000000 --- a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.casic.br.ktd.model - -data class RouteModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java new file mode 100644 index 0000000..e813075 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java @@ -0,0 +1,166 @@ +package com.casic.br.ktd.model; + +import java.util.List; + +public class VehicleRouteModel { + + private Integer code; + private DataModel data; + private String message; + + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } + + public DataModel getData() { + return data; + } + + public void setData(DataModel data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public static class DataModel { + private List rows; + private Integer total; + + public List getRows() { + return rows; + } + + public void setRows(List rows) { + this.rows = rows; + } + + public Integer getTotal() { + return total; + } + + public void setTotal(Integer total) { + this.total = total; + } + + public static class RowsModel { + private String deviceStatus; + private String direction; + private String gas; + private String id; + private String isAlarm; + private String lagitude; + private String longitude; + private String pitch; + private String position; + private String speed; + private String taskId; + private String ts; + + public String getDeviceStatus() { + return deviceStatus; + } + + public void setDeviceStatus(String deviceStatus) { + this.deviceStatus = deviceStatus; + } + + public String getDirection() { + return direction; + } + + public void setDirection(String direction) { + this.direction = direction; + } + + public String getGas() { + return gas; + } + + public void setGas(String gas) { + this.gas = gas; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getIsAlarm() { + return isAlarm; + } + + public void setIsAlarm(String isAlarm) { + this.isAlarm = isAlarm; + } + + public String getLagitude() { + return lagitude; + } + + public void setLagitude(String lagitude) { + this.lagitude = lagitude; + } + + public String getLongitude() { + return longitude; + } + + public void setLongitude(String longitude) { + this.longitude = longitude; + } + + public String getPitch() { + return pitch; + } + + public void setPitch(String pitch) { + this.pitch = pitch; + } + + public String getPosition() { + return position; + } + + public void setPosition(String position) { + this.position = position; + } + + public String getSpeed() { + return speed; + } + + public void setSpeed(String speed) { + this.speed = speed; + } + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public String getTs() { + return ts; + } + + public void setTs(String ts) { + this.ts = ts; + } + } + } +} diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt index 9211b3a..519ab45 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt @@ -49,7 +49,7 @@ @Header("token") token: String, @Body requestBody: RequestBody, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -78,7 +78,7 @@ suspend fun getVehicles( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -88,7 +88,7 @@ suspend fun getDevices( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -101,6 +101,16 @@ ): String /** + * 巡检路径 + */ + @POST("/system/busPatrolTrack/listPage") + suspend fun busTrackRoute( + @Header("token") token: String, + @QueryMap limit: Map, + @QueryMap offset: Map + ): String + + /** * 新增报警规则,主要是阈值 */ @POST("/system/alarmRule/add") @@ -116,7 +126,7 @@ suspend fun getAlarmRules( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -146,6 +156,6 @@ @Header("token") token: String, @Body requestBody: RequestBody, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt index 0f109db..fd9624c 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt @@ -186,6 +186,18 @@ } /** + * 巡检路径 + */ + suspend fun busTrackRoute(): String { + val limitMap = HashMap() + limitMap["limit"] = LocaleConstant.PAGE_LIMIT + + val offsetMap = HashMap() + offsetMap["offset"] = 1 + return api.busTrackRoute(AuthenticationHelper.token, limitMap, offsetMap) + } + + /** * 新增报警规则,主要是阈值 */ suspend fun addAlarmRule(high: String, deviceId: String, ts: String): String { diff --git a/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt deleted file mode 100644 index 92286ad..0000000 --- a/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.br.ktd.utils - -import java.io.File - -interface OnImageCompressListener { - /** - * Fired when a compression returns successfully, override to handle in your own code - */ - fun onSuccess(file: File) - - /** - * Fired when a compression fails to complete, override to handle in your own code - */ - fun onError(e: Throwable) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt b/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt index b3146e7..7d6e558 100644 --- a/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt +++ b/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt @@ -29,7 +29,7 @@ import com.casic.br.ktd.extensions.* import com.casic.br.ktd.model.AlarmParam import com.casic.br.ktd.model.ChartPointModel -import com.casic.br.ktd.model.RouteModel +import com.casic.br.ktd.model.PointModel import com.casic.br.ktd.model.SensorDataModel import com.casic.br.ktd.netty.tcp.SocketManager import com.casic.br.ktd.netty.udp.UdpClient @@ -273,9 +273,9 @@ ) if (isStartInspect) { - val route = LinkedList() + val route = LinkedList() latlngs.forEach { - route.add(RouteModel(it.latitude, it.longitude)) + route.add(PointModel(it.latitude, it.longitude)) } } } diff --git a/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt b/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt index bce4c24..b3c519a 100644 --- a/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt +++ b/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt @@ -21,7 +21,6 @@ import com.casic.br.ktd.fragment.TaskPageFragment import com.casic.br.ktd.utils.LocaleConstant import com.casic.br.ktd.vm.AlarmViewModel -import com.casic.br.ktd.vm.VehicleViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.show @@ -36,7 +35,6 @@ private val fragmentPages = ArrayList() private val slideAdapter by lazy { SlideAdapter(this) } private var clickTime: Long = 0 - private lateinit var vehicleViewModel: VehicleViewModel private lateinit var alarmViewModel: AlarmViewModel init { @@ -71,20 +69,6 @@ //显示首页 switchPage(fragmentPages[0]) - vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] - vehicleViewModel.getVehicles() - vehicleViewModel.vehicleList.observe(this) { - if (it.code == 200) { - if (it.data.rows.isNotEmpty()) { - val model = it.data.rows[0] - SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, model.carPlate) - SaveKeyValues.putValue(LocaleConstant.CAR_ID, model.id) - } else { - Log.d(kTag, "initData => 无可用巡检车") - } - } - } - alarmViewModel = ViewModelProvider(this)[AlarmViewModel::class.java] alarmViewModel.getAlarmRules() alarmViewModel.alarmRuleList.observe(this) { diff --git a/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt b/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt index d81e7d6..c869ed8 100644 --- a/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt +++ b/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt @@ -1,7 +1,15 @@ package com.casic.br.ktd.vm +import androidx.lifecycle.MutableLiveData +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.extensions.separateResponseCode +import com.casic.br.ktd.extensions.toErrorMessage +import com.casic.br.ktd.model.VehicleRouteModel import com.casic.br.ktd.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.launch +import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.vm.BaseViewModel /** @@ -9,6 +17,9 @@ * */ class PointViewModel : BaseViewModel() { + private val gson by lazy { Gson() } + val vehicleRoute = MutableLiveData() + fun uploadPointDetail( isAlarm: String, lagitude: String, @@ -36,4 +47,18 @@ }, { it.printStackTrace() }) + + fun busTrackRoute() = launch({ + val response = RetrofitServiceManager.busTrackRoute() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + vehicleRoute.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + }) } \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml new file mode 100644 index 0000000..aeae610 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/error.xml b/app/src/main/res/drawable/error.xml new file mode 100644 index 0000000..41b3c96 --- /dev/null +++ b/app/src/main/res/drawable/error.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/layout/popu_map_car_window.xml b/app/src/main/res/layout/popu_map_car_window.xml new file mode 100644 index 0000000..b04d908 --- /dev/null +++ b/app/src/main/res/layout/popu_map_car_window.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt new file mode 100644 index 0000000..40b3660 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt @@ -0,0 +1,28 @@ +package com.casic.br.ktd.extensions + +import com.amap.api.maps.model.LatLng +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.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.listener.OnGeocodeSearchListener + +private val geocoderSearch by lazy { GeocodeSearch(BaseApplication.get()) } + +fun LatLng.toChineseAddress(listener: OnGeocodeSearchListener) { + val queryParam = RegeocodeQuery( + LatLonPoint(this.latitude, this.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + listener.onRegionCodeSearched(regeocodeResult.regeocodeAddress.formatAddress) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index 36af820..e090122 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -1,9 +1,9 @@ package com.casic.br.ktd.extensions import android.content.Context +import com.casic.br.ktd.listener.OnImageCompressListener import com.casic.br.ktd.model.ErrorMessageModel import com.casic.br.ktd.utils.LocaleConstant -import com.casic.br.ktd.utils.OnImageCompressListener import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.createCompressImageDir @@ -14,7 +14,8 @@ import top.zibin.luban.OnCompressListener import java.io.File import java.text.SimpleDateFormat -import java.util.* +import java.util.Date +import java.util.Locale import java.util.regex.Pattern diff --git a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt index 40b27b1..a8d1e7a 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt @@ -2,31 +2,55 @@ import android.graphics.Color import android.os.Bundle +import android.os.Handler +import android.os.Message import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.model.BitmapDescriptorFactory import com.amap.api.maps.model.CameraPosition import com.amap.api.maps.model.LatLng +import com.amap.api.maps.model.Marker import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.PolylineOptions import com.casic.br.ktd.R import com.casic.br.ktd.databinding.FragmentHomeBinding +import com.casic.br.ktd.extensions.toChineseAddress +import com.casic.br.ktd.listener.OnGeocodeSearchListener +import com.casic.br.ktd.model.DeviceListModel +import com.casic.br.ktd.model.VehicleListModel +import com.casic.br.ktd.utils.LocaleConstant +import com.casic.br.ktd.vm.DeviceViewModel +import com.casic.br.ktd.vm.VehicleViewModel import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.utils.SaveKeyValues +import com.pengxh.kt.lite.utils.WeakReferenceHandler +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton -class HomePageFragment : KotlinBaseFragment() { +class HomePageFragment : KotlinBaseFragment(), AMap.OnMarkerClickListener, + AMap.InfoWindowAdapter, Handler.Callback { + + private val kTag = "HomePageFragment" + private lateinit var vehicleViewModel: VehicleViewModel + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private lateinit var weakReferenceHandler: WeakReferenceHandler + private var isInfoWindowShow = false + private val handlerVehicleCode = 2023082501 + private val handlerDeviceCode = 2023082502 override fun initViewBinding( - inflater: LayoutInflater, - container: ViewGroup? + inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { return FragmentHomeBinding.inflate(inflater, container, false) } - private lateinit var aMap: AMap - override fun initOnCreate(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -36,6 +60,143 @@ uiSettings.isScaleControlsEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isRotateGesturesEnabled = false//不许地图随手势旋转角度 + // 点击marker弹出自定义popup + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) + + weakReferenceHandler = WeakReferenceHandler(this) + + vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] + vehicleViewModel.getVehicles() + vehicleViewModel.vehicleList.observe(this) { + if (it.code == 200) { + if (it.data.rows.isNotEmpty()) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerVehicleCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + deviceViewModel.deviceList.observe(this) { + if (it.code == 200) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerDeviceCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + handlerVehicleCode -> { + val vehicleModel = msg.obj as VehicleListModel.DataModel.RowsModel + + SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, vehicleModel.carPlate) + SaveKeyValues.putValue(LocaleConstant.CAR_ID, vehicleModel.id) + + val marker = if (vehicleModel.status == "1") { + //在线 + R.mipmap.vehicle_on + } else { + //离线 + R.mipmap.vehicle_on + } + + val latLng = LatLng( + vehicleModel.latitude.toDouble(), vehicleModel.longitude.toDouble() + ) + addMarker(latLng, "Car", marker) + + /** + * 地图PopupWindow数据绑定 + * ****/ + if (isInfoWindowShow) { + windowTitleView.text = vehicleModel.carPlate + val state = if (vehicleModel.status == "1") { + "状态:在线" + } else { + "状态:离线" + } + carStateView.text = state + + timeView.text = "时间:${vehicleModel.ts}" + latLng.toChineseAddress(object : OnGeocodeSearchListener { + override fun onRegionCodeSearched(address: String) { + locationView.text = "位置:$address" + } + }) + } + } + + handlerDeviceCode -> { + if (isInfoWindowShow) { + val deviceModel = msg.obj as DeviceListModel.DataModel.RowsModel + + deviceModelView.text = "云台型号:${deviceModel.deviceModel}" + } + } + } + return true + } + + override fun onMarkerClick(marker: Marker?): Boolean { + //点击Marker显示自定义Popup + marker?.showInfoWindow() + return true + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + + private lateinit var windowTitleView: TextView + private lateinit var taskStateView: QMUIRoundButton + private lateinit var carStateView: TextView + private lateinit var deviceModelView: TextView + private lateinit var timeView: TextView + private lateinit var locationView: TextView + + override fun getInfoWindow(marker: Marker?): View { + isInfoWindowShow = true + + val v = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_car_window, null) + + windowTitleView = v.findViewById(R.id.windowTitleView) + taskStateView = v.findViewById(R.id.taskStateView) + val closeView = v.findViewById(R.id.closeView) + carStateView = v.findViewById(R.id.carStateView) + deviceModelView = v.findViewById(R.id.deviceModelView) + timeView = v.findViewById(R.id.timeView) + locationView = v.findViewById(R.id.locationView) + val routeView = v.findViewById(R.id.routeView) + + if (marker?.title == "Car") { + taskStateView.visibility = View.GONE + routeView.visibility = View.GONE + + vehicleViewModel.getVehicles() + + deviceViewModel.getDevices() + } else { + taskStateView.visibility = View.VISIBLE + routeView.visibility = View.VISIBLE + + routeView.setOnClickListener { + + } + } + + closeView.setOnClickListener { + marker?.hideInfoWindow() + isInfoWindowShow = false + } + return v } override fun initEvent() { @@ -44,9 +205,9 @@ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 1500, null) //设置起点 - addMarker(LatLng(39.914885, 116.272312), R.mipmap.start) + addMarker(LatLng(39.914885, 116.272312), "", R.mipmap.start) //设置终点 - addMarker(LatLng(39.914716, 116.265097), R.mipmap.end) + addMarker(LatLng(39.914716, 116.265097), "", R.mipmap.end) //瞄点画线 val latLngPoints = ArrayList() latLngPoints.add(LatLng(39.914885, 116.272312)) @@ -78,9 +239,10 @@ } - private fun addMarker(point: LatLng, res: Int) { + private fun addMarker(point: LatLng, type: String, res: Int) { val markerOption = MarkerOptions() markerOption.position(point) + markerOption.title(type) markerOption.icon(BitmapDescriptorFactory.fromResource(res)) aMap.addMarker(markerOption) } diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt new file mode 100644 index 0000000..ad16496 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt @@ -0,0 +1,5 @@ +package com.casic.br.ktd.listener + +interface OnGeocodeSearchListener { + fun onRegionCodeSearched(address: String) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt new file mode 100644 index 0000000..61104eb --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt @@ -0,0 +1,15 @@ +package com.casic.br.ktd.listener + +import java.io.File + +interface OnImageCompressListener { + /** + * Fired when a compression returns successfully, override to handle in your own code + */ + fun onSuccess(file: File) + + /** + * Fired when a compression fails to complete, override to handle in your own code + */ + fun onError(e: Throwable) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/model/PointModel.kt b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt new file mode 100644 index 0000000..ec2065d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt @@ -0,0 +1,3 @@ +package com.casic.br.ktd.model + +data class PointModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt b/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt deleted file mode 100644 index c45d645..0000000 --- a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.casic.br.ktd.model - -data class RouteModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java new file mode 100644 index 0000000..e813075 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java @@ -0,0 +1,166 @@ +package com.casic.br.ktd.model; + +import java.util.List; + +public class VehicleRouteModel { + + private Integer code; + private DataModel data; + private String message; + + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } + + public DataModel getData() { + return data; + } + + public void setData(DataModel data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public static class DataModel { + private List rows; + private Integer total; + + public List getRows() { + return rows; + } + + public void setRows(List rows) { + this.rows = rows; + } + + public Integer getTotal() { + return total; + } + + public void setTotal(Integer total) { + this.total = total; + } + + public static class RowsModel { + private String deviceStatus; + private String direction; + private String gas; + private String id; + private String isAlarm; + private String lagitude; + private String longitude; + private String pitch; + private String position; + private String speed; + private String taskId; + private String ts; + + public String getDeviceStatus() { + return deviceStatus; + } + + public void setDeviceStatus(String deviceStatus) { + this.deviceStatus = deviceStatus; + } + + public String getDirection() { + return direction; + } + + public void setDirection(String direction) { + this.direction = direction; + } + + public String getGas() { + return gas; + } + + public void setGas(String gas) { + this.gas = gas; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getIsAlarm() { + return isAlarm; + } + + public void setIsAlarm(String isAlarm) { + this.isAlarm = isAlarm; + } + + public String getLagitude() { + return lagitude; + } + + public void setLagitude(String lagitude) { + this.lagitude = lagitude; + } + + public String getLongitude() { + return longitude; + } + + public void setLongitude(String longitude) { + this.longitude = longitude; + } + + public String getPitch() { + return pitch; + } + + public void setPitch(String pitch) { + this.pitch = pitch; + } + + public String getPosition() { + return position; + } + + public void setPosition(String position) { + this.position = position; + } + + public String getSpeed() { + return speed; + } + + public void setSpeed(String speed) { + this.speed = speed; + } + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public String getTs() { + return ts; + } + + public void setTs(String ts) { + this.ts = ts; + } + } + } +} diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt index 9211b3a..519ab45 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt @@ -49,7 +49,7 @@ @Header("token") token: String, @Body requestBody: RequestBody, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -78,7 +78,7 @@ suspend fun getVehicles( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -88,7 +88,7 @@ suspend fun getDevices( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -101,6 +101,16 @@ ): String /** + * 巡检路径 + */ + @POST("/system/busPatrolTrack/listPage") + suspend fun busTrackRoute( + @Header("token") token: String, + @QueryMap limit: Map, + @QueryMap offset: Map + ): String + + /** * 新增报警规则,主要是阈值 */ @POST("/system/alarmRule/add") @@ -116,7 +126,7 @@ suspend fun getAlarmRules( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -146,6 +156,6 @@ @Header("token") token: String, @Body requestBody: RequestBody, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt index 0f109db..fd9624c 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt @@ -186,6 +186,18 @@ } /** + * 巡检路径 + */ + suspend fun busTrackRoute(): String { + val limitMap = HashMap() + limitMap["limit"] = LocaleConstant.PAGE_LIMIT + + val offsetMap = HashMap() + offsetMap["offset"] = 1 + return api.busTrackRoute(AuthenticationHelper.token, limitMap, offsetMap) + } + + /** * 新增报警规则,主要是阈值 */ suspend fun addAlarmRule(high: String, deviceId: String, ts: String): String { diff --git a/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt deleted file mode 100644 index 92286ad..0000000 --- a/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.br.ktd.utils - -import java.io.File - -interface OnImageCompressListener { - /** - * Fired when a compression returns successfully, override to handle in your own code - */ - fun onSuccess(file: File) - - /** - * Fired when a compression fails to complete, override to handle in your own code - */ - fun onError(e: Throwable) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt b/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt index b3146e7..7d6e558 100644 --- a/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt +++ b/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt @@ -29,7 +29,7 @@ import com.casic.br.ktd.extensions.* import com.casic.br.ktd.model.AlarmParam import com.casic.br.ktd.model.ChartPointModel -import com.casic.br.ktd.model.RouteModel +import com.casic.br.ktd.model.PointModel import com.casic.br.ktd.model.SensorDataModel import com.casic.br.ktd.netty.tcp.SocketManager import com.casic.br.ktd.netty.udp.UdpClient @@ -273,9 +273,9 @@ ) if (isStartInspect) { - val route = LinkedList() + val route = LinkedList() latlngs.forEach { - route.add(RouteModel(it.latitude, it.longitude)) + route.add(PointModel(it.latitude, it.longitude)) } } } diff --git a/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt b/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt index bce4c24..b3c519a 100644 --- a/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt +++ b/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt @@ -21,7 +21,6 @@ import com.casic.br.ktd.fragment.TaskPageFragment import com.casic.br.ktd.utils.LocaleConstant import com.casic.br.ktd.vm.AlarmViewModel -import com.casic.br.ktd.vm.VehicleViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.show @@ -36,7 +35,6 @@ private val fragmentPages = ArrayList() private val slideAdapter by lazy { SlideAdapter(this) } private var clickTime: Long = 0 - private lateinit var vehicleViewModel: VehicleViewModel private lateinit var alarmViewModel: AlarmViewModel init { @@ -71,20 +69,6 @@ //显示首页 switchPage(fragmentPages[0]) - vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] - vehicleViewModel.getVehicles() - vehicleViewModel.vehicleList.observe(this) { - if (it.code == 200) { - if (it.data.rows.isNotEmpty()) { - val model = it.data.rows[0] - SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, model.carPlate) - SaveKeyValues.putValue(LocaleConstant.CAR_ID, model.id) - } else { - Log.d(kTag, "initData => 无可用巡检车") - } - } - } - alarmViewModel = ViewModelProvider(this)[AlarmViewModel::class.java] alarmViewModel.getAlarmRules() alarmViewModel.alarmRuleList.observe(this) { diff --git a/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt b/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt index d81e7d6..c869ed8 100644 --- a/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt +++ b/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt @@ -1,7 +1,15 @@ package com.casic.br.ktd.vm +import androidx.lifecycle.MutableLiveData +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.extensions.separateResponseCode +import com.casic.br.ktd.extensions.toErrorMessage +import com.casic.br.ktd.model.VehicleRouteModel import com.casic.br.ktd.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.launch +import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.vm.BaseViewModel /** @@ -9,6 +17,9 @@ * */ class PointViewModel : BaseViewModel() { + private val gson by lazy { Gson() } + val vehicleRoute = MutableLiveData() + fun uploadPointDetail( isAlarm: String, lagitude: String, @@ -36,4 +47,18 @@ }, { it.printStackTrace() }) + + fun busTrackRoute() = launch({ + val response = RetrofitServiceManager.busTrackRoute() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + vehicleRoute.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + }) } \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml new file mode 100644 index 0000000..aeae610 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/error.xml b/app/src/main/res/drawable/error.xml new file mode 100644 index 0000000..41b3c96 --- /dev/null +++ b/app/src/main/res/drawable/error.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/layout/popu_map_car_window.xml b/app/src/main/res/layout/popu_map_car_window.xml new file mode 100644 index 0000000..b04d908 --- /dev/null +++ b/app/src/main/res/layout/popu_map_car_window.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/vehicle_on.png b/app/src/main/res/mipmap-hdpi/vehicle_on.png new file mode 100644 index 0000000..817609a --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/vehicle_on.png Binary files differ diff --git a/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt new file mode 100644 index 0000000..40b3660 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt @@ -0,0 +1,28 @@ +package com.casic.br.ktd.extensions + +import com.amap.api.maps.model.LatLng +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.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.listener.OnGeocodeSearchListener + +private val geocoderSearch by lazy { GeocodeSearch(BaseApplication.get()) } + +fun LatLng.toChineseAddress(listener: OnGeocodeSearchListener) { + val queryParam = RegeocodeQuery( + LatLonPoint(this.latitude, this.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + listener.onRegionCodeSearched(regeocodeResult.regeocodeAddress.formatAddress) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index 36af820..e090122 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -1,9 +1,9 @@ package com.casic.br.ktd.extensions import android.content.Context +import com.casic.br.ktd.listener.OnImageCompressListener import com.casic.br.ktd.model.ErrorMessageModel import com.casic.br.ktd.utils.LocaleConstant -import com.casic.br.ktd.utils.OnImageCompressListener import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.createCompressImageDir @@ -14,7 +14,8 @@ import top.zibin.luban.OnCompressListener import java.io.File import java.text.SimpleDateFormat -import java.util.* +import java.util.Date +import java.util.Locale import java.util.regex.Pattern diff --git a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt index 40b27b1..a8d1e7a 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt @@ -2,31 +2,55 @@ import android.graphics.Color import android.os.Bundle +import android.os.Handler +import android.os.Message import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.model.BitmapDescriptorFactory import com.amap.api.maps.model.CameraPosition import com.amap.api.maps.model.LatLng +import com.amap.api.maps.model.Marker import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.PolylineOptions import com.casic.br.ktd.R import com.casic.br.ktd.databinding.FragmentHomeBinding +import com.casic.br.ktd.extensions.toChineseAddress +import com.casic.br.ktd.listener.OnGeocodeSearchListener +import com.casic.br.ktd.model.DeviceListModel +import com.casic.br.ktd.model.VehicleListModel +import com.casic.br.ktd.utils.LocaleConstant +import com.casic.br.ktd.vm.DeviceViewModel +import com.casic.br.ktd.vm.VehicleViewModel import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.utils.SaveKeyValues +import com.pengxh.kt.lite.utils.WeakReferenceHandler +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton -class HomePageFragment : KotlinBaseFragment() { +class HomePageFragment : KotlinBaseFragment(), AMap.OnMarkerClickListener, + AMap.InfoWindowAdapter, Handler.Callback { + + private val kTag = "HomePageFragment" + private lateinit var vehicleViewModel: VehicleViewModel + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private lateinit var weakReferenceHandler: WeakReferenceHandler + private var isInfoWindowShow = false + private val handlerVehicleCode = 2023082501 + private val handlerDeviceCode = 2023082502 override fun initViewBinding( - inflater: LayoutInflater, - container: ViewGroup? + inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { return FragmentHomeBinding.inflate(inflater, container, false) } - private lateinit var aMap: AMap - override fun initOnCreate(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -36,6 +60,143 @@ uiSettings.isScaleControlsEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isRotateGesturesEnabled = false//不许地图随手势旋转角度 + // 点击marker弹出自定义popup + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) + + weakReferenceHandler = WeakReferenceHandler(this) + + vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] + vehicleViewModel.getVehicles() + vehicleViewModel.vehicleList.observe(this) { + if (it.code == 200) { + if (it.data.rows.isNotEmpty()) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerVehicleCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + deviceViewModel.deviceList.observe(this) { + if (it.code == 200) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerDeviceCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + handlerVehicleCode -> { + val vehicleModel = msg.obj as VehicleListModel.DataModel.RowsModel + + SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, vehicleModel.carPlate) + SaveKeyValues.putValue(LocaleConstant.CAR_ID, vehicleModel.id) + + val marker = if (vehicleModel.status == "1") { + //在线 + R.mipmap.vehicle_on + } else { + //离线 + R.mipmap.vehicle_on + } + + val latLng = LatLng( + vehicleModel.latitude.toDouble(), vehicleModel.longitude.toDouble() + ) + addMarker(latLng, "Car", marker) + + /** + * 地图PopupWindow数据绑定 + * ****/ + if (isInfoWindowShow) { + windowTitleView.text = vehicleModel.carPlate + val state = if (vehicleModel.status == "1") { + "状态:在线" + } else { + "状态:离线" + } + carStateView.text = state + + timeView.text = "时间:${vehicleModel.ts}" + latLng.toChineseAddress(object : OnGeocodeSearchListener { + override fun onRegionCodeSearched(address: String) { + locationView.text = "位置:$address" + } + }) + } + } + + handlerDeviceCode -> { + if (isInfoWindowShow) { + val deviceModel = msg.obj as DeviceListModel.DataModel.RowsModel + + deviceModelView.text = "云台型号:${deviceModel.deviceModel}" + } + } + } + return true + } + + override fun onMarkerClick(marker: Marker?): Boolean { + //点击Marker显示自定义Popup + marker?.showInfoWindow() + return true + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + + private lateinit var windowTitleView: TextView + private lateinit var taskStateView: QMUIRoundButton + private lateinit var carStateView: TextView + private lateinit var deviceModelView: TextView + private lateinit var timeView: TextView + private lateinit var locationView: TextView + + override fun getInfoWindow(marker: Marker?): View { + isInfoWindowShow = true + + val v = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_car_window, null) + + windowTitleView = v.findViewById(R.id.windowTitleView) + taskStateView = v.findViewById(R.id.taskStateView) + val closeView = v.findViewById(R.id.closeView) + carStateView = v.findViewById(R.id.carStateView) + deviceModelView = v.findViewById(R.id.deviceModelView) + timeView = v.findViewById(R.id.timeView) + locationView = v.findViewById(R.id.locationView) + val routeView = v.findViewById(R.id.routeView) + + if (marker?.title == "Car") { + taskStateView.visibility = View.GONE + routeView.visibility = View.GONE + + vehicleViewModel.getVehicles() + + deviceViewModel.getDevices() + } else { + taskStateView.visibility = View.VISIBLE + routeView.visibility = View.VISIBLE + + routeView.setOnClickListener { + + } + } + + closeView.setOnClickListener { + marker?.hideInfoWindow() + isInfoWindowShow = false + } + return v } override fun initEvent() { @@ -44,9 +205,9 @@ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 1500, null) //设置起点 - addMarker(LatLng(39.914885, 116.272312), R.mipmap.start) + addMarker(LatLng(39.914885, 116.272312), "", R.mipmap.start) //设置终点 - addMarker(LatLng(39.914716, 116.265097), R.mipmap.end) + addMarker(LatLng(39.914716, 116.265097), "", R.mipmap.end) //瞄点画线 val latLngPoints = ArrayList() latLngPoints.add(LatLng(39.914885, 116.272312)) @@ -78,9 +239,10 @@ } - private fun addMarker(point: LatLng, res: Int) { + private fun addMarker(point: LatLng, type: String, res: Int) { val markerOption = MarkerOptions() markerOption.position(point) + markerOption.title(type) markerOption.icon(BitmapDescriptorFactory.fromResource(res)) aMap.addMarker(markerOption) } diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt new file mode 100644 index 0000000..ad16496 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt @@ -0,0 +1,5 @@ +package com.casic.br.ktd.listener + +interface OnGeocodeSearchListener { + fun onRegionCodeSearched(address: String) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt new file mode 100644 index 0000000..61104eb --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt @@ -0,0 +1,15 @@ +package com.casic.br.ktd.listener + +import java.io.File + +interface OnImageCompressListener { + /** + * Fired when a compression returns successfully, override to handle in your own code + */ + fun onSuccess(file: File) + + /** + * Fired when a compression fails to complete, override to handle in your own code + */ + fun onError(e: Throwable) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/model/PointModel.kt b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt new file mode 100644 index 0000000..ec2065d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt @@ -0,0 +1,3 @@ +package com.casic.br.ktd.model + +data class PointModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt b/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt deleted file mode 100644 index c45d645..0000000 --- a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.casic.br.ktd.model - -data class RouteModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java new file mode 100644 index 0000000..e813075 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java @@ -0,0 +1,166 @@ +package com.casic.br.ktd.model; + +import java.util.List; + +public class VehicleRouteModel { + + private Integer code; + private DataModel data; + private String message; + + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } + + public DataModel getData() { + return data; + } + + public void setData(DataModel data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public static class DataModel { + private List rows; + private Integer total; + + public List getRows() { + return rows; + } + + public void setRows(List rows) { + this.rows = rows; + } + + public Integer getTotal() { + return total; + } + + public void setTotal(Integer total) { + this.total = total; + } + + public static class RowsModel { + private String deviceStatus; + private String direction; + private String gas; + private String id; + private String isAlarm; + private String lagitude; + private String longitude; + private String pitch; + private String position; + private String speed; + private String taskId; + private String ts; + + public String getDeviceStatus() { + return deviceStatus; + } + + public void setDeviceStatus(String deviceStatus) { + this.deviceStatus = deviceStatus; + } + + public String getDirection() { + return direction; + } + + public void setDirection(String direction) { + this.direction = direction; + } + + public String getGas() { + return gas; + } + + public void setGas(String gas) { + this.gas = gas; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getIsAlarm() { + return isAlarm; + } + + public void setIsAlarm(String isAlarm) { + this.isAlarm = isAlarm; + } + + public String getLagitude() { + return lagitude; + } + + public void setLagitude(String lagitude) { + this.lagitude = lagitude; + } + + public String getLongitude() { + return longitude; + } + + public void setLongitude(String longitude) { + this.longitude = longitude; + } + + public String getPitch() { + return pitch; + } + + public void setPitch(String pitch) { + this.pitch = pitch; + } + + public String getPosition() { + return position; + } + + public void setPosition(String position) { + this.position = position; + } + + public String getSpeed() { + return speed; + } + + public void setSpeed(String speed) { + this.speed = speed; + } + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public String getTs() { + return ts; + } + + public void setTs(String ts) { + this.ts = ts; + } + } + } +} diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt index 9211b3a..519ab45 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt @@ -49,7 +49,7 @@ @Header("token") token: String, @Body requestBody: RequestBody, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -78,7 +78,7 @@ suspend fun getVehicles( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -88,7 +88,7 @@ suspend fun getDevices( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -101,6 +101,16 @@ ): String /** + * 巡检路径 + */ + @POST("/system/busPatrolTrack/listPage") + suspend fun busTrackRoute( + @Header("token") token: String, + @QueryMap limit: Map, + @QueryMap offset: Map + ): String + + /** * 新增报警规则,主要是阈值 */ @POST("/system/alarmRule/add") @@ -116,7 +126,7 @@ suspend fun getAlarmRules( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -146,6 +156,6 @@ @Header("token") token: String, @Body requestBody: RequestBody, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt index 0f109db..fd9624c 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt @@ -186,6 +186,18 @@ } /** + * 巡检路径 + */ + suspend fun busTrackRoute(): String { + val limitMap = HashMap() + limitMap["limit"] = LocaleConstant.PAGE_LIMIT + + val offsetMap = HashMap() + offsetMap["offset"] = 1 + return api.busTrackRoute(AuthenticationHelper.token, limitMap, offsetMap) + } + + /** * 新增报警规则,主要是阈值 */ suspend fun addAlarmRule(high: String, deviceId: String, ts: String): String { diff --git a/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt deleted file mode 100644 index 92286ad..0000000 --- a/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.br.ktd.utils - -import java.io.File - -interface OnImageCompressListener { - /** - * Fired when a compression returns successfully, override to handle in your own code - */ - fun onSuccess(file: File) - - /** - * Fired when a compression fails to complete, override to handle in your own code - */ - fun onError(e: Throwable) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt b/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt index b3146e7..7d6e558 100644 --- a/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt +++ b/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt @@ -29,7 +29,7 @@ import com.casic.br.ktd.extensions.* import com.casic.br.ktd.model.AlarmParam import com.casic.br.ktd.model.ChartPointModel -import com.casic.br.ktd.model.RouteModel +import com.casic.br.ktd.model.PointModel import com.casic.br.ktd.model.SensorDataModel import com.casic.br.ktd.netty.tcp.SocketManager import com.casic.br.ktd.netty.udp.UdpClient @@ -273,9 +273,9 @@ ) if (isStartInspect) { - val route = LinkedList() + val route = LinkedList() latlngs.forEach { - route.add(RouteModel(it.latitude, it.longitude)) + route.add(PointModel(it.latitude, it.longitude)) } } } diff --git a/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt b/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt index bce4c24..b3c519a 100644 --- a/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt +++ b/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt @@ -21,7 +21,6 @@ import com.casic.br.ktd.fragment.TaskPageFragment import com.casic.br.ktd.utils.LocaleConstant import com.casic.br.ktd.vm.AlarmViewModel -import com.casic.br.ktd.vm.VehicleViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.show @@ -36,7 +35,6 @@ private val fragmentPages = ArrayList() private val slideAdapter by lazy { SlideAdapter(this) } private var clickTime: Long = 0 - private lateinit var vehicleViewModel: VehicleViewModel private lateinit var alarmViewModel: AlarmViewModel init { @@ -71,20 +69,6 @@ //显示首页 switchPage(fragmentPages[0]) - vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] - vehicleViewModel.getVehicles() - vehicleViewModel.vehicleList.observe(this) { - if (it.code == 200) { - if (it.data.rows.isNotEmpty()) { - val model = it.data.rows[0] - SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, model.carPlate) - SaveKeyValues.putValue(LocaleConstant.CAR_ID, model.id) - } else { - Log.d(kTag, "initData => 无可用巡检车") - } - } - } - alarmViewModel = ViewModelProvider(this)[AlarmViewModel::class.java] alarmViewModel.getAlarmRules() alarmViewModel.alarmRuleList.observe(this) { diff --git a/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt b/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt index d81e7d6..c869ed8 100644 --- a/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt +++ b/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt @@ -1,7 +1,15 @@ package com.casic.br.ktd.vm +import androidx.lifecycle.MutableLiveData +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.extensions.separateResponseCode +import com.casic.br.ktd.extensions.toErrorMessage +import com.casic.br.ktd.model.VehicleRouteModel import com.casic.br.ktd.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.launch +import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.vm.BaseViewModel /** @@ -9,6 +17,9 @@ * */ class PointViewModel : BaseViewModel() { + private val gson by lazy { Gson() } + val vehicleRoute = MutableLiveData() + fun uploadPointDetail( isAlarm: String, lagitude: String, @@ -36,4 +47,18 @@ }, { it.printStackTrace() }) + + fun busTrackRoute() = launch({ + val response = RetrofitServiceManager.busTrackRoute() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + vehicleRoute.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + }) } \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml new file mode 100644 index 0000000..aeae610 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/error.xml b/app/src/main/res/drawable/error.xml new file mode 100644 index 0000000..41b3c96 --- /dev/null +++ b/app/src/main/res/drawable/error.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/layout/popu_map_car_window.xml b/app/src/main/res/layout/popu_map_car_window.xml new file mode 100644 index 0000000..b04d908 --- /dev/null +++ b/app/src/main/res/layout/popu_map_car_window.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/vehicle_on.png b/app/src/main/res/mipmap-hdpi/vehicle_on.png new file mode 100644 index 0000000..817609a --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/vehicle_on.png Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/vehicle_on.png b/app/src/main/res/mipmap-mdpi/vehicle_on.png new file mode 100644 index 0000000..817609a --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/vehicle_on.png Binary files differ diff --git a/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt new file mode 100644 index 0000000..40b3660 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt @@ -0,0 +1,28 @@ +package com.casic.br.ktd.extensions + +import com.amap.api.maps.model.LatLng +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.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.listener.OnGeocodeSearchListener + +private val geocoderSearch by lazy { GeocodeSearch(BaseApplication.get()) } + +fun LatLng.toChineseAddress(listener: OnGeocodeSearchListener) { + val queryParam = RegeocodeQuery( + LatLonPoint(this.latitude, this.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + listener.onRegionCodeSearched(regeocodeResult.regeocodeAddress.formatAddress) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index 36af820..e090122 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -1,9 +1,9 @@ package com.casic.br.ktd.extensions import android.content.Context +import com.casic.br.ktd.listener.OnImageCompressListener import com.casic.br.ktd.model.ErrorMessageModel import com.casic.br.ktd.utils.LocaleConstant -import com.casic.br.ktd.utils.OnImageCompressListener import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.createCompressImageDir @@ -14,7 +14,8 @@ import top.zibin.luban.OnCompressListener import java.io.File import java.text.SimpleDateFormat -import java.util.* +import java.util.Date +import java.util.Locale import java.util.regex.Pattern diff --git a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt index 40b27b1..a8d1e7a 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt @@ -2,31 +2,55 @@ import android.graphics.Color import android.os.Bundle +import android.os.Handler +import android.os.Message import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.model.BitmapDescriptorFactory import com.amap.api.maps.model.CameraPosition import com.amap.api.maps.model.LatLng +import com.amap.api.maps.model.Marker import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.PolylineOptions import com.casic.br.ktd.R import com.casic.br.ktd.databinding.FragmentHomeBinding +import com.casic.br.ktd.extensions.toChineseAddress +import com.casic.br.ktd.listener.OnGeocodeSearchListener +import com.casic.br.ktd.model.DeviceListModel +import com.casic.br.ktd.model.VehicleListModel +import com.casic.br.ktd.utils.LocaleConstant +import com.casic.br.ktd.vm.DeviceViewModel +import com.casic.br.ktd.vm.VehicleViewModel import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.utils.SaveKeyValues +import com.pengxh.kt.lite.utils.WeakReferenceHandler +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton -class HomePageFragment : KotlinBaseFragment() { +class HomePageFragment : KotlinBaseFragment(), AMap.OnMarkerClickListener, + AMap.InfoWindowAdapter, Handler.Callback { + + private val kTag = "HomePageFragment" + private lateinit var vehicleViewModel: VehicleViewModel + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private lateinit var weakReferenceHandler: WeakReferenceHandler + private var isInfoWindowShow = false + private val handlerVehicleCode = 2023082501 + private val handlerDeviceCode = 2023082502 override fun initViewBinding( - inflater: LayoutInflater, - container: ViewGroup? + inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { return FragmentHomeBinding.inflate(inflater, container, false) } - private lateinit var aMap: AMap - override fun initOnCreate(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -36,6 +60,143 @@ uiSettings.isScaleControlsEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isRotateGesturesEnabled = false//不许地图随手势旋转角度 + // 点击marker弹出自定义popup + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) + + weakReferenceHandler = WeakReferenceHandler(this) + + vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] + vehicleViewModel.getVehicles() + vehicleViewModel.vehicleList.observe(this) { + if (it.code == 200) { + if (it.data.rows.isNotEmpty()) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerVehicleCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + deviceViewModel.deviceList.observe(this) { + if (it.code == 200) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerDeviceCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + handlerVehicleCode -> { + val vehicleModel = msg.obj as VehicleListModel.DataModel.RowsModel + + SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, vehicleModel.carPlate) + SaveKeyValues.putValue(LocaleConstant.CAR_ID, vehicleModel.id) + + val marker = if (vehicleModel.status == "1") { + //在线 + R.mipmap.vehicle_on + } else { + //离线 + R.mipmap.vehicle_on + } + + val latLng = LatLng( + vehicleModel.latitude.toDouble(), vehicleModel.longitude.toDouble() + ) + addMarker(latLng, "Car", marker) + + /** + * 地图PopupWindow数据绑定 + * ****/ + if (isInfoWindowShow) { + windowTitleView.text = vehicleModel.carPlate + val state = if (vehicleModel.status == "1") { + "状态:在线" + } else { + "状态:离线" + } + carStateView.text = state + + timeView.text = "时间:${vehicleModel.ts}" + latLng.toChineseAddress(object : OnGeocodeSearchListener { + override fun onRegionCodeSearched(address: String) { + locationView.text = "位置:$address" + } + }) + } + } + + handlerDeviceCode -> { + if (isInfoWindowShow) { + val deviceModel = msg.obj as DeviceListModel.DataModel.RowsModel + + deviceModelView.text = "云台型号:${deviceModel.deviceModel}" + } + } + } + return true + } + + override fun onMarkerClick(marker: Marker?): Boolean { + //点击Marker显示自定义Popup + marker?.showInfoWindow() + return true + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + + private lateinit var windowTitleView: TextView + private lateinit var taskStateView: QMUIRoundButton + private lateinit var carStateView: TextView + private lateinit var deviceModelView: TextView + private lateinit var timeView: TextView + private lateinit var locationView: TextView + + override fun getInfoWindow(marker: Marker?): View { + isInfoWindowShow = true + + val v = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_car_window, null) + + windowTitleView = v.findViewById(R.id.windowTitleView) + taskStateView = v.findViewById(R.id.taskStateView) + val closeView = v.findViewById(R.id.closeView) + carStateView = v.findViewById(R.id.carStateView) + deviceModelView = v.findViewById(R.id.deviceModelView) + timeView = v.findViewById(R.id.timeView) + locationView = v.findViewById(R.id.locationView) + val routeView = v.findViewById(R.id.routeView) + + if (marker?.title == "Car") { + taskStateView.visibility = View.GONE + routeView.visibility = View.GONE + + vehicleViewModel.getVehicles() + + deviceViewModel.getDevices() + } else { + taskStateView.visibility = View.VISIBLE + routeView.visibility = View.VISIBLE + + routeView.setOnClickListener { + + } + } + + closeView.setOnClickListener { + marker?.hideInfoWindow() + isInfoWindowShow = false + } + return v } override fun initEvent() { @@ -44,9 +205,9 @@ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 1500, null) //设置起点 - addMarker(LatLng(39.914885, 116.272312), R.mipmap.start) + addMarker(LatLng(39.914885, 116.272312), "", R.mipmap.start) //设置终点 - addMarker(LatLng(39.914716, 116.265097), R.mipmap.end) + addMarker(LatLng(39.914716, 116.265097), "", R.mipmap.end) //瞄点画线 val latLngPoints = ArrayList() latLngPoints.add(LatLng(39.914885, 116.272312)) @@ -78,9 +239,10 @@ } - private fun addMarker(point: LatLng, res: Int) { + private fun addMarker(point: LatLng, type: String, res: Int) { val markerOption = MarkerOptions() markerOption.position(point) + markerOption.title(type) markerOption.icon(BitmapDescriptorFactory.fromResource(res)) aMap.addMarker(markerOption) } diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt new file mode 100644 index 0000000..ad16496 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt @@ -0,0 +1,5 @@ +package com.casic.br.ktd.listener + +interface OnGeocodeSearchListener { + fun onRegionCodeSearched(address: String) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt new file mode 100644 index 0000000..61104eb --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt @@ -0,0 +1,15 @@ +package com.casic.br.ktd.listener + +import java.io.File + +interface OnImageCompressListener { + /** + * Fired when a compression returns successfully, override to handle in your own code + */ + fun onSuccess(file: File) + + /** + * Fired when a compression fails to complete, override to handle in your own code + */ + fun onError(e: Throwable) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/model/PointModel.kt b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt new file mode 100644 index 0000000..ec2065d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt @@ -0,0 +1,3 @@ +package com.casic.br.ktd.model + +data class PointModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt b/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt deleted file mode 100644 index c45d645..0000000 --- a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.casic.br.ktd.model - -data class RouteModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java new file mode 100644 index 0000000..e813075 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java @@ -0,0 +1,166 @@ +package com.casic.br.ktd.model; + +import java.util.List; + +public class VehicleRouteModel { + + private Integer code; + private DataModel data; + private String message; + + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } + + public DataModel getData() { + return data; + } + + public void setData(DataModel data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public static class DataModel { + private List rows; + private Integer total; + + public List getRows() { + return rows; + } + + public void setRows(List rows) { + this.rows = rows; + } + + public Integer getTotal() { + return total; + } + + public void setTotal(Integer total) { + this.total = total; + } + + public static class RowsModel { + private String deviceStatus; + private String direction; + private String gas; + private String id; + private String isAlarm; + private String lagitude; + private String longitude; + private String pitch; + private String position; + private String speed; + private String taskId; + private String ts; + + public String getDeviceStatus() { + return deviceStatus; + } + + public void setDeviceStatus(String deviceStatus) { + this.deviceStatus = deviceStatus; + } + + public String getDirection() { + return direction; + } + + public void setDirection(String direction) { + this.direction = direction; + } + + public String getGas() { + return gas; + } + + public void setGas(String gas) { + this.gas = gas; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getIsAlarm() { + return isAlarm; + } + + public void setIsAlarm(String isAlarm) { + this.isAlarm = isAlarm; + } + + public String getLagitude() { + return lagitude; + } + + public void setLagitude(String lagitude) { + this.lagitude = lagitude; + } + + public String getLongitude() { + return longitude; + } + + public void setLongitude(String longitude) { + this.longitude = longitude; + } + + public String getPitch() { + return pitch; + } + + public void setPitch(String pitch) { + this.pitch = pitch; + } + + public String getPosition() { + return position; + } + + public void setPosition(String position) { + this.position = position; + } + + public String getSpeed() { + return speed; + } + + public void setSpeed(String speed) { + this.speed = speed; + } + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public String getTs() { + return ts; + } + + public void setTs(String ts) { + this.ts = ts; + } + } + } +} diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt index 9211b3a..519ab45 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt @@ -49,7 +49,7 @@ @Header("token") token: String, @Body requestBody: RequestBody, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -78,7 +78,7 @@ suspend fun getVehicles( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -88,7 +88,7 @@ suspend fun getDevices( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -101,6 +101,16 @@ ): String /** + * 巡检路径 + */ + @POST("/system/busPatrolTrack/listPage") + suspend fun busTrackRoute( + @Header("token") token: String, + @QueryMap limit: Map, + @QueryMap offset: Map + ): String + + /** * 新增报警规则,主要是阈值 */ @POST("/system/alarmRule/add") @@ -116,7 +126,7 @@ suspend fun getAlarmRules( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -146,6 +156,6 @@ @Header("token") token: String, @Body requestBody: RequestBody, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt index 0f109db..fd9624c 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt @@ -186,6 +186,18 @@ } /** + * 巡检路径 + */ + suspend fun busTrackRoute(): String { + val limitMap = HashMap() + limitMap["limit"] = LocaleConstant.PAGE_LIMIT + + val offsetMap = HashMap() + offsetMap["offset"] = 1 + return api.busTrackRoute(AuthenticationHelper.token, limitMap, offsetMap) + } + + /** * 新增报警规则,主要是阈值 */ suspend fun addAlarmRule(high: String, deviceId: String, ts: String): String { diff --git a/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt deleted file mode 100644 index 92286ad..0000000 --- a/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.br.ktd.utils - -import java.io.File - -interface OnImageCompressListener { - /** - * Fired when a compression returns successfully, override to handle in your own code - */ - fun onSuccess(file: File) - - /** - * Fired when a compression fails to complete, override to handle in your own code - */ - fun onError(e: Throwable) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt b/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt index b3146e7..7d6e558 100644 --- a/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt +++ b/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt @@ -29,7 +29,7 @@ import com.casic.br.ktd.extensions.* import com.casic.br.ktd.model.AlarmParam import com.casic.br.ktd.model.ChartPointModel -import com.casic.br.ktd.model.RouteModel +import com.casic.br.ktd.model.PointModel import com.casic.br.ktd.model.SensorDataModel import com.casic.br.ktd.netty.tcp.SocketManager import com.casic.br.ktd.netty.udp.UdpClient @@ -273,9 +273,9 @@ ) if (isStartInspect) { - val route = LinkedList() + val route = LinkedList() latlngs.forEach { - route.add(RouteModel(it.latitude, it.longitude)) + route.add(PointModel(it.latitude, it.longitude)) } } } diff --git a/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt b/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt index bce4c24..b3c519a 100644 --- a/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt +++ b/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt @@ -21,7 +21,6 @@ import com.casic.br.ktd.fragment.TaskPageFragment import com.casic.br.ktd.utils.LocaleConstant import com.casic.br.ktd.vm.AlarmViewModel -import com.casic.br.ktd.vm.VehicleViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.show @@ -36,7 +35,6 @@ private val fragmentPages = ArrayList() private val slideAdapter by lazy { SlideAdapter(this) } private var clickTime: Long = 0 - private lateinit var vehicleViewModel: VehicleViewModel private lateinit var alarmViewModel: AlarmViewModel init { @@ -71,20 +69,6 @@ //显示首页 switchPage(fragmentPages[0]) - vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] - vehicleViewModel.getVehicles() - vehicleViewModel.vehicleList.observe(this) { - if (it.code == 200) { - if (it.data.rows.isNotEmpty()) { - val model = it.data.rows[0] - SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, model.carPlate) - SaveKeyValues.putValue(LocaleConstant.CAR_ID, model.id) - } else { - Log.d(kTag, "initData => 无可用巡检车") - } - } - } - alarmViewModel = ViewModelProvider(this)[AlarmViewModel::class.java] alarmViewModel.getAlarmRules() alarmViewModel.alarmRuleList.observe(this) { diff --git a/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt b/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt index d81e7d6..c869ed8 100644 --- a/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt +++ b/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt @@ -1,7 +1,15 @@ package com.casic.br.ktd.vm +import androidx.lifecycle.MutableLiveData +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.extensions.separateResponseCode +import com.casic.br.ktd.extensions.toErrorMessage +import com.casic.br.ktd.model.VehicleRouteModel import com.casic.br.ktd.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.launch +import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.vm.BaseViewModel /** @@ -9,6 +17,9 @@ * */ class PointViewModel : BaseViewModel() { + private val gson by lazy { Gson() } + val vehicleRoute = MutableLiveData() + fun uploadPointDetail( isAlarm: String, lagitude: String, @@ -36,4 +47,18 @@ }, { it.printStackTrace() }) + + fun busTrackRoute() = launch({ + val response = RetrofitServiceManager.busTrackRoute() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + vehicleRoute.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + }) } \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml new file mode 100644 index 0000000..aeae610 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/error.xml b/app/src/main/res/drawable/error.xml new file mode 100644 index 0000000..41b3c96 --- /dev/null +++ b/app/src/main/res/drawable/error.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/layout/popu_map_car_window.xml b/app/src/main/res/layout/popu_map_car_window.xml new file mode 100644 index 0000000..b04d908 --- /dev/null +++ b/app/src/main/res/layout/popu_map_car_window.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/vehicle_on.png b/app/src/main/res/mipmap-hdpi/vehicle_on.png new file mode 100644 index 0000000..817609a --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/vehicle_on.png Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/vehicle_on.png b/app/src/main/res/mipmap-mdpi/vehicle_on.png new file mode 100644 index 0000000..817609a --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/vehicle_on.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/vehicle_on.png b/app/src/main/res/mipmap-xhdpi/vehicle_on.png new file mode 100644 index 0000000..817609a --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/vehicle_on.png Binary files differ diff --git a/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt new file mode 100644 index 0000000..40b3660 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt @@ -0,0 +1,28 @@ +package com.casic.br.ktd.extensions + +import com.amap.api.maps.model.LatLng +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.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.listener.OnGeocodeSearchListener + +private val geocoderSearch by lazy { GeocodeSearch(BaseApplication.get()) } + +fun LatLng.toChineseAddress(listener: OnGeocodeSearchListener) { + val queryParam = RegeocodeQuery( + LatLonPoint(this.latitude, this.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + listener.onRegionCodeSearched(regeocodeResult.regeocodeAddress.formatAddress) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index 36af820..e090122 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -1,9 +1,9 @@ package com.casic.br.ktd.extensions import android.content.Context +import com.casic.br.ktd.listener.OnImageCompressListener import com.casic.br.ktd.model.ErrorMessageModel import com.casic.br.ktd.utils.LocaleConstant -import com.casic.br.ktd.utils.OnImageCompressListener import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.createCompressImageDir @@ -14,7 +14,8 @@ import top.zibin.luban.OnCompressListener import java.io.File import java.text.SimpleDateFormat -import java.util.* +import java.util.Date +import java.util.Locale import java.util.regex.Pattern diff --git a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt index 40b27b1..a8d1e7a 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt @@ -2,31 +2,55 @@ import android.graphics.Color import android.os.Bundle +import android.os.Handler +import android.os.Message import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.model.BitmapDescriptorFactory import com.amap.api.maps.model.CameraPosition import com.amap.api.maps.model.LatLng +import com.amap.api.maps.model.Marker import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.PolylineOptions import com.casic.br.ktd.R import com.casic.br.ktd.databinding.FragmentHomeBinding +import com.casic.br.ktd.extensions.toChineseAddress +import com.casic.br.ktd.listener.OnGeocodeSearchListener +import com.casic.br.ktd.model.DeviceListModel +import com.casic.br.ktd.model.VehicleListModel +import com.casic.br.ktd.utils.LocaleConstant +import com.casic.br.ktd.vm.DeviceViewModel +import com.casic.br.ktd.vm.VehicleViewModel import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.utils.SaveKeyValues +import com.pengxh.kt.lite.utils.WeakReferenceHandler +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton -class HomePageFragment : KotlinBaseFragment() { +class HomePageFragment : KotlinBaseFragment(), AMap.OnMarkerClickListener, + AMap.InfoWindowAdapter, Handler.Callback { + + private val kTag = "HomePageFragment" + private lateinit var vehicleViewModel: VehicleViewModel + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private lateinit var weakReferenceHandler: WeakReferenceHandler + private var isInfoWindowShow = false + private val handlerVehicleCode = 2023082501 + private val handlerDeviceCode = 2023082502 override fun initViewBinding( - inflater: LayoutInflater, - container: ViewGroup? + inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { return FragmentHomeBinding.inflate(inflater, container, false) } - private lateinit var aMap: AMap - override fun initOnCreate(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -36,6 +60,143 @@ uiSettings.isScaleControlsEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isRotateGesturesEnabled = false//不许地图随手势旋转角度 + // 点击marker弹出自定义popup + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) + + weakReferenceHandler = WeakReferenceHandler(this) + + vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] + vehicleViewModel.getVehicles() + vehicleViewModel.vehicleList.observe(this) { + if (it.code == 200) { + if (it.data.rows.isNotEmpty()) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerVehicleCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + deviceViewModel.deviceList.observe(this) { + if (it.code == 200) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerDeviceCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + handlerVehicleCode -> { + val vehicleModel = msg.obj as VehicleListModel.DataModel.RowsModel + + SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, vehicleModel.carPlate) + SaveKeyValues.putValue(LocaleConstant.CAR_ID, vehicleModel.id) + + val marker = if (vehicleModel.status == "1") { + //在线 + R.mipmap.vehicle_on + } else { + //离线 + R.mipmap.vehicle_on + } + + val latLng = LatLng( + vehicleModel.latitude.toDouble(), vehicleModel.longitude.toDouble() + ) + addMarker(latLng, "Car", marker) + + /** + * 地图PopupWindow数据绑定 + * ****/ + if (isInfoWindowShow) { + windowTitleView.text = vehicleModel.carPlate + val state = if (vehicleModel.status == "1") { + "状态:在线" + } else { + "状态:离线" + } + carStateView.text = state + + timeView.text = "时间:${vehicleModel.ts}" + latLng.toChineseAddress(object : OnGeocodeSearchListener { + override fun onRegionCodeSearched(address: String) { + locationView.text = "位置:$address" + } + }) + } + } + + handlerDeviceCode -> { + if (isInfoWindowShow) { + val deviceModel = msg.obj as DeviceListModel.DataModel.RowsModel + + deviceModelView.text = "云台型号:${deviceModel.deviceModel}" + } + } + } + return true + } + + override fun onMarkerClick(marker: Marker?): Boolean { + //点击Marker显示自定义Popup + marker?.showInfoWindow() + return true + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + + private lateinit var windowTitleView: TextView + private lateinit var taskStateView: QMUIRoundButton + private lateinit var carStateView: TextView + private lateinit var deviceModelView: TextView + private lateinit var timeView: TextView + private lateinit var locationView: TextView + + override fun getInfoWindow(marker: Marker?): View { + isInfoWindowShow = true + + val v = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_car_window, null) + + windowTitleView = v.findViewById(R.id.windowTitleView) + taskStateView = v.findViewById(R.id.taskStateView) + val closeView = v.findViewById(R.id.closeView) + carStateView = v.findViewById(R.id.carStateView) + deviceModelView = v.findViewById(R.id.deviceModelView) + timeView = v.findViewById(R.id.timeView) + locationView = v.findViewById(R.id.locationView) + val routeView = v.findViewById(R.id.routeView) + + if (marker?.title == "Car") { + taskStateView.visibility = View.GONE + routeView.visibility = View.GONE + + vehicleViewModel.getVehicles() + + deviceViewModel.getDevices() + } else { + taskStateView.visibility = View.VISIBLE + routeView.visibility = View.VISIBLE + + routeView.setOnClickListener { + + } + } + + closeView.setOnClickListener { + marker?.hideInfoWindow() + isInfoWindowShow = false + } + return v } override fun initEvent() { @@ -44,9 +205,9 @@ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 1500, null) //设置起点 - addMarker(LatLng(39.914885, 116.272312), R.mipmap.start) + addMarker(LatLng(39.914885, 116.272312), "", R.mipmap.start) //设置终点 - addMarker(LatLng(39.914716, 116.265097), R.mipmap.end) + addMarker(LatLng(39.914716, 116.265097), "", R.mipmap.end) //瞄点画线 val latLngPoints = ArrayList() latLngPoints.add(LatLng(39.914885, 116.272312)) @@ -78,9 +239,10 @@ } - private fun addMarker(point: LatLng, res: Int) { + private fun addMarker(point: LatLng, type: String, res: Int) { val markerOption = MarkerOptions() markerOption.position(point) + markerOption.title(type) markerOption.icon(BitmapDescriptorFactory.fromResource(res)) aMap.addMarker(markerOption) } diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt new file mode 100644 index 0000000..ad16496 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt @@ -0,0 +1,5 @@ +package com.casic.br.ktd.listener + +interface OnGeocodeSearchListener { + fun onRegionCodeSearched(address: String) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt new file mode 100644 index 0000000..61104eb --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt @@ -0,0 +1,15 @@ +package com.casic.br.ktd.listener + +import java.io.File + +interface OnImageCompressListener { + /** + * Fired when a compression returns successfully, override to handle in your own code + */ + fun onSuccess(file: File) + + /** + * Fired when a compression fails to complete, override to handle in your own code + */ + fun onError(e: Throwable) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/model/PointModel.kt b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt new file mode 100644 index 0000000..ec2065d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt @@ -0,0 +1,3 @@ +package com.casic.br.ktd.model + +data class PointModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt b/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt deleted file mode 100644 index c45d645..0000000 --- a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.casic.br.ktd.model - -data class RouteModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java new file mode 100644 index 0000000..e813075 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java @@ -0,0 +1,166 @@ +package com.casic.br.ktd.model; + +import java.util.List; + +public class VehicleRouteModel { + + private Integer code; + private DataModel data; + private String message; + + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } + + public DataModel getData() { + return data; + } + + public void setData(DataModel data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public static class DataModel { + private List rows; + private Integer total; + + public List getRows() { + return rows; + } + + public void setRows(List rows) { + this.rows = rows; + } + + public Integer getTotal() { + return total; + } + + public void setTotal(Integer total) { + this.total = total; + } + + public static class RowsModel { + private String deviceStatus; + private String direction; + private String gas; + private String id; + private String isAlarm; + private String lagitude; + private String longitude; + private String pitch; + private String position; + private String speed; + private String taskId; + private String ts; + + public String getDeviceStatus() { + return deviceStatus; + } + + public void setDeviceStatus(String deviceStatus) { + this.deviceStatus = deviceStatus; + } + + public String getDirection() { + return direction; + } + + public void setDirection(String direction) { + this.direction = direction; + } + + public String getGas() { + return gas; + } + + public void setGas(String gas) { + this.gas = gas; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getIsAlarm() { + return isAlarm; + } + + public void setIsAlarm(String isAlarm) { + this.isAlarm = isAlarm; + } + + public String getLagitude() { + return lagitude; + } + + public void setLagitude(String lagitude) { + this.lagitude = lagitude; + } + + public String getLongitude() { + return longitude; + } + + public void setLongitude(String longitude) { + this.longitude = longitude; + } + + public String getPitch() { + return pitch; + } + + public void setPitch(String pitch) { + this.pitch = pitch; + } + + public String getPosition() { + return position; + } + + public void setPosition(String position) { + this.position = position; + } + + public String getSpeed() { + return speed; + } + + public void setSpeed(String speed) { + this.speed = speed; + } + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public String getTs() { + return ts; + } + + public void setTs(String ts) { + this.ts = ts; + } + } + } +} diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt index 9211b3a..519ab45 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt @@ -49,7 +49,7 @@ @Header("token") token: String, @Body requestBody: RequestBody, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -78,7 +78,7 @@ suspend fun getVehicles( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -88,7 +88,7 @@ suspend fun getDevices( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -101,6 +101,16 @@ ): String /** + * 巡检路径 + */ + @POST("/system/busPatrolTrack/listPage") + suspend fun busTrackRoute( + @Header("token") token: String, + @QueryMap limit: Map, + @QueryMap offset: Map + ): String + + /** * 新增报警规则,主要是阈值 */ @POST("/system/alarmRule/add") @@ -116,7 +126,7 @@ suspend fun getAlarmRules( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -146,6 +156,6 @@ @Header("token") token: String, @Body requestBody: RequestBody, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt index 0f109db..fd9624c 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt @@ -186,6 +186,18 @@ } /** + * 巡检路径 + */ + suspend fun busTrackRoute(): String { + val limitMap = HashMap() + limitMap["limit"] = LocaleConstant.PAGE_LIMIT + + val offsetMap = HashMap() + offsetMap["offset"] = 1 + return api.busTrackRoute(AuthenticationHelper.token, limitMap, offsetMap) + } + + /** * 新增报警规则,主要是阈值 */ suspend fun addAlarmRule(high: String, deviceId: String, ts: String): String { diff --git a/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt deleted file mode 100644 index 92286ad..0000000 --- a/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.br.ktd.utils - -import java.io.File - -interface OnImageCompressListener { - /** - * Fired when a compression returns successfully, override to handle in your own code - */ - fun onSuccess(file: File) - - /** - * Fired when a compression fails to complete, override to handle in your own code - */ - fun onError(e: Throwable) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt b/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt index b3146e7..7d6e558 100644 --- a/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt +++ b/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt @@ -29,7 +29,7 @@ import com.casic.br.ktd.extensions.* import com.casic.br.ktd.model.AlarmParam import com.casic.br.ktd.model.ChartPointModel -import com.casic.br.ktd.model.RouteModel +import com.casic.br.ktd.model.PointModel import com.casic.br.ktd.model.SensorDataModel import com.casic.br.ktd.netty.tcp.SocketManager import com.casic.br.ktd.netty.udp.UdpClient @@ -273,9 +273,9 @@ ) if (isStartInspect) { - val route = LinkedList() + val route = LinkedList() latlngs.forEach { - route.add(RouteModel(it.latitude, it.longitude)) + route.add(PointModel(it.latitude, it.longitude)) } } } diff --git a/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt b/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt index bce4c24..b3c519a 100644 --- a/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt +++ b/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt @@ -21,7 +21,6 @@ import com.casic.br.ktd.fragment.TaskPageFragment import com.casic.br.ktd.utils.LocaleConstant import com.casic.br.ktd.vm.AlarmViewModel -import com.casic.br.ktd.vm.VehicleViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.show @@ -36,7 +35,6 @@ private val fragmentPages = ArrayList() private val slideAdapter by lazy { SlideAdapter(this) } private var clickTime: Long = 0 - private lateinit var vehicleViewModel: VehicleViewModel private lateinit var alarmViewModel: AlarmViewModel init { @@ -71,20 +69,6 @@ //显示首页 switchPage(fragmentPages[0]) - vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] - vehicleViewModel.getVehicles() - vehicleViewModel.vehicleList.observe(this) { - if (it.code == 200) { - if (it.data.rows.isNotEmpty()) { - val model = it.data.rows[0] - SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, model.carPlate) - SaveKeyValues.putValue(LocaleConstant.CAR_ID, model.id) - } else { - Log.d(kTag, "initData => 无可用巡检车") - } - } - } - alarmViewModel = ViewModelProvider(this)[AlarmViewModel::class.java] alarmViewModel.getAlarmRules() alarmViewModel.alarmRuleList.observe(this) { diff --git a/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt b/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt index d81e7d6..c869ed8 100644 --- a/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt +++ b/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt @@ -1,7 +1,15 @@ package com.casic.br.ktd.vm +import androidx.lifecycle.MutableLiveData +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.extensions.separateResponseCode +import com.casic.br.ktd.extensions.toErrorMessage +import com.casic.br.ktd.model.VehicleRouteModel import com.casic.br.ktd.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.launch +import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.vm.BaseViewModel /** @@ -9,6 +17,9 @@ * */ class PointViewModel : BaseViewModel() { + private val gson by lazy { Gson() } + val vehicleRoute = MutableLiveData() + fun uploadPointDetail( isAlarm: String, lagitude: String, @@ -36,4 +47,18 @@ }, { it.printStackTrace() }) + + fun busTrackRoute() = launch({ + val response = RetrofitServiceManager.busTrackRoute() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + vehicleRoute.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + }) } \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml new file mode 100644 index 0000000..aeae610 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/error.xml b/app/src/main/res/drawable/error.xml new file mode 100644 index 0000000..41b3c96 --- /dev/null +++ b/app/src/main/res/drawable/error.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/layout/popu_map_car_window.xml b/app/src/main/res/layout/popu_map_car_window.xml new file mode 100644 index 0000000..b04d908 --- /dev/null +++ b/app/src/main/res/layout/popu_map_car_window.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/vehicle_on.png b/app/src/main/res/mipmap-hdpi/vehicle_on.png new file mode 100644 index 0000000..817609a --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/vehicle_on.png Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/vehicle_on.png b/app/src/main/res/mipmap-mdpi/vehicle_on.png new file mode 100644 index 0000000..817609a --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/vehicle_on.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/vehicle_on.png b/app/src/main/res/mipmap-xhdpi/vehicle_on.png new file mode 100644 index 0000000..817609a --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/vehicle_on.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/vehicle_on.png b/app/src/main/res/mipmap-xxhdpi/vehicle_on.png new file mode 100644 index 0000000..817609a --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/vehicle_on.png Binary files differ diff --git a/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt new file mode 100644 index 0000000..40b3660 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt @@ -0,0 +1,28 @@ +package com.casic.br.ktd.extensions + +import com.amap.api.maps.model.LatLng +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.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.listener.OnGeocodeSearchListener + +private val geocoderSearch by lazy { GeocodeSearch(BaseApplication.get()) } + +fun LatLng.toChineseAddress(listener: OnGeocodeSearchListener) { + val queryParam = RegeocodeQuery( + LatLonPoint(this.latitude, this.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + listener.onRegionCodeSearched(regeocodeResult.regeocodeAddress.formatAddress) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index 36af820..e090122 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -1,9 +1,9 @@ package com.casic.br.ktd.extensions import android.content.Context +import com.casic.br.ktd.listener.OnImageCompressListener import com.casic.br.ktd.model.ErrorMessageModel import com.casic.br.ktd.utils.LocaleConstant -import com.casic.br.ktd.utils.OnImageCompressListener import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.createCompressImageDir @@ -14,7 +14,8 @@ import top.zibin.luban.OnCompressListener import java.io.File import java.text.SimpleDateFormat -import java.util.* +import java.util.Date +import java.util.Locale import java.util.regex.Pattern diff --git a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt index 40b27b1..a8d1e7a 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt @@ -2,31 +2,55 @@ import android.graphics.Color import android.os.Bundle +import android.os.Handler +import android.os.Message import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.model.BitmapDescriptorFactory import com.amap.api.maps.model.CameraPosition import com.amap.api.maps.model.LatLng +import com.amap.api.maps.model.Marker import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.PolylineOptions import com.casic.br.ktd.R import com.casic.br.ktd.databinding.FragmentHomeBinding +import com.casic.br.ktd.extensions.toChineseAddress +import com.casic.br.ktd.listener.OnGeocodeSearchListener +import com.casic.br.ktd.model.DeviceListModel +import com.casic.br.ktd.model.VehicleListModel +import com.casic.br.ktd.utils.LocaleConstant +import com.casic.br.ktd.vm.DeviceViewModel +import com.casic.br.ktd.vm.VehicleViewModel import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.utils.SaveKeyValues +import com.pengxh.kt.lite.utils.WeakReferenceHandler +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton -class HomePageFragment : KotlinBaseFragment() { +class HomePageFragment : KotlinBaseFragment(), AMap.OnMarkerClickListener, + AMap.InfoWindowAdapter, Handler.Callback { + + private val kTag = "HomePageFragment" + private lateinit var vehicleViewModel: VehicleViewModel + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private lateinit var weakReferenceHandler: WeakReferenceHandler + private var isInfoWindowShow = false + private val handlerVehicleCode = 2023082501 + private val handlerDeviceCode = 2023082502 override fun initViewBinding( - inflater: LayoutInflater, - container: ViewGroup? + inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { return FragmentHomeBinding.inflate(inflater, container, false) } - private lateinit var aMap: AMap - override fun initOnCreate(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -36,6 +60,143 @@ uiSettings.isScaleControlsEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isRotateGesturesEnabled = false//不许地图随手势旋转角度 + // 点击marker弹出自定义popup + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) + + weakReferenceHandler = WeakReferenceHandler(this) + + vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] + vehicleViewModel.getVehicles() + vehicleViewModel.vehicleList.observe(this) { + if (it.code == 200) { + if (it.data.rows.isNotEmpty()) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerVehicleCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + deviceViewModel.deviceList.observe(this) { + if (it.code == 200) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerDeviceCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + handlerVehicleCode -> { + val vehicleModel = msg.obj as VehicleListModel.DataModel.RowsModel + + SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, vehicleModel.carPlate) + SaveKeyValues.putValue(LocaleConstant.CAR_ID, vehicleModel.id) + + val marker = if (vehicleModel.status == "1") { + //在线 + R.mipmap.vehicle_on + } else { + //离线 + R.mipmap.vehicle_on + } + + val latLng = LatLng( + vehicleModel.latitude.toDouble(), vehicleModel.longitude.toDouble() + ) + addMarker(latLng, "Car", marker) + + /** + * 地图PopupWindow数据绑定 + * ****/ + if (isInfoWindowShow) { + windowTitleView.text = vehicleModel.carPlate + val state = if (vehicleModel.status == "1") { + "状态:在线" + } else { + "状态:离线" + } + carStateView.text = state + + timeView.text = "时间:${vehicleModel.ts}" + latLng.toChineseAddress(object : OnGeocodeSearchListener { + override fun onRegionCodeSearched(address: String) { + locationView.text = "位置:$address" + } + }) + } + } + + handlerDeviceCode -> { + if (isInfoWindowShow) { + val deviceModel = msg.obj as DeviceListModel.DataModel.RowsModel + + deviceModelView.text = "云台型号:${deviceModel.deviceModel}" + } + } + } + return true + } + + override fun onMarkerClick(marker: Marker?): Boolean { + //点击Marker显示自定义Popup + marker?.showInfoWindow() + return true + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + + private lateinit var windowTitleView: TextView + private lateinit var taskStateView: QMUIRoundButton + private lateinit var carStateView: TextView + private lateinit var deviceModelView: TextView + private lateinit var timeView: TextView + private lateinit var locationView: TextView + + override fun getInfoWindow(marker: Marker?): View { + isInfoWindowShow = true + + val v = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_car_window, null) + + windowTitleView = v.findViewById(R.id.windowTitleView) + taskStateView = v.findViewById(R.id.taskStateView) + val closeView = v.findViewById(R.id.closeView) + carStateView = v.findViewById(R.id.carStateView) + deviceModelView = v.findViewById(R.id.deviceModelView) + timeView = v.findViewById(R.id.timeView) + locationView = v.findViewById(R.id.locationView) + val routeView = v.findViewById(R.id.routeView) + + if (marker?.title == "Car") { + taskStateView.visibility = View.GONE + routeView.visibility = View.GONE + + vehicleViewModel.getVehicles() + + deviceViewModel.getDevices() + } else { + taskStateView.visibility = View.VISIBLE + routeView.visibility = View.VISIBLE + + routeView.setOnClickListener { + + } + } + + closeView.setOnClickListener { + marker?.hideInfoWindow() + isInfoWindowShow = false + } + return v } override fun initEvent() { @@ -44,9 +205,9 @@ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 1500, null) //设置起点 - addMarker(LatLng(39.914885, 116.272312), R.mipmap.start) + addMarker(LatLng(39.914885, 116.272312), "", R.mipmap.start) //设置终点 - addMarker(LatLng(39.914716, 116.265097), R.mipmap.end) + addMarker(LatLng(39.914716, 116.265097), "", R.mipmap.end) //瞄点画线 val latLngPoints = ArrayList() latLngPoints.add(LatLng(39.914885, 116.272312)) @@ -78,9 +239,10 @@ } - private fun addMarker(point: LatLng, res: Int) { + private fun addMarker(point: LatLng, type: String, res: Int) { val markerOption = MarkerOptions() markerOption.position(point) + markerOption.title(type) markerOption.icon(BitmapDescriptorFactory.fromResource(res)) aMap.addMarker(markerOption) } diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt new file mode 100644 index 0000000..ad16496 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt @@ -0,0 +1,5 @@ +package com.casic.br.ktd.listener + +interface OnGeocodeSearchListener { + fun onRegionCodeSearched(address: String) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt new file mode 100644 index 0000000..61104eb --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt @@ -0,0 +1,15 @@ +package com.casic.br.ktd.listener + +import java.io.File + +interface OnImageCompressListener { + /** + * Fired when a compression returns successfully, override to handle in your own code + */ + fun onSuccess(file: File) + + /** + * Fired when a compression fails to complete, override to handle in your own code + */ + fun onError(e: Throwable) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/model/PointModel.kt b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt new file mode 100644 index 0000000..ec2065d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt @@ -0,0 +1,3 @@ +package com.casic.br.ktd.model + +data class PointModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt b/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt deleted file mode 100644 index c45d645..0000000 --- a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.casic.br.ktd.model - -data class RouteModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java new file mode 100644 index 0000000..e813075 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java @@ -0,0 +1,166 @@ +package com.casic.br.ktd.model; + +import java.util.List; + +public class VehicleRouteModel { + + private Integer code; + private DataModel data; + private String message; + + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } + + public DataModel getData() { + return data; + } + + public void setData(DataModel data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public static class DataModel { + private List rows; + private Integer total; + + public List getRows() { + return rows; + } + + public void setRows(List rows) { + this.rows = rows; + } + + public Integer getTotal() { + return total; + } + + public void setTotal(Integer total) { + this.total = total; + } + + public static class RowsModel { + private String deviceStatus; + private String direction; + private String gas; + private String id; + private String isAlarm; + private String lagitude; + private String longitude; + private String pitch; + private String position; + private String speed; + private String taskId; + private String ts; + + public String getDeviceStatus() { + return deviceStatus; + } + + public void setDeviceStatus(String deviceStatus) { + this.deviceStatus = deviceStatus; + } + + public String getDirection() { + return direction; + } + + public void setDirection(String direction) { + this.direction = direction; + } + + public String getGas() { + return gas; + } + + public void setGas(String gas) { + this.gas = gas; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getIsAlarm() { + return isAlarm; + } + + public void setIsAlarm(String isAlarm) { + this.isAlarm = isAlarm; + } + + public String getLagitude() { + return lagitude; + } + + public void setLagitude(String lagitude) { + this.lagitude = lagitude; + } + + public String getLongitude() { + return longitude; + } + + public void setLongitude(String longitude) { + this.longitude = longitude; + } + + public String getPitch() { + return pitch; + } + + public void setPitch(String pitch) { + this.pitch = pitch; + } + + public String getPosition() { + return position; + } + + public void setPosition(String position) { + this.position = position; + } + + public String getSpeed() { + return speed; + } + + public void setSpeed(String speed) { + this.speed = speed; + } + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public String getTs() { + return ts; + } + + public void setTs(String ts) { + this.ts = ts; + } + } + } +} diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt index 9211b3a..519ab45 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt @@ -49,7 +49,7 @@ @Header("token") token: String, @Body requestBody: RequestBody, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -78,7 +78,7 @@ suspend fun getVehicles( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -88,7 +88,7 @@ suspend fun getDevices( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -101,6 +101,16 @@ ): String /** + * 巡检路径 + */ + @POST("/system/busPatrolTrack/listPage") + suspend fun busTrackRoute( + @Header("token") token: String, + @QueryMap limit: Map, + @QueryMap offset: Map + ): String + + /** * 新增报警规则,主要是阈值 */ @POST("/system/alarmRule/add") @@ -116,7 +126,7 @@ suspend fun getAlarmRules( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -146,6 +156,6 @@ @Header("token") token: String, @Body requestBody: RequestBody, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt index 0f109db..fd9624c 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt @@ -186,6 +186,18 @@ } /** + * 巡检路径 + */ + suspend fun busTrackRoute(): String { + val limitMap = HashMap() + limitMap["limit"] = LocaleConstant.PAGE_LIMIT + + val offsetMap = HashMap() + offsetMap["offset"] = 1 + return api.busTrackRoute(AuthenticationHelper.token, limitMap, offsetMap) + } + + /** * 新增报警规则,主要是阈值 */ suspend fun addAlarmRule(high: String, deviceId: String, ts: String): String { diff --git a/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt deleted file mode 100644 index 92286ad..0000000 --- a/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.br.ktd.utils - -import java.io.File - -interface OnImageCompressListener { - /** - * Fired when a compression returns successfully, override to handle in your own code - */ - fun onSuccess(file: File) - - /** - * Fired when a compression fails to complete, override to handle in your own code - */ - fun onError(e: Throwable) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt b/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt index b3146e7..7d6e558 100644 --- a/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt +++ b/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt @@ -29,7 +29,7 @@ import com.casic.br.ktd.extensions.* import com.casic.br.ktd.model.AlarmParam import com.casic.br.ktd.model.ChartPointModel -import com.casic.br.ktd.model.RouteModel +import com.casic.br.ktd.model.PointModel import com.casic.br.ktd.model.SensorDataModel import com.casic.br.ktd.netty.tcp.SocketManager import com.casic.br.ktd.netty.udp.UdpClient @@ -273,9 +273,9 @@ ) if (isStartInspect) { - val route = LinkedList() + val route = LinkedList() latlngs.forEach { - route.add(RouteModel(it.latitude, it.longitude)) + route.add(PointModel(it.latitude, it.longitude)) } } } diff --git a/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt b/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt index bce4c24..b3c519a 100644 --- a/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt +++ b/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt @@ -21,7 +21,6 @@ import com.casic.br.ktd.fragment.TaskPageFragment import com.casic.br.ktd.utils.LocaleConstant import com.casic.br.ktd.vm.AlarmViewModel -import com.casic.br.ktd.vm.VehicleViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.show @@ -36,7 +35,6 @@ private val fragmentPages = ArrayList() private val slideAdapter by lazy { SlideAdapter(this) } private var clickTime: Long = 0 - private lateinit var vehicleViewModel: VehicleViewModel private lateinit var alarmViewModel: AlarmViewModel init { @@ -71,20 +69,6 @@ //显示首页 switchPage(fragmentPages[0]) - vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] - vehicleViewModel.getVehicles() - vehicleViewModel.vehicleList.observe(this) { - if (it.code == 200) { - if (it.data.rows.isNotEmpty()) { - val model = it.data.rows[0] - SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, model.carPlate) - SaveKeyValues.putValue(LocaleConstant.CAR_ID, model.id) - } else { - Log.d(kTag, "initData => 无可用巡检车") - } - } - } - alarmViewModel = ViewModelProvider(this)[AlarmViewModel::class.java] alarmViewModel.getAlarmRules() alarmViewModel.alarmRuleList.observe(this) { diff --git a/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt b/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt index d81e7d6..c869ed8 100644 --- a/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt +++ b/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt @@ -1,7 +1,15 @@ package com.casic.br.ktd.vm +import androidx.lifecycle.MutableLiveData +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.extensions.separateResponseCode +import com.casic.br.ktd.extensions.toErrorMessage +import com.casic.br.ktd.model.VehicleRouteModel import com.casic.br.ktd.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.launch +import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.vm.BaseViewModel /** @@ -9,6 +17,9 @@ * */ class PointViewModel : BaseViewModel() { + private val gson by lazy { Gson() } + val vehicleRoute = MutableLiveData() + fun uploadPointDetail( isAlarm: String, lagitude: String, @@ -36,4 +47,18 @@ }, { it.printStackTrace() }) + + fun busTrackRoute() = launch({ + val response = RetrofitServiceManager.busTrackRoute() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + vehicleRoute.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + }) } \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml new file mode 100644 index 0000000..aeae610 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/error.xml b/app/src/main/res/drawable/error.xml new file mode 100644 index 0000000..41b3c96 --- /dev/null +++ b/app/src/main/res/drawable/error.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/layout/popu_map_car_window.xml b/app/src/main/res/layout/popu_map_car_window.xml new file mode 100644 index 0000000..b04d908 --- /dev/null +++ b/app/src/main/res/layout/popu_map_car_window.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/vehicle_on.png b/app/src/main/res/mipmap-hdpi/vehicle_on.png new file mode 100644 index 0000000..817609a --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/vehicle_on.png Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/vehicle_on.png b/app/src/main/res/mipmap-mdpi/vehicle_on.png new file mode 100644 index 0000000..817609a --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/vehicle_on.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/vehicle_on.png b/app/src/main/res/mipmap-xhdpi/vehicle_on.png new file mode 100644 index 0000000..817609a --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/vehicle_on.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/vehicle_on.png b/app/src/main/res/mipmap-xxhdpi/vehicle_on.png new file mode 100644 index 0000000..817609a --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/vehicle_on.png Binary files differ diff --git a/app/src/main/res/mipmap-xxxhdpi/vehicle_on.png b/app/src/main/res/mipmap-xxxhdpi/vehicle_on.png new file mode 100644 index 0000000..817609a --- /dev/null +++ b/app/src/main/res/mipmap-xxxhdpi/vehicle_on.png Binary files differ diff --git a/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt new file mode 100644 index 0000000..40b3660 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/extensions/LatLng.kt @@ -0,0 +1,28 @@ +package com.casic.br.ktd.extensions + +import com.amap.api.maps.model.LatLng +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.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.listener.OnGeocodeSearchListener + +private val geocoderSearch by lazy { GeocodeSearch(BaseApplication.get()) } + +fun LatLng.toChineseAddress(listener: OnGeocodeSearchListener) { + val queryParam = RegeocodeQuery( + LatLonPoint(this.latitude, this.longitude), 200f, GeocodeSearch.AMAP + ) + geocoderSearch.getFromLocationAsyn(queryParam) + geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + listener.onRegionCodeSearched(regeocodeResult.regeocodeAddress.formatAddress) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index 36af820..e090122 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -1,9 +1,9 @@ package com.casic.br.ktd.extensions import android.content.Context +import com.casic.br.ktd.listener.OnImageCompressListener import com.casic.br.ktd.model.ErrorMessageModel import com.casic.br.ktd.utils.LocaleConstant -import com.casic.br.ktd.utils.OnImageCompressListener import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.createCompressImageDir @@ -14,7 +14,8 @@ import top.zibin.luban.OnCompressListener import java.io.File import java.text.SimpleDateFormat -import java.util.* +import java.util.Date +import java.util.Locale import java.util.regex.Pattern diff --git a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt index 40b27b1..a8d1e7a 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/HomePageFragment.kt @@ -2,31 +2,55 @@ import android.graphics.Color import android.os.Bundle +import android.os.Handler +import android.os.Message import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.model.BitmapDescriptorFactory import com.amap.api.maps.model.CameraPosition import com.amap.api.maps.model.LatLng +import com.amap.api.maps.model.Marker import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.PolylineOptions import com.casic.br.ktd.R import com.casic.br.ktd.databinding.FragmentHomeBinding +import com.casic.br.ktd.extensions.toChineseAddress +import com.casic.br.ktd.listener.OnGeocodeSearchListener +import com.casic.br.ktd.model.DeviceListModel +import com.casic.br.ktd.model.VehicleListModel +import com.casic.br.ktd.utils.LocaleConstant +import com.casic.br.ktd.vm.DeviceViewModel +import com.casic.br.ktd.vm.VehicleViewModel import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.utils.SaveKeyValues +import com.pengxh.kt.lite.utils.WeakReferenceHandler +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton -class HomePageFragment : KotlinBaseFragment() { +class HomePageFragment : KotlinBaseFragment(), AMap.OnMarkerClickListener, + AMap.InfoWindowAdapter, Handler.Callback { + + private val kTag = "HomePageFragment" + private lateinit var vehicleViewModel: VehicleViewModel + private lateinit var deviceViewModel: DeviceViewModel + private lateinit var aMap: AMap + private lateinit var weakReferenceHandler: WeakReferenceHandler + private var isInfoWindowShow = false + private val handlerVehicleCode = 2023082501 + private val handlerDeviceCode = 2023082502 override fun initViewBinding( - inflater: LayoutInflater, - container: ViewGroup? + inflater: LayoutInflater, container: ViewGroup? ): FragmentHomeBinding { return FragmentHomeBinding.inflate(inflater, container, false) } - private lateinit var aMap: AMap - override fun initOnCreate(savedInstanceState: Bundle?) { binding.mapView.onCreate(savedInstanceState) aMap = binding.mapView.map @@ -36,6 +60,143 @@ uiSettings.isScaleControlsEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isRotateGesturesEnabled = false//不许地图随手势旋转角度 + // 点击marker弹出自定义popup + aMap.addOnMarkerClickListener(this) + // 点击marker弹出自定义popup + aMap.setInfoWindowAdapter(this) + + weakReferenceHandler = WeakReferenceHandler(this) + + vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] + vehicleViewModel.getVehicles() + vehicleViewModel.vehicleList.observe(this) { + if (it.code == 200) { + if (it.data.rows.isNotEmpty()) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerVehicleCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + deviceViewModel.deviceList.observe(this) { + if (it.code == 200) { + val message = weakReferenceHandler.obtainMessage() + message.what = handlerDeviceCode + message.obj = it.data.rows[0] + weakReferenceHandler.sendMessage(message) + } + } + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + handlerVehicleCode -> { + val vehicleModel = msg.obj as VehicleListModel.DataModel.RowsModel + + SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, vehicleModel.carPlate) + SaveKeyValues.putValue(LocaleConstant.CAR_ID, vehicleModel.id) + + val marker = if (vehicleModel.status == "1") { + //在线 + R.mipmap.vehicle_on + } else { + //离线 + R.mipmap.vehicle_on + } + + val latLng = LatLng( + vehicleModel.latitude.toDouble(), vehicleModel.longitude.toDouble() + ) + addMarker(latLng, "Car", marker) + + /** + * 地图PopupWindow数据绑定 + * ****/ + if (isInfoWindowShow) { + windowTitleView.text = vehicleModel.carPlate + val state = if (vehicleModel.status == "1") { + "状态:在线" + } else { + "状态:离线" + } + carStateView.text = state + + timeView.text = "时间:${vehicleModel.ts}" + latLng.toChineseAddress(object : OnGeocodeSearchListener { + override fun onRegionCodeSearched(address: String) { + locationView.text = "位置:$address" + } + }) + } + } + + handlerDeviceCode -> { + if (isInfoWindowShow) { + val deviceModel = msg.obj as DeviceListModel.DataModel.RowsModel + + deviceModelView.text = "云台型号:${deviceModel.deviceModel}" + } + } + } + return true + } + + override fun onMarkerClick(marker: Marker?): Boolean { + //点击Marker显示自定义Popup + marker?.showInfoWindow() + return true + } + + /** + * 此方法不能修改整个 InfoWindow 的背景和边框,无论自定义的样式是什么样,SDK 都会在最外层添加一个默认的边框 + * */ + override fun getInfoContents(p0: Marker?): View? = null + + private lateinit var windowTitleView: TextView + private lateinit var taskStateView: QMUIRoundButton + private lateinit var carStateView: TextView + private lateinit var deviceModelView: TextView + private lateinit var timeView: TextView + private lateinit var locationView: TextView + + override fun getInfoWindow(marker: Marker?): View { + isInfoWindowShow = true + + val v = LayoutInflater.from(requireContext()).inflate(R.layout.popu_map_car_window, null) + + windowTitleView = v.findViewById(R.id.windowTitleView) + taskStateView = v.findViewById(R.id.taskStateView) + val closeView = v.findViewById(R.id.closeView) + carStateView = v.findViewById(R.id.carStateView) + deviceModelView = v.findViewById(R.id.deviceModelView) + timeView = v.findViewById(R.id.timeView) + locationView = v.findViewById(R.id.locationView) + val routeView = v.findViewById(R.id.routeView) + + if (marker?.title == "Car") { + taskStateView.visibility = View.GONE + routeView.visibility = View.GONE + + vehicleViewModel.getVehicles() + + deviceViewModel.getDevices() + } else { + taskStateView.visibility = View.VISIBLE + routeView.visibility = View.VISIBLE + + routeView.setOnClickListener { + + } + } + + closeView.setOnClickListener { + marker?.hideInfoWindow() + isInfoWindowShow = false + } + return v } override fun initEvent() { @@ -44,9 +205,9 @@ val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition) aMap.animateCamera(cameraUpdate, 1500, null) //设置起点 - addMarker(LatLng(39.914885, 116.272312), R.mipmap.start) + addMarker(LatLng(39.914885, 116.272312), "", R.mipmap.start) //设置终点 - addMarker(LatLng(39.914716, 116.265097), R.mipmap.end) + addMarker(LatLng(39.914716, 116.265097), "", R.mipmap.end) //瞄点画线 val latLngPoints = ArrayList() latLngPoints.add(LatLng(39.914885, 116.272312)) @@ -78,9 +239,10 @@ } - private fun addMarker(point: LatLng, res: Int) { + private fun addMarker(point: LatLng, type: String, res: Int) { val markerOption = MarkerOptions() markerOption.position(point) + markerOption.title(type) markerOption.icon(BitmapDescriptorFactory.fromResource(res)) aMap.addMarker(markerOption) } diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt new file mode 100644 index 0000000..ad16496 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnGeocodeSearchListener.kt @@ -0,0 +1,5 @@ +package com.casic.br.ktd.listener + +interface OnGeocodeSearchListener { + fun onRegionCodeSearched(address: String) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt new file mode 100644 index 0000000..61104eb --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/listener/OnImageCompressListener.kt @@ -0,0 +1,15 @@ +package com.casic.br.ktd.listener + +import java.io.File + +interface OnImageCompressListener { + /** + * Fired when a compression returns successfully, override to handle in your own code + */ + fun onSuccess(file: File) + + /** + * Fired when a compression fails to complete, override to handle in your own code + */ + fun onError(e: Throwable) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/model/PointModel.kt b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt new file mode 100644 index 0000000..ec2065d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/PointModel.kt @@ -0,0 +1,3 @@ +package com.casic.br.ktd.model + +data class PointModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt b/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt deleted file mode 100644 index c45d645..0000000 --- a/app/src/main/java/com/casic/br/ktd/model/RouteModel.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.casic.br.ktd.model - -data class RouteModel(var lat: Double, var lng: Double) diff --git a/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java new file mode 100644 index 0000000..e813075 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/VehicleRouteModel.java @@ -0,0 +1,166 @@ +package com.casic.br.ktd.model; + +import java.util.List; + +public class VehicleRouteModel { + + private Integer code; + private DataModel data; + private String message; + + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } + + public DataModel getData() { + return data; + } + + public void setData(DataModel data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public static class DataModel { + private List rows; + private Integer total; + + public List getRows() { + return rows; + } + + public void setRows(List rows) { + this.rows = rows; + } + + public Integer getTotal() { + return total; + } + + public void setTotal(Integer total) { + this.total = total; + } + + public static class RowsModel { + private String deviceStatus; + private String direction; + private String gas; + private String id; + private String isAlarm; + private String lagitude; + private String longitude; + private String pitch; + private String position; + private String speed; + private String taskId; + private String ts; + + public String getDeviceStatus() { + return deviceStatus; + } + + public void setDeviceStatus(String deviceStatus) { + this.deviceStatus = deviceStatus; + } + + public String getDirection() { + return direction; + } + + public void setDirection(String direction) { + this.direction = direction; + } + + public String getGas() { + return gas; + } + + public void setGas(String gas) { + this.gas = gas; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getIsAlarm() { + return isAlarm; + } + + public void setIsAlarm(String isAlarm) { + this.isAlarm = isAlarm; + } + + public String getLagitude() { + return lagitude; + } + + public void setLagitude(String lagitude) { + this.lagitude = lagitude; + } + + public String getLongitude() { + return longitude; + } + + public void setLongitude(String longitude) { + this.longitude = longitude; + } + + public String getPitch() { + return pitch; + } + + public void setPitch(String pitch) { + this.pitch = pitch; + } + + public String getPosition() { + return position; + } + + public void setPosition(String position) { + this.position = position; + } + + public String getSpeed() { + return speed; + } + + public void setSpeed(String speed) { + this.speed = speed; + } + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public String getTs() { + return ts; + } + + public void setTs(String ts) { + this.ts = ts; + } + } + } +} diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt index 9211b3a..519ab45 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt @@ -49,7 +49,7 @@ @Header("token") token: String, @Body requestBody: RequestBody, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -78,7 +78,7 @@ suspend fun getVehicles( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -88,7 +88,7 @@ suspend fun getDevices( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -101,6 +101,16 @@ ): String /** + * 巡检路径 + */ + @POST("/system/busPatrolTrack/listPage") + suspend fun busTrackRoute( + @Header("token") token: String, + @QueryMap limit: Map, + @QueryMap offset: Map + ): String + + /** * 新增报警规则,主要是阈值 */ @POST("/system/alarmRule/add") @@ -116,7 +126,7 @@ suspend fun getAlarmRules( @Header("token") token: String, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String /** @@ -146,6 +156,6 @@ @Header("token") token: String, @Body requestBody: RequestBody, @QueryMap limit: Map, - @QueryMap offset: Map, + @QueryMap offset: Map ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt index 0f109db..fd9624c 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt @@ -186,6 +186,18 @@ } /** + * 巡检路径 + */ + suspend fun busTrackRoute(): String { + val limitMap = HashMap() + limitMap["limit"] = LocaleConstant.PAGE_LIMIT + + val offsetMap = HashMap() + offsetMap["offset"] = 1 + return api.busTrackRoute(AuthenticationHelper.token, limitMap, offsetMap) + } + + /** * 新增报警规则,主要是阈值 */ suspend fun addAlarmRule(high: String, deviceId: String, ts: String): String { diff --git a/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt b/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt deleted file mode 100644 index 92286ad..0000000 --- a/app/src/main/java/com/casic/br/ktd/utils/OnImageCompressListener.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.br.ktd.utils - -import java.io.File - -interface OnImageCompressListener { - /** - * Fired when a compression returns successfully, override to handle in your own code - */ - fun onSuccess(file: File) - - /** - * Fired when a compression fails to complete, override to handle in your own code - */ - fun onError(e: Throwable) -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt b/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt index b3146e7..7d6e558 100644 --- a/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt +++ b/app/src/main/java/com/casic/br/ktd/view/InspectionActivity.kt @@ -29,7 +29,7 @@ import com.casic.br.ktd.extensions.* import com.casic.br.ktd.model.AlarmParam import com.casic.br.ktd.model.ChartPointModel -import com.casic.br.ktd.model.RouteModel +import com.casic.br.ktd.model.PointModel import com.casic.br.ktd.model.SensorDataModel import com.casic.br.ktd.netty.tcp.SocketManager import com.casic.br.ktd.netty.udp.UdpClient @@ -273,9 +273,9 @@ ) if (isStartInspect) { - val route = LinkedList() + val route = LinkedList() latlngs.forEach { - route.add(RouteModel(it.latitude, it.longitude)) + route.add(PointModel(it.latitude, it.longitude)) } } } diff --git a/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt b/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt index bce4c24..b3c519a 100644 --- a/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt +++ b/app/src/main/java/com/casic/br/ktd/view/MainActivity.kt @@ -21,7 +21,6 @@ import com.casic.br.ktd.fragment.TaskPageFragment import com.casic.br.ktd.utils.LocaleConstant import com.casic.br.ktd.vm.AlarmViewModel -import com.casic.br.ktd.vm.VehicleViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.show @@ -36,7 +35,6 @@ private val fragmentPages = ArrayList() private val slideAdapter by lazy { SlideAdapter(this) } private var clickTime: Long = 0 - private lateinit var vehicleViewModel: VehicleViewModel private lateinit var alarmViewModel: AlarmViewModel init { @@ -71,20 +69,6 @@ //显示首页 switchPage(fragmentPages[0]) - vehicleViewModel = ViewModelProvider(this)[VehicleViewModel::class.java] - vehicleViewModel.getVehicles() - vehicleViewModel.vehicleList.observe(this) { - if (it.code == 200) { - if (it.data.rows.isNotEmpty()) { - val model = it.data.rows[0] - SaveKeyValues.putValue(LocaleConstant.CAR_NUMBER, model.carPlate) - SaveKeyValues.putValue(LocaleConstant.CAR_ID, model.id) - } else { - Log.d(kTag, "initData => 无可用巡检车") - } - } - } - alarmViewModel = ViewModelProvider(this)[AlarmViewModel::class.java] alarmViewModel.getAlarmRules() alarmViewModel.alarmRuleList.observe(this) { diff --git a/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt b/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt index d81e7d6..c869ed8 100644 --- a/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt +++ b/app/src/main/java/com/casic/br/ktd/vm/PointViewModel.kt @@ -1,7 +1,15 @@ package com.casic.br.ktd.vm +import androidx.lifecycle.MutableLiveData +import com.casic.br.ktd.base.BaseApplication +import com.casic.br.ktd.extensions.separateResponseCode +import com.casic.br.ktd.extensions.toErrorMessage +import com.casic.br.ktd.model.VehicleRouteModel import com.casic.br.ktd.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken import com.pengxh.kt.lite.extensions.launch +import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.vm.BaseViewModel /** @@ -9,6 +17,9 @@ * */ class PointViewModel : BaseViewModel() { + private val gson by lazy { Gson() } + val vehicleRoute = MutableLiveData() + fun uploadPointDetail( isAlarm: String, lagitude: String, @@ -36,4 +47,18 @@ }, { it.printStackTrace() }) + + fun busTrackRoute() = launch({ + val response = RetrofitServiceManager.busTrackRoute() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + vehicleRoute.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + }) } \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml new file mode 100644 index 0000000..aeae610 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_transparent_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/error.xml b/app/src/main/res/drawable/error.xml new file mode 100644 index 0000000..41b3c96 --- /dev/null +++ b/app/src/main/res/drawable/error.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/layout/popu_map_car_window.xml b/app/src/main/res/layout/popu_map_car_window.xml new file mode 100644 index 0000000..b04d908 --- /dev/null +++ b/app/src/main/res/layout/popu_map_car_window.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/vehicle_on.png b/app/src/main/res/mipmap-hdpi/vehicle_on.png new file mode 100644 index 0000000..817609a --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/vehicle_on.png Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/vehicle_on.png b/app/src/main/res/mipmap-mdpi/vehicle_on.png new file mode 100644 index 0000000..817609a --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/vehicle_on.png Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/vehicle_on.png b/app/src/main/res/mipmap-xhdpi/vehicle_on.png new file mode 100644 index 0000000..817609a --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/vehicle_on.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/vehicle_on.png b/app/src/main/res/mipmap-xxhdpi/vehicle_on.png new file mode 100644 index 0000000..817609a --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/vehicle_on.png Binary files differ diff --git a/app/src/main/res/mipmap-xxxhdpi/vehicle_on.png b/app/src/main/res/mipmap-xxxhdpi/vehicle_on.png new file mode 100644 index 0000000..817609a --- /dev/null +++ b/app/src/main/res/mipmap-xxxhdpi/vehicle_on.png Binary files differ diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index df43a53..3a6c845 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -24,4 +24,13 @@ @color/black @dimen/sp_18 + + \ No newline at end of file