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..ca45c1db 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,6 +36,9 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/java/com/navinfo/omqs/Constant.kt b/app/src/main/java/com/navinfo/omqs/Constant.kt
index ed6d845b..8e7477a7 100644
--- a/app/src/main/java/com/navinfo/omqs/Constant.kt
+++ b/app/src/main/java/com/navinfo/omqs/Constant.kt
@@ -45,6 +45,11 @@ class Constant {
*/
lateinit var DOWNLOAD_PATH: String
+ /**
+ * 室内整理工具IP
+ */
+ lateinit var INDOOR_IPS: 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/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/http/NetworkService.kt b/app/src/main/java/com/navinfo/omqs/http/NetworkService.kt
index 5fe4dd2d..2fee5544 100644
--- a/app/src/main/java/com/navinfo/omqs/http/NetworkService.kt
+++ b/app/src/main/java/com/navinfo/omqs/http/NetworkService.kt
@@ -3,6 +3,7 @@ package com.navinfo.omqs.http
import com.navinfo.omqs.bean.OfflineMapCityBean
import com.navinfo.collect.library.data.entity.TaskBean
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 +16,20 @@ 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>
}
\ 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..cf6bdcdd 100644
--- a/app/src/main/java/com/navinfo/omqs/http/NetworkServiceImpl.kt
+++ b/app/src/main/java/com/navinfo/omqs/http/NetworkServiceImpl.kt
@@ -3,6 +3,7 @@ package com.navinfo.omqs.http
import com.navinfo.omqs.bean.OfflineMapCityBean
import com.navinfo.collect.library.data.entity.TaskBean
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 +76,23 @@ 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)
+ 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..d948588a 100644
--- a/app/src/main/java/com/navinfo/omqs/http/RetrofitNetworkServiceAPI.kt
+++ b/app/src/main/java/com/navinfo/omqs/http/RetrofitNetworkServiceAPI.kt
@@ -4,6 +4,7 @@ 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.LoginUserBean
+import com.navinfo.omqs.bean.QRCodeBean
import com.navinfo.omqs.bean.SysUserBean
import okhttp3.ResponseBody
import retrofit2.Response
@@ -64,6 +65,14 @@ interface RetrofitNetworkServiceAPI {
@Query("evaluatorNo") evaluatorNo: String,
): Response>>
+
+
+ /**
+ * 获取离线地图城市列表
+ */
+ @GET("/drdc/MapDownload/maplist")
+ suspend fun retrofitConnectIndoorTools(@Url url: String): 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/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/map/MainActivity.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt
index 286bf347..2e158b6c 100644
--- a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt
+++ b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt
@@ -123,8 +123,6 @@ class MainActivity : BaseActivity() {
checkIntent.action = TextToSpeech.Engine.ACTION_CHECK_TTS_DATA
someActivityResultLauncher.launch(checkIntent)
-
-
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
//初始化地图
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..3160edbf
--- /dev/null
+++ b/app/src/main/java/com/navinfo/omqs/ui/activity/scan/QRCodeActivity.kt
@@ -0,0 +1,125 @@
+package com.navinfo.omqs.ui.activity.scan
+
+import android.annotation.SuppressLint
+import android.content.Intent
+import android.graphics.Rect
+import android.graphics.RectF
+import android.os.Bundle
+import android.util.Log
+import androidx.activity.viewModels
+import androidx.appcompat.app.AppCompatActivity
+import androidx.camera.core.ImageCapture
+import androidx.camera.view.LifecycleCameraController
+import androidx.databinding.DataBindingUtil
+import androidx.lifecycle.viewModelScope
+import com.navinfo.omqs.R
+import com.navinfo.omqs.databinding.ActivityQrCodeBinding
+import com.navinfo.omqs.ui.activity.login.LoginViewModel
+import com.navinfo.omqs.ui.listener.QRCodeAnalyser
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Executors
+
+/**
+ * date:2021/6/18
+ * author:zhangteng
+ * description:二维码扫描
+ */
+class QRCodeActivity : AppCompatActivity() {
+ 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
+
+ initController()
+ }
+
+ @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) {
+ viewModel.connect(this, result)
+
+ Log.e("qj", "QRCodeActivity === $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/activity/scan/QRCodeViewModel.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/scan/QRCodeViewModel.kt
new file mode 100644
index 00000000..12b767c5
--- /dev/null
+++ b/app/src/main/java/com/navinfo/omqs/ui/activity/scan/QRCodeViewModel.kt
@@ -0,0 +1,151 @@
+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.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 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 {
+ /**
+ * 访问服务器登陆中
+ */
+ LOGIN_STATUS_NET_LOADING,
+
+ /**
+ * 访问离线地图列表
+ */
+ LOGIN_STATUS_NET_OFFLINE_MAP,
+
+ /**
+ * 初始化文件夹
+ */
+ LOGIN_STATUS_FOLDER_INIT,
+
+ /**
+ * 创建文件夹失败
+ */
+ LOGIN_STATUS_FOLDER_FAILURE,
+
+ /**
+ * 网络访问失败
+ */
+ LOGIN_STATUS_NET_FAILURE,
+
+ /**
+ * 成功
+ */
+ LOGIN_STATUS_SUCCESS,
+
+ /**
+ * 取消
+ */
+ LOGIN_STATUS_CANCEL,
+}
+
+@HiltViewModel
+class QRCodeViewModel @Inject constructor(
+ private val networkService: NetworkService
+) : ViewModel() {
+ //用户信息
+ val qrCodeBean: MutableLiveData = MutableLiveData()
+
+ //是不是连接成功
+ val qrCodeStatus: MutableLiveData = MutableLiveData()
+
+ var jobQRCodeStatus: Job? = null;
+
+ 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 DefaultResponse
+ if (defaultUserResponse.success) {
+
+ } else {
+ withContext(Dispatchers.Main) {
+ Toast.makeText(
+ context,
+ "${defaultUserResponse.msg}",
+ Toast.LENGTH_SHORT
+ )
+ .show()
+ }
+ }
+
+ } catch (e: IOException) {
+ }
+ }
+ }
+
+ 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()
+ }
+ }
+
+ else -> {}
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
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 82b04705..5667aa16 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,10 @@ class PersonalCenterFragment(private var backListener: (() -> Unit?)? = null) :
R.id.personal_center_menu_layer_manager -> { // 图层管理
findNavController().navigate(R.id.QsLayerManagerFragment)
}
+ R.id.personal_center_menu_scan_qr_code -> {
+ //跳转二维码扫描界面
+ checkPermission()
+ }
}
true
}
@@ -134,6 +141,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 +159,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/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/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/layout/activity_qr_code.xml b/app/src/main/res/layout/activity_qr_code.xml
new file mode 100644
index 00000000..a802f372
--- /dev/null
+++ b/app/src/main/res/layout/activity_qr_code.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ 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 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/personal_center_menu.xml b/app/src/main/res/menu/personal_center_menu.xml
index f0aee773..c181edb5 100644
--- a/app/src/main/res/menu/personal_center_menu.xml
+++ b/app/src/main/res/menu/personal_center_menu.xml
@@ -22,6 +22,10 @@
android:id="@+id/personal_center_menu_import_yuan_data"
android:icon="@drawable/ic_baseline_scatter_plot_24"
android:title="导入元数据" />
+