Merge branch 'master' of gitlab.navinfo.com:CollectVehicle/OneMapQS

 Conflicts:
	app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt
	app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt
	app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/EvaluationResultViewModel.kt
	collect-library/src/main/java/com/navinfo/collect/library/map/handler/MarkHandler.kt
This commit is contained in:
squallzhjch 2023-07-21 15:30:20 +08:00
commit 6c386505d6
22 changed files with 1518 additions and 306 deletions

View File

@ -59,6 +59,11 @@ class Constant {
const val DEBUG = true
/**
* 是否自动定位
*/
var AUTO_LOCATION = false
var IS_VIDEO_SPEED by kotlin.properties.Delegates.notNull<Boolean>()
const val message_status_late = "预约,待发送"

View File

@ -0,0 +1,8 @@
package com.navinfo.omqs.bean
data class TraceVideoBean(
var userid: String = "",
var playMode: String = "",
var time: String = "",
var command: String = "",
)

View File

@ -6,8 +6,7 @@ import com.navinfo.omqs.bean.IndoorConnectionInfoBean
import com.navinfo.omqs.bean.LoginUserBean
import com.navinfo.omqs.bean.QRCodeBean
import com.navinfo.omqs.bean.SysUserBean
import okhttp3.ResponseBody
import retrofit2.Response
import com.navinfo.omqs.bean.TraceVideoBean
/**
@ -38,4 +37,9 @@ interface NetworkService {
* 更新用户信息
*/
suspend fun updateServerInfo(url: String,indoorConnectionInfoBean: IndoorConnectionInfoBean): NetResult<QRCodeBean>
/**
* 设置轨迹对应的视频
*/
suspend fun sendServerCommand(url: String,traceVideoBean: TraceVideoBean): NetResult<QRCodeBean>
}

View File

