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

This commit is contained in:
2023-04-24 17:21:31 +08:00
55 changed files with 1346 additions and 648 deletions

View File

@@ -22,13 +22,26 @@ class Constant {
/**
* 当前用户ID
*/
lateinit var CURRENT_USER_ID: String
lateinit var USER_ID: String
//数据版本
lateinit var VERSION_ID: String
/**
* 用户数据目录
*/
lateinit var USER_DATA_PATH: String
/**
* 离线地图目录
*/
lateinit var OFFLINE_MAP_PATH: String
/**
* 下载目录
*/
lateinit var DOWNLOAD_PATH: String
/**
* 服务器地址
*/
@@ -41,6 +54,28 @@ class Constant {
const val message_version_right_off = "1" //立即发送
const val MESSAGE_PAGE_SIZE = 30 //消息列表一页最多数量
lateinit var realm: Realm
//选择相机默认或者外设
const val SELECT_CAMERA_STATE = "select_camera_state"
//是否连接
const val CAMERA_CONNECT_STATE = "camera_connect_state"
//是否可以点击
const val CAMERA_CLICK_STATE = "camera_click_state"
//拍照模式
const val TAKE_CAMERA_MODE = "take_camera_mode"
const val TAKE_CAMERA_IP = "take_camera_ip"
const val TAKE_CAMERA_MAC = "take_camera_mac"
//选择拍照或者录像
const val SELECT_TAKEPHOTO_OR_RECORD = "select_takephoto_or_record"
const val OMDB_CONFIG = "omdb.config"
}

View File

@@ -1,16 +1,11 @@
package com.navinfo.omqs
import android.app.Application
import android.util.Log
import com.navinfo.omqs.db.MyRealmModule
import com.navinfo.omqs.tools.FileManager
import com.navinfo.omqs.ui.manager.TakePhotoManager
import com.navinfo.omqs.util.NetUtils
import dagger.hilt.android.HiltAndroidApp
import org.videolan.vlc.Util
import io.realm.Realm
import io.realm.RealmConfiguration
import java.io.File
import java.security.MessageDigest
@HiltAndroidApp

View File

@@ -2,7 +2,6 @@ package com.navinfo.omqs.bean
import com.google.gson.annotations.SerializedName
import com.navinfo.omqs.Constant
import com.navinfo.omqs.system.SystemConstant
import com.navinfo.omqs.tools.FileManager.Companion.FileDownloadStatus
import io.realm.RealmList
import io.realm.RealmObject

View File

@@ -36,7 +36,7 @@ class ImportOMDBHelper @AssistedInject constructor(@Assisted("context") val cont
@Inject
lateinit var gson: Gson
private val database by lazy { omdbHiltFactory.obtainOmdbDataBaseHelper(context, omdbFile.absolutePath, 1).writableDatabase }
private val configFile: File = File("${Constant.DATA_PATH}/${Constant.CURRENT_USER_ID}", Constant.OMDB_CONFIG)
private val configFile: File = File("${Constant.USER_DATA_PATH}", Constant.OMDB_CONFIG)
/**
* 读取config的配置文件

View File

@@ -104,13 +104,13 @@ class TaskDownloadScope(
var randomAccessFile: RandomAccessFile? = null
try {
//创建离线地图 下载文件夹,.map文件夹的下一级
val fileDir = File("${Constant.OFFLINE_MAP_PATH}download")
val fileDir = File("${Constant.DOWNLOAD_PATH}download")
if (!fileDir.exists()) {
fileDir.mkdirs()
}
val fileTemp =
File("${Constant.OFFLINE_MAP_PATH}download/${taskBean.id}_${taskBean.dataVersion}")
File("${Constant.DOWNLOAD_PATH}${taskBean.id}_${taskBean.dataVersion}")
val startPosition = taskBean.currentSize
//验证断点有效性
if (startPosition < 0) throw IOException("jingo Start position less than zero")
@@ -119,8 +119,13 @@ class TaskDownloadScope(
url = taskBean.getDownLoadUrl()
)
val responseBody = response.body()
change(FileDownloadStatus.LOADING)
responseBody ?: throw IOException("jingo ResponseBody is null")
if (startPosition == 0L) {
taskBean.fileSize = responseBody.contentLength()
}
//写入文件
randomAccessFile = RandomAccessFile(fileTemp, "rwd")
randomAccessFile.seek(startPosition)
@@ -144,7 +149,7 @@ class TaskDownloadScope(
Log.e("jingo", "文件下载完成 ${taskBean.currentSize} == ${taskBean.fileSize}")
if (taskBean.currentSize == taskBean.fileSize) {
val res =
fileTemp.renameTo(File("${Constant.OFFLINE_MAP_PATH}${taskBean.evaluationTaskName}.zip"))
fileTemp.renameTo(File("${Constant.DOWNLOAD_PATH}${taskBean.evaluationTaskName}.zip"))
Log.e("jingo", "文件下载完成 修改文件 $res")
change(FileDownloadStatus.DONE)
} else {

View File

@@ -1,42 +0,0 @@
package com.navinfo.omqs.system;
import java.util.UUID;
/**
* 系统变量对象
*/
public class SystemConstant {
public static String USER_ID = "1";
//选择相机默认或者外设
public static String SELECT_CAMERA_STATE = "select_camera_state";
//是否连接
public static String CAMERA_CONNECT_STATE = "camera_connect_state";
//是否可以点击
public static String CAMERA_CLICK_STATE = "camera_click_state";
//拍照模式
public static String TAKE_CAMERA_MODE = "take_camera_mode";
public static String TAKE_CAMERA_IP = "take_camera_ip";
public static String TAKE_CAMERA_MAC = "take_camera_mac";
//选择拍照或者录像
public static String SELECT_TAKEPHOTO_OR_RECORD = "select_takephoto_or_record";
/**
* 获取uuid
* @param isUpperCase
* true 大写 false 小写
*/
public static String getUuid(boolean isUpperCase){
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
if(isUpperCase)
uuid = uuid.toUpperCase();
return uuid;
}
}

View File

@@ -3,6 +3,7 @@ package com.navinfo.omqs.tools
import android.content.Context
import com.navinfo.omqs.Constant
import com.navinfo.omqs.bean.OfflineMapCityBean
import com.navinfo.omqs.bean.TaskBean
import java.io.File
class FileManager {
@@ -20,13 +21,14 @@ class FileManager {
}
//初始化数据文件夹
fun initRootDir(context:Context){
fun initRootDir(context: Context) {
// 在SD卡创建项目目录
val sdCardPath = context.getExternalFilesDir(null)
sdCardPath?.let {
Constant.ROOT_PATH = sdCardPath.absolutePath
Constant.MAP_PATH = Constant.ROOT_PATH + "/map/"
Constant.OFFLINE_MAP_PATH = Constant.MAP_PATH + "offline/"
Constant.DOWNLOAD_PATH = Constant.ROOT_PATH + "/download/"
val file = File(Constant.MAP_PATH)
if (!file.exists()) {
file.mkdirs()
@@ -37,7 +39,7 @@ class FileManager {
with(File(Constant.DATA_PATH)) {
if (!this.exists()) this.mkdirs()
}
}else{
} else {
Constant.DATA_PATH = Constant.ROOT_PATH + "/data/"
}
}
@@ -102,5 +104,65 @@ class FileManager {
}
}
}
/**
* 检查离线地图文件
*/
suspend fun checkOMDBFileInfo(taskBean: TaskBean) {
//访问离线地图文件夹
val fileDir = File("${Constant.DOWNLOAD_PATH}")
//如果连本地文件夹还没有,就不用修改任何数据了
if (!fileDir.exists()) {
return
}
//访问离线地图临时下载文件夹
val fileTempDir = File(Constant.DOWNLOAD_PATH)
//是否有一份.map文件了
var mapFile: File? = null
//文件夹里文件挨个访问
for (item in fileDir.listFiles()) {
//先找到对应的省市文件例如540000_西藏自治区_20230401195018.map",以id开头
if (item.isFile && item.name.startsWith("${taskBean.id}_")) {
//如果本地文件与从网络获取到版本号一致,表示这个文件已经下载完毕,不用处理了
if (item.name == "${taskBean.id}_${taskBean.dataVersion}") {
taskBean.status = FileDownloadStatus.DONE
return
}
//文件存在,版本号不对应,留给下面流程处理
mapFile = item
break
}
}
//临时下载文件夹
if (fileTempDir.exists()) {
for (item in fileTempDir.listFiles()) {
//先找到对应的省市文件例如540000_20230401195018",以id开头
if (item.isFile && item.name.startsWith("${taskBean.id}_")) {
//如果本地文件与从网络获取到版本号一致,表示这个文件已经在下载列表中
if (item.name == "${taskBean.id}_${taskBean.dataVersion}") {
//如果这个临时文件的大小和下载大小是一致的,说明已经下载完了,但是在下载环节没有更名移动成功,需要重命名和移动文件夹
if (item.length() == taskBean.fileSize) {
//移动更名文件后删除旧数据,修改状态
if (item.renameTo(File("${Constant.OFFLINE_MAP_PATH}${taskBean.evaluationTaskName}.zip"))) {
//删除旧版本数据
mapFile?.delete()
taskBean.status = FileDownloadStatus.DONE
return
}
} else { // 临时文件大小和目标不一致,说明下载了一半
taskBean.status = FileDownloadStatus.PAUSE
taskBean.currentSize = item.length()
return
}
} else { //虽然省市id开头一致但是版本号不一致说明之前版本下载了一部分现在要更新了原来下载的文件直接删除
taskBean.status = FileDownloadStatus.UPDATE
item.delete()
return
}
break
}
}
}
}
}
}

View File

@@ -18,8 +18,8 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import io.realm.Realm
import io.realm.RealmConfiguration
import kotlinx.coroutines.*
import okio.IOException
import java.io.File
import java.io.IOException
import javax.inject.Inject
enum class LoginStatus {
@@ -154,11 +154,12 @@ class LoginViewModel @Inject constructor(
/**
* 创建用户目录
*/
@Throws(IOException::class)
private fun createUserFolder(context: Context, userId: String) {
Constant.USER_ID = userId
Constant.VERSION_ID = userId
Constant.USER_DATA_PATH = Constant.DATA_PATH + Constant.USER_ID + "/" + Constant.VERSION_ID
// 在SD卡创建用户目录解压资源等
val userFolder = File("${Constant.DATA_PATH}/${userId}")
Constant.CURRENT_USER_ID = userId
// 初始化Realm
Realm.init(context.applicationContext)
val password = "encryp".encodeToByteArray().copyInto(ByteArray(64))

View File

@@ -14,10 +14,7 @@ import com.navinfo.omqs.Constant
import com.navinfo.omqs.R
import com.navinfo.omqs.databinding.ActivityMainBinding
import com.navinfo.omqs.http.offlinemapdownload.OfflineMapDownloadManager
import com.navinfo.omqs.system.SystemConstant
import com.navinfo.omqs.ui.activity.BaseActivity
import com.navinfo.omqs.ui.fragment.evaluationresult.EvaluationResultFragment
import com.navinfo.omqs.ui.fragment.evaluationresult.EvaluationResultViewModel
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
@@ -48,7 +45,7 @@ class MainActivity : BaseActivity() {
binding.mainActivityMap,
null,
Constant.MAP_PATH,
Constant.DATA_PATH+ SystemConstant.USER_ID+"/trace.sqlite"
Constant.USER_DATA_PATH+"/trace.sqlite"
)
//关联生命周期
binding.lifecycleOwner = this
@@ -71,8 +68,9 @@ class MainActivity : BaseActivity() {
mapController.locationLayerHandler.startLocation()
//启动轨迹存储
mapController.locationLayerHandler.setNiLocationListener(NiLocationListener {
viewModel.addSaveTrace(it)
// binding.viewModel!!.startSaveTraceThread(this)
ToastUtils.showLong("定位${it.longitude}")
binding!!.viewModel!!.addSaveTrace(it)
binding!!.viewModel!!.startSaveTraceThread(this)
})
//显示轨迹图层
// mapController.layerManagerHandler.showNiLocationLayer(Constant.DATA_PATH+ SystemConstant.USER_ID+"/trace.sqlite")
@@ -106,9 +104,8 @@ class MainActivity : BaseActivity() {
* 打开相机预览
*/
fun openCamera() {
binding.viewModel!!.onClickCameraButton(this)
//显示轨迹图层
//binding!!.viewModel!!.onClickCameraButton(this)
binding!!.viewModel!!.onClickCameraButton(this)
}
/**

View File

@@ -16,7 +16,6 @@ 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.system.SystemConstant
import com.navinfo.omqs.ui.dialog.CommonDialog
import com.navinfo.omqs.ui.manager.TakePhotoManager
import dagger.hilt.android.lifecycle.HiltViewModel
@@ -39,7 +38,7 @@ class MainViewModel @Inject constructor(
private var niLocationList: MutableList<NiLocation> = ArrayList<NiLocation>()
init {
mapController.layerManagerHandler.setOnQsRecordItemClickListener(object :
mapController.markerHandle.setOnQsRecordItemClickListener(object :
OnQsRecordItemClickListener {
override fun onQsRecordList(list: MutableList<String>) {
liveDataQsRecordIdList.value = list
@@ -122,7 +121,7 @@ class MainViewModel @Inject constructor(
TraceDataBase.getDatabase(
context,
Constant.DATA_PATH + SystemConstant.USER_ID + "/trace.sqlite"
Constant.USER_DATA_PATH + "/trace.sqlite"
).niLocationDao.insert(niLocation)
niLocationList.removeAt(0)
Log.e("qj", "saveTrace")

View File

@@ -36,11 +36,10 @@ import com.navinfo.collect.library.garminvirbxe.SensorParams;
import com.navinfo.collect.library.garminvirbxe.HostBean;
import com.navinfo.omqs.Constant;
import com.navinfo.omqs.R;
import com.navinfo.omqs.system.SystemConstant;
import com.navinfo.omqs.system.SystemDateTime;
import com.navinfo.omqs.ui.activity.map.MainActivity;
import com.navinfo.omqs.ui.manager.TakePhotoManager;
import com.navinfo.omqs.ui.other.BaseToast;
import com.navinfo.omqs.util.DateTimeUtil;
import com.navinfo.omqs.util.FileUtils;
import com.navinfo.omqs.util.NetUtils;
import com.navinfo.omqs.util.ShareUtil;
@@ -282,13 +281,13 @@ public class CommonDialog extends Dialog implements SurfaceHolder.Callback, IVid
Log.e("AAA", "连接中");
connectstate = false;
mShareUtil.setConnectstate(SystemConstant.USER_ID, connectstate);
mShareUtil.setConnectstate(Constant.USER_ID, connectstate);
mOneBtConnect.setText("连接中");
updateCameraResources(2, getmDeviceNum());
} else {
connectstate = false;
mShareUtil.setConnectstate(SystemConstant.USER_ID, connectstate);
mShareUtil.setConnectstate(Constant.USER_ID, connectstate);
click_state = true;
mOneBtConnect.setEnabled(click_state);
@@ -357,11 +356,11 @@ public class CommonDialog extends Dialog implements SurfaceHolder.Callback, IVid
Message msg = new Message();
String picPath = Constant.DATA_PATH + "/" + SystemConstant.USER_ID + "/pic.jpg";
String picPath = Constant.DATA_PATH + "/" + Constant.USER_ID + "/pic.jpg";
//创建目录
if(!new File(Constant.DATA_PATH + "/" + SystemConstant.USER_ID).exists()){
new File(Constant.DATA_PATH + "/" + SystemConstant.USER_ID).mkdirs();
if(!new File(Constant.DATA_PATH + "/" + Constant.USER_ID).exists()){
new File(Constant.DATA_PATH + "/" + Constant.USER_ID).mkdirs();
}
//多次获取照片信息,解决概率事件无法获取有效照片问题
@@ -376,7 +375,7 @@ public class CommonDialog extends Dialog implements SurfaceHolder.Callback, IVid
Log.e("AAA", "获取单张拍照时间" + time+"次数"+i);
if (!TextUtils.isEmpty(time)) {
long picTime = SystemDateTime.getPicTime(time);
long picTime = DateTimeUtil.getPicTime(time);
long disTime = mStartCheckTime - picTime / 1000;
@@ -482,7 +481,7 @@ public class CommonDialog extends Dialog implements SurfaceHolder.Callback, IVid
updateCameraResources(0, getmDeviceNum());
connectstate = true;
mShareUtil.setConnectstate(SystemConstant.USER_ID, connectstate);
mShareUtil.setConnectstate(Constant.USER_ID, connectstate);
stopVideo();
mOneBtConnect.setPressed(true);
mOneBtConnect.setBackgroundResource(R.drawable.btn_red_disconnect_bg);
@@ -614,7 +613,7 @@ public class CommonDialog extends Dialog implements SurfaceHolder.Callback, IVid
mGpsTv.setText("相机GPS信号差请稍等片刻或将相机移到开发地带。");
mGpsTv.setVisibility(View.VISIBLE);
mStartOrEndTakePicture.setEnabled(status);
mShareUtil.setContinusTakePhotoState(SystemConstant.USER_ID, true);
mShareUtil.setContinusTakePhotoState(Constant.USER_ID, true);
}
}
@@ -778,7 +777,7 @@ public class CommonDialog extends Dialog implements SurfaceHolder.Callback, IVid
ImageView ivStatus = (ImageView) findViewById(resId);
if (ivStatus != null) {
String time = SystemDateTime.getDateSimpleTime(SystemDateTime.getTimeInfo(SystemDateTime.getTime()) - 0/*MainActivity.disGoogleTime*/);
String time = DateTimeUtil.getDateSimpleTime(DateTimeUtil.getTimeInfo(DateTimeUtil.getTime()) - 0/*MainActivity.disGoogleTime*/);
ivStatus.setImageDrawable(null);
@@ -810,7 +809,7 @@ public class CommonDialog extends Dialog implements SurfaceHolder.Callback, IVid
if (connectstate) {
Log.i("chentao", "打开/结束连拍:" + arg1);
mShareUtil.setContinusTakePhotoState(SystemConstant.USER_ID, arg1);
mShareUtil.setContinusTakePhotoState(Constant.USER_ID, arg1);
if (!arg1) {
@@ -829,7 +828,7 @@ public class CommonDialog extends Dialog implements SurfaceHolder.Callback, IVid
mStartOrEndTakePicture.setChecked(true);
mShareUtil.setContinusTakePhotoState(SystemConstant.USER_ID, true);
mShareUtil.setContinusTakePhotoState(Constant.USER_ID, true);
BaseToast.makeText(context, "外接相机没有连接成功!不能进行连续拍照!", Toast.LENGTH_SHORT).show();
}
@@ -845,9 +844,9 @@ public class CommonDialog extends Dialog implements SurfaceHolder.Callback, IVid
connectstate = false;
mShareUtil.setContinusTakePhotoState(SystemConstant.USER_ID, true);
mShareUtil.setContinusTakePhotoState(Constant.USER_ID, true);
mShareUtil.setConnectstate(SystemConstant.USER_ID, connectstate);
mShareUtil.setConnectstate(Constant.USER_ID, connectstate);
mStartOrEndTakePicture.setChecked(true);
@@ -908,10 +907,10 @@ public class CommonDialog extends Dialog implements SurfaceHolder.Callback, IVid
public void onCheckedChanged(CompoundButton arg0, boolean arg1) {
if (connectstate) {
Log.i("chentao", "选择相机:" + arg1);
mShareUtil.setSelectCameraKind(SystemConstant.USER_ID, arg1);
mShareUtil.setSelectCameraKind(Constant.USER_ID, arg1);
} else {
mSelectCamera.setChecked(false);
mShareUtil.setSelectCameraKind(SystemConstant.USER_ID, false);
mShareUtil.setSelectCameraKind(Constant.USER_ID, false);
BaseToast.makeText(context, "外接相机没有连接成功!只能使用系统相机,谢谢!", Toast.LENGTH_SHORT).show();
}
}
@@ -962,7 +961,7 @@ public class CommonDialog extends Dialog implements SurfaceHolder.Callback, IVid
}
//重置拍照按钮
mShareUtil.setContinusTakePhotoState(SystemConstant.USER_ID, true);
mShareUtil.setContinusTakePhotoState(Constant.USER_ID, true);
}
//设置另外一台相机状态
@@ -980,11 +979,11 @@ public class CommonDialog extends Dialog implements SurfaceHolder.Callback, IVid
}
shareUtilOther.setSelectTakePhotoOrRecord(SystemConstant.USER_ID, !isCheck);
shareUtilOther.setSelectTakePhotoOrRecord(Constant.USER_ID, !isCheck);
shareUtilOther.setContinusTakePhotoState(SystemConstant.USER_ID, true);
shareUtilOther.setContinusTakePhotoState(Constant.USER_ID, true);
mShareUtil.setSelectTakePhotoOrRecord(SystemConstant.USER_ID, isCheck);
mShareUtil.setSelectTakePhotoOrRecord(Constant.USER_ID, isCheck);
if (isCheck) {
@@ -993,18 +992,18 @@ public class CommonDialog extends Dialog implements SurfaceHolder.Callback, IVid
takephotoManager.setCameraMode(getmDeviceNum(), SensorWorkingMode.CAMERA_VEDIO_TIMELAPSE);
mShareUtil.setTakeCameraMode(SystemConstant.USER_ID, 0);
mShareUtil.setTakeCameraMode(Constant.USER_ID, 0);
shareUtilOther.setTakeCameraMode(SystemConstant.USER_ID, 1);
shareUtilOther.setTakeCameraMode(Constant.USER_ID, 1);
} else {
mTakePhotoOrRecord.setText("拍照");
setmImgViewImageDrawable(1);
mShareUtil.setTakeCameraMode(SystemConstant.USER_ID, 1);
mShareUtil.setTakeCameraMode(Constant.USER_ID, 1);
shareUtilOther.setTakeCameraMode(SystemConstant.USER_ID, 0);
shareUtilOther.setTakeCameraMode(Constant.USER_ID, 0);
takephotoManager.setCameraMode(getmDeviceNum(), SensorWorkingMode.CAMEAR_PHOTO_CONTINUOUS_PHOTO);
@@ -1074,7 +1073,7 @@ public class CommonDialog extends Dialog implements SurfaceHolder.Callback, IVid
BaseToast.makeText(context, TextUtils.isEmpty(msg) ? "相机丢失连接,请检查网络是否畅通!" : msg, Toast.LENGTH_SHORT).show();
connectstate = false;
mShareUtil.setConnectstate(SystemConstant.USER_ID, connectstate);
mShareUtil.setConnectstate(Constant.USER_ID, connectstate);
mOneBtConnect.setPressed(false);
mOneBtConnect.setBackgroundResource(R.drawable.btn_connect_bg_enabled);
mOneBtConnect.setText("一键连接");
@@ -1536,9 +1535,9 @@ public class CommonDialog extends Dialog implements SurfaceHolder.Callback, IVid
mHostBean = hostBean;
mShareUtil.setTakeCameraIP(SystemConstant.USER_ID, hostBean.ipAddress.toString());
mShareUtil.setTakeCameraIP(Constant.USER_ID, hostBean.ipAddress.toString());
mShareUtil.setTakeCameraMac(SystemConstant.USER_ID, hostBean.hardwareAddress.toString());
mShareUtil.setTakeCameraMac(Constant.USER_ID, hostBean.hardwareAddress.toString());
takephotoManager.connect(getmDeviceNum(), hostBean, params);
}

View File

@@ -212,7 +212,7 @@ class EvaluationResultViewModel @Inject constructor(
it.copyToRealmOrUpdate(liveDataQsRecordBean.value)
}
// realm.close()
mapController.layerManagerHandler.addOrUpdateQsRecordMark(liveDataQsRecordBean.value!!)
mapController.markerHandle.addOrUpdateQsRecordMark(liveDataQsRecordBean.value!!)
liveDataFinish.postValue(true)
}
}
@@ -228,7 +228,7 @@ class EvaluationResultViewModel @Inject constructor(
objects?.deleteFromRealm()
}
// realm.close()
mapController.layerManagerHandler.removeQsRecordMark(liveDataQsRecordBean.value!!)
mapController.markerHandle.removeQsRecordMark(liveDataQsRecordBean.value!!)
liveDataFinish.postValue(true)
}
}

