diff --git a/app/build.gradle b/app/build.gradle index 027eb8ae..ab7fa750 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -115,6 +115,18 @@ dependencies { //kotlin反射 implementation "org.jetbrains.kotlin:kotlin-stdlib:1.7.0" implementation "org.jetbrains.kotlin:kotlin-reflect:1.7.0" + + implementation 'com.permissionx.guolindev:permissionx:1.4.0' + def camerax_version = "1.1.0-alpha04" + // The following line is optional, as the core library is included indirectly by camera-camera2 + implementation "androidx.camera:camera-core:${camerax_version}" + implementation "androidx.camera:camera-camera2:${camerax_version}" + // If you want to additionally use the CameraX Lifecycle library + implementation "androidx.camera:camera-lifecycle:${camerax_version}" + // If you want to additionally use the CameraX View class + implementation "androidx.camera:camera-view:1.0.0-alpha24" + + implementation 'com.google.mlkit:barcode-scanning:16.1.1' } //允许引用生成的代码 kapt { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 449d6cf9..d84e4a52 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -4,6 +4,11 @@ android:versionCode="3" android:versionName="1.4" package="com.navinfo.omqs"> + + + @@ -31,7 +36,13 @@ + + + + + + + + + + + + diff --git a/app/src/main/java/com/navinfo/omqs/Constant.kt b/app/src/main/java/com/navinfo/omqs/Constant.kt index 328830fe..a885a6ea 100644 --- a/app/src/main/java/com/navinfo/omqs/Constant.kt +++ b/app/src/main/java/com/navinfo/omqs/Constant.kt @@ -52,6 +52,11 @@ class Constant { * */ var LAYER_CONFIG_LIST: List? = null + /** + * 室内整理工具IP + */ + lateinit var INDOOR_IP: String + const val DEBUG = true var IS_VIDEO_SPEED by kotlin.properties.Delegates.notNull() diff --git a/app/src/main/java/com/navinfo/omqs/bean/EvaluationInfo.kt b/app/src/main/java/com/navinfo/omqs/bean/EvaluationInfo.kt index 7f257d6e..b1418d1d 100644 --- a/app/src/main/java/com/navinfo/omqs/bean/EvaluationInfo.kt +++ b/app/src/main/java/com/navinfo/omqs/bean/EvaluationInfo.kt @@ -38,8 +38,8 @@ data class EvaluationInfo( @SerializedName("problemLink") val problemLink: String = "",//问题环节 - @SerializedName("problemReason") - val problemReason: String = "",//问题原因 + @SerializedName("preliminaryAnalysis") + val preliminaryAnalysis: String = "",//初步分析 @SerializedName("evaluatorName") val evaluatorName: String = "",//测评人名称 diff --git a/app/src/main/java/com/navinfo/omqs/bean/IndoorConnectionInfoBean.kt b/app/src/main/java/com/navinfo/omqs/bean/IndoorConnectionInfoBean.kt new file mode 100644 index 00000000..3cc05594 --- /dev/null +++ b/app/src/main/java/com/navinfo/omqs/bean/IndoorConnectionInfoBean.kt @@ -0,0 +1,11 @@ +package com.navinfo.omqs.bean + +data class IndoorConnectionInfoBean( + var username: String = "", + var uname: String = "", + var userid: String = "", + var token: String = "", + var baseurl: String = "", + var plate: String = "", + var platform: String = "Android", +) \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/bean/QRCodeBean.kt b/app/src/main/java/com/navinfo/omqs/bean/QRCodeBean.kt new file mode 100644 index 00000000..4790dd17 --- /dev/null +++ b/app/src/main/java/com/navinfo/omqs/bean/QRCodeBean.kt @@ -0,0 +1,6 @@ +package com.navinfo.omqs.bean + +data class QRCodeBean( + var errcode: Int = -1, + var msg: String = "" +) \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/db/dao/ScProblemTypeDao.kt b/app/src/main/java/com/navinfo/omqs/db/dao/ScProblemTypeDao.kt index b1e163d2..3940ed99 100644 --- a/app/src/main/java/com/navinfo/omqs/db/dao/ScProblemTypeDao.kt +++ b/app/src/main/java/com/navinfo/omqs/db/dao/ScProblemTypeDao.kt @@ -30,8 +30,8 @@ interface ScProblemTypeDao { /** * 获取问题分类,并去重 */ - @Query("select DISTINCT CLASS_TYPE from ScProblemType order by CLASS_TYPE") - suspend fun findClassTypeList(): List? + @Query("select * from ScProblemType group by CLASS_TYPE") + suspend fun findClassTypeList(): List? @Query("select DISTINCT CLASS_TYPE from ScProblemType where ELEMENT_CODE=:code") suspend fun findClassTypeByCode(code: Int): String? diff --git a/app/src/main/java/com/navinfo/omqs/http/NetworkService.kt b/app/src/main/java/com/navinfo/omqs/http/NetworkService.kt index 5fe4dd2d..beca12b6 100644 --- a/app/src/main/java/com/navinfo/omqs/http/NetworkService.kt +++ b/app/src/main/java/com/navinfo/omqs/http/NetworkService.kt @@ -2,7 +2,9 @@ package com.navinfo.omqs.http import com.navinfo.omqs.bean.OfflineMapCityBean import com.navinfo.collect.library.data.entity.TaskBean +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 @@ -15,14 +17,25 @@ interface NetworkService { /** * 获取离线地图城市列表 */ - suspend fun getOfflineMapCityList():NetResult> + suspend fun getOfflineMapCityList(): NetResult> + /** * 获取任务列表 */ - suspend fun getTaskList(evaluatorNo:String): NetResult>> + suspend fun getTaskList(evaluatorNo: String): NetResult>> /** * 登录接口 */ suspend fun loginUser(loginUserBean: LoginUserBean): NetResult> + + /** + * 连接室内整理工具 + */ + suspend fun connectIndoorTools(url: String): NetResult + + /** + * 更新用户信息 + */ + suspend fun updateServerInfo(url: String,indoorConnectionInfoBean: IndoorConnectionInfoBean): NetResult } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/http/NetworkServiceImpl.kt b/app/src/main/java/com/navinfo/omqs/http/NetworkServiceImpl.kt index 374bd7e6..5bcd2782 100644 --- a/app/src/main/java/com/navinfo/omqs/http/NetworkServiceImpl.kt +++ b/app/src/main/java/com/navinfo/omqs/http/NetworkServiceImpl.kt @@ -2,7 +2,9 @@ package com.navinfo.omqs.http import com.navinfo.omqs.bean.OfflineMapCityBean import com.navinfo.collect.library.data.entity.TaskBean +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 kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -75,4 +77,42 @@ class NetworkServiceImpl @Inject constructor( NetResult.Error(e) } } + + override suspend fun connectIndoorTools(url: String): NetResult = + //在IO线程中运行 + withContext(Dispatchers.IO) { + return@withContext try { + val result = netApi.retrofitConnectIndoorTools(url = url) + if (result.isSuccessful) { + if (result.code() == 200) { + NetResult.Success(result.body()) + } else { + NetResult.Failure(result.code(), result.message()) + } + } else { + NetResult.Failure(result.code(), result.message()) + } + } catch (e: Exception) { + NetResult.Error(e) + } + } + + override suspend fun updateServerInfo(url: String,indoorConnectionInfoBean: IndoorConnectionInfoBean): NetResult = + //在IO线程中运行 + withContext(Dispatchers.IO) { + return@withContext try { + val result = netApi.retrofitUpdateServerInfo(url,indoorConnectionInfoBean) + if (result.isSuccessful) { + if (result.code() == 200) { + NetResult.Success(result.body()) + } else { + NetResult.Failure(result.code(), result.message()) + } + } else { + NetResult.Failure(result.code(), result.message()) + } + } catch (e: Exception) { + NetResult.Error(e) + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/http/RetrofitNetworkServiceAPI.kt b/app/src/main/java/com/navinfo/omqs/http/RetrofitNetworkServiceAPI.kt index 67136348..2f56bbab 100644 --- a/app/src/main/java/com/navinfo/omqs/http/RetrofitNetworkServiceAPI.kt +++ b/app/src/main/java/com/navinfo/omqs/http/RetrofitNetworkServiceAPI.kt @@ -3,7 +3,9 @@ package com.navinfo.omqs.http import com.navinfo.omqs.bean.EvaluationInfo import com.navinfo.omqs.bean.OfflineMapCityBean import com.navinfo.collect.library.data.entity.TaskBean +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 @@ -64,6 +66,22 @@ interface RetrofitNetworkServiceAPI { @Query("evaluatorNo") evaluatorNo: String, ): Response>> + + + /** + * 连接室内整理工具 + */ + @Streaming + @GET + suspend fun retrofitConnectIndoorTools(@Url url: String): Response + + /** + * 登录接口 + */ + @Headers("Content-Type: application/json") + @POST + suspend fun retrofitUpdateServerInfo(@Url url: String,@Body indoorConnectionInfoBean: IndoorConnectionInfoBean): Response + @Headers("Content-Type: application/json") @POST("/devcp/uploadSceneProblem") suspend fun postRequest(@Body listEvaluationInfo: List?): Response> diff --git a/app/src/main/java/com/navinfo/omqs/http/taskupload/TaskUploadScope.kt b/app/src/main/java/com/navinfo/omqs/http/taskupload/TaskUploadScope.kt index e7534861..78101d7a 100644 --- a/app/src/main/java/com/navinfo/omqs/http/taskupload/TaskUploadScope.kt +++ b/app/src/main/java/com/navinfo/omqs/http/taskupload/TaskUploadScope.kt @@ -146,12 +146,12 @@ class TaskUploadScope( markId = hadLinkDvoBean.mesh,//"20065597" trackPhotoNumber = "", markGeometry = it.geometry, - featureName = it.classType, + featureName = it.classCode, problemType = problemType, problemPhenomenon = it.phenomenon, problemDesc = it.description, problemLink = it.problemLink, - problemReason = it.cause, + preliminaryAnalysis = it.cause, evaluatorName = it.checkUserId, evaluationDate = it.checkTime, evaluationWay = evaluationWay, @@ -166,10 +166,17 @@ class TaskUploadScope( bodyList.add(evaluationInfo) } }else{ + val linkStatus = 1 + //存在原因标记未测评 + if(hadLinkDvoBean.reason.isNotEmpty()){ + val linkStatus = 0 + }else{ + val linkStatus = 1 + } val evaluationInfo = EvaluationInfo( evaluationTaskId = taskBean.id.toString(), linkPid = hadLinkDvoBean.linkPid,//"84207223282277331" - linkStatus = 0, + linkStatus = linkStatus, markId = hadLinkDvoBean.mesh,//"20065597" trackPhotoNumber = "", markGeometry = "", @@ -178,13 +185,13 @@ class TaskUploadScope( problemPhenomenon = "", problemDesc = "", problemLink = "", - problemReason = "", + preliminaryAnalysis = "", evaluatorName = "", evaluationDate = "", evaluationWay = 2, roadClassfcation = "", roadFunctionGrade = "", - noEvaluationreason = "", + noEvaluationreason = hadLinkDvoBean.reason, linkLength = 0.0, dataLevel = "", linstringLength = 0.0, diff --git a/app/src/main/java/com/navinfo/omqs/server/TimeTask.kt b/app/src/main/java/com/navinfo/omqs/server/TimeTask.kt new file mode 100644 index 00000000..1ccdbb02 --- /dev/null +++ b/app/src/main/java/com/navinfo/omqs/server/TimeTask.kt @@ -0,0 +1,131 @@ +package com.navinfo.omqs.server + +import android.annotation.SuppressLint +import android.app.AlarmManager +import android.app.PendingIntent +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.os.Build +import android.os.SystemClock + +/** + * date:2023/6/18 + * author:qj + * description:定时器 + */ +class TimeTask(context: Context, actionName: String, task: T) { + + private var mContext: Context? + private val mActionName: String + private var mReceiver: TimeTaskReceiver? = null + private val mTask: T? + + companion object { + private var mPendingIntent: PendingIntent? = null + } + + init { + mContext = context + mActionName = actionName + mTask = task + initReceiver(context, actionName) + } + + fun startLooperTask() { + if (null != mTask) { + mTask.exeTask() + configureAlarmManager(mTask.period()) + } + } + + fun stopLooperTask() { + cancelAlarmManager() + } + + fun onClose() { + mContext!!.unregisterReceiver(mReceiver) + mContext = null + } + + @SuppressLint("ObsoleteSdkInt") + private fun configureAlarmManager(time: Long) { + val manager = mContext!!.getSystemService(Context.ALARM_SERVICE) as AlarmManager + val pendIntent = pendingIntent + when { + Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> { + manager.setExactAndAllowWhileIdle( + AlarmManager.ELAPSED_REALTIME_WAKEUP, + SystemClock.elapsedRealtime() + time, + pendIntent + ) + } + Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT -> { + manager.setExact( + AlarmManager.ELAPSED_REALTIME_WAKEUP, + SystemClock.elapsedRealtime() + time, + pendIntent + ) + } + else -> { + manager[AlarmManager.ELAPSED_REALTIME_WAKEUP, + SystemClock.elapsedRealtime() + time] = pendIntent + } + } + } + + @get:SuppressLint("UnspecifiedImmutableFlag") + private val pendingIntent: PendingIntent? + get() { + if (mPendingIntent == null) { + val requestCode = 0 + val intent = Intent() + intent.action = mActionName + when { + Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { + mPendingIntent = PendingIntent.getBroadcast( + mContext, requestCode, intent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE + ) + } + else -> { + mPendingIntent = PendingIntent.getBroadcast( + mContext, + requestCode, + intent, + PendingIntent.FLAG_UPDATE_CURRENT + ) + } + } + } + return mPendingIntent + } + + private fun cancelAlarmManager() { + val manager = mContext!!.getSystemService(Context.ALARM_SERVICE) as AlarmManager + manager.cancel(pendingIntent) + } + + private fun initReceiver(context: Context, actionName: String) { + mReceiver = TimeTaskReceiver() + val intentFilter = IntentFilter() + intentFilter.addAction(actionName) + context.registerReceiver(mReceiver, intentFilter) + } + + internal inner class TimeTaskReceiver : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + startLooperTask() + } + } + + interface Task { + fun period(): Long { + // 默认时间5S + return 5000L + } + + fun exeTask() + } +} diff --git a/app/src/main/java/com/navinfo/omqs/ui/activity/CheckPermissionsActivity.java b/app/src/main/java/com/navinfo/omqs/ui/activity/CheckPermissionsActivity.java index 6690ea72..00150288 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/activity/CheckPermissionsActivity.java +++ b/app/src/main/java/com/navinfo/omqs/ui/activity/CheckPermissionsActivity.java @@ -37,7 +37,8 @@ public class CheckPermissionsActivity extends BaseActivity { Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, - Manifest.permission.RECORD_AUDIO + Manifest.permission.RECORD_AUDIO, + Manifest.permission.CAMERA, }; private static final int PERMISSON_REQUESTCODE = 0; @@ -53,6 +54,7 @@ public class CheckPermissionsActivity extends BaseActivity { Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO, + Manifest.permission.CAMERA, BACKGROUND_LOCATION_PERMISSION }; } diff --git a/app/src/main/java/com/navinfo/omqs/ui/activity/scan/QRCodeViewModel.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/scan/QRCodeViewModel.kt new file mode 100644 index 00000000..36921971 --- /dev/null +++ b/app/src/main/java/com/navinfo/omqs/ui/activity/scan/QRCodeViewModel.kt @@ -0,0 +1,256 @@ +package com.navinfo.omqs.ui.activity.scan + +import android.content.Context +import android.text.TextUtils +import android.widget.Toast +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.navinfo.omqs.Constant +import com.navinfo.omqs.bean.IndoorConnectionInfoBean +import com.navinfo.omqs.bean.QRCodeBean +import com.navinfo.omqs.bean.SysUserBean +import com.navinfo.omqs.http.DefaultResponse +import com.navinfo.omqs.http.NetResult +import com.navinfo.omqs.http.NetworkService +import com.navinfo.omqs.ui.activity.login.LoginStatus +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import java.io.IOException +import javax.inject.Inject + +enum class QrCodeStatus { + /** + * 网络访问失败 + */ + QR_CODE_STATUS_NET_FAILURE, + + /** + * 成功 + */ + QR_CODE_STATUS_SUCCESS, + + /** + * 信息更新成功 + */ + QR_CODE_STATUS_SERVER_INFO_SUCCESS, +} + +@HiltViewModel +class QrCodeViewModel @Inject constructor( + private val networkService: NetworkService +) : ViewModel() { + //用户信息 + val qrCodeBean: MutableLiveData = MutableLiveData() + + //是不是连接成功 + val qrCodeStatus: MutableLiveData = MutableLiveData() + + + init { + qrCodeBean.value = QRCodeBean() + } + + + /** + * 扫一扫按钮 + */ + fun connect(context: Context, ips: String) { + + if (TextUtils.isEmpty(ips)) { + Toast.makeText(context, "获取ip失败!", Toast.LENGTH_LONG).show() + return + } + + val ipArray = ips.split(";".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() + //测试代码 + //final String[] ipArray = new String[]{"172.21.2.137"}; + if (ipArray.isEmpty()) { + Toast.makeText(context, "获取ip失败!", Toast.LENGTH_SHORT).show() + return + } + + ipArray.forEach { ip -> + if (!TextUtils.isEmpty(ip)) { + viewModelScope.launch(Dispatchers.Default) { + val ipTemp: String = ip + val url = "http://$ipTemp:8080/sensor/service/keepalive" + when (val result = networkService.connectIndoorTools(url)) { + is NetResult.Success<*> -> { + + if (result.data != null) { + try { + + val defaultUserResponse = result.data as QRCodeBean + + if (defaultUserResponse.errcode == 0) { + + Constant.INDOOR_IP = ipTemp + + qrCodeStatus.postValue(QrCodeStatus.QR_CODE_STATUS_SUCCESS) + + withContext(Dispatchers.Main) { + Toast.makeText( + context, + "连接室内整理工具成功。", + Toast.LENGTH_LONG + ).show() + } + } else { + withContext(Dispatchers.Main) { + Toast.makeText( + context, + "${defaultUserResponse.msg}", + Toast.LENGTH_SHORT + ) + .show() + } + } + + } 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() + } + qrCodeStatus.postValue(QrCodeStatus.QR_CODE_STATUS_NET_FAILURE) + } + + is NetResult.Failure<*> -> { + withContext(Dispatchers.Main) { + Toast.makeText( + context, + "${result.code}:${result.msg}", + Toast.LENGTH_SHORT + ) + .show() + } + qrCodeStatus.postValue(QrCodeStatus.QR_CODE_STATUS_NET_FAILURE) + } + + else -> {} + } + } + } + } + } + + /** + * 扫一扫按钮 + */ + fun updateServerInfo(context: Context) { + + if (TextUtils.isEmpty(Constant.INDOOR_IP)) { + Toast.makeText(context, "获取ip失败!", Toast.LENGTH_LONG).show() + return + } + + viewModelScope.launch(Dispatchers.Default) { + val url = "http://${Constant.INDOOR_IP}:8080/sensor/service/connection" + when (val result = networkService.updateServerInfo( + url = url, + indoorConnectionInfoBean = IndoorConnectionInfoBean( + Constant.USER_ID, + Constant.USER_ID, + Constant.USER_ID, + Constant.USER_ID, + com.navinfo.collect.library.system.Constant.SERVER_ADDRESS, + Constant.USER_ID, + "Android" + ) + )) { + 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() + qrCodeStatus.postValue(QrCodeStatus.QR_CODE_STATUS_SERVER_INFO_SUCCESS) + } + } else { + withContext(Dispatchers.Main) { + Toast.makeText( + context, + "${defaultUserResponse.msg}", + Toast.LENGTH_SHORT + ) + .show() + } + } + + } 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() + } + qrCodeStatus.postValue(QrCodeStatus.QR_CODE_STATUS_NET_FAILURE) + } + + is NetResult.Failure<*> -> { + withContext(Dispatchers.Main) { + Toast.makeText( + context, + "${result.code}:${result.msg}", + Toast.LENGTH_SHORT + ) + .show() + } + qrCodeStatus.postValue(QrCodeStatus.QR_CODE_STATUS_NET_FAILURE) + } + + else -> {} + } + + } + + } + + + override fun onCleared() { + super.onCleared() + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/ui/activity/scan/QrCodeActivity.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/scan/QrCodeActivity.kt new file mode 100644 index 00000000..12706f25 --- /dev/null +++ b/app/src/main/java/com/navinfo/omqs/ui/activity/scan/QrCodeActivity.kt @@ -0,0 +1,147 @@ +package com.navinfo.omqs.ui.activity.scan + +import android.annotation.SuppressLint +import android.graphics.Rect +import android.graphics.RectF +import android.os.Bundle +import android.util.Log +import androidx.activity.viewModels +import androidx.camera.core.ImageCapture +import androidx.camera.view.LifecycleCameraController +import androidx.databinding.DataBindingUtil +import com.navinfo.omqs.R +import com.navinfo.omqs.databinding.ActivityQrCodeBinding +import com.navinfo.omqs.ui.activity.BaseActivity +import com.navinfo.omqs.ui.listener.QRCodeAnalyser +import dagger.hilt.android.AndroidEntryPoint +import java.util.concurrent.ExecutorService +import java.util.concurrent.Executors +import androidx.lifecycle.Observer +import com.navinfo.omqs.ui.activity.login.LoginStatus + +/** + * date:2023/6/18 + * author:qj + * description:二维码扫描 + */ +@AndroidEntryPoint +class QrCodeActivity : BaseActivity() { + private lateinit var binding: ActivityQrCodeBinding + private lateinit var lifecycleCameraController: LifecycleCameraController + private lateinit var cameraExecutor: ExecutorService + private val viewModel by viewModels() + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + binding = DataBindingUtil.setContentView(this, R.layout.activity_qr_code) + + binding.qrCodeModel = viewModel + binding.lifecycleOwner = this + binding.activity = this + + initView() + initController() + } + + private fun initView() { + //登录校验,初始化成功 + viewModel.qrCodeStatus.observe(this, qrCodeObserve) + } + + /* + * 监听扫描结果 + * */ + private val qrCodeObserve = Observer { + when (it) { + QrCodeStatus.QR_CODE_STATUS_SUCCESS -> { + finish() + } + QrCodeStatus.QR_CODE_STATUS_NET_FAILURE -> { + + } + QrCodeStatus.QR_CODE_STATUS_SERVER_INFO_SUCCESS -> { + + } + } + } + + @SuppressLint("ClickableViewAccessibility", "UnsafeOptInUsageError") + private fun initController() { + cameraExecutor = Executors.newSingleThreadExecutor() + lifecycleCameraController = LifecycleCameraController(this) + lifecycleCameraController.bindToLifecycle(this) + lifecycleCameraController.imageCaptureFlashMode = ImageCapture.FLASH_MODE_AUTO + lifecycleCameraController.setImageAnalysisAnalyzer( + cameraExecutor, + QRCodeAnalyser { barcodes, imageWidth, imageHeight -> + if (barcodes.isEmpty()) { + return@QRCodeAnalyser + } + initScale(imageWidth, imageHeight) + val list = ArrayList() + val strList = ArrayList() + + barcodes.forEach { barcode -> + barcode.boundingBox?.let { rect -> + val translateRect = translateRect(rect) + list.add(translateRect) + Log.e( + "ztzt", "left:${translateRect.left} +" + + " top:${translateRect.top} + right:${translateRect.right}" + + " + bottom:${translateRect.bottom}" + ) + Log.e("ztzt", "barcode.rawValue:${barcode.rawValue}") + strList.add(barcode.rawValue ?: "No Value") + } + } + judgeIntent(strList) + binding.scanView.setRectList(list) + + }) + binding.previewView.controller = lifecycleCameraController + } + + fun judgeIntent(list: ArrayList) { + val sb = StringBuilder() + list.forEach { + sb.append(it) + sb.append("\n") + } + intentToResult(sb.toString()) + } + + private fun intentToResult(result: String) { + + Log.e("qj", "QRCodeActivity === $result") + + viewModel.connect(this, result) + + /* val intent = Intent(this, QRCodeResultActivity::class.java) + intent.putExtra(QRCodeResultActivity.RESULT_KEY, result) + startActivity(intent) + finish()*/ + } + + + private var scaleX = 0f + private var scaleY = 0f + + private fun translateX(x: Float): Float = x * scaleX + private fun translateY(y: Float): Float = y * scaleY + + //将扫描的矩形换算为当前屏幕大小 + private fun translateRect(rect: Rect) = RectF( + translateX(rect.left.toFloat()), + translateY(rect.top.toFloat()), + translateX(rect.right.toFloat()), + translateY(rect.bottom.toFloat()) + ) + + //初始化缩放比例 + private fun initScale(imageWidth: Int, imageHeight: Int) { + Log.e("ztzt", "imageWidth:${imageWidth} + imageHeight:${imageHeight}") + scaleY = binding.scanView.height.toFloat() / imageWidth.toFloat() + scaleX = binding.scanView.width.toFloat() / imageHeight.toFloat() + Log.e("ztzt", "scaleX:${scaleX} + scaleY:${scaleY}") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/ui/activity/scan/QrCodeResultActivity.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/scan/QrCodeResultActivity.kt new file mode 100644 index 00000000..de4c3c93 --- /dev/null +++ b/app/src/main/java/com/navinfo/omqs/ui/activity/scan/QrCodeResultActivity.kt @@ -0,0 +1,30 @@ +package com.navinfo.omqs.ui.activity.scan + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.navinfo.omqs.databinding.ActivityResultBinding + +/** + * date:2021/6/18 + * author:zhangteng + * description: + */ +class QRCodeResultActivity : AppCompatActivity() { + private lateinit var binding: ActivityResultBinding + + companion object { + const val RESULT_KEY = "result_key"; + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityResultBinding.inflate(layoutInflater) + setContentView(binding.root) + + val intent = intent + binding.text.text = intent.getStringExtra(RESULT_KEY) + binding.button.setOnClickListener { + finish() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/EvaluationResultViewModel.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/EvaluationResultViewModel.kt index a415a767..e5f47088 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/EvaluationResultViewModel.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/EvaluationResultViewModel.kt @@ -26,6 +26,7 @@ import com.navinfo.collect.library.utils.GeometryTools import com.navinfo.omqs.Constant import com.navinfo.omqs.R import com.navinfo.omqs.bean.ChatMsgEntity +import com.navinfo.omqs.bean.ScProblemTypeBean import com.navinfo.omqs.bean.SignBean import com.navinfo.omqs.db.RealmOperateHelper import com.navinfo.omqs.db.RoomAppDatabase @@ -65,7 +66,7 @@ class EvaluationResultViewModel @Inject constructor( /** * 问题分类 liveData,给[LeftAdapter]展示的数据 */ - val liveDataLeftTypeList = MutableLiveData>() + val liveDataLeftTypeList = MutableLiveData>() /** * 问题类型 liveData 给[MiddleAdapter]展示的数据 @@ -95,6 +96,8 @@ class EvaluationResultViewModel @Inject constructor( var classTypeTemp: String = "" + var classCodeTemp: String = "" + init { liveDataQsRecordBean.value = QsRecordBean(id = UUID.randomUUID().toString()) viewModelScope.launch { @@ -194,22 +197,24 @@ class EvaluationResultViewModel @Inject constructor( list?.let { if (list.isNotEmpty()) { //通知页面更新 - var classType = list[0] + var classType = list[0].classType + var classCode = list[0].elementCode liveDataLeftTypeList.postValue(it) if (bean != null) { - val classType2 = roomAppDatabase.getScProblemTypeDao() - .findClassTypeByCode(bean.renderEntity.code) + val classType2 = roomAppDatabase.getScProblemTypeDao().findClassTypeByCode(bean.renderEntity.code) if (classType2 != null) { classType = classType2 } } //如果右侧栏没数据,给个默认值 if (liveDataQsRecordBean.value!!.classType.isEmpty()) { - liveDataQsRecordBean.value!!.classType = classType + liveDataQsRecordBean.value!!.classCode = classCode classTypeTemp = classType + classCodeTemp = classCode } else { classType = liveDataQsRecordBean.value!!.classType + classCode = liveDataQsRecordBean.value!!.classCode } getProblemList(classType) } @@ -298,6 +303,7 @@ class EvaluationResultViewModel @Inject constructor( */ fun setPhenomenonMiddleBean(adapterBean: RightBean) { liveDataQsRecordBean.value!!.classType = classTypeTemp + liveDataQsRecordBean.value!!.classCode = classCodeTemp liveDataQsRecordBean.value!!.phenomenon = adapterBean.text liveDataQsRecordBean.value!!.problemType = adapterBean.title liveDataQsRecordBean.postValue(liveDataQsRecordBean.value) diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/LeftAdapter.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/LeftAdapter.kt index 383a515c..9668f889 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/LeftAdapter.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/evaluationresult/LeftAdapter.kt @@ -5,12 +5,13 @@ import android.view.LayoutInflater import android.view.ViewGroup import androidx.annotation.RequiresApi import com.navinfo.omqs.R +import com.navinfo.omqs.bean.ScProblemTypeBean 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) : - BaseRecyclerViewAdapter() { + BaseRecyclerViewAdapter() { private var selectTitle = "" @@ -24,18 +25,18 @@ class LeftAdapter(private var itemListener: ((Int, String) -> Unit?)? = null) : override fun onBindViewHolder(holder: BaseViewHolder, position: Int) { val bd = holder.viewBinding as TextItemSelectBinding val title = data[position] - bd.itemId.text = title - holder.viewBinding.root.isSelected = selectTitle == title + bd.itemId.text = title.classType + holder.viewBinding.root.isSelected = selectTitle == title.classType bd.root.setOnClickListener { - if (selectTitle != title) { - selectTitle = title + if (selectTitle != title.classType) { + selectTitle = title.classType notifyDataSetChanged() } - itemListener?.invoke(position, title) + itemListener?.invoke(position, title.classType) } } - override fun refreshData(newData: List) { + override fun refreshData(newData: List) { data = newData notifyDataSetChanged() } diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterFragment.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterFragment.kt index 3c687be0..8e96c2c5 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterFragment.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterFragment.kt @@ -1,13 +1,14 @@ package com.navinfo.omqs.ui.fragment.personalcenter +import android.Manifest import android.content.Intent import android.net.Uri import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.Toast import androidx.fragment.app.viewModels -import androidx.lifecycle.lifecycleScope import androidx.navigation.fragment.findNavController import com.blankj.utilcode.util.ToastUtils import com.blankj.utilcode.util.UriUtils @@ -21,6 +22,8 @@ import com.navinfo.omqs.db.ImportOMDBHelper import com.navinfo.omqs.hilt.ImportOMDBHiltFactory import com.navinfo.omqs.tools.CoroutineUtils import com.navinfo.omqs.ui.fragment.BaseFragment +import com.navinfo.omqs.ui.activity.scan.QrCodeActivity +import com.permissionx.guolindev.PermissionX import dagger.hilt.android.AndroidEntryPoint import org.oscim.core.GeoPoint import javax.inject.Inject @@ -123,6 +126,16 @@ class PersonalCenterFragment(private var backListener: (() -> Unit?)? = null) : // R.id.personal_center_menu_layer_manager -> { // 图层管理 // findNavController().navigate(R.id.QsLayerManagerFragment) // } +/* R.id.personal_center_menu_qs_record_list -> { + findNavController().navigate(R.id.QsRecordListFragment) + } + R.id.personal_center_menu_layer_manager -> { // 图层管理 + findNavController().navigate(R.id.QsLayerManagerFragment) + }*/ + R.id.personal_center_menu_scan_qr_code -> { + //跳转二维码扫描界面 + checkPermission() + } } true } @@ -134,6 +147,11 @@ class PersonalCenterFragment(private var backListener: (() -> Unit?)? = null) : fileChooser.setCallbacks(this@PersonalCenterFragment) } + private fun intentTOQRCode() { + var intent = Intent(context, QrCodeActivity::class.java); + startActivity(intent) + } + override fun onDestroyView() { super.onDestroyView() _binding = null @@ -147,4 +165,18 @@ class PersonalCenterFragment(private var backListener: (() -> Unit?)? = null) : super.onActivityResult(requestCode, resultCode, data) fileChooser.onActivityResult(requestCode, resultCode, data) } + + private fun checkPermission() { + PermissionX.init(this) + .permissions(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO) + .request { allGranted, grantedList, deniedList -> + if (allGranted) { + //所有权限已经授权 + Toast.makeText(context,"授权成功",Toast.LENGTH_LONG).show() + intentTOQRCode() + } else { + Toast.makeText(context, "拒绝权限: $deniedList", Toast.LENGTH_LONG).show() + } + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/tasklist/TaskViewModel.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/tasklist/TaskViewModel.kt index 3bf42632..e3c4e290 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/tasklist/TaskViewModel.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/tasklist/TaskViewModel.kt @@ -4,6 +4,7 @@ import android.content.Context import android.graphics.Color import android.os.Build import android.widget.Toast +import androidx.annotation.RequiresApi import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -95,18 +96,21 @@ class TaskViewModel @Inject constructor( } } } + 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 -> {} } val realm = Realm.getDefaultInstance() @@ -139,41 +143,42 @@ class TaskViewModel @Inject constructor( /** * 设置当前选择的任务,并高亮当前任务的所有link */ + @RequiresApi(Build.VERSION_CODES.M) fun setSelectTaskBean(taskBean: TaskBean) { currentSelectTaskBean = taskBean + liveDataTaskLinks.value = taskBean.hadLinkDvoList - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - mapController.lineHandler.omdbTaskLinkLayer.removeAll() - if(taskBean.hadLinkDvoList.isNotEmpty()){ - mapController.lineHandler.omdbTaskLinkLayer.addLineList(taskBean.hadLinkDvoList) - var maxX = 0.0 - var maxY = 0.0 - var minX = 0.0 - var minY = 0.0 - for (item in taskBean.hadLinkDvoList) { - val geometry = GeometryTools.createGeometry(item.geometry) - if(geometry!=null){ - val envelope = geometry.envelopeInternal - if (envelope.maxX > maxX) { - maxX = envelope.maxX - } - if (envelope.maxY > maxY) { - maxY = envelope.maxY - } - if (envelope.minX < minX || minX == 0.0) { - minX = envelope.minX - } - if (envelope.minY < minY || minY == 0.0) { - minY = envelope.minY - } + + mapController.lineHandler.omdbTaskLinkLayer.removeAll() + if (taskBean.hadLinkDvoList.isNotEmpty()) { + mapController.lineHandler.omdbTaskLinkLayer.addLineList(taskBean.hadLinkDvoList) + var maxX = 0.0 + var maxY = 0.0 + var minX = 0.0 + var minY = 0.0 + for (item in taskBean.hadLinkDvoList) { + val geometry = GeometryTools.createGeometry(item.geometry) + if (geometry != null) { + val envelope = geometry.envelopeInternal + if (envelope.maxX > maxX) { + maxX = envelope.maxX + } + if (envelope.maxY > maxY) { + maxY = envelope.maxY + } + if (envelope.minX < minX || minX == 0.0) { + minX = envelope.minX + } + if (envelope.minY < minY || minY == 0.0) { + minY = envelope.minY } } - //增加异常数据判断 - if(maxX!=0.0&&maxY!=0.0&&minX!=0.0&&minY!=0.0){ - mapController.animationHandler.animateToBox( - maxX = maxX, maxY = maxY, minX = minX, minY = minY - ) - } + } + //增加异常数据判断 + if (maxX != 0.0 && maxY != 0.0 && minX != 0.0 && minY != 0.0) { + mapController.animationHandler.animateToBox( + maxX = maxX, maxY = maxY, minX = minX, minY = minY + ) } } } @@ -181,20 +186,20 @@ class TaskViewModel @Inject constructor( /** * 高亮当前选中的link */ + @RequiresApi(Build.VERSION_CODES.M) fun showCurrentLink(link: HadLinkDvoBean) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - mapController.lineHandler.omdbTaskLinkLayer.showSelectLine(link) - val geometry = GeometryTools.createGeometry(link.geometry) - if(geometry!=null){ - val envelope = geometry.envelopeInternal - mapController.animationHandler.animateToBox( - maxX = envelope.maxX, - maxY = envelope.maxY, - minX = envelope.minX, - minY = envelope.minY - ) - } + mapController.lineHandler.omdbTaskLinkLayer.showSelectLine(link) + val geometry = GeometryTools.createGeometry(link.geometry) + if (geometry != null) { + val envelope = geometry.envelopeInternal + mapController.animationHandler.animateToBox( + maxX = envelope.maxX, + maxY = envelope.maxY, + minX = envelope.minX, + minY = envelope.minY + ) } + } override fun onCleared() { diff --git a/app/src/main/java/com/navinfo/omqs/ui/listener/QrCodeAnalyzer.kt b/app/src/main/java/com/navinfo/omqs/ui/listener/QrCodeAnalyzer.kt new file mode 100644 index 00000000..c7216cfa --- /dev/null +++ b/app/src/main/java/com/navinfo/omqs/ui/listener/QrCodeAnalyzer.kt @@ -0,0 +1,43 @@ +package com.navinfo.omqs.ui.listener + +import android.annotation.SuppressLint +import android.util.Log +import androidx.camera.core.ImageAnalysis +import androidx.camera.core.ImageProxy +import com.google.mlkit.vision.barcode.Barcode +import com.google.mlkit.vision.barcode.BarcodeScannerOptions +import com.google.mlkit.vision.barcode.BarcodeScanning +import com.google.mlkit.vision.common.InputImage + +class QRCodeAnalyser(private val listener: (List, Int, Int) -> Unit) : + ImageAnalysis.Analyzer { + //配置当前扫码格式 + private val options = BarcodeScannerOptions.Builder() + .setBarcodeFormats( + Barcode.FORMAT_QR_CODE, + Barcode.FORMAT_AZTEC + ).build() + + //获取解析器 + private val detector = BarcodeScanning.getClient(options) + + @SuppressLint("UnsafeExperimentalUsageError", "UnsafeOptInUsageError") + override fun analyze(imageProxy: ImageProxy) { + val mediaImage = imageProxy.image ?: kotlin.run { + imageProxy.close() + return + } + val image = InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees) + detector.process(image) + .addOnSuccessListener { barCodes -> + Log.e("ztzt", "barCodes: ${barCodes.size}") + if (barCodes.size > 0) { + listener.invoke(barCodes, imageProxy.width, imageProxy.height) + //接收到结果后,就关闭解析 + detector.close() + } + } + .addOnFailureListener { Log.e("ztzt", "Error: ${it.message}") } + .addOnCompleteListener { imageProxy.close() } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/ui/widget/ScanView.kt b/app/src/main/java/com/navinfo/omqs/ui/widget/ScanView.kt new file mode 100644 index 00000000..bfc487a7 --- /dev/null +++ b/app/src/main/java/com/navinfo/omqs/ui/widget/ScanView.kt @@ -0,0 +1,88 @@ +package com.navinfo.omqs.ui.widget + +import android.animation.ObjectAnimator +import android.content.Context +import android.graphics.* +import android.util.AttributeSet +import android.view.View +import androidx.core.content.ContextCompat +import com.navinfo.omqs.R + +/** + * Author:zhangteng + * description: + * date:2021/6/19 + */ +class ScanView(context: Context, attrs: AttributeSet) : View(context, attrs) { + private val circlePaint = Paint() //二维码圆圈画笔 + private var rectList: ArrayList? = null //二维码数组 + private var scanLine: Bitmap//横线 + private var isShowLine = true//是否显示扫描线 + private var animator: ObjectAnimator? = null + private var floatYFraction = 0f + set(value) { + field = value + invalidate() + } + + init { + circlePaint.apply { + this.style = Paint.Style.FILL + this.color = ContextCompat.getColor( + context, android.R.color.holo_green_dark + ) + } + + scanLine = BitmapFactory.decodeResource(resources, R.drawable.scan_light) + getAnimator().start() + } + + override fun onDraw(canvas: Canvas?) { + super.onDraw(canvas) + parseResult(canvas) + if (isShowLine) { + canvas?.drawBitmap(scanLine, (width - scanLine.width) / 2f, height * floatYFraction, circlePaint) + } + } + + private fun getAnimator(): ObjectAnimator { + if (animator == null) { + animator = ObjectAnimator.ofFloat( + this, + "floatYFraction", + 0f, + 1f + ) + animator?.duration = 5000 + animator?.repeatCount = -1 //-1代表无限循环 + } + return animator!! + } + + private fun parseResult(canvas: Canvas?) { + rectList?.let { list -> + if (list.isEmpty()) { + return + } + list.forEach { + canvas?.drawCircle( + it.left + (it.right - it.left) / 2f, + it.top + (it.bottom - it.top) / 2f, + 50f, + circlePaint + ) + } + } + } + + fun setRectList(list: ArrayList?) { + rectList = list + rectList?.let { + if (it.isNotEmpty()) { + isShowLine = false + getAnimator().cancel() + invalidate() + } + } + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-xhdpi/icon_finish_disable.png b/app/src/main/res/drawable-xhdpi/icon_finish_disable.png new file mode 100644 index 00000000..626e4b3d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_finish_disable.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_finish_nor.png b/app/src/main/res/drawable-xhdpi/icon_finish_nor.png new file mode 100644 index 00000000..c09a06a8 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_finish_nor.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_finish_press.png b/app/src/main/res/drawable-xhdpi/icon_finish_press.png new file mode 100644 index 00000000..f572d57d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_finish_press.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_forward_disable.png b/app/src/main/res/drawable-xhdpi/icon_forward_disable.png new file mode 100644 index 00000000..63978baf Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_forward_disable.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_forward_nor.png b/app/src/main/res/drawable-xhdpi/icon_forward_nor.png new file mode 100644 index 00000000..c8a5a518 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_forward_nor.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_forward_press.png b/app/src/main/res/drawable-xhdpi/icon_forward_press.png new file mode 100644 index 00000000..5beaed1d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_forward_press.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_mediaflag.png b/app/src/main/res/drawable-xhdpi/icon_mediaflag.png new file mode 100644 index 00000000..2ba4e658 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_mediaflag.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_mediaflag_disable.png b/app/src/main/res/drawable-xhdpi/icon_mediaflag_disable.png new file mode 100644 index 00000000..09f8a835 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_mediaflag_disable.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_next_disable.png b/app/src/main/res/drawable-xhdpi/icon_next_disable.png new file mode 100644 index 00000000..41a0abe7 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_next_disable.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_next_nor.png b/app/src/main/res/drawable-xhdpi/icon_next_nor.png new file mode 100644 index 00000000..fe4a563d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_next_nor.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_next_press.png b/app/src/main/res/drawable-xhdpi/icon_next_press.png new file mode 100644 index 00000000..9863d55c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_next_press.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_no_mediaflag.png b/app/src/main/res/drawable-xhdpi/icon_no_mediaflag.png new file mode 100644 index 00000000..feaf39a7 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_no_mediaflag.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_pause_nor.png b/app/src/main/res/drawable-xhdpi/icon_pause_nor.png new file mode 100644 index 00000000..e2aa3f68 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_pause_nor.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_play_disable.png b/app/src/main/res/drawable-xhdpi/icon_play_disable.png new file mode 100644 index 00000000..c421e09b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_play_disable.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_play_nor.png b/app/src/main/res/drawable-xhdpi/icon_play_nor.png new file mode 100644 index 00000000..643fb4d2 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_play_nor.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_select_point_disable.png b/app/src/main/res/drawable-xhdpi/icon_select_point_disable.png new file mode 100644 index 00000000..f0573f27 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_select_point_disable.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_select_point_nor.png b/app/src/main/res/drawable-xhdpi/icon_select_point_nor.png new file mode 100644 index 00000000..e1e8b2f9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_select_point_nor.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_select_point_press.png b/app/src/main/res/drawable-xhdpi/icon_select_point_press.png new file mode 100644 index 00000000..f0b0cbc3 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_select_point_press.png differ diff --git a/app/src/main/res/drawable-xhdpi/scan_light.png b/app/src/main/res/drawable-xhdpi/scan_light.png new file mode 100644 index 00000000..1acef0b8 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/scan_light.png differ diff --git a/app/src/main/res/drawable/map_trace_finish.xml b/app/src/main/res/drawable/map_trace_finish.xml new file mode 100644 index 00000000..013c9395 --- /dev/null +++ b/app/src/main/res/drawable/map_trace_finish.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/app/src/main/res/drawable/map_trace_forward.xml b/app/src/main/res/drawable/map_trace_forward.xml new file mode 100644 index 00000000..4f0afa14 --- /dev/null +++ b/app/src/main/res/drawable/map_trace_forward.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/app/src/main/res/drawable/map_trace_mediaflag.xml b/app/src/main/res/drawable/map_trace_mediaflag.xml new file mode 100644 index 00000000..6c196508 --- /dev/null +++ b/app/src/main/res/drawable/map_trace_mediaflag.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/app/src/main/res/drawable/map_trace_next.xml b/app/src/main/res/drawable/map_trace_next.xml new file mode 100644 index 00000000..59e80266 --- /dev/null +++ b/app/src/main/res/drawable/map_trace_next.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/app/src/main/res/drawable/map_trace_pause.xml b/app/src/main/res/drawable/map_trace_pause.xml new file mode 100644 index 00000000..006cc188 --- /dev/null +++ b/app/src/main/res/drawable/map_trace_pause.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/app/src/main/res/drawable/map_trace_select_point.xml b/app/src/main/res/drawable/map_trace_select_point.xml new file mode 100644 index 00000000..0c0ed8bb --- /dev/null +++ b/app/src/main/res/drawable/map_trace_select_point.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index c45d8fb2..eb4204c8 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -130,6 +130,73 @@ android:elevation="2dp" android:onClick="@{()->mainActivity.onClickMenu()}" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_result.xml b/app/src/main/res/layout/activity_result.xml new file mode 100644 index 00000000..37e4275c --- /dev/null +++ b/app/src/main/res/layout/activity_result.xml @@ -0,0 +1,19 @@ + + + + + +