package com.example.chemical.ui.verify import android.os.* import android.view.LayoutInflater import android.view.MotionEvent import android.view.View import android.widget.TextView import com.bumptech.glide.Glide import com.bumptech.glide.load.engine.DiskCacheStrategy import com.bumptech.glide.request.RequestOptions import com.example.chemical.ChemicalApp import com.example.chemical.R import com.example.chemical.comm.Constants import com.example.chemical.databinding.ActivityTwoPersonBinding import com.example.chemical.ui.DoubleDialogBean import com.example.chemical.ui.common.BaseCountDownActivity import com.example.chemical.utils.MediaPlayerHelper import com.example.chemical.utils.SharedPreferencesHelper import com.example.chemical.utils.UiManager import com.example.chemical.weidith.CustomDialog import com.example.chemical.weidith.DoublePeopleDialog import com.rc.core.log.RcLog import com.rc.httpcore.HttpClient import com.rc.httpcore.HttpConfig import com.rc.httpcore.bean.UserValidationBean import com.rc.httpcore.client.ApiRepository import com.rc.httpcore.exception.NetException import com.rc.httpcore.vo.request.FaceCompareReq import io.fotoapparat.Fotoapparat import io.fotoapparat.facedetector.processor.FaceDetectorProcessor import io.fotoapparat.log.fileLogger import io.fotoapparat.log.logcat import io.fotoapparat.log.loggers import io.fotoapparat.selector.back import io.fotoapparat.selector.front import retrofit2.HttpException import java.io.File import java.net.ConnectException import java.net.SocketTimeoutException import java.text.SimpleDateFormat import java.util.* //双人-人脸验证 class TwoPersonActivity : BaseCountDownActivity() { //第一个人 private lateinit var mFotoapparat: Fotoapparat //第二个人 private lateinit var mFotoapparatTwo: Fotoapparat //人脸验证时间 private val totalTimeInMillis: Long = 60 * 1000 // 总时常 private var count = 1 //认证次数 private var mChemicalLevel: Int = 0 //管控类型 private var mTag = 0 //0 新增入库 1 归还废弃空瓶等 2 待入库 3 领用认证需要换api 需要判断不同权限 进行验证通过 private var mUserId: String? = null //第二个人 private var mDoorId: String? = null private var isLogin = false //是否是登陆人 private val mDoubleDialogBean = mutableListOf() //双人认证 需要显示的 private val handlerBack = Handler(Looper.getMainLooper()) private val handlerBackTwo = Handler(Looper.getMainLooper()) private val countHandler = Handler(Looper.getMainLooper()) //整个页面 60秒后 直接关闭 override fun createViewBinding() = ActivityTwoPersonBinding.inflate(LayoutInflater.from(this)) override fun initViews(savedInstanceState: Bundle?) { super.initViews(savedInstanceState) Constants.AUTHENTICATION = false try { SharedPreferencesHelper.clearList(this) } catch (e: Exception) { } viewBinding.deptName.text = "${ChemicalApp.confs!!.deptName}-${ChemicalApp.confs!!.roomNum}" viewBinding.tvReturn.text = "返回${ChemicalApp.confs!!.backTime}s" Glide.with(this) .load("${HttpConfig.API_BASE_IMG_URL}${ChemicalApp.confs!!.circularLogo}") .apply(RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.AUTOMATIC)) .into(viewBinding.image) mTag = intent.getIntExtra("mTag", 0) mDoorId = intent.getStringExtra("doorId") //柜子id mChemicalLevel = intent.getIntExtra("chemicalLevel", 0) val intExtra = intent.getIntExtra("hides", 0) when (intExtra) { 4 -> { viewBinding.lint.visibility = View.GONE viewBinding.lintTwo.visibility = View.GONE } 0 -> { viewBinding.scan.visibility = View.GONE viewBinding.scanTwo.visibility = View.GONE } 1 -> { viewBinding.campus.visibility = View.GONE viewBinding.campusTwo.visibility = View.GONE } } val map = mutableMapOf() //跳转扫码 map["chemicalLevel"] = mChemicalLevel //管控类型 map["doorId"] = "$mDoorId" //柜子id map["mTag"] = mTag map["hides"] = intExtra //隐藏扫码 viewBinding.scan.setOnClickListener { UiManager.switcher(this, map, ScanCodeTwoActivity::class.java) finish() } viewBinding.campus.setOnClickListener { UiManager.switcher(this, map, SwipeCodeTwoActivity::class.java) finish() } viewBinding.scanTwo.setOnClickListener { UiManager.switcher(this, map, ScanCodeTwoActivity::class.java) finish() } viewBinding.campusTwo.setOnClickListener { UiManager.switcher(this, map, SwipeCodeTwoActivity::class.java) finish() } viewBinding.tvReturn.setOnClickListener { finish() } mFotoapparat = Fotoapparat.with(this) .into(viewBinding.cameraView) .lensPosition( if (Constants.FACE_TAG == 0) { front() } else { back() } )//front()前置 back 后置 .frameProcessor( FaceDetectorProcessor.with(this) .listener { faces -> RcLog.info("=========认证中") viewBinding.rectanglesView.setRectangles(faces) }.build() ) .logger(loggers(logcat(), fileLogger(this))) .build() MediaPlayerHelper.playRawMp3( this@TwoPersonActivity, R.raw.diyiren_renlianshibie ) handlerBackTwo.post(countdownRunnableTwo) countHandler.postDelayed({ finish() }, totalTimeInMillis) // 15秒后关闭对话框 } override fun onStart() { super.onStart() mFotoapparat.start() } override fun onStop() { super.onStop() try { mFotoapparat.stop() } catch (e: Exception) { } try { mFotoapparatTwo.stop() } catch (e: Exception) { } } private fun toggleCameraTwo() { mFotoapparat.stop() //停止第一个 打开第二个 mFotoapparatTwo.stop() mFotoapparatTwo.start() } //第二个人脸 private fun faceTwo() { count++ // toggleCameraTwo() mFotoapparatTwo = Fotoapparat.with(this) .into(viewBinding.cameraViewTwo) .lensPosition( if (Constants.FACE_TAG == 0) { front() } else { back() } )//front()前置 back 后置 .frameProcessor( FaceDetectorProcessor.with(this) .listener { faces -> viewBinding.rectanglesViewTwo.setRectangles(faces) }.build() ) .logger(loggers(logcat(), fileLogger(this))) .build() mFotoapparatTwo.stop() mFotoapparatTwo.start() } private val countdownRunnableTwo = object : Runnable { override fun run() { // if (timeLeftInSeconds > 0) { // mTvView!!.text = "${timeLeftInSeconds}秒后自动返回首页" // timeLeftInSeconds-- // handlerBack.postDelayed(this, 1000) // } else { // mDialogsAut!!.dismiss() // finish() // } RcLog.info("=======双人刷卡人脸认证中") takePicture() handlerBackTwo.postDelayed(this, 4500) } } override fun onBackPressed() { super.onBackPressed() finish() } override fun cdTime(cd: Int) { viewBinding.tvReturn.text = "返回${cd}s" } private fun callFaceMatchingApi( featureData: File, ) { showLoading("认证中....") val param = FaceCompareReq().apply { data = null subId = ChemicalApp.subjectId doorId = mDoorId } val disposable = ApiRepository.checkUserFaceByPic(featureData, param) .subscribe({ data -> dismissLoading() // if (count == 1) { // RcLog.info("第a一个人 $mUserId ${data.userId}") // } if (mUserId!=null){ if (mUserId.equals(data.userId)) { customDialogView(0, "不能是同一个人") // startHandler() return@subscribe } } //0 新增入库 1 领用归还废弃空瓶等 2 待入库 需要判断不同权限 进行验证通过 when (mTag) { 0 -> { //新增入库 if (count == 1) { if (data.userId == ChemicalApp.userData!!.userId) { isLogin = true faceTwo() customDialog(data.userName, data.faceImg,data.userId) var bean = DoubleDialogBean(data.userName, data.faceImg, data.userId) mDoubleDialogBean.add(bean) } else { if (mChemicalLevel == 1) { //管控 校级管理员或院级管理 if (data.adminUser == true || data.safeUser == true || data.cabinetAdmin == true) { var bean = DoubleDialogBean( data.userName, data.faceImg, data.userId ) mDoubleDialogBean.add(bean) customDialog(data.userName, data.faceImg, data.userId) faceTwo() // if (count == 2) { // var bean = DoubleDialogBean( // data.userName, // data.faceImg, // data.userId // ) // mDoubleDialogBean.add(bean) // customDialog(data.userName, data.faceImg, data.userId) // faceTwo() // } else { // var bean = DoubleDialogBean( // data.userName, // data.faceImg, // data.userId // ) // mDoubleDialogBean.add(bean) // passThrough() // } } else { customDialogView(0, "无权限信息") } } else { if (data.adminUser == true || data.safeUser == true || data.cabinetAdmin == true) { faceTwo() customDialog(data.userName, data.faceImg, data.userId) var bean = DoubleDialogBean( data.userName, data.faceImg, data.userId ) mDoubleDialogBean.add(bean) // if (count == 2) { // faceTwo() // customDialog(data.userName, data.faceImg, data.userId) // var bean = DoubleDialogBean( // data.userName, // data.faceImg, // data.userId // ) // mDoubleDialogBean.add(bean) // } else { // var bean = DoubleDialogBean( // data.userName, // data.faceImg, // data.userId // ) // mDoubleDialogBean.add(bean) // passThrough() // } } else { customDialogView(0, "无权限信息") } } } } else { if (isLogin) { //已经有登陆人 if (mChemicalLevel == 1) { //管控 校级管理员或院级管理 if (data.adminUser == true || data.safeUser == true || data.cabinetAdmin == true) { var bean = DoubleDialogBean( data.userName, data.faceImg, data.userId ) mDoubleDialogBean.add(bean) passThrough() } else { customDialogView(0, "无权限信息") } } else { if (data.adminUser == true || data.safeUser == true || data.cabinetAdmin == true) { var bean = DoubleDialogBean( data.userName, data.faceImg, data.userId ) mDoubleDialogBean.add(bean) passThrough() } else { customDialogView(0, "无权限信息") } } } else { if (data.userId == ChemicalApp.userData!!.userId) { var bean = DoubleDialogBean( data.userName, data.faceImg, data.userId ) mDoubleDialogBean.add(bean) passThrough() } else { customDialogView(0, "无权限信息") } } } } 1 -> { //归还业务 标签管理 if (count == 1) { if (data.userId == ChemicalApp.userData!!.userId) { isLogin = true faceTwo() customDialog(data.userName, data.faceImg, data.userId) var bean = DoubleDialogBean(data.userName, data.faceImg, data.userId) mDoubleDialogBean.add(bean) } else { obtainCertification(data) } } else { if (isLogin) { if (data.adminUser == true || data.safeUser == true || data.cabinetAdmin == true) { var bean = DoubleDialogBean( data.userName, data.faceImg, data.userId ) mDoubleDialogBean.add(bean) passThrough() } else { customDialogView(0, "认证失败") } } else { if (data.userId == ChemicalApp.userData!!.userId) { var bean = DoubleDialogBean( data.userName, data.faceImg, data.userId ) mDoubleDialogBean.add(bean) passThrough() } else { customDialogView(0, "认证失败") } } } } 2 -> {//待入库 if (count == 1) { if (data.userId == ChemicalApp.userData!!.userId) { isLogin = true count++ faceTwo() customDialog(data.userName, data.faceImg, data.userId) var bean = DoubleDialogBean(data.userName, data.faceImg, data.userId) mDoubleDialogBean.add(bean) } else { toBeStored(data) } } else { if (isLogin) { if (mChemicalLevel == 1) { //管控 if (data.adminUser == true || data.safeUser == true || data.cabinetAdmin == true) { var bean = DoubleDialogBean( data.userName, data.faceImg, data.userId ) mDoubleDialogBean.add(bean) passThrough() } else { customDialogView(0, "认证失败") } } else { //非管控 实验室负责人or安全负责人or柜锁管理员 if (data.safeUser == true || data.adminUser == true || data.cabinetAdmin == true) { var bean = DoubleDialogBean( data.userName, data.faceImg, data.userId ) mDoubleDialogBean.add(bean) passThrough() } else { customDialogView(0, "认证失败") } } } else { if (data.userId == ChemicalApp.userData!!.userId) { var bean = DoubleDialogBean( data.userName, data.faceImg, data.userId ) mDoubleDialogBean.add(bean) passThrough() } else { customDialogView(0, "认证失败") } } } } } }, { throwable -> dismissLoading() // mFotoapparat.stop() // handlerBack.removeCallbacks(countdownRunnable) // handlerBack.removeCallbacksAndMessages(null) throwableView(throwable) }) addDisposable(disposable) } private fun obtainCertification(data: UserValidationBean) { //校级管理员 schoolLevelAdmin //院级管理员 collegeAdmin //实验室负责人 adminUser //安全负责人 safeUser //柜锁管理员 cabinetAdmin //是否化学品归属人 belongUser //是否化学品归属课题组下成员 toipcUser if (data.adminUser == true || data.safeUser == true || data.cabinetAdmin == true) { count++ faceTwo() customDialog(data.userName, data.faceImg, data.userId) var bean = DoubleDialogBean(data.userName, data.faceImg, data.userId) mDoubleDialogBean.add(bean) } else { customDialogView(0, "认证失败") } } private fun toBeStored(data: UserValidationBean) { //校级管理员 schoolLevelAdmin //院级管理员 collegeAdmin //实验室负责人 adminUser //安全负责人 safeUser //柜锁管理员 cabinetAdmin //是否化学品归属人 belongUser //是否化学品归属课题组下成员 toipcUser if (mChemicalLevel == 1) { //管控 if (data.belongUser == true || data.toipcUser == true || data.adminUser == true || data.safeUser == true || data.cabinetAdmin == true) { count++ faceTwo() customDialog(data.userName, data.faceImg, data.userId) var bean = DoubleDialogBean(data.userName, data.faceImg, data.userId) mDoubleDialogBean.add(bean) } else { customDialogView(0, "认证失败") } } else { //非管控 实验室负责人or安全负责人or柜锁管理员 if (data.safeUser == true || data.adminUser == true || data.cabinetAdmin == true) { count++ faceTwo() customDialog(data.userName, data.faceImg, data.userId) var bean = DoubleDialogBean(data.userName, data.faceImg, data.userId) mDoubleDialogBean.add(bean) } else { customDialogView(0, "认证失败") } } } private fun customDialog(userName: String, imgUrl: String?, userId: String) { mUserId = userId viewBinding.through.visibility = View.VISIBLE viewBinding.userName.text = "$userName" Glide.with(this) .load("${HttpConfig.API_BASE_IMG_URL}$imgUrl") .apply(RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.AUTOMATIC)) .error(R.mipmap.icon_zhan_wei) .into(viewBinding.imgView) MediaPlayerHelper.playRawMp3(this@TwoPersonActivity, R.raw.dierwei_renlianshibie) } private fun takePicture() { val format = SimpleDateFormat("yyyyMMdd_HHmmssSSS", Locale.getDefault()) val fileName = "${format.format(Calendar.getInstance().time)}.jpg" val photoFile = File(this.getExternalFilesDir("photos"), fileName) RcLog.info("==========当前认证数 $count") if (count == 1) { mFotoapparat.takePicture() .saveToFile(photoFile) .whenAvailable { RcLog.info("=====人脸识别D=${HttpClient.token} $it $photoFile") callFaceMatchingApi(photoFile) } } else { mFotoapparatTwo.takePicture() .saveToFile(photoFile) .whenAvailable { RcLog.info("=====人脸识别B=${HttpClient.token}") callFaceMatchingApi(photoFile) } } } override fun onDestroy() { super.onDestroy() try { RcLog.info("=====清空双人认证1 人脸信息") mFotoapparat.stop() RcLog.info("=====清空双人认证2 人脸信息") RcLog.info("=====清空双人认证3 人脸信息") handlerBackTwo.removeCallbacks(countdownRunnableTwo) RcLog.info("=====清空双人认证4 人脸信息") handlerBackTwo.removeCallbacksAndMessages(null) RcLog.info("=====清空双人认证5 人脸信息") } catch (e: Exception) { } try { mFotoapparatTwo.stop() RcLog.info("=====清空双人认证6 人脸信息") } catch (e: Exception) { } try { handlerBack.removeCallbacks(countdownRunnable) RcLog.info("=====清空双人认证7 人脸信息") } catch (e: Exception) { } try { handlerBack.removeCallbacksAndMessages(null) RcLog.info("=====清空双人认证8 人脸信息") } catch (e: Exception) { } try { countHandler.removeCallbacksAndMessages(null) } catch (e: Exception) { } } /** * 0 没有图标 1 绿色(成功) 2红色(失败) * 失败或者成功的弹框 */ private fun customDialogView(types: Int, msg: String) { val customDialog = CustomDialog(this, types, msg) if (!this.isFinishing && !this.isDestroyed) { customDialog.show() } } /** * 异常处理 */ private fun throwableView(throwable: Throwable) { when (throwable) { is NetException -> { if (throwable.message.isNullOrEmpty()) { "接口请求失败(${throwable.code})" } else { throwable.message!! } } is SocketTimeoutException -> "请求超时,请稍后重试" is ConnectException -> "无法连接服务器,请检查网络" is HttpException -> "服务器繁忙,请稍后重试" else -> null }?.let { customDialogView(2, "$it") } } private lateinit var dialogsAut: DoublePeopleDialog private var timeLeftInSeconds = 2 private var mTvView: TextView? = null //验证通过 private fun passThrough() { // 在需要时关闭定时器 try { RcLog.info("=====清空双人认证3 人脸信息") mFotoapparatTwo.stop() handlerBackTwo.removeCallbacks(countdownRunnableTwo) RcLog.info("=====清空双人认证4 人脸信息") handlerBackTwo.removeCallbacksAndMessages(null) } catch (e: Exception) { } Constants.AUTHENTICATION = true // 存储集合到 SharedPreferences SharedPreferencesHelper.saveList(this, mDoubleDialogBean) dialogsAut = DoublePeopleDialog(this, mDoubleDialogBean, object : DoublePeopleDialog.IClickLit { override fun onUpView(tvView: TextView) { mTvView = tvView } }) dialogsAut.show() // 开始倒计时 handlerBack.post(countdownRunnable) // 获取对话框的 Window 对象 dialogsAut?.window?.decorView?.setOnTouchListener { _, event -> // 判断是否点击了对话框外部空白区域 if (event.action == MotionEvent.ACTION_DOWN) { val x = event.x val y = event.y val dialogView = dialogsAut?.window?.decorView if (dialogView != null && (x < 0 || x > dialogView.width || y < 0 || y > dialogView.height)) { // 在此处执行点击对话框外部空白区域时的操作 // 例如关闭对话框 dialogsAut.dismiss() finish() return@setOnTouchListener true } } return@setOnTouchListener false } MediaPlayerHelper.playRawMp3(this, R.raw.shuangren_tongguo) } private val countdownRunnable = object : Runnable { override fun run() { if (timeLeftInSeconds > 0) { mTvView!!.text = "${timeLeftInSeconds}秒后自动返回首页" timeLeftInSeconds-- handlerBack.postDelayed(this, 1000) } else { dialogsAut!!.dismiss() finish() } } } }