View File

@@ -125,6 +125,9 @@ class PersonalCenterFragment : BaseFragment(), FSAFActivityCallbacks {
R.id.personal_center_menu_task_list -> {
findNavController().navigate(R.id.TaskListFragment)
}
R.id.personal_center_menu_qs_record_list -> {
findNavController().navigate(R.id.QsRecordListFragment)
}
}
true
}

View File

@@ -0,0 +1,64 @@
package com.navinfo.omqs.ui.fragment.tasklist
import android.content.Context
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.Observer
import com.navinfo.collect.library.data.entity.QsRecordBean
import com.navinfo.omqs.R
import com.navinfo.omqs.bean.TaskBean
import com.navinfo.omqs.databinding.AdapterQsRecordListBinding
import com.navinfo.omqs.databinding.AdapterTaskListBinding
import com.navinfo.omqs.http.taskdownload.TaskDownloadManager
import com.navinfo.omqs.tools.FileManager.Companion.FileDownloadStatus
import com.navinfo.omqs.ui.other.BaseRecyclerViewAdapter
import com.navinfo.omqs.ui.other.BaseViewHolder
/**
* 离线地图城市列表 RecyclerView 适配器
*
* 在 RecycleView 的 ViewHolder 中监听 ViewModel 的 LiveData然后此时传递的 lifecycleOwner 是对应的 Fragment。由于 ViewHolder 的生命周期是比 Fragment 短的,所以当 ViewHolder 销毁时,由于 Fragment 的 Lifecycle 还没有结束,此时 ViewHolder 会发生内存泄露(监听的 LiveData 没有解绑)
* 这种场景下有两种解决办法:
*使用 LiveData 的 observeForever 然后在 ViewHolder 销毁前手动调用 removeObserver
*使用 LifecycleRegistry 给 ViewHolder 分发生命周期(这里使用了这个)
*/
class QsRecordListAdapter(
private val context: Context
) : BaseRecyclerViewAdapter<QsRecordBean>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {
val viewBinding =
AdapterQsRecordListBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return BaseViewHolder(viewBinding)
}
override fun onViewRecycled(holder: BaseViewHolder) {
super.onViewRecycled(holder)
//页面滑动时会用holder重构页面但是对进度条的监听回调会一直返回扰乱UI所以当当前holder去重构的时候移除监听
}
override fun onBindViewHolder(holder: BaseViewHolder, position: Int) {
val binding: AdapterQsRecordListBinding =
holder.viewBinding as AdapterQsRecordListBinding
val qsRecordBean = data[position]
//tag 方便onclick里拿到数据
holder.tag = qsRecordBean.id.toString()
changeViews(binding, qsRecordBean)
}
private fun changeViews(binding: AdapterQsRecordListBinding, qsRecordBean: QsRecordBean) {
binding.qsRecordClassType.text = qsRecordBean.classType
binding.qsRecordProblemType.text = qsRecordBean.problemType
binding.qsRecordPhenomenon.text = qsRecordBean.phenomenon
binding.qsRecordProblemLink.text = qsRecordBean.problemLink
}
override fun getItemViewRes(position: Int): Int {
return R.layout.adapter_qs_record_list
}
}

