Commit bb1105be authored by yinjiacheng's avatar yinjiacheng

add 营业执照相册选择上传+OCR逻辑

parent e93bde32
package com.yidian.shenghuoquan.newscontent.ui.auth package com.yidian.shenghuoquan.newscontent.ui.auth
import android.app.Activity
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.provider.MediaStore
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.content.FileProvider
import com.yidian.common.base.BaseFragment import com.yidian.common.base.BaseFragment
import com.yidian.shenghuoquan.newscontent.R import com.yidian.shenghuoquan.newscontent.R
import com.yidian.shenghuoquan.newscontent.adapter.BottomSelectAdapter import com.yidian.shenghuoquan.newscontent.adapter.BottomSelectAdapter
import com.yidian.shenghuoquan.newscontent.bean.BottomSelectBean import com.yidian.shenghuoquan.newscontent.bean.BottomSelectBean
import com.yidian.shenghuoquan.newscontent.constant.Constant import com.yidian.shenghuoquan.newscontent.constant.Constant
import com.yidian.shenghuoquan.newscontent.databinding.FragmentLifeAccountBusinessLicenseAuthBinding import com.yidian.shenghuoquan.newscontent.databinding.FragmentLifeAccountBusinessLicenseAuthBinding
import com.yidian.shenghuoquan.newscontent.http.ApiService
import com.yidian.shenghuoquan.newscontent.http.httpbean.BusinessLicenseOCRBean
import com.yidian.shenghuoquan.newscontent.http.httpbean.IBusinessLicenseOCRCallback
import com.yidian.shenghuoquan.newscontent.ui.dialog.BottomSelectDialog import com.yidian.shenghuoquan.newscontent.ui.dialog.BottomSelectDialog
import com.yidian.shenghuoquan.newscontent.utils.BitmapUtil
import com.yidian.shenghuoquan.newscontent.utils.FileUtil
import com.yidian.shenghuoquan.newscontent.utils.KS3Core
import java.io.File
/** /**
* author: yinjiacheng * author: yinjiacheng
...@@ -19,7 +33,18 @@ import com.yidian.shenghuoquan.newscontent.ui.dialog.BottomSelectDialog ...@@ -19,7 +33,18 @@ import com.yidian.shenghuoquan.newscontent.ui.dialog.BottomSelectDialog
*/ */
class LifeAccountBusinessLicenseAuthFragment : class LifeAccountBusinessLicenseAuthFragment :
BaseFragment<FragmentLifeAccountBusinessLicenseAuthBinding>(), View.OnClickListener, BaseFragment<FragmentLifeAccountBusinessLicenseAuthBinding>(), View.OnClickListener,
BottomSelectAdapter.OnItemClickListener<BottomSelectBean> { BottomSelectAdapter.OnItemClickListener<BottomSelectBean>, KS3Core.OnKS3TaskListener,
IBusinessLicenseOCRCallback {
/**
* sdcard/Android/data/package/cache
*/
private val commonPath by lazy { activity?.externalCacheDir?.absolutePath }
/**
* 调用系统相机拍照,照片保存位置的Uri
*/
private var photoUri: Uri? = null
override fun createViewBinding( override fun createViewBinding(
inflater: LayoutInflater, inflater: LayoutInflater,
...@@ -60,15 +85,142 @@ class LifeAccountBusinessLicenseAuthFragment : ...@@ -60,15 +85,142 @@ class LifeAccountBusinessLicenseAuthFragment :
} }
} }
R.id.iv_clear -> { R.id.iv_clear -> {
// TODO: 5/29/21 清除已上传的营业执照 // 清除已上传的营业执照
viewBinding.ivBusinessLicense.setImageDrawable(null)
// 清除OCR或用户输入内容 // 清除OCR或用户输入内容
viewBinding.evRegistrationName.clearEditContent() viewBinding.evRegistrationName.clearEditContent()
viewBinding.evRegistrationCode.clearEditContent() viewBinding.evRegistrationCode.clearEditContent()
// 设置上传区域可点击
viewBinding.clBusinessLicenseUpload.isEnabled = true
// 隐藏清除按钮
viewBinding.ivClear.visibility = View.GONE
} }
} }
} }
override fun onItemClick(view: View, position: Int, data: BottomSelectBean) { override fun onItemClick(view: View, position: Int, data: BottomSelectBean) {
when (data.item) {
Constant.ITEM_TAKE_PHOTO -> {
// 调用系统相机进行营业执照采集
val file = File(commonPath + Constant.FILE_PATH_BUSINESS_LICENSE_CAMERA)
if (file.exists()) file.delete()
file.parentFile?.mkdirs()
file.createNewFile()
photoUri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
//适配Android 7.0文件权限,通过FileProvider创建一个content类型的Uri
activity?.let {
FileProvider.getUriForFile(
it,
"${activity?.packageName}.provider",
file
)
}
} else {
Uri.fromFile(file)
}
startActivityForResult(
Intent(MediaStore.ACTION_IMAGE_CAPTURE).putExtra(
MediaStore.EXTRA_OUTPUT,
photoUri
),
Constant.REQUEST_CODE_OPEN_CAMERA
)
}
Constant.ITEM_OPEN_ALBUM -> {
// 打开系统相册
startActivityForResult(
Intent(Intent.ACTION_PICK).setDataAndType(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
"image/*"
),
Constant.REQUEST_CODE_OPEN_ALBUM
)
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK) {
val uri = if (requestCode == Constant.REQUEST_CODE_OPEN_ALBUM) data?.data else photoUri
val bitmap =
BitmapUtil.generateBitmapFromUri(activity, uri, viewBinding.ivBusinessLicense)
viewBinding.ivBusinessLicense.setImageBitmap(bitmap)
FileUtil.generateFileFromUri(
activity, uri,
commonPath + Constant.FILE_PATH_BUSINESS_LICENSE
)
// 删除从相机拍摄的照片
if (requestCode == Constant.REQUEST_CODE_OPEN_CAMERA) File(commonPath + Constant.FILE_PATH_BUSINESS_LICENSE_CAMERA).delete()
// 显示清除按钮
viewBinding.ivClear.visibility = View.VISIBLE
// 上传区域不可点击
viewBinding.clBusinessLicenseUpload.isEnabled = false
// 执行上传金山云
startUpload()
}
}
/**
* 执行营业执照上传金山云
*/
private fun startUpload() {
// 上传前压缩图像
BitmapUtil.compressImage(
commonPath + Constant.FILE_PATH_BUSINESS_LICENSE,
10
)
KS3Core.INSTANCE.uploadObject(
File(commonPath + Constant.FILE_PATH_BUSINESS_LICENSE),
KS3Core.ObjectType.IMAGE, this
)
}
/**
* 执行营业执照OCR
*/
private fun startBusinessLicenseOCR(objectKey: String?) {
val request = BusinessLicenseOCRBean.Request(objectKey)
ApiService.businessLicenseOCR(this, request)
}
override fun onTaskStart() {
}
override fun onTaskProgress(progress: Double) {
}
override fun onTaskFinish() {
}
override fun onTaskCancel() {
}
override fun onTaskSuccess(bucket: String?, objectKey: String?) {
// 执行营业执照OCR
startBusinessLicenseOCR(objectKey)
}
override fun onTaskFailure(statesCode: Int, message: String?) {
}
override fun businessLicenseOCRSuccess(result: BusinessLicenseOCRBean.Response?) {
// 回显OCR结果
viewBinding.evRegistrationName.fillEditContent(result?.name)
viewBinding.evRegistrationCode.fillEditContent(result?.code)
// 此时营业执照已上传并OCR识别完成 删除本地临时存储文件
File(commonPath + Constant.FILE_PATH_BUSINESS_LICENSE).delete()
}
override fun businessLicenseOCRFailure(message: String?) {
Log.e(
Constant.LIFE_ACCOUNT_AUTH_TAG,
"request business license ocr failure, message: $message"
)
} }
} }
\ No newline at end of file
...@@ -29,6 +29,7 @@ import com.yidian.shenghuoquan.newscontent.http.httpbean.GetIDCardOCRBean ...@@ -29,6 +29,7 @@ import com.yidian.shenghuoquan.newscontent.http.httpbean.GetIDCardOCRBean
import com.yidian.shenghuoquan.newscontent.http.httpbean.IGetIDCardOCRCallback import com.yidian.shenghuoquan.newscontent.http.httpbean.IGetIDCardOCRCallback
import com.yidian.shenghuoquan.newscontent.ui.dialog.BottomSelectDialog import com.yidian.shenghuoquan.newscontent.ui.dialog.BottomSelectDialog
import com.yidian.shenghuoquan.newscontent.utils.BitmapUtil import com.yidian.shenghuoquan.newscontent.utils.BitmapUtil
import com.yidian.shenghuoquan.newscontent.utils.FileUtil
import com.yidian.shenghuoquan.newscontent.utils.KS3Core import com.yidian.shenghuoquan.newscontent.utils.KS3Core
import com.yidian.utils.ToastUtil import com.yidian.utils.ToastUtil
import java.io.File import java.io.File
...@@ -40,7 +41,8 @@ import java.io.FileOutputStream ...@@ -40,7 +41,8 @@ import java.io.FileOutputStream
* description: 生活号身份证认证 * description: 生活号身份证认证
*/ */
class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuthBinding>(), class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuthBinding>(),
View.OnClickListener, BottomSelectAdapter.OnItemClickListener<BottomSelectBean> { View.OnClickListener, BottomSelectAdapter.OnItemClickListener<BottomSelectBean>,
IGetIDCardOCRCallback {
companion object { companion object {
// 身份证采集页面回传数据 // 身份证采集页面回传数据
...@@ -59,7 +61,7 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth ...@@ -59,7 +61,7 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
private var idCardNationalEmblemFaceObjectKey: String? = null private var idCardNationalEmblemFaceObjectKey: String? = null
/** /**
* cache dirs * sdcard/Android/data/package/cache
*/ */
private val commonPath by lazy { activity?.externalCacheDir?.absolutePath } private val commonPath by lazy { activity?.externalCacheDir?.absolutePath }
...@@ -197,9 +199,12 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth ...@@ -197,9 +199,12 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
viewBinding.ivIdCardPortraitFace viewBinding.ivIdCardPortraitFace
) )
viewBinding.ivIdCardPortraitFace.setImageBitmap(bitmap) viewBinding.ivIdCardPortraitFace.setImageBitmap(bitmap)
BitmapUtil.generateFileFromBitmap( FileUtil.generateFileFromUri(
bitmap, 15, commonPath + Constant.FILE_PATH_ID_CARD_PORTRAIT_FACE activity,
data?.data,
commonPath + Constant.FILE_PATH_ID_CARD_PORTRAIT_FACE
) )
BitmapUtil.compressImage(commonPath + Constant.FILE_PATH_ID_CARD_PORTRAIT_FACE, 10)
} else { } else {
val bitmap = BitmapUtil.generateBitmapFromUri( val bitmap = BitmapUtil.generateBitmapFromUri(
activity, activity,
...@@ -207,9 +212,12 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth ...@@ -207,9 +212,12 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
viewBinding.ivIdCardNationalEmblemFace viewBinding.ivIdCardNationalEmblemFace
) )
viewBinding.ivIdCardNationalEmblemFace.setImageBitmap(bitmap) viewBinding.ivIdCardNationalEmblemFace.setImageBitmap(bitmap)
BitmapUtil.generateFileFromBitmap( FileUtil.generateFileFromUri(
bitmap, 15, commonPath + Constant.FILE_PATH_ID_CARD_NATIONAL_EMBLEM_FACE activity,
data?.data,
commonPath + Constant.FILE_PATH_ID_CARD_NATIONAL_EMBLEM_FACE
) )
BitmapUtil.compressImage(commonPath + Constant.FILE_PATH_ID_CARD_PORTRAIT_FACE, 10)
} }
if (File(commonPath + Constant.FILE_PATH_ID_CARD_PORTRAIT_FACE).exists() && File( if (File(commonPath + Constant.FILE_PATH_ID_CARD_PORTRAIT_FACE).exists() && File(
commonPath + Constant.FILE_PATH_ID_CARD_NATIONAL_EMBLEM_FACE commonPath + Constant.FILE_PATH_ID_CARD_NATIONAL_EMBLEM_FACE
...@@ -329,23 +337,26 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth ...@@ -329,23 +337,26 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
* 执行身份证OCR * 执行身份证OCR
*/ */
private fun startIDCardOCR() { private fun startIDCardOCR() {
ApiService.getIDCardOCR(object : IGetIDCardOCRCallback { ApiService.getIDCardOCR(
override fun getIDCardOCRSuccess(result: GetIDCardOCRBean.Response?) { this,
// 回显OCR结果 GetIDCardOCRBean.Request(idCardPortraitFaceObjectKey, idCardNationalEmblemFaceObjectKey)
viewBinding.evRealName.fillEditContent(result?.posit?.name) )
viewBinding.evIdCardNumber.fillEditContent(result?.posit?.idcard_number) }
// 此时身份证两面均已上传并OCR识别完成 删除本地临时存储文件
File(commonPath + Constant.FILE_PATH_ID_CARD_PORTRAIT_FACE).delete()
File(commonPath + Constant.FILE_PATH_ID_CARD_NATIONAL_EMBLEM_FACE).delete()
}
override fun getIDCardOCRFailure(message: String?) { override fun getIDCardOCRSuccess(result: GetIDCardOCRBean.Response?) {
Log.e( // 回显OCR结果
Constant.LIFE_ACCOUNT_AUTH_TAG, viewBinding.evRealName.fillEditContent(result?.posit?.name)
"request id card ocr failure, message: $message" viewBinding.evIdCardNumber.fillEditContent(result?.posit?.idcard_number)
) // 此时身份证两面均已上传并OCR识别完成 删除本地临时存储文件
} File(commonPath + Constant.FILE_PATH_ID_CARD_PORTRAIT_FACE).delete()
}, GetIDCardOCRBean.Request(idCardPortraitFaceObjectKey, idCardNationalEmblemFaceObjectKey)) File(commonPath + Constant.FILE_PATH_ID_CARD_NATIONAL_EMBLEM_FACE).delete()
}
override fun getIDCardOCRFailure(message: String?) {
Log.e(
Constant.LIFE_ACCOUNT_AUTH_TAG,
"request id card ocr failure, message: $message"
)
} }
/** /**
......
...@@ -6,6 +6,7 @@ import android.graphics.BitmapFactory ...@@ -6,6 +6,7 @@ import android.graphics.BitmapFactory
import android.net.Uri import android.net.Uri
import android.view.View import android.view.View
import java.io.File import java.io.File
import java.io.FileNotFoundException
import java.io.FileOutputStream import java.io.FileOutputStream
/** /**
...@@ -46,9 +47,9 @@ object BitmapUtil { ...@@ -46,9 +47,9 @@ object BitmapUtil {
} }
/** /**
* Bitmap to File * 从Bitmap生成File
* @param quality 压缩质量 * @param quality 压缩质量
* @param destPath 目标文件路径 * @param destPath 目标文件路径
*/ */
fun generateFileFromBitmap(bitmap: Bitmap?, quality: Int, destPath: String) { fun generateFileFromBitmap(bitmap: Bitmap?, quality: Int, destPath: String) {
val file = File(destPath) val file = File(destPath)
...@@ -57,4 +58,16 @@ object BitmapUtil { ...@@ -57,4 +58,16 @@ object BitmapUtil {
file.createNewFile() file.createNewFile()
bitmap?.compress(Bitmap.CompressFormat.JPEG, quality, FileOutputStream(destPath)) bitmap?.compress(Bitmap.CompressFormat.JPEG, quality, FileOutputStream(destPath))
} }
/**
* 图片压缩
* @param path 将要压缩的图片圈路径,同时也是压缩完成后的图片 即覆盖原图片
* @param quality 压缩质量
*/
fun compressImage(path: String, quality: Int) {
if (!File(path).exists()) throw FileNotFoundException("compress file not exist!")
BitmapFactory.decodeFile(path)
.compress(Bitmap.CompressFormat.JPEG, quality, FileOutputStream(path))
}
} }
\ No newline at end of file
package com.yidian.shenghuoquan.newscontent.utils
import android.content.Context
import android.net.Uri
import java.io.FileOutputStream
/**
* author: yinjiacheng
* date: 5/31/21 4:29 PM
* description: 文件相关操作
*/
object FileUtil {
/**
* 从Uri生成File
* @param path 生成文件的全路径
*/
fun generateFileFromUri(context: Context?, uri: Uri?, path: String) {
if (uri != null) {
context?.contentResolver?.openInputStream(uri)?.copyTo(FileOutputStream(path))
}
}
}
\ No newline at end of file
...@@ -60,6 +60,16 @@ class LifeAccountAuthBusinessInfoEditView @JvmOverloads constructor( ...@@ -60,6 +60,16 @@ class LifeAccountAuthBusinessInfoEditView @JvmOverloads constructor(
} }
} }
/**
* 填充传入的文字
*/
fun fillEditContent(content: String?) {
if (!TextUtils.isEmpty(content)) {
viewBinding.etContent.setText(content)
viewBinding.ivClear.visibility = View.VISIBLE
}
}
override fun onClick(v: View?) { override fun onClick(v: View?) {
if (v?.id == R.id.iv_clear) { if (v?.id == R.id.iv_clear) {
// 清除输入框中的内容 // 清除输入框中的内容
......
...@@ -61,7 +61,7 @@ class LifeAccountAuthIdentityInfoEditView @JvmOverloads constructor( ...@@ -61,7 +61,7 @@ class LifeAccountAuthIdentityInfoEditView @JvmOverloads constructor(
} }
/** /**
* 填传入的文字 * 填传入的文字
*/ */
fun fillEditContent(content: String?) { fun fillEditContent(content: String?) {
if (!TextUtils.isEmpty(content)) { if (!TextUtils.isEmpty(content)) {
......
...@@ -59,6 +59,12 @@ ...@@ -59,6 +59,12 @@
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" /> app:layout_constraintStart_toStartOf="parent" />
<com.yidian.nightmode.widget.YdImageView
android:id="@+id/iv_business_license"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY" />
<com.yidian.nightmode.widget.YdImageView <com.yidian.nightmode.widget.YdImageView
android:id="@+id/iv_clear" android:id="@+id/iv_clear"
android:layout_width="23dp" android:layout_width="23dp"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment