Explorar o código

添加指纹登录功能

Frankensteinly hai 8 meses
pai
achega
df21dfc9f5

+ 360 - 0
app/src/main/java/com/grkj/iscs/util/FingerprintUtil.kt

@@ -0,0 +1,360 @@
+package com.grkj.iscs.util
+
+import android.Manifest
+import android.content.Context
+import android.graphics.Bitmap
+import android.hardware.usb.UsbDevice
+import android.hardware.usb.UsbManager
+import android.util.Base64
+import android.util.Log
+import androidx.appcompat.app.AppCompatActivity.USB_SERVICE
+import com.grkj.iscs.MyApplication
+import com.grkj.iscs.util.log.LogUtil
+import com.grkj.iscs.view.activity.test.fingerprint.DBManager
+import com.grkj.iscs.view.activity.test.fingerprint.PermissionUtils
+import com.grkj.iscs.view.activity.test.fingerprint.ZKUSBManager.ZKUSBManager
+import com.grkj.iscs.view.activity.test.fingerprint.ZKUSBManager.ZKUSBManagerListener
+import com.zkteco.android.biometric.FingerprintExceptionListener
+import com.zkteco.android.biometric.core.device.ParameterHelper
+import com.zkteco.android.biometric.core.device.TransportType
+import com.zkteco.android.biometric.core.utils.LogHelper
+import com.zkteco.android.biometric.core.utils.ToolUtils
+import com.zkteco.android.biometric.module.fingerprintreader.FingerprintCaptureListener
+import com.zkteco.android.biometric.module.fingerprintreader.FingerprintSensor
+import com.zkteco.android.biometric.module.fingerprintreader.FingprintFactory
+import com.zkteco.android.biometric.module.fingerprintreader.ZKFingerService
+import com.zkteco.android.biometric.module.fingerprintreader.exception.FingerprintException
+
+object FingerprintUtil {
+    private const val REQUEST_PERMISSION_CODE = 9
+    private const val ZKTECO_VID: Int = 0x1b55
+    private const val LIVE20R_PID: Int = 0x0120
+    private const val LIVE10R_PID: Int = 0x0124
+    private const val ENROLL_COUNT: Int = 3
+
+    private var bStarted = false
+    private var usb_pid = 0
+    private var zkusbManager: ZKUSBManager? = null
+    private val usb_vid: Int = ZKTECO_VID
+    private var fingerprintSensor: FingerprintSensor? = null
+    private var bRegister = false
+    private var enroll_index = 0
+    private var isReseted = false
+    private val deviceIndex = 0
+    private val regtemparray = Array(3) {
+        ByteArray(
+            2048
+        )
+    }
+//    private val dbManager: DBManager = DBManager()
+    private var strUid: String? = null
+//    private var dbFileName: String? = null
+
+    private var onScanListener: OnScanListener? = null
+
+    fun setScanListener(listener: OnScanListener) {
+        onScanListener = listener
+    }
+
+    fun init(ctx: Context) {
+//        dbFileName = ctx.filesDir.absolutePath + "/zkfinger10.db"
+        checkStoragePermission()
+        zkusbManager ?: let {
+            zkusbManager = ZKUSBManager(ctx, zkusbManagerListener)
+        }
+        zkusbManager?.registerUSBPermissionReceiver()
+    }
+
+    fun unInit() {
+        if (bStarted) {
+            closeDevice()
+        }
+        zkusbManager!!.unRegisterUSBPermissionReceiver()
+    }
+
+    fun start() {
+        if (bStarted) {
+//            mBinding?.txtResult?.setText("Device already connected!")
+            LogUtil.i("Device already connected!")
+            return
+        }
+        if (!enumSensor()) {
+//            mBinding?.txtResult?.setText("Device not found!")
+            LogUtil.i("Device not found!")
+            return
+        }
+        tryGetUSBPermission()
+    }
+
+    fun stop() {
+        if (!bStarted) {
+//            mBinding?.txtResult?.setText("Device not connected!")
+            LogUtil.i("Device not connected!")
+            return
+        }
+        closeDevice()
+//        mBinding?.txtResult?.setText("Device closed!")
+        LogUtil.i("Device closed!")
+    }
+
+    private fun checkStoragePermission() {
+        val permission = arrayOf(
+            Manifest.permission.READ_EXTERNAL_STORAGE,
+            Manifest.permission.WRITE_EXTERNAL_STORAGE
+        )
+        val deniedPermissions: ArrayList<String> = PermissionUtils.checkPermissions(
+            ActivityUtils.currentActivity(), permission
+        )
+        if (deniedPermissions.isEmpty()) {
+            //permission all granted
+            LogUtil.i("[checkStoragePermission]: all granted")
+        } else {
+            val size = deniedPermissions.size
+            val deniedPermissionArray = deniedPermissions.toTypedArray<String>()
+            PermissionUtils.requestPermission(ActivityUtils.currentActivity(), deniedPermissionArray, REQUEST_PERMISSION_CODE)
+        }
+    }
+
+    private fun afterGetUsbPermission() {
+        openDevice()
+    }
+
+    private fun tryGetUSBPermission() {
+        zkusbManager?.initUSBPermission(usb_vid, usb_pid)
+    }
+
+
+    private val fingerprintCaptureListener: FingerprintCaptureListener =
+        object : FingerprintCaptureListener {
+            override fun captureOK(fpImage: ByteArray?) {
+                val bitmap: Bitmap = ToolUtils.renderCroppedGreyScaleBitmap(
+                    fpImage,
+                    fingerprintSensor?.getImageWidth()!!,
+                    fingerprintSensor?.getImageHeight()!!
+                )
+                Executor.runOnMain {
+                    onScanListener?.onScan(bitmap)
+                }
+            }
+
+            override fun captureError(e: FingerprintException?) {
+                // nothing to do
+            }
+
+            override fun extractOK(fpTemplate: ByteArray?) {
+                if (bRegister) {
+                    doRegister(fpTemplate)
+                } else {
+                    doIdentify(fpTemplate)
+                }
+            }
+
+            override fun extractError(i: Int) {
+                // nothing to do
+            }
+        }
+
+    private val fingerprintExceptionListener: FingerprintExceptionListener =
+        object : FingerprintExceptionListener {
+            override fun onDeviceException() {
+                LogUtil.e("usb exception!!!")
+                if (!isReseted) {
+                    try {
+                        fingerprintSensor?.openAndReboot(deviceIndex)
+                    } catch (e: FingerprintException) {
+                        e.printStackTrace()
+                    }
+                    isReseted = true
+                }
+            }
+        }
+
+    private val zkusbManagerListener: ZKUSBManagerListener = object : ZKUSBManagerListener {
+        override fun onCheckPermission(result: Int) {
+            afterGetUsbPermission()
+        }
+
+        override fun onUSBArrived(device: UsbDevice?) {
+            if (bStarted) {
+                closeDevice()
+                tryGetUSBPermission()
+            }
+        }
+
+        override fun onUSBRemoved(device: UsbDevice?) {
+            LogUtil.d("usb removed!")
+        }
+    }
+
+    private fun openDevice() {
+        createFingerprintSensor()
+        bRegister = false
+        enroll_index = 0
+        isReseted = false
+        try {
+            //fingerprintSensor?.setCaptureMode(1);
+            fingerprintSensor?.open(deviceIndex)
+            //load all templates form db
+//            if (dbManager.opendb(dbFileName) && dbManager.getCount() > 0) {
+//                val vUserList: HashMap<String, String> = dbManager.queryUserList()
+//                var ret = 0
+//                if (vUserList.size > 0) {
+//                    for ((strID, strFeature) in vUserList) {
+//                        val blobFeature = Base64.decode(strFeature, Base64.NO_WRAP)
+//                        ret = ZKFingerService.save(blobFeature, strID)
+//                        if (0 != ret) {
+//                            LogUtil.e("add [$strID] template failed, ret=$ret")
+//                        }
+//                    }
+//                }
+//            }
+            run {
+                // device parameter
+                LogUtil.d("sdk version" + fingerprintSensor?.getSDK_Version())
+                LogUtil.d("firmware version" + fingerprintSensor?.getFirmwareVersion())
+                LogUtil.d("serial:" + fingerprintSensor?.getStrSerialNumber())
+                LogUtil.d("width=" + fingerprintSensor?.getImageWidth() + ", height=" + fingerprintSensor?.getImageHeight())
+            }
+            fingerprintSensor?.setFingerprintCaptureListener(deviceIndex, fingerprintCaptureListener)
+            fingerprintSensor?.SetFingerprintExceptionListener(fingerprintExceptionListener)
+            fingerprintSensor?.startCapture(deviceIndex)
+            bStarted = true
+//            mBinding?.txtResult?.setText("connect success!")
+            LogUtil.i("connect success!")
+        } catch (e: FingerprintException) {
+            e.printStackTrace()
+            // try to  reboot the sensor
+            try {
+                fingerprintSensor?.openAndReboot(deviceIndex)
+            } catch (ex: FingerprintException) {
+                ex.printStackTrace()
+            }
+//            mBinding?.txtResult?.setText("connect failed!")
+            LogUtil.i("connect failed!")
+        }
+    }
+
+    private fun closeDevice() {
+        if (bStarted) {
+            try {
+                fingerprintSensor?.stopCapture(deviceIndex)
+                fingerprintSensor?.close(deviceIndex)
+            } catch (e: FingerprintException) {
+                e.printStackTrace()
+            }
+            bStarted = false
+        }
+    }
+
+    private fun enumSensor(): Boolean {
+        val usbManager = MyApplication.instance?.applicationContext?.getSystemService(USB_SERVICE) as UsbManager
+        for (device in usbManager.deviceList.values) {
+            val device_vid = device.vendorId
+            val device_pid = device.productId
+            if (device_vid == ZKTECO_VID && (device_pid == LIVE20R_PID || device_pid == LIVE10R_PID)) {
+                usb_pid = device_pid
+                return true
+            }
+        }
+        return false
+    }
+
+    private fun createFingerprintSensor() {
+        if (null != fingerprintSensor) {
+            FingprintFactory.destroy(fingerprintSensor)
+            fingerprintSensor = null
+        }
+        // Define output log level
+        LogHelper.setLevel(Log.VERBOSE)
+        LogHelper.setNDKLogLevel(Log.ASSERT)
+        // Start fingerprint sensor
+        val deviceParams = HashMap<String?, Any?>()
+        //set vid
+        deviceParams[ParameterHelper.PARAM_KEY_VID] = usb_vid
+        //set pid
+        deviceParams[ParameterHelper.PARAM_KEY_PID] = usb_pid
+        fingerprintSensor = FingprintFactory.createFingerprintSensor(
+            MyApplication.instance?.applicationContext,
+            TransportType.USB,
+            deviceParams
+        )
+    }
+
+    fun doRegister(template: ByteArray?) {
+        val bufids = ByteArray(256)
+        var ret = ZKFingerService.identify(template, bufids, 70, 1)
+        if (ret > 0) {
+            val strRes = String(bufids).split("\t".toRegex()).dropLastWhile { it.isEmpty() }
+                .toTypedArray()
+            setResult("the finger already enroll by " + strRes[0] + ",cancel enroll")
+            bRegister = false
+            enroll_index = 0
+            return
+        }
+        if (enroll_index > 0 && (ZKFingerService.verify(
+                regtemparray.get(enroll_index - 1),
+                template
+            ).also {
+                ret = it
+            }) <= 0
+        ) {
+            setResult("please press the same finger 3 times for the enrollment, cancel enroll, socre=$ret")
+            bRegister = false
+            enroll_index = 0
+            return
+        }
+        System.arraycopy(template, 0, regtemparray.get(enroll_index), 0, 2048)
+        enroll_index++
+        if (enroll_index == ENROLL_COUNT) {
+            bRegister = false
+            enroll_index = 0
+            val regTemp = ByteArray(2048)
+            if (0 < (ZKFingerService.merge(
+                    regtemparray.get(0),
+                    regtemparray.get(1),
+                    regtemparray.get(2),
+                    regTemp
+                ).also {
+                    ret = it
+                })
+            ) {
+                var retVal = 0
+                retVal = ZKFingerService.save(regTemp, strUid)
+                if (0 == retVal) {
+                    val strFeature = Base64.encodeToString(regTemp, 0, ret, Base64.NO_WRAP)
+//                    dbManager.insertUser(strUid, strFeature)
+                    setResult("enroll succ")
+                } else {
+                    setResult("enroll fail, add template fail, ret=$retVal")
+                }
+            } else {
+                setResult("enroll fail")
+            }
+            bRegister = false
+        } else {
+            setResult("You need to press the " + (3 - enroll_index) + " times fingerprint")
+        }
+    }
+
+    private fun setResult(result: String) {
+        LogUtil.i(result)
+//        val mStrText = result
+//        runOnUiThread { mBinding?.txtResult?.setText(mStrText) }
+    }
+
+    fun doIdentify(template: ByteArray?) {
+        val bufids = ByteArray(256)
+        val ret = ZKFingerService.identify(template, bufids, 70, 1)
+        if (ret > 0) {
+            val strRes = String(bufids).split("\t".toRegex()).dropLastWhile { it.isEmpty() }
+                .toTypedArray()
+            setResult("identify succ, userid:" + strRes[0].trim { it <= ' ' } + ", score:" + strRes[1].trim { it <= ' ' })
+        } else {
+            setResult("identify fail, ret=$ret")
+        }
+    }
+
+    interface OnScanListener {
+        fun onScan(bitmap: Bitmap)
+    }
+}

