人脸识别支付流程
This commit is contained in:
@@ -41,4 +41,9 @@ class CashPayPresentation(
|
||||
append(amount, AbsoluteSizeSpan(48, true), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDisplayRemoved() {
|
||||
super.onDisplayRemoved()
|
||||
onDismissListener()
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.sw.dualscreen.presentation.pay
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Dialog
|
||||
import android.app.Presentation
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.Bitmap
|
||||
@@ -10,24 +11,26 @@ import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.text.Spanned
|
||||
import android.text.SpannedString
|
||||
import android.text.TextUtils
|
||||
import android.text.style.AbsoluteSizeSpan
|
||||
import android.view.Display
|
||||
import android.view.TextureView
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewTreeObserver
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.text.buildSpannedString
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.arcsoft.face.ErrorInfo
|
||||
import com.sw.dualscreen.GlobalKey
|
||||
import com.sw.dualscreen.R
|
||||
import com.sw.dualscreen.activity.PayActivity
|
||||
import com.sw.dualscreen.databinding.PresentationFacePayBinding
|
||||
import com.sw.dualscreen.ext.dp
|
||||
import com.sw.dualscreen.presentation.MainScreenPresentation
|
||||
import com.sw.dualscreen.utils.SPUtil
|
||||
import com.sw.dualscreen.ext.load
|
||||
import com.sw.dualscreen.view.CustomDialog
|
||||
import com.sw.dualscreen.viewmodel.UserViewModel
|
||||
import com.sw.plate.utils.ToastUtils
|
||||
import com.sw.plate.utils.arcface.ConfigUtil
|
||||
@@ -45,13 +48,13 @@ import com.sw.plate.utils.arcface.face.model.RecognizeConfiguration
|
||||
import com.sw.plate.utils.arcface.viewmodel.RecognizeViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class FacePayPresentation(
|
||||
val activity: PayActivity,
|
||||
display: Display,
|
||||
val userViewModel: UserViewModel,
|
||||
val recognizeViewModel: RecognizeViewModel,
|
||||
// val //parentTextureView: TextureView,
|
||||
private val onDismissListener: () -> Unit = {}
|
||||
) : Presentation(activity, display) , ViewTreeObserver.OnGlobalLayoutListener {
|
||||
|
||||
@@ -75,16 +78,20 @@ class FacePayPresentation(
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = PresentationFacePayBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
window?.setBackgroundDrawableResource(R.color.transparent)
|
||||
window?.setBackgroundDrawableResource(android.R.color.white)
|
||||
initView()
|
||||
setupArcCamera()
|
||||
registerDataChange()
|
||||
|
||||
pauseCamera()
|
||||
}
|
||||
|
||||
override fun show() {
|
||||
super.show()
|
||||
|
||||
resumeCamera()
|
||||
binding.root.postDelayed({
|
||||
resumeCamera()
|
||||
}, 1500)
|
||||
}
|
||||
|
||||
var foodName: String? = null
|
||||
@@ -92,6 +99,14 @@ class FacePayPresentation(
|
||||
private fun initView() {
|
||||
binding.tvFoodName.text = foodName
|
||||
binding.tvRealAmount.text = getAmountText(payAmount ?: "")
|
||||
// binding.ivPreviewImage.let {
|
||||
// it.outlineProvider = object : ViewOutlineProvider() {
|
||||
// override fun getOutline(view: View, outline: Outline) {
|
||||
// outline.setRoundRect(0, 0, view.width, view.height, 12f.dp)
|
||||
// }
|
||||
// }
|
||||
// it.clipToOutline = true
|
||||
// }
|
||||
}
|
||||
|
||||
private fun getAmountText(amount: String): SpannedString {
|
||||
@@ -104,6 +119,7 @@ class FacePayPresentation(
|
||||
override fun onGlobalLayout() {
|
||||
Timber.tag(TAG).d("onGlobalLayout")
|
||||
binding.dualCameraTexturePreviewRgb.getViewTreeObserver().removeOnGlobalLayoutListener(this)
|
||||
//parentTextureView.getViewTreeObserver().removeOnGlobalLayoutListener(this)
|
||||
openCamera()
|
||||
}
|
||||
private fun openCamera() {
|
||||
@@ -249,17 +265,16 @@ class FacePayPresentation(
|
||||
val userId = faceEntity.userName
|
||||
if (userId == null ) return@Observer
|
||||
activity.runOnUiThread {
|
||||
ToastUtils.showToast("获取用户id成功")
|
||||
//ToastUtils.showToast("用户人脸识别成功,挑战支付页面")
|
||||
showWaitingDialog("刷脸支付中,请稍后……")
|
||||
binding.root.postDelayed({
|
||||
hideWaitingDialog()
|
||||
activity.paySuccess()
|
||||
binding.root.postDelayed({
|
||||
dismiss()
|
||||
},500)
|
||||
},1500)
|
||||
}
|
||||
// if (currentFood == null) {
|
||||
// //重新识别
|
||||
// activity.runOnUiThread {
|
||||
// ToastUtils.showToast("currentFood == null")
|
||||
// }
|
||||
// //activity.recognizeFood()
|
||||
// //step1FoodRecognizing()
|
||||
// return@Observer
|
||||
// }
|
||||
// userViewModel.getUserNutritionData(
|
||||
// userId = userId,
|
||||
// foodId = currentFood!!.id!!
|
||||
@@ -274,6 +289,7 @@ class FacePayPresentation(
|
||||
private fun initArcView() {
|
||||
//在布局结束后才做初始化操作
|
||||
binding.dualCameraTexturePreviewRgb.getViewTreeObserver().addOnGlobalLayoutListener(this)
|
||||
//parentTextureView.getViewTreeObserver().addOnGlobalLayoutListener(this)
|
||||
recognizeViewModel.getCompareResultList().getValue()
|
||||
}
|
||||
|
||||
@@ -337,8 +353,10 @@ class FacePayPresentation(
|
||||
val layoutParams = previewView.layoutParams
|
||||
// layoutParams.width = (608.dp * 1.5).roundToInt()
|
||||
// layoutParams.height = (456.dp * 1.5).roundToInt()
|
||||
layoutParams.width = (600.dp * 1.5).roundToInt()
|
||||
layoutParams.height = (400.dp * 1.5).roundToInt()
|
||||
// layoutParams.width = (608.dp * 1.5).roundToInt()
|
||||
// layoutParams.height = (456.dp * 1.5).roundToInt()
|
||||
layoutParams.width = 1024
|
||||
layoutParams.height = 768
|
||||
previewView.setLayoutParams(layoutParams)
|
||||
faceRectView.setLayoutParams(layoutParams)
|
||||
return layoutParams
|
||||
@@ -440,6 +458,9 @@ class FacePayPresentation(
|
||||
.previewOn(binding.dualCameraTexturePreviewRgb)
|
||||
.cameraListener(cameraListener)
|
||||
.build()
|
||||
rgbCameraHelper!!.setSurfaceFrameCallback { frame ->
|
||||
activity.facePayFragment?.loadBitmap(frame)
|
||||
}
|
||||
rgbCameraHelper!!.init()
|
||||
// rgbCameraHelper!!.start()
|
||||
}
|
||||
@@ -543,7 +564,6 @@ class FacePayPresentation(
|
||||
)
|
||||
// 识别成功
|
||||
binding.dualCameraFaceRectView.drawRealtimeFaceInfo(rgbDrawInfoList)
|
||||
ToastUtils.showToast("识别到人脸信息")
|
||||
}
|
||||
|
||||
if (facePreviewInfoList.isEmpty() || (lastFaceTrackId != facePreviewInfoList[0]!!.trackId)) {
|
||||
@@ -561,11 +581,30 @@ class FacePayPresentation(
|
||||
}
|
||||
}
|
||||
private var lastFaceTrackId: Int = -1 // 上一次的人脸信息
|
||||
|
||||
fun updateImage(bitmap: Bitmap) {
|
||||
activity.runOnUiThread {
|
||||
// binding.ivPreviewImage.setImageBitmap(bitmap)
|
||||
}
|
||||
private var mDialogWaiting:CustomDialog?=null
|
||||
/**
|
||||
* 显示等待提示框
|
||||
*/
|
||||
fun showWaitingDialog(tip: String?): Dialog? {
|
||||
hideWaitingDialog()
|
||||
val view = View.inflate(activity, R.layout.dialog_waiting, null)
|
||||
if (!TextUtils.isEmpty(tip)) (view.findViewById<View?>(R.id.tvTip) as TextView).text = tip
|
||||
mDialogWaiting = CustomDialog(activity, view, R.style.MyDialog)
|
||||
mDialogWaiting!!.show()
|
||||
mDialogWaiting!!.setCancelable(true)
|
||||
return mDialogWaiting
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏等待提示框
|
||||
*/
|
||||
fun hideWaitingDialog() {
|
||||
mDialogWaiting?.dismiss()
|
||||
mDialogWaiting = null
|
||||
}
|
||||
|
||||
override fun onDisplayRemoved() {
|
||||
super.onDisplayRemoved()
|
||||
onDismissListener()
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package com.sw.dualscreen.presentation.pay
|
||||
|
||||
import android.app.Presentation
|
||||
import android.os.Bundle
|
||||
import android.text.Spanned
|
||||
import android.text.SpannedString
|
||||
import android.text.style.AbsoluteSizeSpan
|
||||
import android.view.Display
|
||||
import androidx.core.text.buildSpannedString
|
||||
import com.sw.dualscreen.activity.PayActivity
|
||||
import com.sw.dualscreen.databinding.PresentationQrcodePayBinding
|
||||
import com.sw.dualscreen.ext.load
|
||||
|
||||
class QrCodePayPresentation(
|
||||
val activity: PayActivity,
|
||||
display: Display,
|
||||
private val onDismissListener: () -> Unit = {}
|
||||
) : Presentation(activity, display) {
|
||||
|
||||
private lateinit var binding: PresentationQrcodePayBinding
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = PresentationQrcodePayBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
window?.setBackgroundDrawableResource(android.R.color.transparent)
|
||||
initView()
|
||||
}
|
||||
|
||||
var foodName: String? = null
|
||||
var payAmount: String? = null
|
||||
var payQrCodePic: Any? = null
|
||||
private fun initView() {
|
||||
binding.tvFoodName.text = foodName
|
||||
binding.tvRealAmount.text = getAmountText(payAmount ?: "")
|
||||
binding.ivPayQrCode.load(payQrCodePic)
|
||||
}
|
||||
|
||||
private fun getAmountText(amount: String): SpannedString {
|
||||
return buildSpannedString {
|
||||
append("¥", AbsoluteSizeSpan(32, true), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
append(amount, AbsoluteSizeSpan(48, true), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
package com.sw.dualscreen.presentation.pay
|
||||
|
||||
import android.app.Presentation
|
||||
import android.os.Bundle
|
||||
import android.text.Spanned
|
||||
import android.text.SpannedString
|
||||
import android.text.style.AbsoluteSizeSpan
|
||||
import android.text.style.ForegroundColorSpan
|
||||
import android.view.Display
|
||||
import androidx.core.graphics.toColorInt
|
||||
import androidx.core.text.buildSpannedString
|
||||
import com.sw.dualscreen.R
|
||||
import com.sw.dualscreen.activity.PayActivity
|
||||
import com.sw.dualscreen.databinding.PresentationScanQrcodePayBinding
|
||||
import com.sw.dualscreen.ext.gone
|
||||
import com.sw.dualscreen.ext.load
|
||||
import com.sw.dualscreen.ext.visible
|
||||
|
||||
class ScanQrCodePayPresentation(
|
||||
val activity: PayActivity,
|
||||
display: Display,
|
||||
val type:Int,
|
||||
private val onDismissListener: () -> Unit = {}
|
||||
) : Presentation(activity, display) {
|
||||
|
||||
//type = 0,扫码支付默认显示二维码
|
||||
//type = 1,会员结算显示二维码,是会员则显示名字、头像、手机号、可用余额
|
||||
//type = 2,支付成功,是会员则显示名字、头像、手机号、可用余额
|
||||
|
||||
private lateinit var binding: PresentationScanQrcodePayBinding
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = PresentationScanQrcodePayBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
window?.setBackgroundDrawableResource(android.R.color.transparent)
|
||||
initView()
|
||||
}
|
||||
|
||||
var foodName: String? = null
|
||||
var payAmount: String? = null
|
||||
var payQrCodePic: Any? = null
|
||||
private fun initView() {
|
||||
when(type) {
|
||||
0->{
|
||||
binding.layoutVip.gone()
|
||||
binding.layoutPaySuccess.gone()
|
||||
binding.layoutScanQrCode.visible()
|
||||
|
||||
binding.tvPayTip.text = "请扫码支付或出示付款码"
|
||||
binding.tvFoodName.text = foodName
|
||||
binding.tvRealAmount.text = getAmountText(payAmount ?: "")
|
||||
binding.ivPayQrCode.load(payQrCodePic)
|
||||
}
|
||||
1->{
|
||||
binding.layoutVip.visible()
|
||||
binding.layoutPaySuccess.gone()
|
||||
binding.layoutScanQrCode.visible()
|
||||
|
||||
binding.tvFoodName.text = foodName
|
||||
binding.tvRealAmount.text = getAmountText(payAmount ?: "")
|
||||
binding.ivPayQrCode.load(payQrCodePic)
|
||||
|
||||
binding.ivHeadPic.load(R.mipmap.ic_launcher)
|
||||
binding.tvUserName.text = "张三"
|
||||
binding.tvUserPhone.text = "132****5678"
|
||||
binding.tvUserBalance.text = getBalanceText("0.00")
|
||||
|
||||
binding.tvPayTip.text = getPayTip("-16.80", "22.00")
|
||||
}
|
||||
2->{
|
||||
binding.layoutVip.visible()
|
||||
binding.layoutPaySuccess.visible()
|
||||
binding.layoutScanQrCode.gone()
|
||||
|
||||
binding.ivHeadPic.load(R.mipmap.ic_launcher)
|
||||
binding.tvUserName.text = "张三"
|
||||
binding.tvUserPhone.text = "132****5678"
|
||||
binding.tvUserBalance.text = getBalanceText("0.00")
|
||||
|
||||
binding.tvPayInfo.text = "余额扣除 16.80 元,在线支付 20.00 元"
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getPayTip(startAmount:String, endAmount: String): SpannedString {
|
||||
return buildSpannedString {
|
||||
append("余额扣除 ", ForegroundColorSpan("#FF5E7585".toColorInt()), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
append(startAmount, ForegroundColorSpan("#FF0A1428".toColorInt()), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
append(" 元,还需支付 ", ForegroundColorSpan("#FF5E7585".toColorInt()), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
append(endAmount, ForegroundColorSpan("#FF0A1428".toColorInt()), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
append(" 元", ForegroundColorSpan("#FF5E7585".toColorInt()), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getBalanceText(amount: String): SpannedString {
|
||||
return buildSpannedString {
|
||||
append("¥", AbsoluteSizeSpan(20, true), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
append(amount, AbsoluteSizeSpan(32, true), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getAmountText(amount: String): SpannedString {
|
||||
return buildSpannedString {
|
||||
append("¥", AbsoluteSizeSpan(32, true), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
append(amount, AbsoluteSizeSpan(48, true), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDisplayRemoved() {
|
||||
super.onDisplayRemoved()
|
||||
onDismissListener()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user