import android.hardware.Sensor import android.hardware.SensorEvent import android.hardware.SensorEventListener import android.hardware.SensorManager import android.media.AudioAttributes import android.media.SoundPool import android.os.Bundle import androidx.lifecycle.lifecycleScope import com.amap.api.location.AMapLocation import com.amap.api.maps.AMapUtils import com.amap.api.maps.model.LatLng import com.casic.common.detector.gd.R import com.casic.common.detector.gd.base.BaseApplication import com.casic.common.detector.gd.callback.OnGetLocationListener import com.casic.common.detector.gd.databinding.ActivitySearchMarkerAuditBinding import com.casic.common.detector.gd.utils.LocaleConstant import com.casic.common.detector.gd.utils.LocationKit import com.casic.common.detector.gd.widgets.MarkerDetailDialog import com.casic.common.detector.gd.widgets.NewMarkerDetailDialog import com.casic.common.detector.gd.widgets.RadarScanView import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.show import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.util.Timer import java.util.TimerTask import kotlin.math.atan2 class SearchMarkerActivity : KotlinBaseActivity<ActivitySearchMarkerAuditBinding>(), SensorEventListener { private val kTag = "SearchMarkerActivity" private val context = this private val locationKit by lazy { LocationKit(this) } private val sensorManager by lazy { getSystemService(SENSOR_SERVICE) as SensorManager } private val markerBeanDao by lazy { BaseApplication.Companion.get().dataBase.markerBeanDao() } private val attr = AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_ALARM) .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build() private val soundPool = SoundPool.Builder().setMaxStreams(16).setAudioAttributes(attr).build() private val rotationMatrix = FloatArray(9)//旋转矩阵缓存 private val valueArray = FloatArray(3)//方位角数值 private var nearestMarkerId = ""//探测不到标识器的时候计算出来的最近的标识器ID private var gravity: FloatArray? = null private var geomagnetic: FloatArray? = null private lateinit var searchSignalEnergyTimer: Timer override fun initOnCreate(savedInstanceState: Bundle?) { val fastSoundResourceId = soundPool.load(this, R.raw.ring2, 1) //点位渲染,每次定位都计算当前位置与符合条件的点距离 locationKit.getCurrentLocation(false, object : OnGetLocationListener { override fun onSuccess(location: AMapLocation) { renderDataPoint(location) } override fun onError() { "当前位置信号差,无法获取定位".show(context) } }) searchSignalEnergyTimer = Timer() searchSignalEnergyTimer.schedule(object : TimerTask() { override fun run() { soundPool.play(fastSoundResourceId, 1f, 1f, 0, 0, 1f) } }, 0, 100) } override fun initEvent() { binding.markerInfoButton.setOnClickListener { //查库 val result = markerBeanDao.queryMarkerById(nearestMarkerId) if (result.isNotEmpty()) { MarkerDetailDialog(this).setMarker(result.first()).show() } else { NewMarkerDetailDialog(this, nearestMarkerId) } } } /** * 计算并渲染数据点。点太多采用协程计算,不然会有点卡顿。默认2s计算一次 * @param location 定位点(RTK获取) * */ private fun renderDataPoint(location: AMapLocation) { val longitude = location.longitude val latitude = location.latitude lifecycleScope.launch(Dispatchers.IO) { val dataPoints = ArrayList<RadarScanView.DataPoint>() markerBeanDao.loadAll().forEach { val distance = AMapUtils.calculateLineDistance( LatLng(it.lat.toDouble(), it.lng.toDouble()), LatLng(latitude, longitude) ) val formatDistance = "%.2f".format(distance).toFloat() val angle = atan2( (it.lat.toDouble() - latitude), (it.lng.toDouble() - longitude) ) + Math.PI val formatAngle = "%.2f".format(angle).toDouble() dataPoints.add( RadarScanView.DataPoint(it.markerId, formatAngle, formatDistance) ) } withContext(Dispatchers.Main) { binding.radarScanView.renderPointData( dataPoints, onGetNearestPoint = { point -> if (point == null) { binding.distanceValueView.text = "大于5.5m" binding.distancePgBar.progress = 100 } else { nearestMarkerId = point.markerId binding.distanceValueView.text = "${point.distance}m" val progress = if (point.distance > LocaleConstant.MAX_DISTANCE) { 100 } else { (point.distance / LocaleConstant.MAX_DISTANCE) * 100 } binding.distancePgBar.progress = progress.toInt() } } ) } } } override fun initViewBinding(): ActivitySearchMarkerAuditBinding { return ActivitySearchMarkerAuditBinding.inflate(layoutInflater) } override fun observeRequestState() { } override fun setupTopBarLayout() { } override fun onResume() { super.onResume() //注册加速度传感器监听 val accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL) //注册磁场传感器监听 val magnetic = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) sensorManager.registerListener(this, magnetic, SensorManager.SENSOR_DELAY_NORMAL) } override fun onPause() { super.onPause() sensorManager.unregisterListener(this) } override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) { //精度发生变化时触发 } override fun onSensorChanged(event: SensorEvent?) { //值发生变化时触发 val type = event?.sensor?.type if (type == Sensor.TYPE_ACCELEROMETER) { gravity = event.values } else if (type == Sensor.TYPE_MAGNETIC_FIELD) { geomagnetic = event.values } if (gravity == null || geomagnetic == null) { return } if (SensorManager.getRotationMatrix(rotationMatrix, null, gravity, geomagnetic)) { SensorManager.getOrientation(rotationMatrix, valueArray) val degree = ((360f + valueArray[0] * 180f / Math.PI) % 360).toInt() //更新罗盘角度 binding.radarScanView.setDegreeValue(degree) } } override fun onDestroy() { super.onDestroy() searchSignalEnergyTimer.cancel() soundPool.release() locationKit.stopLocation() } }