View File

@@ -0,0 +1,60 @@
package com.navinfo.omqs.ui.fragment.qsrecordlist
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView.VERTICAL
import com.navinfo.omqs.R
import com.navinfo.omqs.databinding.FragmentQsRecordListBinding
import com.navinfo.omqs.ui.fragment.BaseFragment
import com.navinfo.omqs.ui.fragment.tasklist.QsRecordListAdapter
import com.navinfo.omqs.ui.widget.RecycleViewDivider
import dagger.hilt.android.AndroidEntryPoint
import org.apache.poi.xwpf.usermodel.VerticalAlign
import javax.inject.Inject
@AndroidEntryPoint
class QsRecordListFragment : BaseFragment(){
private var _binding: FragmentQsRecordListBinding? = null
private val viewModel by viewModels<QsRecordListViewModel>()
private val binding get() = _binding!!
private val adapter: QsRecordListAdapter by lazy {
QsRecordListAdapter(
requireContext()
)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentQsRecordListBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val layoutManager = LinearLayoutManager(context)
//// 设置 RecyclerView 的固定大小,避免在滚动时重新计算视图大小和布局,提高性能
binding.qsRecyclerview.setHasFixedSize(true)
binding.qsRecyclerview.layoutManager = layoutManager
binding.qsRecyclerview.adapter = adapter
viewModel.liveDataQSList.observe(viewLifecycleOwner) {
adapter.refreshData(it)
}
val itemDecoration = DividerItemDecoration(context, DividerItemDecoration.VERTICAL)
itemDecoration.setDrawable(resources.getDrawable(R.drawable.separator))
binding.qsRecyclerview.addItemDecoration(itemDecoration)
viewModel.getList(requireContext())
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}

View File

@@ -0,0 +1,30 @@
package com.navinfo.omqs.ui.fragment.qsrecordlist
import android.content.Context
import android.util.Log
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.navinfo.collect.library.data.entity.QsRecordBean
import dagger.hilt.android.lifecycle.HiltViewModel
import io.realm.Realm
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class QsRecordListViewModel @Inject constructor(
) : ViewModel() {
val liveDataQSList = MutableLiveData<List<QsRecordBean>>()
fun getList(context: Context) {
viewModelScope.launch(Dispatchers.IO) {
val realm = Realm.getDefaultInstance()
Log.e("jingo","realm hashCOde ${realm.hashCode()}")
val objects = realm.where(QsRecordBean::class.java).findAll()
liveDataQSList.postValue(realm.copyFromRealm(objects))
}
}
}

View File

@@ -23,7 +23,7 @@ import com.navinfo.omqs.ui.other.BaseViewHolder
*使用 LifecycleRegistry 给 ViewHolder 分发生命周期(这里使用了这个)
*/
class TaskListAdapter(
private val downloadManager: TaskDownloadManager, private val context: Context
private val downloadManager: TaskDownloadManager
) : BaseRecyclerViewAdapter<TaskBean>() {
@@ -70,6 +70,8 @@ class TaskListAdapter(
binding.taskDownloadBtn.tag = position
binding.taskDownloadBtn.setOnClickListener(downloadBtnClick)
binding.taskName.text = taskBean.evaluationTaskName
binding.taskCityName.text = taskBean.cityName
binding.taskDataVersion.text = "版本号:${taskBean.dataVersion}"
// binding.offlineMapCitySize.text = cityBean.getFileSizeText()
}
@@ -82,10 +84,12 @@ class TaskListAdapter(
}
private fun changeViews(binding: AdapterTaskListBinding, cityBean: TaskBean) {
binding.taskProgress.progress =
(cityBean.currentSize * 100 / cityBean.fileSize).toInt()
when (cityBean.status) {
private fun changeViews(binding: AdapterTaskListBinding, taskBean: TaskBean) {
if (taskBean.fileSize > 0L) {
binding.taskProgress.progress =
(taskBean.currentSize * 100 / taskBean.fileSize).toInt()
}
when (taskBean.status) {
FileDownloadStatus.NONE -> {
if (binding.taskProgress.visibility == View.VISIBLE) binding.taskProgress.visibility =
View.INVISIBLE

View File

@@ -5,6 +5,7 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import com.navinfo.omqs.databinding.FragmentTaskListBinding
import com.navinfo.omqs.http.taskdownload.TaskDownloadManager
@@ -22,7 +23,6 @@ class TaskListFragment : BaseFragment(){
private val adapter: TaskListAdapter by lazy {
TaskListAdapter(
downloadManager,
requireContext()
)
}
@@ -46,6 +46,9 @@ class TaskListFragment : BaseFragment(){
adapter.refreshData(it)
}
viewModel.getTaskList(requireContext())
binding.taskBack.setOnClickListener{
findNavController().navigateUp()
}
}
override fun onDestroyView() {

View File

@@ -52,8 +52,11 @@ class TaskListViewModel @Inject constructor(
else -> {}
}
val objects = realm.where(TaskBean::class.java).findAll()
liveDataTaskList.postValue(realm.copyFromRealm(objects))
// realm.close()
val taskList = realm.copyFromRealm(objects)
for(item in taskList){
FileManager.checkOMDBFileInfo(item)
}
liveDataTaskList.postValue(taskList)
}
}

View File

@@ -16,9 +16,9 @@ import com.navinfo.collect.library.sensor.ISensor.SensorWorkingMode;
import com.navinfo.collect.library.sensor.ISensor.enmSensorType;
import com.navinfo.collect.library.sensor.ISensor.enmSignalQuality;
import com.navinfo.collect.library.sensor.SensorManager;
import com.navinfo.omqs.system.SystemConstant;
import com.navinfo.collect.library.utils.StringUtil;
import com.navinfo.omqs.Constant;
import com.navinfo.omqs.util.ShareUtil;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
@@ -392,7 +392,7 @@ public class TakePhotoManager {
setCameraMode(indexClent, SensorWorkingMode.CAMERA_VEDIO_TIMELAPSE);
ShareUtil.getCameraMode(mCon).setContinusTakePhotoState(SystemConstant.USER_ID, false);
ShareUtil.getCameraMode(mCon).setContinusTakePhotoState(Constant.USER_ID, false);
StartRecording(hostBean, indexClent);
@@ -405,7 +405,7 @@ public class TakePhotoManager {
if (hostBean != null) {
CameraGarminVirbXE cameraGarminVirbXE = findCameraGarminVirbXE(hostBean, index);
if (cameraGarminVirbXE != null) {
cameraGarminVirbXE.snapPicture(SystemConstant.getUuid(true));
cameraGarminVirbXE.snapPicture(StringUtil.Companion.createUUID());
}
}
}

View File

@@ -0,0 +1,144 @@
package com.navinfo.omqs.ui.widget
import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.view.View
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
/**
* Create by --- on 2018/12/6 0006.
*@description:
*/
/**
* 默认分割线高度为2px颜色为灰色
*
* @param context
* @param orientation 列表方向 LinearLayoutManager.VERTICAL或LinearLayoutManager.HORIZONTAL
*/
class RecycleViewDivider(context: Context, private val mOrientation: Int) : RecyclerView.ItemDecoration() {
private var mPaint: Paint? = null
private var mDivider: Drawable? = null
private var mDividerHeight = 2//分割线高度默认为1px
init {
if (mOrientation != LinearLayoutManager.VERTICAL && mOrientation != LinearLayoutManager.HORIZONTAL) {
throw IllegalArgumentException("请输入正确的参数!")
}
val a = context.obtainStyledAttributes(ATTRS)
mDivider = a.getDrawable(0)
a.recycle()
}
/**
* 自定义分割线
*
* @param context
* @param orientation 列表方向
* @param drawableId 分割线图片
*/
constructor(context: Context, orientation: Int, drawableId: Int) : this(context, orientation) {
mDivider = ContextCompat.getDrawable(context, drawableId)
mDividerHeight = mDivider!!.intrinsicHeight
}
/**
* 自定义分割线
*
* @param context
* @param orientation 列表方向
* @param dividerHeight 分割线高度
* @param dividerColor 分割线颜色
*/
constructor(context: Context, orientation: Int, dividerHeight: Int, dividerColor: Int) : this(
context,
orientation
) {
mDividerHeight = dividerHeight
mPaint = Paint(Paint.ANTI_ALIAS_FLAG)
mPaint!!.color = dividerColor
mPaint!!.style = Paint.Style.FILL
}
//获取分割线尺寸
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
super.getItemOffsets(outRect, view, parent, state)
if (mOrientation == LinearLayoutManager.VERTICAL) {
outRect.set(0, 0, 0, mDividerHeight)
} else {
outRect.set(0, 0, mDividerHeight, 0)
}
}
//绘制分割线
override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
super.onDraw(c, parent, state)
if (mOrientation == LinearLayoutManager.VERTICAL) {
drawVertical(c, parent)
} else {
drawHorizontal(c, parent)
}
}
/**
* 绘制纵向列表时的分隔线 这时分隔线是横着的
* 每次 left相同top根据child变化right相同bottom也变化
* @param canvas
* @param parent
*/
private fun drawVertical(canvas: Canvas, parent: RecyclerView) {
val left = parent.paddingLeft
val right = parent.measuredWidth - parent.paddingRight
val childSize = parent.childCount
for (i in 0 until childSize) {
val child = parent.getChildAt(i)
val layoutParams = child.layoutParams as RecyclerView.LayoutParams
val top = child.bottom + layoutParams.bottomMargin
val bottom = top + mDividerHeight
if (mDivider != null) {
mDivider!!.setBounds(left, top, right, bottom)
mDivider!!.draw(canvas)
}
if (mPaint != null) {
canvas.drawRect(left.toFloat(), top.toFloat(), right.toFloat(), bottom.toFloat(), mPaint!!)
}
}
}
/**
* 绘制横向列表时的分隔线 这时分隔线是竖着的
* l、r 变化; t、b 不变
* @param canvas
* @param parent
*/
private fun drawHorizontal(canvas: Canvas, parent: RecyclerView) {
val top = parent.paddingTop
val bottom = parent.measuredHeight - parent.paddingBottom
val childSize = parent.childCount
for (i in 0 until childSize) {
val child = parent.getChildAt(i)
val layoutParams = child.layoutParams as RecyclerView.LayoutParams
val left = child.right + layoutParams.rightMargin
val right = left + mDividerHeight
if (mDivider != null) {
mDivider!!.setBounds(left, top, right, bottom)
mDivider!!.draw(canvas)
}
if (mPaint != null) {
canvas.drawRect(left.toFloat(), top.toFloat(), right.toFloat(), bottom.toFloat(), mPaint!!)
}
}
}
companion object {
private val ATTRS = intArrayOf(android.R.attr.listDivider)
}
}

View File

@@ -1,4 +1,4 @@
package com.navinfo.omqs.system;
package com.navinfo.omqs.util;
import java.text.ParseException;
import java.text.ParsePosition;
@@ -13,7 +13,7 @@ import java.util.Date;
* @Date 2023年4月17日 下午1:56:02
* @Description: 时间工具类
*/
public class SystemDateTime {
public class DateTimeUtil {
// 时间字符串
private static String systemDate;
// 全部时间信息

View File

@@ -3,7 +3,7 @@ package com.navinfo.omqs.util;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import com.navinfo.omqs.system.SystemConstant;
import com.navinfo.omqs.Constant;
/**
* @ClassName: ShareUtil.java
@@ -57,9 +57,9 @@ public class ShareUtil {
return false;
if(mSharePre==null){
mSharePre = mContext.getSharedPreferences(SystemConstant.SELECT_CAMERA_STATE, Context.MODE_PRIVATE);
mSharePre = mContext.getSharedPreferences(Constant.SELECT_CAMERA_STATE, Context.MODE_PRIVATE);
}
return mSharePre.getBoolean(mDeviceNum+SystemConstant.USER_ID+SELECT_CAMERA_KIND, false);
return mSharePre.getBoolean(mDeviceNum+Constant.USER_ID+SELECT_CAMERA_KIND, false);
}
/**
@@ -76,7 +76,7 @@ public class ShareUtil {
return ;
if(mSharePre==null){
mSharePre = mContext.getSharedPreferences(SystemConstant.SELECT_CAMERA_STATE, Context.MODE_PRIVATE);
mSharePre = mContext.getSharedPreferences(Constant.SELECT_CAMERA_STATE, Context.MODE_PRIVATE);
}
editor=mSharePre.edit();
@@ -98,10 +98,10 @@ public class ShareUtil {
return true;
if(mSharePre==null){
mSharePre = mContext.getSharedPreferences(SystemConstant.SELECT_TAKEPHOTO_OR_RECORD, Context.MODE_PRIVATE);
mSharePre = mContext.getSharedPreferences(Constant.SELECT_TAKEPHOTO_OR_RECORD, Context.MODE_PRIVATE);
}
return mSharePre.getBoolean(mDeviceNum+SystemConstant.USER_ID+SELECT_TAKE_PHOTO_OR_RECORD, mDeviceNum==1?true:false);
return mSharePre.getBoolean(mDeviceNum+Constant.USER_ID+SELECT_TAKE_PHOTO_OR_RECORD, mDeviceNum==1?true:false);
}
@@ -119,7 +119,7 @@ public class ShareUtil {
return ;
if(mSharePre==null){
mSharePre = mContext.getSharedPreferences(SystemConstant.SELECT_TAKEPHOTO_OR_RECORD, Context.MODE_PRIVATE);
mSharePre = mContext.getSharedPreferences(Constant.SELECT_TAKEPHOTO_OR_RECORD, Context.MODE_PRIVATE);
}
editor=mSharePre.edit();
@@ -139,9 +139,9 @@ public class ShareUtil {
return true;
if(mSharePre==null){
mSharePre = mContext.getSharedPreferences(SystemConstant.SELECT_CAMERA_STATE, Context.MODE_PRIVATE);
mSharePre = mContext.getSharedPreferences(Constant.SELECT_CAMERA_STATE, Context.MODE_PRIVATE);
}
return mSharePre.getBoolean(mDeviceNum+SystemConstant.USER_ID+CONTINUS_TAKE_PHOTO_STATE, true);
return mSharePre.getBoolean(mDeviceNum+Constant.USER_ID+CONTINUS_TAKE_PHOTO_STATE, true);
}
@@ -159,7 +159,7 @@ public class ShareUtil {
return ;
if(mSharePre==null){
mSharePre = mContext.getSharedPreferences(SystemConstant.SELECT_CAMERA_STATE, Context.MODE_PRIVATE);
mSharePre = mContext.getSharedPreferences(Constant.SELECT_CAMERA_STATE, Context.MODE_PRIVATE);
}
editor=mSharePre.edit();
@@ -178,9 +178,9 @@ public class ShareUtil {
return false;
if(mSharePre==null){
mSharePre = mContext.getSharedPreferences(SystemConstant.CAMERA_CONNECT_STATE, Context.MODE_PRIVATE);
mSharePre = mContext.getSharedPreferences(Constant.CAMERA_CONNECT_STATE, Context.MODE_PRIVATE);
}
return mSharePre.getBoolean(mDeviceNum+SystemConstant.USER_ID+CAMERA_CONNECT_STATE, false);
return mSharePre.getBoolean(mDeviceNum+Constant.USER_ID+CAMERA_CONNECT_STATE, false);
}
/**
@@ -197,7 +197,7 @@ public class ShareUtil {
return ;
if(mSharePre==null){
mSharePre = mContext.getSharedPreferences(SystemConstant.CAMERA_CONNECT_STATE, Context.MODE_PRIVATE);
mSharePre = mContext.getSharedPreferences(Constant.CAMERA_CONNECT_STATE, Context.MODE_PRIVATE);
}
editor=mSharePre.edit();
@@ -216,10 +216,10 @@ public class ShareUtil {
return 0;
if(mSharePre==null){
mSharePre = mContext.getSharedPreferences(SystemConstant.TAKE_CAMERA_MODE, Context.MODE_PRIVATE);
mSharePre = mContext.getSharedPreferences(Constant.TAKE_CAMERA_MODE, Context.MODE_PRIVATE);
}
return mSharePre.getInt(mDeviceNum+SystemConstant.USER_ID+TAKE_CAMERA_MODE, mDeviceNum==1?0:1);
return mSharePre.getInt(mDeviceNum+Constant.USER_ID+TAKE_CAMERA_MODE, mDeviceNum==1?0:1);
}
@@ -238,7 +238,7 @@ public class ShareUtil {
if(mSharePre==null){
mSharePre = mContext.getSharedPreferences(SystemConstant.TAKE_CAMERA_MODE, Context.MODE_PRIVATE);
mSharePre = mContext.getSharedPreferences(Constant.TAKE_CAMERA_MODE, Context.MODE_PRIVATE);
}
editor=mSharePre.edit();
@@ -257,9 +257,9 @@ public class ShareUtil {
return "";
if(mSharePre==null){
mSharePre = mContext.getSharedPreferences(SystemConstant.TAKE_CAMERA_IP, Context.MODE_PRIVATE);
mSharePre = mContext.getSharedPreferences(Constant.TAKE_CAMERA_IP, Context.MODE_PRIVATE);
}
String ip=mSharePre.getString(mDeviceNum+SystemConstant.USER_ID+TAKE_CAMERA_IP, "");
String ip=mSharePre.getString(mDeviceNum+Constant.USER_ID+TAKE_CAMERA_IP, "");
return ip;
}
@@ -277,7 +277,7 @@ public class ShareUtil {
return ;
if(mSharePre==null){
mSharePre = mContext.getSharedPreferences(SystemConstant.TAKE_CAMERA_IP, Context.MODE_PRIVATE);
mSharePre = mContext.getSharedPreferences(Constant.TAKE_CAMERA_IP, Context.MODE_PRIVATE);
}
editor=mSharePre.edit();
@@ -297,9 +297,9 @@ public class ShareUtil {
return "";
if(mSharePre==null){
mSharePre = mContext.getSharedPreferences(SystemConstant.TAKE_CAMERA_MAC, Context.MODE_PRIVATE);
mSharePre = mContext.getSharedPreferences(Constant.TAKE_CAMERA_MAC, Context.MODE_PRIVATE);
}
String mac=mSharePre.getString(mDeviceNum+SystemConstant.USER_ID+TAKE_CAMERA_MAC, "");
String mac=mSharePre.getString(mDeviceNum+Constant.USER_ID+TAKE_CAMERA_MAC, "");
return mac;
}
@@ -317,7 +317,7 @@ public class ShareUtil {
return ;
if(mSharePre==null){
mSharePre = mContext.getSharedPreferences(SystemConstant.TAKE_CAMERA_MAC, Context.MODE_PRIVATE);
mSharePre = mContext.getSharedPreferences(Constant.TAKE_CAMERA_MAC, Context.MODE_PRIVATE);
}
editor=mSharePre.edit();