123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362 |
- package xn.hxp.ui.login
- import android.os.Bundle
- import android.os.Handler
- import android.os.Looper
- import android.util.Log
- import android.view.LayoutInflater
- import android.view.MotionEvent
- import android.view.View
- import android.widget.TextView
- import androidx.viewbinding.ViewBinding
- import com.blankj.utilcode.util.LogUtils
- import com.bumptech.glide.Glide
- import com.bumptech.glide.load.engine.DiskCacheStrategy
- import com.bumptech.glide.request.RequestOptions
- import com.rc.core.ui.activity.BaseActivity
- import com.rc.httpcore.HttpClient
- import com.rc.httpcore.HttpConfig
- 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 xn.hxp.R
- import xn.hxp.app.ChemicalApp
- import xn.hxp.comm.Constants
- import xn.hxp.databinding.ActivityFacialLoginBinding
- import xn.hxp.utils.AudioPlayer
- import xn.hxp.utils.UiManager
- import xn.hxp.weidith.AuthenticationDialog
- import xn.hxp.weidith.CustomDialog
- import java.io.File
- import java.lang.Boolean
- import java.net.ConnectException
- import java.net.SocketTimeoutException
- import java.text.SimpleDateFormat
- import java.util.Calendar
- import java.util.Locale
- /**
- * 人脸登录
- */
- class FacialLoginActivity : BaseActivity() {
- private lateinit var mFotoapparat: Fotoapparat
- // private lateinit var mCountDownTimer: CountDownTimer
- private lateinit var faceList: String
- private val handlerBack = Handler(Looper.getMainLooper())
- private var timeLeftInSeconds = 2
- private var mTvView: TextView? = null
- private var mDialogsAut: AuthenticationDialog? = null
- lateinit var viewBinding: ActivityFacialLoginBinding
- override fun setViewBinding(): ViewBinding {
- viewBinding = ActivityFacialLoginBinding.inflate(layoutInflater)
- return viewBinding
- }
- override fun onInit() {
- AudioPlayer.getInstance().play(R.raw.face_detect_hint)
- // 使用 Glide 加载网络图片
- viewBinding.deptName.text = "${ChemicalApp.confs!!.deptName}-${ChemicalApp.confs!!.roomNum}"
- Glide.with(this)
- .load("${HttpConfig.API_BASE_IMG_URL}${ChemicalApp.confs!!.circularLogo}")
- .apply(RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.AUTOMATIC))
- .into(viewBinding.image)
- var str = ""
- try {
- str = intent.getStringExtra("faceList")!!
- } catch (e: Exception) {
- }
- val mtypes = intent.getStringExtra("mtypes")
- try {
- when (mtypes) {
- "1" -> {
- viewBinding.linType.visibility = View.GONE
- }
- "4" -> {
- viewBinding.tvScan.visibility = View.GONE
- }
- "5" -> {
- viewBinding.tvSwipe.visibility = View.GONE
- }
- }
- } catch (e: Exception) {
- }
- val map = mutableMapOf<String, String>()
- if (mtypes != null) {
- map["mtypes"] = mtypes
- }
- if (str != null && str.length > 0) {
- // 去除字符串首尾的中括号
- faceList = str.removeSurrounding("[", "]")
- map["faceList"] = str
- }
- //跳转刷卡登录
- viewBinding.tvSwipe.setOnClickListener {
- UiManager.switcher(this, map, SwipeActivity::class.java)
- finish()
- }
- //跳转扫码登录
- viewBinding.tvScan.setOnClickListener {
- UiManager.switcher(this, map, ScanLoginActivity::class.java)
- finish()
- }
- viewBinding.tvReturn.text = "返回${ChemicalApp.confs!!.backTime}s"
- 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 ->
- viewBinding.rectanglesView.setRectangles(faces)
- }.build()
- )
- .logger(loggers(logcat(), fileLogger(this)))
- .build()
- mFotoapparat.stop()
- mFotoapparat.start()
- handlerBack.post(countdownRunnableTwo)
- }
- override fun onBackPressed() {
- super.onBackPressed()
- finish()
- }
- override fun cdTime(cd: Int) {
- viewBinding.tvReturn.text = "返回${cd}s"
- }
- override fun onDestroy() {
- super.onDestroy()
- if (null != mDialogsAut && mDialogsAut!!.isShowing) {
- mDialogsAut!!.dismiss()
- }
- // cancelTime()//手动关闭
- LogUtils.i("=============onDestroy")
- // handlerUtil.removeCallbacks(task)
- // handlerUtil.stopAllTasks()
- // 移除回调,以防止内存泄漏
- try {
- mFotoapparat.stop()
- handlerBack.removeCallbacks(countdownRunnable)
- handlerBack.removeCallbacks(countdownRunnableTwo)
- handlerBack.removeCallbacksAndMessages(null)
- dismissLoading()
- } catch (e: Exception) {
- }
- }
- override fun cdFinish() {
- finish()
- }
- private fun takePicture() {
- LogUtils.i("=======111人脸登录任务进行中")
- val format = SimpleDateFormat("yyyyMMdd_HHmmssSSS", Locale.getDefault())
- val fileName = "${format.format(Calendar.getInstance().time)}.jpg"
- val photoFile = File(this.getExternalFilesDir("photos"), fileName)
- try {
- mFotoapparat.takePicture()
- .saveToFile(photoFile)
- .whenAvailable {
- callFaceMatchingApi(photoFile)
- }
- } catch (e: Exception) {
- }
- }
- private fun callFaceMatchingApi(
- featureData: File,
- ) {
- showLoading("比对中....")
- val param = FaceCompareReq().apply {
- data = null
- userIds = faceList
- }
- val disposable = ApiRepository.faceCompare(featureData, param)
- .subscribe({ success ->
- dismissLoading()
- ChemicalApp.userData = success
- LogUtils.d(success.userId, ChemicalApp.subjectId)
- authenticationInfo(success.userId, ChemicalApp.subjectId!!)
- }, { throwable ->
- dismissLoading()
- throwableView(throwable)
- })
- addDisposable(disposable)
- }
- //验证当前人员身份
- private fun authenticationInfo(userId: String, subId: String) {
- LogUtils.d(userId, subId)
- showLoading("验证中...")
- val disposable = ApiRepository.userCardValidation(userId, subId)
- .subscribe({ data ->
- dismissLoading()
- val allFalse =
- Boolean.TRUE == data.cabinetAdmin || Boolean.TRUE == data.belongUser || Boolean.TRUE == data.toipcUser || Boolean.TRUE == data.safeUser || Boolean.TRUE == data.collegeAdmin || Boolean.TRUE == data.schoolLevelAdmin || Boolean.TRUE == data.adminUser || Boolean.TRUE == data.apply || Boolean.TRUE == data.white
- if (!allFalse) {
- HttpClient.token = null
- ChemicalApp.userData = null
- customDialogView(2, "身份认证不通过")
- } else {
- //校级管理员 schoolLevelAdmin
- //院级管理员 collegeAdmin
- //实验室负责人 adminUser
- //安全负责人 safeUser
- //柜锁管理员 cabinetAdmin
- //是否化学品归属人 belongUser
- //是否化学品归属课题组下成员 toipcUser
- if (data.schoolLevelAdmin == true || data.collegeAdmin == true) {
- //院级管理员 or 校级管理员
- authenticationDialog(data.faceImg, data.userName)
- } else if (data.adminUser == true || data.safeUser == true || data.cabinetAdmin == true) {
- //实验室负责人 or 安全负责人 or 柜锁管理员
- authenticationDialog(data.faceImg, data.userName)
- } else if (data.belongUser == true || data.toipcUser == true) { //当前身份 归属人or课题组
- authenticationDialog(data.faceImg, data.userName)
- } else if (data.white == true || data.apply == true) {// 白名单和实验室准入
- authenticationDialog(data.faceImg, data.userName)
- } else {
- HttpClient.token = null
- ChemicalApp.userData = null
- customDialogView(2, "身份认证不通过")
- }
- }
- }, { throwable ->
- dismissLoading()
- //暂时注释掉 防止异步请求后 在认证时 token 丢失
- // startCountdownAndExecuteMethod()
- throwableView(throwable)
- })
- addDisposable(disposable)
- }
- //身份认证成功
- private fun authenticationDialog(faceImg: String?, userName: String) {
- mFotoapparat.stop()
- handlerBack.removeCallbacks(countdownRunnableTwo)
- AudioPlayer.getInstance().play(R.raw.verify_success)
- mDialogsAut = AuthenticationDialog(
- this,
- faceImg,
- ChemicalApp.confs!!.subName,
- ChemicalApp.confs!!.deptName,
- "${ChemicalApp.confs!!.buildName}${ChemicalApp.confs!!.floorName}",
- userName, object : AuthenticationDialog.IClickLit {
- override fun onUpView(tvView: TextView) {
- mTvView = tvView
- }
- })
- mDialogsAut!!.show()
- // 开始倒计时
- handlerBack.post(countdownRunnable)
- // 获取对话框的 Window 对象
- mDialogsAut!!.window?.decorView?.setOnTouchListener { _, event ->
- // 判断是否点击了对话框外部空白区域
- if (event.action == MotionEvent.ACTION_DOWN) {
- val x = event.x
- val y = event.y
- val dialogView = mDialogsAut!!.window?.decorView
- if (dialogView != null && (x < 0 || x > dialogView.width || y < 0 || y > dialogView.height)) {
- // 在此处执行点击对话框外部空白区域时的操作
- // 例如关闭对话框
- // 移除回调,以防止内存泄漏
- mDialogsAut!!.dismiss()
- finish()
- return@setOnTouchListener true
- }
- }
- return@setOnTouchListener false
- }
- }
- private val countdownRunnable = object : Runnable {
- override fun run() {
- if (timeLeftInSeconds > 0) {
- mTvView!!.text = "${timeLeftInSeconds}秒后自动返回首页"
- timeLeftInSeconds--
- handlerBack.postDelayed(this, 1000)
- } else {
- mDialogsAut!!.dismiss()
- finish()
- }
- }
- }
- private val countdownRunnableTwo = object : Runnable {
- override fun run() {
- takePicture()
- handlerBack.postDelayed(this, 4000)
- }
- }
- /**
- * 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) {
- LogUtils.e(Log.getStackTraceString(throwable))
- when (throwable) {
- is NetException -> {
- if (throwable.message.isNullOrEmpty()) {
- "接口请求失败(${throwable.code})"
- } else {
- throwable.message!!
- }
- }
- is SocketTimeoutException -> "请求超时,请稍后重试"
- is ConnectException -> "无法连接服务器,请检查网络"
- is HttpException -> "服务器繁忙,请稍后重试"
- else -> "服务器异常"
- }?.let { customDialogView(2, "$it") }
- }
- }
|