+ 23 - 0
app/src/main/java/com/grkj/iscs/view/dialog/LoginDialog.kt

@@ -1,6 +1,7 @@
 package com.grkj.iscs.view.dialog
 
 import android.content.Context
+import android.graphics.Bitmap
 import android.view.InputDevice
 import android.view.KeyEvent
 import android.view.View
@@ -8,9 +9,13 @@ import com.grkj.iscs.R
 import com.grkj.iscs.databinding.DialogLoginBinding
 import com.grkj.iscs.extentions.toByteArrays
 import com.grkj.iscs.extentions.toHexStrings
+import com.grkj.iscs.model.vo.FileStreamReqParam
 import com.grkj.iscs.model.vo.card.CardInfoRespVO
 import com.grkj.iscs.model.vo.user.UserInfoRespVO
+import com.grkj.iscs.util.CommonUtils
 import com.grkj.iscs.util.Executor
+import com.grkj.iscs.util.FingerprintUtil
+import com.grkj.iscs.util.NetApi
 import com.grkj.iscs.util.log.LogUtil
 import com.grkj.iscs.view.base.BaseDialog
 import com.grkj.iscs.view.presenter.LoginPresenter
@@ -58,6 +63,21 @@ class LoginDialog(val presenter: LoginPresenter?, val ctx: Context, private var
             mBinding?.llEasyContainer?.visibility = View.VISIBLE
             mBinding?.ivIcon?.setImageResource(mPairList[loginType].second)
             mBinding?.tvTip?.text = mPairList[loginType].first
+            if (loginType == 1) {
+                FingerprintUtil.init(ctx)
+                FingerprintUtil.start()
+                FingerprintUtil.setScanListener(object : FingerprintUtil.OnScanListener {
+                    override fun onScan(bitmap: Bitmap) {
+
+                        presenter?.fingerprintLogin(bitmap) { isSuccess, cardInfoRespVO, userInfoRespVO ->
+                            if (isSuccess) {
+                                dismiss()
+                            }
+                            callBack?.invoke(isSuccess, cardInfoRespVO, userInfoRespVO)
+                        }
+                    }
+                })
+            }
         }
         show()
     }
@@ -99,6 +119,9 @@ class LoginDialog(val presenter: LoginPresenter?, val ctx: Context, private var
         if (mLoginType == 3) {
             mBinding?.etAccount?.text?.clear()
             mBinding?.etPassword?.text?.clear()
+        } else if (mLoginType == 1) {
+            FingerprintUtil.stop()
+            FingerprintUtil.unInit()
         }
     }
 }