@ -6,6 +6,7 @@ import com.navinfo.omqs.bean.IndoorConnectionInfoBean
import com.navinfo.omqs.bean.LoginUserBean
import com.navinfo.omqs.bean.QRCodeBean
import com.navinfo.omqs.bean.SysUserBean
import com.navinfo.omqs.bean.TraceVideoBean
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.ResponseBody
@ -110,6 +111,33 @@ class NetworkServiceImpl @Inject constructor(
map["baseurl"] = indoorConnectionInfoBean.baseurl
map["platform"] = indoorConnectionInfoBean.platform
val result = netApi.retrofitUpdateServerInfo(url,map)
if (result.isSuccessful) {
if (result.code() == 200) {
NetResult.Success(result.body())
} else {
NetResult.Failure<Any>(result.code(), result.message())
}
} else {
NetResult.Failure<Any>(result.code(), result.message())
}
} catch (e: Exception) {
NetResult.Error<Any>(e)
}
}
override suspend fun sendServerCommand(
url: String,
traceVideoBean: TraceVideoBean
): NetResult<QRCodeBean> =
//在IO线程中运行
withContext(Dispatchers.IO) {
return@withContext try {
val map: MutableMap<String, String> = HashMap()
map["userid"] = traceVideoBean.userid
map["playMode"] = traceVideoBean.playMode
map["time"] = traceVideoBean.time
val result = netApi.retrofitUpdateServerInfo(url,map)
if (result.isSuccessful) {
if (result.code() == 200) {

View File

@ -1,6 +1,7 @@
package com.navinfo.omqs.ui.activity.login
import android.content.Context
import android.content.SharedPreferences
import android.util.Log
import android.view.View
import android.widget.Toast
@ -16,11 +17,11 @@ import com.navinfo.omqs.http.DefaultResponse
import com.navinfo.omqs.http.NetResult
import com.navinfo.omqs.http.NetworkService
import com.navinfo.omqs.tools.FileManager
import com.navinfo.omqs.util.NetUtils
import dagger.hilt.android.lifecycle.HiltViewModel
import io.realm.Realm
import io.realm.RealmConfiguration
import kotlinx.coroutines.*
import retrofit2.Response
import java.io.File
import java.io.IOException
import javax.inject.Inject
@ -73,7 +74,9 @@ class LoginViewModel @Inject constructor(
//是不是登录成功
val loginStatus: MutableLiveData<LoginStatus> = MutableLiveData()
var jobLogin: Job? = null;
var jobLogin: Job? = null
var sharedPreferences: SharedPreferences? = null
init {
loginUser.value = LoginUserBean(userCode = "haofuyue00213", passWord = "123456")
@ -98,10 +101,26 @@ class LoginViewModel @Inject constructor(
if (password.isEmpty()) {
Toast.makeText(context, "请输入密码", Toast.LENGTH_SHORT).show()
}
sharedPreferences =
context.getSharedPreferences("USER_SHAREDPREFERENCES", Context.MODE_PRIVATE)
val userNameCache = sharedPreferences?.getString("userName", null)
val passwordCache = sharedPreferences?.getString("passWord", null)
val userCodeCache = sharedPreferences?.getString("userCode", null)
//增加缓存记录,不用每次连接网络登录
if (userNameCache != null && passwordCache != null && userCodeCache != null) {
if (userNameCache == userName && passwordCache == password) {
viewModelScope.launch(Dispatchers.IO) {
createUserFolder(context, userCodeCache)
loginStatus.postValue(LoginStatus.LOGIN_STATUS_SUCCESS)
}
return
}
}
//不指定IO会在主线程里运行
jobLogin = viewModelScope.launch(Dispatchers.IO) {
loginCheck(context, userName, password)
}
}
/**
@ -115,25 +134,33 @@ class LoginViewModel @Inject constructor(
loginStatus.postValue(LoginStatus.LOGIN_STATUS_NET_LOADING)
var userCode = "99999";
//登录访问
when (val result = networkService.loginUser(LoginUserBean(userName,password))) {
is NetResult.Success<*> ->{
if (result.data!=null) {
when (val result = networkService.loginUser(LoginUserBean(userName, password))) {
is NetResult.Success<*> -> {
if (result.data != null) {
try {
val defaultUserResponse = result.data as DefaultResponse<SysUserBean>
if(defaultUserResponse.success){
if(defaultUserResponse.obj==null|| defaultUserResponse.obj!!.userCode==null){
if (defaultUserResponse.success) {
if (defaultUserResponse.obj == null || defaultUserResponse.obj!!.userCode == null) {
withContext(Dispatchers.Main) {
Toast.makeText(context, "服务返回用户Code信息错误", Toast.LENGTH_SHORT)
Toast.makeText(
context,
"服务返回用户Code信息错误",
Toast.LENGTH_SHORT
)
.show()
}
loginStatus.postValue(LoginStatus.LOGIN_STATUS_CANCEL)
return
}else{
} else {
userCode = defaultUserResponse.obj?.userCode.toString()
}
}else{
} else {
withContext(Dispatchers.Main) {
Toast.makeText(context, "${defaultUserResponse.msg}", Toast.LENGTH_SHORT)
Toast.makeText(
context,
"${defaultUserResponse.msg}",
Toast.LENGTH_SHORT
)
.show()
}
loginStatus.postValue(LoginStatus.LOGIN_STATUS_CANCEL)
@ -145,7 +172,8 @@ class LoginViewModel @Inject constructor(
}
}
}
is NetResult.Error<*> ->{
is NetResult.Error<*> -> {
withContext(Dispatchers.Main) {
Toast.makeText(context, "${result.exception.message}", Toast.LENGTH_SHORT)
.show()
@ -153,7 +181,8 @@ class LoginViewModel @Inject constructor(
loginStatus.postValue(LoginStatus.LOGIN_STATUS_CANCEL)
return
}
is NetResult.Failure<*> ->{
is NetResult.Failure<*> -> {
withContext(Dispatchers.Main) {
Toast.makeText(context, "${result.code}:${result.msg}", Toast.LENGTH_SHORT)
.show()
@ -161,12 +190,16 @@ class LoginViewModel @Inject constructor(
loginStatus.postValue(LoginStatus.LOGIN_STATUS_CANCEL)
return
}
else -> {}
}
//文件夹初始化
try {
loginStatus.postValue(LoginStatus.LOGIN_STATUS_FOLDER_INIT)
sharedPreferences?.edit()?.putString("userName", userName)?.commit()
sharedPreferences?.edit()?.putString("passWord", password)?.commit()
sharedPreferences?.edit()?.putString("userCode", userCode)?.commit()
createUserFolder(context, userCode)
} catch (e: IOException) {
loginStatus.postValue(LoginStatus.LOGIN_STATUS_FOLDER_FAILURE)
@ -185,18 +218,21 @@ class LoginViewModel @Inject constructor(
roomAppDatabase.getOfflineMapDao().insertOrUpdate(result.data)
}
}
is NetResult.Error<*> -> {
withContext(Dispatchers.Main) {
Toast.makeText(context, "${result.exception.message}", Toast.LENGTH_SHORT)
.show()
}
}
is NetResult.Failure<*> -> {
withContext(Dispatchers.Main) {
Toast.makeText(context, "${result.code}:${result.msg}", Toast.LENGTH_SHORT)
.show()
}
}
is NetResult.Loading -> {}
else -> {}
}
@ -234,7 +270,7 @@ class LoginViewModel @Inject constructor(
// 拷贝配置文件到用户目录下
val omdbConfigFile = File(userFolder.absolutePath, Constant.OMDB_CONFIG);
// if (!omdbConfigFile.exists()) {
ResourceUtils.copyFileFromAssets(Constant.OMDB_CONFIG, omdbConfigFile.absolutePath)
ResourceUtils.copyFileFromAssets(Constant.OMDB_CONFIG, omdbConfigFile.absolutePath)
// }
}

View File

@ -20,11 +20,13 @@ import androidx.navigation.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.navinfo.collect.library.data.entity.NiLocation
import com.navinfo.collect.library.map.NIMapController
import com.navinfo.omqs.Constant
import com.navinfo.omqs.R
import com.navinfo.omqs.bean.ImportConfig
import com.navinfo.omqs.bean.SignBean
import com.navinfo.omqs.bean.TraceVideoBean
import com.navinfo.omqs.databinding.ActivityMainBinding
import com.navinfo.omqs.http.offlinemapdownload.OfflineMapDownloadManager
import com.navinfo.omqs.tools.LayerConfigUtils
@ -34,12 +36,14 @@ import com.navinfo.omqs.ui.fragment.offlinemap.OfflineMapFragment
import com.navinfo.omqs.ui.fragment.qsrecordlist.QsRecordListFragment
import com.navinfo.omqs.ui.fragment.signMoreInfo.SignMoreInfoFragment
import com.navinfo.omqs.ui.fragment.tasklist.TaskManagerFragment
import com.navinfo.omqs.ui.other.BaseToast
import com.navinfo.omqs.ui.widget.RecyclerViewSpacesItemDecoration
import com.navinfo.omqs.util.FlowEventBus
import com.navinfo.omqs.util.SpeakMode
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import org.oscim.core.GeoPoint
import org.oscim.layers.marker.MarkerItem
import org.oscim.renderer.GLViewport
import org.videolan.vlc.Util
import java.math.BigDecimal
@ -179,6 +183,7 @@ class MainActivity : BaseActivity() {
MotionEvent.ACTION_DOWN -> {
voiceOnTouchStart()//Do Something
}
MotionEvent.ACTION_UP -> {
voiceOnTouchStop()//Do Something
}
@ -228,10 +233,18 @@ class MainActivity : BaseActivity() {
)
}
//捕捉列表变化回调
//捕捉轨迹点
viewModel.liveDataNILocationList.observe(this) {
if (viewModel.isSelectTrace()) {
Toast.makeText(this, "轨迹被点击了", Toast.LENGTH_LONG).show()
//Toast.makeText(this,"轨迹被点击了",Toast.LENGTH_LONG).show()
viewModel.showMarker(this, it)
viewModel.setCurrentIndexNiLocation(it)
val traceVideoBean = TraceVideoBean(
command = "videotime?",
userid = Constant.USER_ID,
time = "${it.time}:000"
)
viewModel.sendServerCommand(this, traceVideoBean, IndoorToolsCommand.SELECT_POINT)
}
}
@ -311,6 +324,55 @@ class MainActivity : BaseActivity() {
}
}
viewModel.liveIndoorToolsResp.observe(this) {
when (it) {
IndoorToolsResp.QR_CODE_STATUS_UPDATE_VIDEO_INFO_SUCCESS -> {
if (viewModel.indoorToolsCommand == IndoorToolsCommand.SELECT_POINT) {
selectPointFinish(true)
}
//启动自动播放
if (viewModel.indoorToolsCommand == IndoorToolsCommand.PLAY) {
viewModel.startTimer()
}
}
IndoorToolsResp.QR_CODE_STATUS_UPDATE_VIDEO_INFO_FAILURE -> {
if (viewModel.indoorToolsCommand == IndoorToolsCommand.SELECT_POINT) {
selectPointFinish(false)
}
}
}
}
//室内整理工具反向控制
viewModel.liveIndoorToolsCommand.observe(this) {
when (it) {
IndoorToolsCommand.PLAY -> {
setPlayStatus()
}
IndoorToolsCommand.INDEXING -> {
pausePlayTrace()
}
IndoorToolsCommand.SELECT_POINT -> {
}
IndoorToolsCommand.NEXT -> {
}
IndoorToolsCommand.REWIND -> {
}
IndoorToolsCommand.STOP -> {
//切换为暂停状态
pausePlayTrace()
}
}
}
lifecycleScope.launch {
// 初始化地图图层控制接收器
FlowEventBus.subscribe<List<ImportConfig>>(
@ -330,8 +392,13 @@ class MainActivity : BaseActivity() {
}
}
supportFragmentManager.beginTransaction()
.add(R.id.console_fragment_layout, ConsoleFragment()).commit()
//自动连接相机
if (viewModel.isAutoCamera()) {
viewModel.autoCamera()
} else {
supportFragmentManager.beginTransaction()
.add(R.id.console_fragment_layout, ConsoleFragment()).commit()
}
}
//根据输入的经纬度跳转坐标
@ -534,10 +601,14 @@ class MainActivity : BaseActivity() {
*/
fun tracePointsOnclick() {
viewModel.setSelectTrace(!viewModel.isSelectTrace())
binding.mainActivityTraceSnapshotPoints.isSelected = viewModel.isSelectTrace()
if (viewModel.isSelectTrace()) {
Toast.makeText(this, "请选择轨迹点!", Toast.LENGTH_LONG).show()
//调用撤销自动播放
setViewEnable(false)
viewModel.cancelTrace()
}
binding.mainActivityTraceSnapshotPoints.isSelected = viewModel.isSelectTrace()
}
/**
@ -548,8 +619,9 @@ class MainActivity : BaseActivity() {
viewModel.setSelectTrace(false)
viewModel.setMediaFlag(false)
viewModel.setSelectPauseTrace(false)
binding.mainActivityMenuIndoorGroup.visibility = View.GONE
binding.mainActivityTraceSnapshotPoints.isSelected = viewModel.isSelectTrace()
binding.mainActivitySnapshotMediaFlag.isSelected = viewModel.isMediaFlag()
//binding.mainActivitySnapshotMediaFlag.isSelected = viewModel.isMediaFlag()
binding.mainActivitySnapshotPause.isSelected = viewModel.isSelectPauseTrace()
}
@ -557,15 +629,29 @@ class MainActivity : BaseActivity() {
* 点击结束轨迹操作
*/
fun mediaFlagOnclick() {
viewModel.setMediaFlag(!viewModel.isMediaFlag())
binding.mainActivitySnapshotMediaFlag.isSelected = viewModel.isMediaFlag()
/* viewModel.setMediaFlag(!viewModel.isMediaFlag())
binding.mainActivitySnapshotMediaFlag.isSelected = viewModel.isMediaFlag()*/
}
/**
* 点击上一个轨迹点播放操作
*/
fun rewindTraceOnclick() {
pasePlayTrace()
pausePlayTrace()
val item =
mapController.markerHandle.getNILocation(viewModel.getCurrentNiLocationIndex() - 1)
if (item != null) {
viewModel.setCurrentIndexLoction(viewModel.getCurrentNiLocationIndex() - 1)
viewModel.showMarker(this, item)
val traceVideoBean = TraceVideoBean(
command = "videotime?",
userid = Constant.USER_ID,
time = "${item.time}:000"
)
viewModel.sendServerCommand(this, traceVideoBean, IndoorToolsCommand.REWIND)
} else {
dealNoData()
}
}
/**
@ -576,13 +662,74 @@ class MainActivity : BaseActivity() {
binding.mainActivitySnapshotPause.isSelected = viewModel.isSelectPauseTrace()
viewModel.setSelectTrace(false)
binding.mainActivityTraceSnapshotPoints.isSelected = viewModel.isSelectTrace()
if (viewModel.isSelectPauseTrace()) {
playVideo()
} else {
pauseVideo()
viewModel.cancelTrace()
}
}
@RequiresApi(Build.VERSION_CODES.N)
fun playVideo() {
if (mapController.markerHandle.getCurrentMark() == null) {
BaseToast.makeText(this, "请先选择轨迹点!", BaseToast.LENGTH_SHORT).show()
return
}
viewModel.setSelectTrace(false)
binding.mainActivityTraceSnapshotPoints.isSelected = viewModel.isSelectTrace()
val traceVideoBean = TraceVideoBean(command = "playVideo?", userid = Constant.USER_ID)
viewModel.sendServerCommand(this, traceVideoBean, IndoorToolsCommand.PLAY)
}
/**
* 设置为播放状态
*/
@RequiresApi(Build.VERSION_CODES.N)
fun setPlayStatus() {
//切换为播放
viewModel.setSelectPauseTrace(true)
binding.mainActivitySnapshotPause.isSelected = viewModel.isSelectPauseTrace()
playVideo()
}
@RequiresApi(Build.VERSION_CODES.N)
fun pauseVideo() {
val traceVideoBean = TraceVideoBean(command = "pauseVideo?", userid = Constant.USER_ID)
viewModel.sendServerCommand(this, traceVideoBean, IndoorToolsCommand.STOP)
}
/**
* 点击下一个轨迹点
*/
fun nextTraceOnclick() {
pasePlayTrace()
pausePlayTrace()
val item =
mapController.markerHandle.getNILocation(viewModel.getCurrentNiLocationIndex() + 1)
if (item != null) {
viewModel.setCurrentIndexLoction(viewModel.getCurrentNiLocationIndex() + 1)
viewModel.showMarker(this, item)
val traceVideoBean = TraceVideoBean(
command = "videotime?",
userid = Constant.USER_ID,
time = "${item.time}:000"
)
viewModel.sendServerCommand(this, traceVideoBean, IndoorToolsCommand.NEXT)
} else {
dealNoData()
}
}
private fun dealNoData() {
BaseToast.makeText(this, "无数据了!", Toast.LENGTH_SHORT).show()
//无数据时自动暂停播放,并停止轨迹
if (viewModel.isSelectPauseTrace()) {
pauseVideo()
viewModel.cancelTrace()
viewModel.setSelectPauseTrace(false)
binding.mainActivitySnapshotPause.isSelected = viewModel.isSelectPauseTrace()
}
}
fun pasePlayTrace() {
@ -590,6 +737,27 @@ class MainActivity : BaseActivity() {
binding.mainActivityTraceSnapshotPoints.isSelected = viewModel.isSelectTrace()
viewModel.setSelectPauseTrace(false)
binding.mainActivitySnapshotPause.isSelected = viewModel.isSelectPauseTrace()
viewModel.cancelTrace()
}
/**
* 选点结束
* @param value true 选点成功 false 选点失败
*/
private fun selectPointFinish(value: Boolean) {
if (value) {
setViewEnable(true)
viewModel.setSelectPauseTrace(false)
binding.mainActivitySnapshotPause.isSelected = viewModel.isSelectPauseTrace()
}
}
private fun setViewEnable(value: Boolean) {
binding.mainActivitySnapshotRewind.isEnabled = value
binding.mainActivitySnapshotNext.isEnabled = value
binding.mainActivitySnapshotPause.isEnabled = value
binding.mainActivitySnapshotFinish.isEnabled = value
viewModel.cancelTrace()
}
@ -686,7 +854,7 @@ class MainActivity : BaseActivity() {
private fun setIndoorGroupEnable(enable: Boolean) {
binding.mainActivitySnapshotFinish.isEnabled = enable
binding.mainActivityTraceSnapshotPoints.isEnabled = enable
binding.mainActivitySnapshotMediaFlag.isEnabled = enable
//binding.mainActivitySnapshotMediaFlag.isEnabled = enable
binding.mainActivitySnapshotRewind.isEnabled = enable
binding.mainActivitySnapshotPause.isEnabled = enable
binding.mainActivitySnapshotNext.isEnabled = enable

View File

@ -15,31 +15,39 @@ import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.PopupWindow
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.navigation.findNavController
import com.blankj.utilcode.util.ToastUtils
import com.blankj.utilcode.util.ViewUtils.runOnUiThread
import com.navinfo.collect.library.data.dao.impl.TraceDataBase
import com.navinfo.collect.library.data.entity.*
import com.navinfo.collect.library.garminvirbxe.HostBean
import com.navinfo.collect.library.map.NIMapController
import com.navinfo.collect.library.map.OnGeoPointClickListener
import com.navinfo.collect.library.map.handler.ONNoteItemClickListener
import com.navinfo.collect.library.map.handler.OnNiLocationItemListener
import com.navinfo.collect.library.map.handler.OnQsRecordItemClickListener
import com.navinfo.collect.library.map.handler.OnTaskLinkItemClickListener
import com.navinfo.collect.library.utils.GeometryTools
import com.navinfo.collect.library.utils.GeometryToolsKt
import com.navinfo.omqs.Constant
import com.navinfo.omqs.R
import com.navinfo.omqs.bean.ImportConfig
import com.navinfo.omqs.bean.QRCodeBean
import com.navinfo.omqs.bean.SignBean
import com.navinfo.omqs.bean.TraceVideoBean
import com.navinfo.omqs.db.RealmOperateHelper
import com.navinfo.omqs.http.NetResult
import com.navinfo.omqs.http.NetworkService
import com.navinfo.omqs.ui.dialog.CommonDialog
import com.navinfo.omqs.ui.manager.TakePhotoManager
import com.navinfo.omqs.ui.other.BaseToast
import com.navinfo.omqs.ui.widget.SignUtil
import com.navinfo.omqs.util.DateTimeUtil
import com.navinfo.omqs.util.ShareUtil
import com.navinfo.omqs.util.SoundMeter
import com.navinfo.omqs.util.SpeakMode
import dagger.hilt.android.lifecycle.HiltViewModel
@ -52,11 +60,14 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.oscim.core.GeoPoint
import org.oscim.core.MapPosition
import org.oscim.layers.marker.MarkerItem
import org.oscim.map.Map
import org.videolan.libvlc.LibVlcUtil
import java.io.File
import java.io.IOException
import java.util.*
import javax.inject.Inject
import kotlin.concurrent.fixedRateTimer
/**
* 创建Activity全局viewmode
@ -67,8 +78,9 @@ class MainViewModel @Inject constructor(
private val mapController: NIMapController,
private val traceDataBase: TraceDataBase,
private val realmOperateHelper: RealmOperateHelper,
private val networkService: NetworkService,
private val sharedPreferences: SharedPreferences
) : ViewModel(), SharedPreferences.OnSharedPreferenceChangeListener {
) : ViewModel(), SocketServer.OnConnectSinsListener, SharedPreferences.OnSharedPreferenceChangeListener {
private val TAG = "MainViewModel"
@ -100,6 +112,8 @@ class MainViewModel @Inject constructor(
*/
val liveDataSignMoreInfo = MutableLiveData<RenderEntity>()
private var traceTag: String = "TRACE_TAG"
/**
* 右上角菜单状态
*/
@ -131,6 +145,12 @@ class MainViewModel @Inject constructor(
var currentTaskBean: TaskBean? = null
//状态
val liveIndoorToolsResp: MutableLiveData<IndoorToolsResp> = MutableLiveData()
//状态
val liveIndoorToolsCommand: MutableLiveData<IndoorToolsCommand> = MutableLiveData()
/**
* 是不是线选择模式
*/
@ -155,6 +175,18 @@ class MainViewModel @Inject constructor(
private var lastNiLocaion: NiLocation? = null
private var currentIndexNiLocation: Int = 0
private var socketServer: SocketServer? = null
var indoorToolsCommand: IndoorToolsCommand? = null
private var shareUtil: ShareUtil? = null
private var timer: Timer? = null
private var disTime :Long = 1000
init {
mapController.mMapView.vtmMap.events.bind(Map.UpdateListener { e, mapPosition ->
@ -164,6 +196,9 @@ class MainViewModel @Inject constructor(
}
})
shareUtil = ShareUtil(mapController.mMapView.context, 1)
initLocation()
/**
* 处理点击道路捕捉回调功能
@ -231,6 +266,7 @@ class MainViewModel @Inject constructor(
initNILocationData()
}
sharedPreferences.registerOnSharedPreferenceChangeListener(this)
socketServer = SocketServer(mapController, traceDataBase, sharedPreferences)
}
@ -310,21 +346,10 @@ class MainViewModel @Inject constructor(
* 初始化定位信息
*/
private fun initLocation() {
//用于定位点存储到数据库
viewModelScope.launch(Dispatchers.Default) {
//用于定位点捕捉道路
mapController.locationLayerHandler.niLocationFlow.collectLatest { location ->
if (!isSelectRoad() && !GeometryTools.isCheckError(
location.longitude, location.latitude
)
) {
captureLink(
GeoPoint(
location.latitude, location.longitude
)
)
}
}
mapController.locationLayerHandler.niLocationFlow.collect { location ->
//过滤掉无效点
@ -354,34 +379,52 @@ class MainViewModel @Inject constructor(
}
val id = sharedPreferences.getInt(Constant.SELECT_TASK_ID, -1)
location.taskId = id.toString()
if (shareUtil?.connectstate == true) {
location.media = 1
}
var disance = 0.0
//增加间距判断
if (lastNiLocaion != null) {
val disance = GeometryTools.getDistance(
location.latitude,
location.longitude,
lastNiLocaion!!.latitude,
lastNiLocaion!!.longitude
disance = GeometryTools.getDistance(
location.latitude, location.longitude,
lastNiLocaion!!.latitude, lastNiLocaion!!.longitude
)
//相距差距大于2.5米以上进行存储
if (disance > 2.5) {
traceDataBase.niLocationDao.insert(location)
mapController.markerHandle.addNiLocationMarkerItem(location)
mapController.mMapView.vtmMap.updateMap(true)
lastNiLocaion = location
}
} else {
}
//室内整理工具时不能进行轨迹存储判断轨迹间隔要超过2.5并小于60米
if (Constant.INDOOR_IP.isEmpty() && (disance == 0.0 || (disance > 2.5 && disance < 60))) {
traceDataBase.niLocationDao.insert(location)
/* mapController.markerHandle.addNiLocationMarkerItem(location)
mapController.mMapView.vtmMap.updateMap(true)*/
mapController.markerHandle.addNiLocationMarkerItem(location)
mapController.mMapView.vtmMap.updateMap(true)
lastNiLocaion = location
}
}
}
}
}
viewModelScope.launch(Dispatchers.Default) {
//用于定位点捕捉道路
mapController.locationLayerHandler.niLocationFlow.collectLatest { location ->
if (!isSelectRoad() && !GeometryTools.isCheckError(
location.longitude, location.latitude
)
) {
captureLink(
GeoPoint(
location.latitude, location.longitude
)
)
}
withContext(Dispatchers.Main){
if(Constant.AUTO_LOCATION){
mapController.mMapView.vtmMap.animator()
.animateTo(GeoPoint( location.longitude, location.latitude))
}
}
}
}
//显示轨迹图层
mapController.layerManagerHandler.showNiLocationLayer()
}
@ -528,17 +571,8 @@ class MainViewModel @Inject constructor(
Log.e("qj", LibVlcUtil.hasCompatibleCPU(context).toString())
if (mCameraDialog == null) {
mCameraDialog = CommonDialog(
context,
context.resources.getDimension(R.dimen.head_img_width)
.toInt() * 3 + context.resources.getDimension(R.dimen.ten)
.toInt() + context.resources.getDimension(R.dimen.twenty_four).toInt(),
context.resources.getDimension(R.dimen.head_img_width).toInt() + 10,
1
)
mCameraDialog!!.setCancelable(true)
}
initCameraDialog(context)
mCameraDialog!!.openCamear(mCameraDialog!!.getmShareUtil().continusTakePhotoState)
mCameraDialog!!.show()
mCameraDialog!!.setOnDismissListener(DialogInterface.OnDismissListener {
@ -563,6 +597,20 @@ class MainViewModel @Inject constructor(
})
}
private fun initCameraDialog(context:Context){
if (mCameraDialog == null) {
mCameraDialog = CommonDialog(
context,
context.resources.getDimension(R.dimen.head_img_width)
.toInt() * 3 + context.resources.getDimension(R.dimen.ten)
.toInt() + context.resources.getDimension(R.dimen.twenty_four).toInt(),
context.resources.getDimension(R.dimen.head_img_width).toInt() + 10,
1
)
mCameraDialog!!.setCancelable(true)
}
}
fun startSoundMetter(context: Context, v: View) {
//语音识别动画
@ -727,5 +775,246 @@ class MainViewModel @Inject constructor(
liveDataSignMoreInfo.value = data
}
fun sendServerCommand(
context: Context,
traceVideoBean: TraceVideoBean,
indoorToolsCommand: IndoorToolsCommand
) {
if (TextUtils.isEmpty(Constant.INDOOR_IP)) {
Toast.makeText(context, "获取ip失败", Toast.LENGTH_LONG).show()
return
}
this.indoorToolsCommand = indoorToolsCommand
viewModelScope.launch(Dispatchers.Default) {
val url = "http://${Constant.INDOOR_IP}:8080/sensor/service/${traceVideoBean.command}?"
when (val result = networkService.sendServerCommand(
url = url,
traceVideoBean = traceVideoBean
)) {
is NetResult.Success<*> -> {
if (result.data != null) {
try {
val defaultUserResponse = result.data as QRCodeBean
if (defaultUserResponse.errcode == 0) {
withContext(Dispatchers.Main) {
Toast.makeText(
context,
"命令成功。",
Toast.LENGTH_LONG
).show()
liveIndoorToolsResp.postValue(IndoorToolsResp.QR_CODE_STATUS_UPDATE_VIDEO_INFO_SUCCESS)
//启动双向控制服务
//启动双向控制服务
if (socketServer != null && socketServer!!.isServerClose) {
socketServer!!.connect(
Constant.INDOOR_IP,
this@MainViewModel
)
}
}
} else {
withContext(Dispatchers.Main) {
Toast.makeText(
context,
"命令无效${defaultUserResponse.errmsg}",
Toast.LENGTH_SHORT
)
.show()
}
liveIndoorToolsResp.postValue(IndoorToolsResp.QR_CODE_STATUS_UPDATE_VIDEO_INFO_FAILURE)
}
} catch (e: IOException) {
withContext(Dispatchers.Main) {
Toast.makeText(
context,
"${e.message}",
Toast.LENGTH_SHORT
).show()
}
}
}
}
is NetResult.Error<*> -> {
withContext(Dispatchers.Main) {
Toast.makeText(
context,
"${result.exception.message}",
Toast.LENGTH_SHORT
)
.show()
}
liveIndoorToolsResp.postValue(IndoorToolsResp.QR_CODE_STATUS_UPDATE_VIDEO_INFO_FAILURE)
}
is NetResult.Failure<*> -> {
withContext(Dispatchers.Main) {
Toast.makeText(
context,
"${result.code}:${result.msg}",
Toast.LENGTH_SHORT
)
.show()
}
liveIndoorToolsResp.postValue(IndoorToolsResp.QR_CODE_STATUS_UPDATE_VIDEO_INFO_FAILURE)
}
else -> {}
}
}
}
/**
* 显示marker
* @param trackCollection 轨迹点
* @param type 1 提示最后一个轨迹点 非1提示第一个轨迹点
*/
fun showMarker(context: Context, niLocation: NiLocation) {
if (mapController.markerHandle != null) {
mapController.markerHandle.removeMarker(traceTag)
if (niLocation != null) {
mapController.markerHandle.addMarker(
GeoPoint(
niLocation.latitude,
niLocation.longitude
), traceTag, "", niLocation as java.lang.Object
)
}
}
}
/**
* 显示索引位置
* @param niLocation 轨迹点
*/
fun setCurrentIndexNiLocation(niLocation: NiLocation) {
viewModelScope.launch ( Dispatchers.IO ){
Log.e("qj","开始$currentIndexNiLocation")
currentIndexNiLocation = mapController.markerHandle.getNILocationIndex(niLocation)!!
Log.e("qj","结束$currentIndexNiLocation")
}
}
/**
* 设置索引位置
* @param index 索引
*/
fun setCurrentIndexLoction(index: Int) {
currentIndexNiLocation = index
}
/**
*
* @return index 索引
*/
fun getCurrentNiLocationIndex(): Int {
return currentIndexNiLocation
}
override fun onConnect(success: Boolean) {
if (!success && socketServer != null) {
BaseToast.makeText(
mapController.mMapView.context,
"轨迹反向控制服务失败,请确认连接是否正常!",
Toast.LENGTH_SHORT
).show()
}
}
override fun onIndexing() {
//切换为暂停状态
liveIndoorToolsCommand.postValue(IndoorToolsCommand.INDEXING)
}
override fun onStop() {
liveIndoorToolsCommand.postValue(IndoorToolsCommand.STOP)
}
override fun onPlay() {
liveIndoorToolsCommand.postValue(IndoorToolsCommand.PLAY)
}
override fun onParseEnd() {
}
override fun onReceiveLocation(mNiLocation: NiLocation?) {
if (mNiLocation != null) {
setCurrentIndexNiLocation(mNiLocation)
showMarker(mapController.mMapView.context, mNiLocation)
Log.e("qj","反向控制$currentIndexNiLocation")
} else {
BaseToast.makeText(
mapController.mMapView.context,
"没有找到对应轨迹点!",
Toast.LENGTH_SHORT
).show()
}
}
fun isAutoCamera():Boolean{
return shareUtil?.connectstate == true
}
fun autoCamera(){
if (shareUtil?.connectstate == true) {
val hostBean1 = HostBean()
hostBean1.ipAddress = shareUtil!!.takeCameraIP
hostBean1.hardwareAddress = shareUtil!!.takeCameraMac
onClickCameraButton(mapController.mMapView.context)
mCameraDialog?.connection(hostBean1)
}
}
fun startTimer() {
if(timer!=null){
cancelTrace()
}
timer = fixedRateTimer("", false, disTime, disTime) {
if(currentIndexNiLocation<mapController.markerHandle.getNILocationItemizedLayerSize()){
Log.e("qj","定时器")
val niLocation = mapController.markerHandle.getNILocation(currentIndexNiLocation)
val nextNiLocation = mapController.markerHandle.getNILocation(currentIndexNiLocation+1)
if(nextNiLocation!=null&&niLocation!=null){
var nilocationDisTime = nextNiLocation.timeStamp.toLong() - niLocation.timeStamp.toLong()
disTime = if(nilocationDisTime<1000){
1000
}else{
nilocationDisTime
}
showMarker(mapController.mMapView.context,nextNiLocation)
currentIndexNiLocation += 1
//再次启动
startTimer()
}
}else{
Toast.makeText(mapController.mMapView.context,"无数据了!",Toast.LENGTH_LONG).show()
cancelTrace()
}
}
}
/**
* 结束自动播放
*/
fun cancelTrace() {
timer?.cancel()
}
}
}

View File

@ -0,0 +1,606 @@
package com.navinfo.omqs.ui.activity.map
import android.app.Service
import android.content.Intent
import android.content.SharedPreferences
import android.os.Binder
import android.os.Handler
import android.os.IBinder
import android.os.Message
import android.text.TextUtils
import android.util.Log
import com.navinfo.collect.library.data.dao.impl.TraceDataBase
import com.navinfo.collect.library.data.entity.NiLocation
import com.navinfo.collect.library.map.NIMapController
import com.navinfo.omqs.Constant
import com.navinfo.omqs.util.DateTimeUtil
import org.json.JSONObject
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import java.io.Serializable
import java.net.Socket
import java.util.Collections
import kotlin.math.abs
enum class IndoorToolsCommand {
PLAY,
SELECT_POINT,
INDEXING,
NEXT,
REWIND,
STOP
}
enum class IndoorToolsResp{
/**
* 信息更新轨迹成功
*/
QR_CODE_STATUS_UPDATE_VIDEO_INFO_SUCCESS,
/**
* 信息更新轨迹失败
*/
QR_CODE_STATUS_UPDATE_VIDEO_INFO_FAILURE,
}
/**
* @author qj
* @version V1.0
* @Date 2018/4/18.
* @Description: 轨迹反向控制服务
*/
class SocketServer(
private val mapController: NIMapController,
private val traceDataBase: TraceDataBase,
private val sharedPreferences: SharedPreferences
) : Service() {
//类标识
private val TAG = "SocketServer"
//线程池
private val threadConnect = ThreadLocal<Socket>()
//读的线程
private var tRecv: RecvThread? = null
//解析线程
private var tParse: ParseThread? = null
//输出流
private var outStr: OutputStream? = null
//输入流
private var inStr: InputStream? = null
//状态
var connectstatus = false
//socket
private var client: Socket? = null
//接收缓存
private val sData = ByteArray(512)
//反馈接口
private var mListener: OnConnectSinsListener? = null
//服务
private val mBinder: MyBinder = MyBinder()
//接收集合
private val mTaskList = Collections.synchronizedList(ArrayList<String>())
//连接线程
private var connectThread: Thread? = null
//缓存ip
private var lastIp = ""
private val mHandler: Handler = object : Handler() {
override fun handleMessage(msg: Message) {
when (msg.what) {
0x11 -> if (mListener != null) {
if (msg.obj != null && msg.obj is NiLocation) {
mListener!!.onReceiveLocation(msg.obj as NiLocation)
} else {
mListener!!.onReceiveLocation(null)
}
}
0x22 -> //索引定位中
if (mListener != null) {
mListener!!.onIndexing()
}
0x33 -> if (mListener != null) {
mListener!!.onConnect(true)
}
0x44 -> if (mListener != null) {
mListener!!.onConnect(false)
}
0x55 -> if (mListener != null) {
mListener!!.onPlay()
}
0x66 -> if (mListener != null) {
mListener!!.onStop()
}
0x99 -> if (mListener != null) {
mListener!!.onParseEnd()
}
0x999 -> if (mListener != null) {
mListener!!.onConnect(false)
disconnect()
}
}
}
}
override fun onCreate() {
super.onCreate()
}
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
return super.onStartCommand(intent, flags, startId)
}
override fun onDestroy() {
super.onDestroy()
}
override fun onBind(intent: Intent): IBinder? {
return mBinder
}
inner class MyBinder : Binder() {
// 返回Activity所关联的Service对象这样在Activity里就可调用Service里的一些公用方法 和公用属性
val service: SocketServer
get() =// 返回Activity所关联的Service对象这样在Activity里就可调用Service里的一些公用方法 和公用属性
this@SocketServer
}
/**
* 启动sock连接
*
* @param ip
* @param listener 结果回调
*/
fun connect(ip: String, listener: OnConnectSinsListener?) {
if (connectThread != null && connectThread!!.isAlive && TextUtils.equals(lastIp, ip)) {
return
}
mListener = listener
lastIp = ip
connectThread = object : Thread() {
override fun run() {
try {
client = threadConnect.get()
if (client == null) {
client = Socket(ip, 8010)
client!!.soTimeout = 3000000
client!!.keepAlive = true
threadConnect.set(client)
}
outStr = client!!.getOutputStream()
inStr = client!!.getInputStream()
if (tRecv != null) {
tRecv!!.cancel()
}
tRecv = RecvThread()
val thread = Thread(tRecv)
thread.start()
//解析线程
if (tParse != null) {
tParse!!.cancel()
}
tParse = ParseThread()
val parsethread = Thread(tParse)
parsethread.start()
//socket启动成功
val msg = Message()
msg.what = 0x33
mHandler.sendMessage(msg)
if (!connectstatus) {
connectstatus = true // 更改连接状态
}
} catch (e: Exception) {
e.printStackTrace()
//启动失败
val msg = Message()
msg.what = 0x44
mHandler.sendMessage(msg)
}
}
}
(connectThread as Thread).start()
}
/**
* sock是否启动
*
* @return true 启动 false停止
*/
val isStart: Boolean
get() = if (connectThread != null && connectThread!!.isAlive) {
true
} else false
/**
* 销毁连接
*/
fun disconnect() {
try {
//销毁线程
if (tRecv != null) {
tRecv!!.cancel()
}
//销毁线程
if (tParse != null) {
tParse!!.cancel()
}
} catch (e: Exception) {
}
try {
if (outStr != null) outStr!!.close()
if (inStr != null) inStr!!.close()
if (client != null) client!!.close()
} catch (e: IOException) {
e.printStackTrace()
}
}
/**
* 解析接收到得线程
*/
private inner class ParseThread : Runnable {
private var runFlag = true
//轨迹时间buffer
private val traceTimeBuffer = 1500
private var timeIndex = 0
fun cancel() {
runFlag = false
}
override fun run() {
try {
while (runFlag) {
if (mTaskList.size > 0) {
timeIndex = mTaskList.size - 1
val result = parseResult(mTaskList[timeIndex])
var resultNiLocation: NiLocation? = null
var index: Int = -1
if (result != null) {
when (result.type) {
1 -> {
//先暂停播放
val msg = Message()
msg.what = 0x22
mHandler.sendMessage(msg)
val currentTime: Long = DateTimeUtil.getTimePointSSS(
result.data
)
val currentTimeStr: String = DateTimeUtil.TimePointSSSToTime(
result.data
)
Log.e(TAG, "反向"+result.data)
val startTime = currentTime - traceTimeBuffer
val endTme = currentTime + traceTimeBuffer
//转换为数据库时间
val startTimeStr: String =
DateTimeUtil.getDateSimpleTime(startTime)
//转换为数据库时间
val endTimeStr: String =
DateTimeUtil.getDateSimpleTime(endTme)
if (!TextUtils.isEmpty(startTimeStr) && !TextUtils.isEmpty(
endTimeStr
)
) {
Log.e(TAG, "getTraceData开始")
val list: List<NiLocation>? = getTrackList(startTimeStr, endTimeStr, currentTimeStr)
Log.e(TAG, "getTraceData结束")
if (list != null && list.size > 0) {
var disTime: Long = 0
//只有一个点不进行判断直接返回结果
if (list.size == 1) {
resultNiLocation = list[0]
} else {
//遍历集合取最近时间的轨迹点
b@ for (nilocation in list) {
if (!TextUtils.isEmpty(nilocation.time)) {
//只获取到秒的常量
val time: Long =
nilocation.timeStamp.toLong()
val disTimeTemp = abs(time - currentTime)
//如果时间相同直接返回该点
if (disTimeTemp == 0L) {
resultNiLocation = nilocation
break@b
} else {
//第一次不对比,取当前值
if (disTime == 0L) {
disTime = disTimeTemp
resultNiLocation = nilocation
} else {
//前一个差值大于当前差值则取当前相对小的值
if (disTime - disTimeTemp > 0) {
disTime = disTimeTemp
resultNiLocation = nilocation
}
}
}
}
}
}
}
}
val msg1 = Message()
msg1.what = 0x11
msg1.obj = resultNiLocation
if (resultNiLocation != null) {
Log.e(TAG, "反向app"+resultNiLocation.time)
}
mHandler.sendMessage(msg1)
}
2 -> {
val msg4 = Message()
msg4.what = 0x55
mHandler.sendMessage(msg4)
}
3 -> {
val msg5 = Message()
msg5.what = 0x66
mHandler.sendMessage(msg5)
}
}
}
//解析时索引与集合索引对比,如果不相同代表有新命令,需要继续解析最后一条,否则清空集合不在解析
try {
if (timeIndex == mTaskList.size - 1) {
mTaskList.clear()
}
} catch (e: Exception) {
}
val msg2 = Message()
msg2.what = 0x99
mHandler.sendMessage(msg2)
}
}
Thread.sleep(10)
} catch (e: Exception) {
e.printStackTrace()
val msg = Message()
msg.what = 0x99
mHandler.sendMessage(msg)
}
}
}
/**
* 获取轨迹数据
*
* @param startTimeStr 起始时间
* @param endTimeStr 结束时间
* @param currentTimeStr 当前点时间如果存在便直接获取一个点
* @return list 数据集合
*/
private fun getTrackList(
startTimeStr: String,
endTimeStr: String,
currentTimeStr: String
): List<NiLocation>? {
if (!TextUtils.isEmpty(startTimeStr) && !TextUtils.isEmpty(endTimeStr)) {
var startTime: Long = 0
var endTime: Long = 0
try {
startTime = startTimeStr.toLong()
endTime = endTimeStr.toLong()
} catch (e: java.lang.Exception) {
}
if (startTime != 0L && endTime != 0L) {
val id = sharedPreferences.getInt(Constant.SELECT_TASK_ID, -1)
val list: MutableList<NiLocation> = traceDataBase.niLocationDao.findToTaskIdAll(id.toString())
if (list.size > 0) return list
}
}
return null
}
/**
* 接收管道数据
*/
private inner class RecvThread : Runnable {
private var runFlag = true
fun cancel() {
runFlag = false
}
override fun run() {
var rlRead: Int
try {
while (runFlag) {
var line: String = ""
if (!isServerClose) {
rlRead = inStr!!.read(sData) //对方断开返回-1
if (rlRead > 0) {
Log.e(TAG, sData.toString() + "")
line = String(sData, 0, rlRead)
mTaskList.add(line)
} else {
connectFaild("连接断开")
}
} else {
connectFaild("连接断开")
}
}
Thread.sleep(10)
} catch (e: IOException) {
connectFaild(e.toString())
e.printStackTrace()
}
}
}
/**
* 连接失败
* @param e 原因
*/
private fun connectFaild(e: String) {
val msg2 = Message()
msg2.what = 0x999
mHandler.sendMessage(msg2)
}
/**
* 判断是否断开连接断开返回true,没有返回false
* @return
*/
val isServerClose: Boolean
get() {
return try {
client!!.sendUrgentData(0) //发送1个字节的紧急数据默认情况下服务器端没有开启紧急数据处理不影响正常通信
false
} catch (se: Exception) {
true
}
}
/**
* 停止接收管道数据
*/
fun stop() {
Log.e(TAG, "stop!")
connectstatus = false
if (tRecv != null) {
tRecv!!.cancel()
}
if (tParse != null) {
tParse!!.cancel()
}
}
/**
* 开始接收管道数据
*/
fun start() {
Log.e(TAG, "start!")
if (tRecv != null) {
tRecv!!.cancel()
}
tRecv = RecvThread()
val thread = Thread(tRecv)
thread.start()
//解析线程
if (tParse != null) {
tParse!!.cancel()
}
tParse = ParseThread()
val parsethread = Thread(tParse)
parsethread.start()
}
fun setTraceMap() {
}
/**
* 轨迹反向控制回调接口
*/
interface OnConnectSinsListener {
/**
* 连接状态
*
* @param success true 连接成功 false 连接失败
*/
fun onConnect(success: Boolean)
/**
* 索引中
*/
fun onIndexing()
/**
* 暂停
*/
fun onStop()
/**
* 播放
*/
fun onPlay()
/**
* 结束完成
*/
fun onParseEnd()
/**
* 轨迹点
*
* @param mNiLocation
*/
fun onReceiveLocation(mNiLocation: NiLocation?)
}
/**
* 解析返回值
*
* @return 时间信息
*/
private fun parseResult(data: String): Result? {
var data = data
if (!TextUtils.isEmpty(data)) {
try {
data = data.replace("\n".toRegex(), "")
val json = JSONObject(data)
val type = json.optInt("type")
val mResult: Result = Result()
mResult.type = type
if (type == 1) {
mResult.data = json.optString("data", "")
}
return mResult
} catch (e: Exception) {
}
}
return null
}
//结果类对象
internal inner class Result : Serializable {
var type = 0
var data: String? = null
}
}

View File

@ -33,6 +33,7 @@ enum class QrCodeStatus {
* 信息更新成功
*/
QR_CODE_STATUS_SERVER_INFO_SUCCESS,
}
@HiltViewModel

View File

@ -676,6 +676,7 @@ public class CommonDialog extends Dialog implements SurfaceHolder.Callback, IVid
//当前为连接时启动已有的状态
if (connectstate) {
mOneBtConnect.setPressed(true);
mOneBtConnect.setBackgroundResource(R.drawable.shape_btn_red_disconnect_bg);
@ -1525,7 +1526,7 @@ public class CommonDialog extends Dialog implements SurfaceHolder.Callback, IVid
}
//连接
private void connection(HostBean hostBean) {
public void connection(HostBean hostBean) {
if (hostBean != null) {
SensorParams params = new SensorParams();

View File

@ -257,6 +257,7 @@ class EvaluationResultViewModel @Inject constructor(
if (classType2 != null) {
classType = classType2
}
classCode = bean.renderEntity.code.toString()
}
//如果右侧栏没数据,给个默认值
if (liveDataQsRecordBean.value!!.classType.isEmpty()) {
@ -343,11 +344,12 @@ class EvaluationResultViewModel @Inject constructor(
/**
* 查询问题类型列表
*/
fun getProblemTypeList(classType: String) {
fun getProblemTypeList(scProblemTypeBean: ScProblemTypeBean) {
viewModelScope.launch(Dispatchers.IO) {
getProblemList(classType)
getProblemList(scProblemTypeBean.classType)
}
classTypeTemp = classType
classTypeTemp = scProblemTypeBean.classType
classCodeTemp = scProblemTypeBean.elementCode
}
/**
@ -464,7 +466,7 @@ class EvaluationResultViewModel @Inject constructor(
mapController.markerHandle.addMarker(
GeoPoint(
p.latitude, p.longitude
), TAG
), TAG, "", null
)
//获取linkid
@ -484,163 +486,163 @@ class EvaluationResultViewModel @Inject constructor(
liveDataQsRecordBean.value?.attachmentBeanList = it.attachmentBeanList
// 显示语音数据到界面
getChatMsgEntityList()
}
}
} else {
liveDataToastMessage.postValue("数据读取失败")
}
}
}
}
}
/**
* 查询问题类型列表
*/
/**
* 查询问题类型列表
*/
private suspend fun getChatMsgEntityList() {
val chatMsgEntityList: MutableList<ChatMsgEntity> = ArrayList()
liveDataQsRecordBean.value?.attachmentBeanList?.forEach {
//1 录音
if (it.type == 1) {
val chatMsgEntity = ChatMsgEntity()
chatMsgEntity.name = it.name
chatMsgEntity.voiceUri = Constant.USER_DATA_ATTACHEMNT_PATH
chatMsgEntityList.add(chatMsgEntity)
}
}
listDataChatMsgEntityList.postValue(chatMsgEntityList)
}
fun addChatMsgEntity(filePath: String) {
if (filePath.isNotEmpty()) {
var chatMsgEntityList: MutableList<ChatMsgEntity> = ArrayList()
if (listDataChatMsgEntityList.value?.isEmpty() == false) {
chatMsgEntityList = listDataChatMsgEntityList.value!!
}
val chatMsgEntityList: MutableList<ChatMsgEntity> = ArrayList()
liveDataQsRecordBean.value?.attachmentBeanList?.forEach {
//1 录音
if (it.type == 1) {
val chatMsgEntity = ChatMsgEntity()
chatMsgEntity.name = filePath.replace(Constant.USER_DATA_ATTACHEMNT_PATH, "").toString()
chatMsgEntity.name = it.name
chatMsgEntity.voiceUri = Constant.USER_DATA_ATTACHEMNT_PATH
chatMsgEntityList.add(chatMsgEntity)
var attachmentList: RealmList<AttachmentBean> = RealmList()
//赋值处理
if (liveDataQsRecordBean.value?.attachmentBeanList?.isEmpty() == false) {
attachmentList = liveDataQsRecordBean.value?.attachmentBeanList!!
}
val attachmentBean = AttachmentBean()
attachmentBean.name = chatMsgEntity.name!!
attachmentBean.type = 1
attachmentList.add(attachmentBean)
liveDataQsRecordBean.value?.attachmentBeanList = attachmentList
listDataChatMsgEntityList.postValue(chatMsgEntityList)
}
}
listDataChatMsgEntityList.postValue(chatMsgEntityList)
}
fun startSoundMetter(activity: Activity, v: View) {
fun addChatMsgEntity(filePath: String) {
if (mSpeakMode == null) {
mSpeakMode = SpeakMode(activity)
if (filePath.isNotEmpty()) {
var chatMsgEntityList: MutableList<ChatMsgEntity> = ArrayList()
if (listDataChatMsgEntityList.value?.isEmpty() == false) {
chatMsgEntityList = listDataChatMsgEntityList.value!!
}
val chatMsgEntity = ChatMsgEntity()
chatMsgEntity.name = filePath.replace(Constant.USER_DATA_ATTACHEMNT_PATH, "").toString()
chatMsgEntity.voiceUri = Constant.USER_DATA_ATTACHEMNT_PATH
chatMsgEntityList.add(chatMsgEntity)
var attachmentList: RealmList<AttachmentBean> = RealmList()
//赋值处理
if (liveDataQsRecordBean.value?.attachmentBeanList?.isEmpty() == false) {
attachmentList = liveDataQsRecordBean.value?.attachmentBeanList!!
}
//语音识别动画
if (pop == null) {
pop = PopupWindow()
pop!!.width = ViewGroup.LayoutParams.MATCH_PARENT
pop!!.height = ViewGroup.LayoutParams.WRAP_CONTENT
pop!!.setBackgroundDrawable(BitmapDrawable())
val view =
View.inflate(activity as Context, R.layout.cv_card_voice_rcd_hint_window, null)
pop!!.contentView = view
volume = view.findViewById(R.id.volume)
}
val attachmentBean = AttachmentBean()
attachmentBean.name = chatMsgEntity.name!!
attachmentBean.type = 1
attachmentList.add(attachmentBean)
liveDataQsRecordBean.value?.attachmentBeanList = attachmentList
pop!!.update()
listDataChatMsgEntityList.postValue(chatMsgEntityList)
}
}
Constant.IS_VIDEO_SPEED = true
//录音动画
if (pop != null) {
pop!!.showAtLocation(v, Gravity.CENTER, 0, 0)
}
volume!!.setBackgroundResource(R.drawable.pop_voice_img)
val animation = volume!!.background as AnimationDrawable
animation.start()
fun startSoundMetter(activity: Activity, v: View) {
val name: String = DateTimeUtil.getTimeSSS().toString() + ".m4a"
if (mSoundMeter == null) {
mSoundMeter = SoundMeter()
}
mSoundMeter!!.setmListener(object : SoundMeter.OnSoundMeterListener {
@RequiresApi(Build.VERSION_CODES.Q)
override fun onSuccess(filePath: String?) {
if (!TextUtils.isEmpty(filePath) && File(filePath).exists()) {
if (File(filePath) == null || File(filePath).length() < 1600) {
ToastUtils.showLong("语音时间太短,无效!")
mSpeakMode!!.speakText("语音时间太短,无效")
stopSoundMeter()
return
}
if (mSpeakMode == null) {
mSpeakMode = SpeakMode(activity)
}
//语音识别动画
if (pop == null) {
pop = PopupWindow()
pop!!.width = ViewGroup.LayoutParams.MATCH_PARENT
pop!!.height = ViewGroup.LayoutParams.WRAP_CONTENT
pop!!.setBackgroundDrawable(BitmapDrawable())
val view =
View.inflate(activity as Context, R.layout.cv_card_voice_rcd_hint_window, null)
pop!!.contentView = view
volume = view.findViewById(R.id.volume)
}
pop!!.update()
Constant.IS_VIDEO_SPEED = true
//录音动画
if (pop != null) {
pop!!.showAtLocation(v, Gravity.CENTER, 0, 0)
}
volume!!.setBackgroundResource(R.drawable.pop_voice_img)
val animation = volume!!.background as AnimationDrawable
animation.start()
val name: String = DateTimeUtil.getTimeSSS().toString() + ".m4a"
if (mSoundMeter == null) {
mSoundMeter = SoundMeter()
}
mSoundMeter!!.setmListener(object : SoundMeter.OnSoundMeterListener {
@RequiresApi(Build.VERSION_CODES.Q)
override fun onSuccess(filePath: String?) {
if (!TextUtils.isEmpty(filePath) && File(filePath).exists()) {
if (File(filePath) == null || File(filePath).length() < 1600) {
ToastUtils.showLong("语音时间太短,无效!")
mSpeakMode!!.speakText("语音时间太短,无效")
stopSoundMeter()
return
}
mSpeakMode!!.speakText("结束录音")
addChatMsgEntity(filePath!!)
}
@RequiresApi(api = Build.VERSION_CODES.Q)
override fun onfaild(message: String?) {
ToastUtils.showLong("录制失败!")
mSpeakMode!!.speakText("录制失败")
stopSoundMeter()
}
})
mSpeakMode!!.speakText("结束录音")
mSoundMeter!!.start(Constant.USER_DATA_ATTACHEMNT_PATH + name)
ToastUtils.showLong("开始录音")
mSpeakMode!!.speakText("开始录音")
}
//停止语音录制
@RequiresApi(api = Build.VERSION_CODES.Q)
fun stopSoundMeter() {
//先重置标识,防止按钮抬起时触发语音结束
Constant.IS_VIDEO_SPEED = false
if (mSoundMeter != null && mSoundMeter!!.isStartSound) {
mSoundMeter!!.stop()
addChatMsgEntity(filePath!!)
}
pop?.let {
if (it.isShowing) {
it.dismiss()
}
@RequiresApi(api = Build.VERSION_CODES.Q)
override fun onfaild(message: String?) {
ToastUtils.showLong("录制失败!")
mSpeakMode!!.speakText("录制失败")
stopSoundMeter()
}
})
mSoundMeter!!.start(Constant.USER_DATA_ATTACHEMNT_PATH + name)
ToastUtils.showLong("开始录音")
mSpeakMode!!.speakText("开始录音")
}
//停止语音录制
@RequiresApi(api = Build.VERSION_CODES.Q)
fun stopSoundMeter() {
//先重置标识,防止按钮抬起时触发语音结束
Constant.IS_VIDEO_SPEED = false
if (mSoundMeter != null && mSoundMeter!!.isStartSound) {
mSoundMeter!!.stop()
}
pop?.let {
if (it.isShowing) {
it.dismiss()
}
}
}
fun savePhoto(bitmap: Bitmap) {
viewModelScope.launch(Dispatchers.IO) {
// 创建一个名为 "MyApp" 的文件夹
val myAppDir = File(Constant.USER_DATA_ATTACHEMNT_PATH)
fun savePhoto(bitmap: Bitmap) {
viewModelScope.launch(Dispatchers.IO) {
// 创建一个名为 "MyApp" 的文件夹
val myAppDir = File(Constant.USER_DATA_ATTACHEMNT_PATH)
if (!myAppDir.exists()) myAppDir.mkdirs() // 确保文件夹已创建
// 创建一个名为 fileName 的文件
val file = File(myAppDir, "${UUID.randomUUID()}.png")
file.createNewFile() // 创建文件
// 创建一个名为 fileName 的文件
val file = File(myAppDir, "${UUID.randomUUID()}.png")
file.createNewFile() // 创建文件
// 将 Bitmap 压缩为 JPEG 格式,并将其写入文件中
val out = FileOutputStream(file)
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out)
out.flush()
out.close()
var picList = mutableListOf<String>()
if (liveDataPictureList.value == null) {
picList.add(file.absolutePath)
} else {
picList.addAll(liveDataPictureList.value!!)
picList.add(file.absolutePath)
}
liveDataPictureList.postValue(picList)
// 将 Bitmap 压缩为 JPEG 格式,并将其写入文件中
val out = FileOutputStream(file)
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out)
out.flush()
out.close()
var picList = mutableListOf<String>()
if (liveDataPictureList.value == null) {
picList.add(file.absolutePath)
} else {
picList.addAll(liveDataPictureList.value!!)
picList.add(file.absolutePath)
}
liveDataPictureList.postValue(picList)
}
}
@ -658,5 +660,5 @@ class EvaluationResultViewModel @Inject constructor(
}
}
}
}
}
}

View File

@ -7,7 +7,7 @@ import com.navinfo.omqs.databinding.TextItemSelectBinding
import com.navinfo.omqs.ui.other.BaseRecyclerViewAdapter
import com.navinfo.omqs.ui.other.BaseViewHolder
class LeftAdapter(private var itemListener: ((Int, String) -> Unit?)? = null) :
class LeftAdapter(private var itemListener: ((Int, ScProblemTypeBean) -> Unit?)? = null) :
BaseRecyclerViewAdapter<ScProblemTypeBean>() {
private var selectTitle = ""
@ -28,7 +28,7 @@ class LeftAdapter(private var itemListener: ((Int, String) -> Unit?)? = null) :
selectTitle = title.classType
notifyDataSetChanged()
}
itemListener?.invoke(position, title.classType)
itemListener?.invoke(position, title)
}
}

View File

@ -17,6 +17,7 @@ import com.github.k1rakishou.fsaf.callback.FSAFActivityCallbacks
import com.github.k1rakishou.fsaf.callback.FileChooserCallback
import com.navinfo.collect.library.data.entity.TaskBean
import com.navinfo.collect.library.map.NIMapController
import com.navinfo.omqs.Constant
import com.navinfo.omqs.R
import com.navinfo.omqs.databinding.FragmentPersonalCenterBinding
import com.navinfo.omqs.db.ImportOMDBHelper
@ -114,12 +115,18 @@ class PersonalCenterFragment(private var indoorDataListener: ((Boolean) -> Unit?
}
})
}
R.id.personal_center_menu_open_auto_location -> {
Constant.AUTO_LOCATION = true
}
R.id.personal_center_menu_close_auto_location -> {
Constant.AUTO_LOCATION = false
}
R.id.personal_center_menu_test -> {
viewModel.readRealmData()
//108.91056000267433 34.29635901721207
//108.90107116103331 34.29568928574205
// 定位到指定位置
niMapController.mMapView.vtmMap.animator()
.animateTo(GeoPoint( 34.29635901721207, 108.91056000267433))
.animateTo(GeoPoint( 34.29568928574205, 108.90107116103331))
}
// R.id.personal_center_menu_task_list -> {
// findNavController().navigate(R.id.TaskManagerFragment)

View File

@ -370,4 +370,5 @@ public class ShareUtil {
return null;
}
}

View File

@ -345,7 +345,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
app:constraint_referenced_ids="main_activity_snapshot_finish,main_activity_trace_snapshot_points,main_activity_snapshot_media_flag,main_activity_snapshot_rewind,main_activity_snapshot_pause,main_activity_snapshot_next" />
app:constraint_referenced_ids="main_activity_snapshot_finish,main_activity_trace_snapshot_points,main_activity_snapshot_rewind,main_activity_snapshot_pause,main_activity_snapshot_next" />
<ImageButton
android:id="@+id/main_activity_snapshot_finish"
@ -359,11 +359,12 @@
android:onClick="@{()->mainActivity.tracePointsOnclick()}"
android:src="@drawable/map_trace_select_point" />
<ImageButton
<!-- <ImageButton
android:id="@+id/main_activity_snapshot_media_flag"
style="@style/top_right_drawer_btns_style"
android:visibility="gone"
android:onClick="@{()->mainActivity.mediaFlagOnclick()}"
android:src="@drawable/map_trace_mediaflag" />
android:src="@drawable/map_trace_mediaflag" />-->
<ImageButton
android:id="@+id/main_activity_snapshot_rewind"
@ -380,6 +381,7 @@
<ImageButton
android:id="@+id/main_activity_snapshot_next"
style="@style/top_right_drawer_btns_style"
android:onClick="@{()->mainActivity.nextTraceOnclick()}"
android:src="@drawable/map_trace_next" />
<View

View File

@ -56,6 +56,18 @@
<!-- android:icon="@drawable/ic_baseline_layers_24"-->
<!-- android:title="图层管理" />-->
<item
android:id="@+id/personal_center_menu_open_auto_location"
android:icon="@drawable/baseline_person_24"
android:visible="true"
android:title="开启自动定位" />
<item
android:id="@+id/personal_center_menu_close_auto_location"
android:icon="@drawable/baseline_person_24"
android:visible="true"
android:title="关闭自动定位" />
<item
android:id="@+id/personal_center_menu_test"
android:icon="@drawable/baseline_person_24"

View File

@ -1707,48 +1707,56 @@
</m>0
<!-- 道路边界类型 -->
<m v="OMDB_RDBOUND_BOUNDARYTYPE">
<outline-layer id="boundaryType" stroke="#fcba5a" width="0.2" />
<outline-layer id="boundaryType" stroke="#8e44ad" width="0.2" />
<m k="boundaryType" v="0|2|3|4|5|6|7|8|9">
<line stroke="#ffffff" use="boundaryType" width="0.2"/>
</m>
<m k="boundaryType" v="1">
<!--无标线无可区分边界-->
<line dasharray="20,8" repeat-start="0" stroke="#ffffff" width="0.2"/>
</m>
<!-- <outline-layer id="boundaryType" stroke="#fcba5a" width="0.2" />
<m k="boundaryType" v="0">
<!--不应用-->
&lt;!&ndash;不应用&ndash;&gt;
<line stroke="#fcba5a" use="boundaryType"/>
<lineSymbol repeat-gap="12" repeat-start="12" symbol-height="16" symbol-width="16" src="assets:omdb/icon_2083_0.svg" />
</m>
<m k="boundaryType" v="1">
<!--无标线无可区分边界-->
&lt;!&ndash;无标线无可区分边界&ndash;&gt;
<line dasharray="10,2,2,2,2,2,2,2" repeat-start="0" stroke="#fcba5a" width="0.2" />
</m>
<m k="boundaryType" v="2">
<!--标线-->
&lt;!&ndash;标线&ndash;&gt;
<line stroke="#fcba5a" use="boundaryType"/>
</m>
<m k="boundaryType" v="3">
<!--路牙-->
&lt;!&ndash;路牙&ndash;&gt;
<line dasharray="10,4" repeat-start="0" stroke="#fcba5a" width="0.2" />
</m>
<m k="boundaryType" v="4">
<!--护栏-->
&lt;!&ndash;护栏&ndash;&gt;
<line dasharray="10,2,2,2" repeat-start="0" stroke="#fcba5a" width="0.2"/>
</m>
<m k="boundaryType" v="5">
<!---->
&lt;!&ndash;&ndash;&gt;
<line stroke="#fcba5a" use="boundaryType"/>
<line dasharray="10,5" stroke="#fcba5a" width="0.5" />
</m>
<m k="boundaryType" v="6">
<!--道路面铺设边缘-->
&lt;!&ndash;道路面铺设边缘&ndash;&gt;
<line stroke="#fcba5a" use="boundaryType"/>
<lineSymbol repeat-gap="32" repeat-start="0" symbol-height="32" src="assets:omdb/icon_2083_6.svg" />
</m>
<m k="boundaryType" v="7">
<!--虚拟三角岛-->
&lt;!&ndash;虚拟三角岛&ndash;&gt;
<line stroke="#fcba5a" use="boundaryType"/>
<line src="assets:omdb/icon_2083_7_1.svg" symbol-height="12" symbol-width="12" symbol-percent="20" width="1" />
</m>
<m k="boundaryType" v="9">
<!--杆状障碍物-->
&lt;!&ndash;杆状障碍物&ndash;&gt;
<line stroke="#fcba5a" use="boundaryType"/>
<lineSymbol repeat-gap="16" repeat-start="12" symbol-height="24" symbol-width="8" src="assets:omdb/icon_2083_9.svg" />
</m>
</m>-->
</m>
<!-- 车道边界类型 -->
<m v="OMDB_LANE_MARK_BOUNDARYTYPE">
@ -1758,13 +1766,13 @@
<m v="2">
<m k="markType">
<!--其他|实线-->
<m v="0|1">
<m v="0|1|2|3|4|5|6|7|8">
<m k="markColor">
<m v="0|1">
<m v="1">
<line stroke="#ffffff" use="boundaryType" />
</m>
<m v="2">
<line stroke="#eccc68" use="boundaryType" />
<line dasharray="10,2,2,2,2,2,2,2" repeat-start="0" stroke="#eccc68" use="boundaryType" />
</m>
<m v="6">
<line stroke="#0000ff" use="boundaryType" />
@ -1772,12 +1780,12 @@
<m v="7">
<line stroke="#00ff00" use="boundaryType" />
</m>
<m v="9">
<m v="0|9">
<line stroke="#8e44ad" use="boundaryType" />
</m>
</m>
</m>
<!--虚线-->
<!-- &lt;!&ndash;虚线&ndash;&gt;
<m v="2">
<m k="markColor">
<m v="0|1">
@ -1802,18 +1810,21 @@
</m>
</m>
</m>
<!--导流区边线-->
&lt;!&ndash;导流区边线&ndash;&gt;
<m v="4">
<line outline="boundary" stroke="#545D6C"></line>
<lineSymbol repeat-gap="0.5" repeat-start="0"
src="assets:omdb/icon_right.png" />
</m>
<!-- &lt;!&ndash;铺设路面边缘&ndash;&gt;-->
<!-- <m v="5">-->
<!-- <line outline="#ffffff" fix="true" src="assets:omdb/icon_close.png" stroke="#ffffffff" use="boundaryType"/>-->
<!-- </m>-->
</m>-->
</m>
</m>
<m v="0|3|4|5|6|7|8|9">
<line stroke="#ffffff" use="boundaryType" />
</m>
<!--只区分虚线与实线-->
<m v="1">
<line dasharray="20,8" repeat-start="0" stroke="#ffffff" width="0.2"/>
</m>
</m>
</m>

View File

@ -47,6 +47,9 @@ public interface INiLocationDao {
@Query("SELECT * FROM niLocation")
List<NiLocation> findAll();
@Query("SELECT * FROM niLocation where time>=:startTime and time<=:endTime and taskId=:taskId")
List<NiLocation> taskIdAndTimeTofindList(String taskId,long startTime,long endTime);
@Query("SELECT * FROM niLocation where taskId =:taskId")
List<NiLocation> findToTaskIdAll(String taskId);
}

View File

@ -14,7 +14,7 @@ import java.util.UUID;
* @Date 2022/4/14
* @Description: ${TODO}(数据基类)
*/
public class Feature implements Serializable, Cloneable {
public class Feature extends Object implements Serializable, Cloneable {
// //主键
// @PrimaryKey(autoGenerate = true)
// public int rowId;

View File

@ -30,7 +30,7 @@ class LocationLayerHandler(context: AppCompatActivity, mapView: NIMapView) :
//
// }
val niLocationFlow = MutableSharedFlow<NiLocation>(3)
val niLocationFlow = MutableSharedFlow<NiLocation>(5)
init {
///添加定位图层到地图,[NIMapView.LAYER_GROUPS.NAVIGATION] 是最上层layer组
@ -67,18 +67,12 @@ class LocationLayerHandler(context: AppCompatActivity, mapView: NIMapView) :
val errorCode = it.locType
mCurrentLocation = it
mLocationLayer.setPosition(it.latitude, it.longitude, it.radius)
// Log.e(
// "qj",
// "location==${it.longitude}==errorCode===$errorCode===${it.locTypeDescription}"
// )
Log.e("qj", "location==${it.longitude}==errorCode===$errorCode===${it.locTypeDescription}")
// if (niLocationListener != null) {
getCurrentNiLocation()?.let { it1 ->
mContext.lifecycleScope.launch(Dispatchers.Default) {
mContext.lifecycleScope.launch {
niLocationFlow.emit(it1)
}
// }// niLocationListener.call(it1) }
}
//第一次定位成功显示当前位置
if (this.bFirst) {

View File

@ -4,7 +4,6 @@ import android.content.Context
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.Color
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.res.ResourcesCompat
import com.navinfo.collect.library.R
@ -197,6 +196,7 @@ class MarkHandler(context: AppCompatActivity, mapView: NIMapView) :
if (listener is OnNiLocationItemListener) {
listener.onNiLocation(
tag,
index,
(niLocationItemizedLayer.itemList[index] as MarkerItem).uid as NiLocation
)
break
@ -211,6 +211,7 @@ class MarkHandler(context: AppCompatActivity, mapView: NIMapView) :
}
})
addLayer(layer, NIMapView.LAYER_GROUPS.OPERATE_MARKER)
layer
}
@ -287,7 +288,8 @@ class MarkHandler(context: AppCompatActivity, mapView: NIMapView) :
fun addMarker(
geoPoint: GeoPoint,
title: String?,
description: String? = ""
description: String? = "",
uid: java.lang.Object? = null,
) {
var marker: MarkerItem? = null
for (e in mDefaultMarkerLayer.itemList) {
@ -302,6 +304,7 @@ class MarkHandler(context: AppCompatActivity, mapView: NIMapView) :
tempTitle = StringUtil.createUUID()
}
val marker = MarkerItem(
uid,
tempTitle,
description,
geoPoint
@ -317,6 +320,14 @@ class MarkHandler(context: AppCompatActivity, mapView: NIMapView) :
}
}
fun getCurrentMark(): MarkerInterface? {
if (mDefaultMarkerLayer != null) {
return mDefaultMarkerLayer.itemList[mDefaultMarkerLayer.itemList.size - 1]
}
return null
}
/**
* 移除marker
*/
@ -484,70 +495,61 @@ class MarkHandler(context: AppCompatActivity, mapView: NIMapView) :
/**
* 添加质检数据marker
*/
public suspend fun addNiLocationMarkerItem(niLocation: NiLocation) {
fun addNiLocationMarkerItem(niLocation: NiLocation) {
synchronized(this) {
Log.e("jingo", "插入定位点0 ")
var itemizedLayer: ItemizedLayer? = null
val direction: Double = niLocation.direction
val geoMarkerItem: MarkerItem = ClusterMarkerItem(
niLocation,
niLocation.id,
niLocation.time,
GeoPoint(niLocation.latitude, niLocation.longitude)
)
//角度
when (niLocation.media) {
0 -> {
//角度不为0时需要预先设置marker样式并进行角度设置否则使用图层默认的sym即可
//角度不为0时需要预先设置marker样式并进行角度设置否则使用图层默认的sym即可
if (direction != 0.0) {
val symbolGpsTemp =
MarkerSymbol(niLocationBitmap, MarkerSymbol.HotspotPlace.CENTER, false)
geoMarkerItem.marker = symbolGpsTemp
geoMarkerItem.setRotation(direction.toFloat())
} else {
val symbolGpsTemp =
MarkerSymbol(niLocationBitmap2, MarkerSymbol.HotspotPlace.CENTER, false)
geoMarkerItem.marker = symbolGpsTemp
}
Log.e(
"jingo",
"插入定位点1 ${geoMarkerItem.geoPoint.longitude} ${geoMarkerItem.geoPoint.latitude}"
)
niLocationItemizedLayer.addItem(geoMarkerItem)
itemizedLayer = niLocationItemizedLayer
}
1 -> {
//角度不为0时需要预先设置marker样式并进行角度设置否则使用图层默认的sym即可
//角度不为0时需要预先设置marker样式并进行角度设置否则使用图层默认的sym即可
if (direction != 0.0) {
val symbolLidarTemp =
MarkerSymbol(niLocationBitmap1, MarkerSymbol.HotspotPlace.CENTER, false)
geoMarkerItem.marker = symbolLidarTemp
geoMarkerItem.setRotation(direction.toFloat())
} else {
val symbolGpsTemp =
MarkerSymbol(niLocationBitmap3, MarkerSymbol.HotspotPlace.CENTER, false)
geoMarkerItem.marker = symbolGpsTemp
}
Log.e(
"jingo",
"插入定位点2 ${geoMarkerItem.geoPoint.longitude} ${geoMarkerItem.geoPoint.latitude}"
)
niLocationItemizedLayer.addItem(geoMarkerItem)
itemizedLayer = niLocationItemizedLayer
}
}
itemizedLayer?.update()
var geoMarkerItem = createNILocationBitmap(niLocation)
niLocationItemizedLayer.addItem(geoMarkerItem)
niLocationItemizedLayer.update()
}
}
private fun createNILocationBitmap(niLocation: NiLocation): MarkerItem {
val direction: Double = niLocation.direction
val geoMarkerItem: MarkerItem = ClusterMarkerItem(
niLocation,
niLocation.id,
niLocation.time,
GeoPoint(niLocation.latitude, niLocation.longitude)
)
//角度
when (niLocation.media) {
0 -> {
//角度不为0时需要预先设置marker样式并进行角度设置否则使用图层默认的sym即可
//角度不为0时需要预先设置marker样式并进行角度设置否则使用图层默认的sym即可
if (direction > 0.0) {
val symbolGpsTemp =
MarkerSymbol(niLocationBitmap, MarkerSymbol.HotspotPlace.CENTER, false)
geoMarkerItem.marker = symbolGpsTemp
geoMarkerItem.setRotation(direction.toFloat())
} else {
val symbolGpsTemp =
MarkerSymbol(niLocationBitmap2, MarkerSymbol.HotspotPlace.CENTER, false)
geoMarkerItem.marker = symbolGpsTemp
}
}
1 -> {
//角度不为0时需要预先设置marker样式并进行角度设置否则使用图层默认的sym即可
//角度不为0时需要预先设置marker样式并进行角度设置否则使用图层默认的sym即可
if (direction > 0.0) {
val symbolLidarTemp =
MarkerSymbol(niLocationBitmap1, MarkerSymbol.HotspotPlace.CENTER, false)
geoMarkerItem.marker = symbolLidarTemp
geoMarkerItem.setRotation(direction.toFloat())
} else {
val symbolGpsTemp =
MarkerSymbol(niLocationBitmap3, MarkerSymbol.HotspotPlace.CENTER, false)
geoMarkerItem.marker = symbolGpsTemp
}
}
}
return geoMarkerItem
}
/**
* 文字和图片拼装文字换行
@ -775,6 +777,38 @@ class MarkHandler(context: AppCompatActivity, mapView: NIMapView) :
mMapView.updateMap(true)
}
fun getNILocationItemizedLayerSize(): Int {
return niLocationItemizedLayer.itemList.size
}
fun getNILocation(index: Int): NiLocation? {
return if (index > -1 && index < getNILocationItemizedLayerSize()) {
((niLocationItemizedLayer.itemList[index]) as MarkerItem).uid as NiLocation
} else {
null
}
}
fun getNILocationIndex(niLocation: NiLocation): Int? {
var list = niLocationItemizedLayer.itemList
if (niLocation != null && list.isNotEmpty()) {
var index = -1
list.forEach {
index += 1
if (((it as MarkerItem).uid as NiLocation).id.equals(niLocation.id)) {
return index
}
}
}
return -1
}
}
interface OnQsRecordItemClickListener : BaseClickListener {
@ -786,5 +820,5 @@ interface ONNoteItemClickListener : BaseClickListener {
}
interface OnNiLocationItemListener : BaseClickListener {
fun onNiLocation(tag: String, it: NiLocation)
fun onNiLocation(tag: String, index: Int, it: NiLocation)
}

2
vtm

@ -1 +1 @@
Subproject commit 1ee201a41f78f169873848209a3f3bdac36f185a
Subproject commit dd13e533c38b5738ab404c2737d7ccadeff01323