当前位置:   article > 正文

Android:身份证识别功能实现_android身份证识别

android身份证识别

说明:

此文使用华为SDK、百度SDK、百度在线API三种方式实现。

一、使用华为SDK实现身份证识别

说明:免费,不需要联网。

1.AndroidManifest.xml添加权限:
  1. <uses-permission android:name="android.permission.INTERNET" />
  2. <uses-permission android:name="android.permission.CAMERA"/>
  3. <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
  4. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  5. <uses-feature android:name="android.hardware.camera" />
  6. <uses-feature android:name="android.hardware.camera.autofocus" />

2. 工程根目录build.gradle:

  1. buildscript {
  2. repositories {
  3. //...省略之前配的其他地址
  4. maven { url "https://developer.huawei.com/repo/" }
  5. }
  6. dependencies {
  7. //...省略之前配的其他地址
  8. classpath 'com.huawei.agconnect:agcp:1.6.0.300'
  9. }
  10. }
  11. allprojects {
  12. repositories {
  13. //...省略之前配的其他地址
  14. maven { url "https://developer.huawei.com/repo/" }
  15. }
  16. }
3.工程/app/build.gradle:
  1. //...省略之前配的其他地址
  2. apply plugin: 'com.huawei.agconnect'
  3. android {
  4. //...省略之前配的其他地址
  5. packagingOptions {
  6. exclude 'lib/arm64-v8a/libmsoptimize.so'
  7. }
  8. }
  9. dependencies {
  10. //...省略之前配的其他地址
  11. implementation 'com.huawei.hms:ml-computer-card-icr-cn:2.0.3.303'
  12. implementation 'com.huawei.hms:ml-computer-vision-ocr:2.0.5.301'
  13. implementation 'com.huawei.hms:ml-computer-vision-ocr-cn-model:2.0.5.301'
  14. implementation 'com.huawei.hms:ml-computer-vision-ocr-jk-model:2.0.5.301'
  15. implementation 'com.huawei.hms:ml-computer-vision-ocr-latin-model:2.0.5.301'
  16. implementation 'com.huawei.hms:ml-computer-card-gcr-plugin:2.0.1.301'
  17. }
4.调用身份证SDK:

(1)身份证识别业务类:

  1. public class HWIDCardScanBiz {
  2. private static HWIDCardScanBiz I;
  3. public static HWIDCardScanBiz I() {
  4. if (I == null) {
  5. I = new HWIDCardScanBiz();
  6. }
  7. return I;
  8. }
  9. /**
  10. * 打开身份证识别页,调用之前要申请蓝牙动态权限
  11. */
  12. public void startIDCardScanActivity(Context context, IDCardScanCallback callback) {
  13. MLCnIcrCaptureConfig config = new MLCnIcrCaptureConfig.Factory()
  14. .setFront(true)
  15. .create();
  16. MLCnIcrCapture icrCapture = MLCnIcrCaptureFactory.getInstance().getIcrCapture(config);
  17. icrCapture.capture(new HWIDScanCallback(callback), context);
  18. }
  19. private class HWIDScanCallback implements MLCnIcrCapture.CallBack {
  20. private IDCardScanCallback callback;
  21. public HWIDScanCallback(IDCardScanCallback callback) {
  22. this.callback = callback;
  23. }
  24. /**
  25. * 识别成功回调
  26. */
  27. @Override
  28. public void onSuccess(MLCnIcrCaptureResult result) {
  29. if (result == null) {
  30. Toast.makeText(XApp.Companion.getContext(), "识别失败", Toast.LENGTH_SHORT);
  31. return;
  32. }
  33. if (callback != null) {
  34. IDCardInfo info = new IDCardInfo(result.name, result.sex, result.nation, result.birthday, result.address, result.idNum, result.authority, result.validDate, result.sideType);
  35. callback.onIDCardResult(info);
  36. }
  37. }
  38. @Override
  39. public void onCanceled() {
  40. }
  41. @Override
  42. public void onFailure(int retCode, Bitmap bitmap) {
  43. Toast.makeText(XApp.Companion.getContext(), "识别失败", Toast.LENGTH_SHORT);
  44. }
  45. @Override
  46. public void onDenied() {
  47. }
  48. }
  49. public interface IDCardScanCallback {
  50. void onIDCardResult(IDCardInfo result);
  51. }
  52. }

(2)调用识别业务类,更新UI:

  1. HWIDCardScanBiz.I().startIDCardScanActivity(context, new HWIDCardScanBiz.IDCardScanCallback() {
  2. @Override
  3. public void onIDCardResult(IDCardInfo result) {
  4. /*
  5. result.name: 姓名
  6. result.sex:性别
  7. result.nation:国籍
  8. result.birthday:生日
  9. result.address:地址
  10. result.idNum:身份证号
  11. result.validDate:有效期
  12. */
  13. }
  14. });

二、使用百度云SDK实现身份证识别:

说明:免费额度个人帐户每月1千次/企业帐户每月2千次,要联网。

1.添加配置:
(1)AndroidManifest.xml添加权限:
  1. <uses-permission android:name="android.permission.INTERNET" />
  2. <uses-permission android:name="android.permission.CAMERA"/>
  3. <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
  4. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  5. <uses-feature android:name="android.hardware.camera" />
  6. <uses-feature android:name="android.hardware.camera.autofocus" />
(2)proguard-rules.pro添加混淆例外:
  1. -keep class com.baidu.ocr.sdk.**{*;}
  2. -dontwarn com.baidu.ocr.**
(3)将ocrsdk.aar放入工程\app\libs目录下。

(4)从以下地址(控制台-公有云-应用列表-进入某个应用详情页)下载aip-ocr.license放入工程\app\src\main\assets下:
https://console.bce.baidu.com/ai/#/ai/ocr/app/detail~appId=4571869
(5)将ocr_ui模块工程放入工程根目录下,在settings.gradle中添加导入模块工程的配置:
include ':app', 'ocrsdk', 'ocr_ui'
(6)工程/app/build.gradle,导入ocrsdk.aar与ocr_ui模块工程:
  1. //...省略之前配的其他地址
  2. repositories {
  3. flatDir {
  4. dirs 'libs'
  5. }
  6. }
  7. dependencies {
  8. //...省略之前配的其他地址
  9. implementation(name: 'ocrsdk', ext: 'aar')
  10. implementation project(path: ':ocr_ui')
  11. }
2.调用代码实现身份证识别:
第1步:调用SDK方法获取token;
第2步:调用SDK方法打开身份证识别界面;
第3步,在调用的Activity的onActivityResult中调用SDK识别图片中的身份信息。

身份证SDK业务类:
  1. public class IDCardScanBiz {
  2. public static final int REQUEST_CODE_CAMERA = 100;
  3. private boolean mHasGotToken;
  4. private static IDCardScanBiz I;
  5. public static IDCardScanBiz I() {
  6. if (I == null) {
  7. I = new IDCardScanBiz();
  8. }
  9. return I;
  10. }
  11. /**
  12. * 第1步,调用此方法获取token
  13. */
  14. public void initToken() {
  15. OCR.getInstance(ExampleApplication.Companion.getContext()).initAccessTokenWithAkSk(new OnResultListener() {
  16. @Override
  17. public void onResult(Object o) {
  18. Log.i("BDIDCard", "getAccessToken onResult >>> o: " + o.toString());
  19. mHasGotToken = true;
  20. init();
  21. }
  22. @Override
  23. public void onError(OCRError error) {
  24. Log.i("BDIDCard", "getAccessToken onError >>> error: " + error.toString());
  25. // 调用失败,返回OCRError子类SDKError对象
  26. }
  27. }, ExampleApplication.Companion.getContext(), "gPxzwMwJVfENiggqd6csyE85", "hcTVlJYj8sKGEgWngy8Qmp83mNxVqp8O");
  28. }
  29. /**
  30. * 初始化本地质量控制模型
  31. */
  32. private void init() {
  33. Context context = ExampleApplication.Companion.getContext();
  34. CameraNativeHelper.init(context, OCR.getInstance(context).getLicense(), (errorCode, e) -> Log.i("BDIDCard", "init onError >>> errorCode: " + errorCode));
  35. }
  36. /**
  37. * 第2步:调用此方法打开身份证识别界面
  38. */
  39. public void startIDCardScanActivity(Activity act) {
  40. if (!mHasGotToken) return;
  41. Intent intent = new Intent(act, CameraActivity.class);
  42. intent.putExtra(CameraActivity.KEY_OUTPUT_FILE_PATH, getSaveFile().getAbsolutePath());
  43. intent.putExtra(CameraActivity.KEY_NATIVE_ENABLE, true);
  44. intent.putExtra(CameraActivity.KEY_NATIVE_MANUAL, true);
  45. intent.putExtra(CameraActivity.KEY_CONTENT_TYPE, CameraActivity.CONTENT_TYPE_ID_CARD_FRONT);
  46. act.startActivityForResult(intent, REQUEST_CODE_CAMERA);
  47. }
  48. /**
  49. * 第3步,在onActivityResult中调此方法,调用百度云API获取照片中的身份证信息
  50. */
  51. public void readIDCard() {
  52. if (!mHasGotToken) return;
  53. String filePath = getSaveFile().getAbsolutePath();
  54. IDCardParams param = new IDCardParams();
  55. param.setImageFile(new File(filePath));
  56. // 设置身份证正反面
  57. param.setIdCardSide(IDCardParams.ID_CARD_SIDE_FRONT);
  58. // 设置方向检测
  59. param.setDetectDirection(true);
  60. // 设置图像参数压缩质量0-100, 越大图像质量越好但是请求时间越长。 不设置则默认值为20
  61. param.setImageQuality(20);
  62. param.setDetectRisk(true);
  63. OCR.getInstance(ExampleApplication.Companion.getContext()).recognizeIDCard(param, new OnResultListener<IDCardResult>() {
  64. @Override
  65. public void onResult(IDCardResult result) {
  66. Log.i("BDIDCard", "recIDCard result >>> result: " + result.toString());
  67. if (result != null) {//获取身份信息
  68. }
  69. }
  70. @Override
  71. public void onError(OCRError error) {
  72. Log.i("BDIDCard", "recIDCard result >>> error: " + error.toString());
  73. }
  74. });
  75. }
  76. public static File getSaveFile() {
  77. File file = new File(ExampleApplication.Companion.getContext().getFilesDir(), "pic.jpg");
  78. return file;
  79. }
  80. }

调用业务类的Activity:

  1. class MainActivity : Activity() {
  2. override fun onCreate(savedInstanceState: Bundle?) {
  3. super.onCreate(savedInstanceState)
  4. setContentView(R.layout.activity_main)
  5. var ps = arrayOf(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE)
  6. ActivityCompat.requestPermissions(this, ps, 100);
  7. IDCardScanBiz.I().initToken()
  8. }
  9. fun onScanClick(v: View) {
  10. IDCardScanBiz.I().startIDCardScanActivity(this)
  11. }
  12. override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
  13. super.onActivityResult(requestCode, resultCode, data)
  14. if (requestCode == IDCardScanBiz.REQUEST_CODE_CAMERA && resultCode == RESULT_OK) {
  15. IDCardScanBiz.I().readIDCard()
  16. }
  17. }
  18. }

三、使用百度云API实现身份证识别:

说明:免费额度个人帐户每月1千次/企业帐户每月2千次,要联网。

1.AndroidManifest.xml添加权限:

同上面两种

2.调用代码实现身份证识别:
第1步,调用百度API获取token:

  1. public static String getToken() {
  2. String url = "https://aip.baidubce.com/oauth/2.0/token?client_id=" + Config.CLIENT_ID + "&client_secret=" + Config.CLIENT_SECRET + "&grant_type=client_credentials";
  3. if (!NetHelp.getCurConnectStatus()) {
  4. return null;
  5. }
  6. Response response = null;
  7. try {
  8. Request request = new Request.Builder().url(url).get().build();
  9. LogUtils.d("getToken request url :" + url);
  10. response = httpClient.newCall(request).execute();
  11. } catch (IOException e) {
  12. LogUtils.d("getToken request exception: " + e.getMessage());
  13. e.printStackTrace();
  14. return null;
  15. }
  16. LogUtils.d("getToken response isSuccessful: " + response.isSuccessful());
  17. if (response != null && response.isSuccessful()) {
  18. try {
  19. String strRecData = response.body().string();
  20. LogUtils.d("getToken response body: " + strRecData);
  21. if (strRecData != null && strRecData.length() > 2) {
  22. JSONObject jsonObj = new JSONObject(strRecData);
  23. if (jsonObj != null && !jsonObj.isNull("access_token")) {
  24. return jsonObj.getString("access_token");
  25. }
  26. }
  27. return response.body().string();
  28. } catch (Exception e) {
  29. LogUtils.d("getToken response parse exception: " + e.getMessage());
  30. e.printStackTrace();
  31. return null;
  32. }
  33. }
  34. return null;
  35. }

第2步,调用系统相机拍身份证照片(可以自已实现带身份证头像框的拍照功能,界面更加美观):

  1. /**
  2. * 调起系统相机进行拍照,此步可以自已实现拍照功能,界面更美观
  3. */
  4. public void startIDCardScanActivity(Activity act) {
  5. Log.i("IDCard", "IDCard startIDCardScanActivity >>>");
  6. Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
  7. if (intent.resolveActivity(act.getPackageManager()) != null) {
  8. act.startActivityForResult(intent, REQUEST_CODE_CAMERA);
  9. }
  10. }

第3步,在onActivityResult中,将图片上传百度API获取身份证信息:

  1. /**
  2. * 解析身份证图片,获取身份信息
  3. */
  4. public void handlerData(Activity act, Intent data, IDCardScanCallback callback) {
  5. new Thread() {
  6. @Override
  7. public void run() {
  8. Bundle bundle = data.getExtras();
  9. Log.i("IDCard", "IDCard handlerData bundle >>> : " + bundle);
  10. if (bundle == null) return;
  11. Bitmap bitmap = (Bitmap) bundle.get("data");
  12. Log.i("IDCard", "IDCard handlerData bitmap >>> : " + bitmap);
  13. if (bitmap == null) return;
  14. File file = new File(App.getContext().getCacheDir(), System.currentTimeMillis() + ".jpeg");
  15. if (!file.getParentFile().exists()) file.mkdirs();
  16. try {
  17. FileOutputStream out = new FileOutputStream(file);
  18. bitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);
  19. out.flush();
  20. out.close();
  21. Log.i("IDCard", "IDCard saveBitmap filePath: " + file.getAbsolutePath() + " fileLen: " + file.length());
  22. } catch (IOException ex) {
  23. ex.printStackTrace();
  24. }
  25. String filePath = file.getAbsolutePath();
  26. Log.i("IDCard", "IDCard parseImage >>> filePath: " + filePath);
  27. final IDCardInfo info = HttpHelp.getIDCard(new File(filePath));
  28. if (info != null && callback != null) {
  29. act.runOnUiThread(() -> callback.onIDCardResult(info));
  30. }
  31. }
  32. }.start();
  33. }
  34. public static IDCardInfo getIDCard(File file){
  35. if (!NetHelp.getCurConnectStatus() || file == null || file.length() <= 0){
  36. return null;
  37. }
  38. String accessToken = getToken();
  39. if (TextUtils.isEmpty(accessToken)) return null;
  40. String url = "https://aip.baidubce.com/rest/2.0/ocr/v1/idcard?access_token=" + accessToken;
  41. String img = null;
  42. try {
  43. img = FileUtils.base64File(file);
  44. } catch (Exception e) {
  45. e.printStackTrace();
  46. }
  47. if (TextUtils.isEmpty(img)) return null;
  48. Response response = null;
  49. try {
  50. FormBody.Builder builder = new FormBody.Builder()
  51. .add("id_card_side", "front")
  52. .add("image", img);
  53. Request request = new Request.Builder()
  54. .url(url)
  55. .post(builder.build())
  56. .build();
  57. LogUtils.d("getIDCard request url :" + url + " img: " + img);
  58. response = httpClient.newCall(request).execute();
  59. } catch (IOException e) {
  60. LogUtils.d("getIDCard request exception: " + e.getMessage());
  61. e.printStackTrace();
  62. return null;
  63. }
  64. LogUtils.d("getIDCard response isSuccessful: " + response.isSuccessful());
  65. if (response != null && response.isSuccessful()) {
  66. try {
  67. String strRecData = response.body().string();
  68. LogUtils.d("getIDCard response body: " + strRecData);
  69. if (strRecData != null && strRecData.length() > 2) {
  70. JSONObject rootObj = new JSONObject(strRecData);
  71. if (rootObj != null && !rootObj.isNull("words_result")) {
  72. JSONObject wordObj = rootObj.getJSONObject("words_result");
  73. IDCardInfo info = new IDCardInfo();
  74. if (!wordObj.isNull("姓名") && !wordObj.getJSONObject("姓名").isNull("words")) {
  75. info.name = wordObj.getJSONObject("姓名").getString("words");
  76. }
  77. if (wordObj != null && !wordObj.isNull("民族") && !wordObj.getJSONObject("民族").isNull("words")) {
  78. info.nation = wordObj.getJSONObject("民族").getString("words");
  79. }
  80. if (wordObj != null && !wordObj.isNull("住址") && !wordObj.getJSONObject("住址").isNull("words")) {
  81. info.address = wordObj.getJSONObject("住址").getString("words");
  82. }
  83. if (wordObj != null && !wordObj.isNull("公民身份号码") && !wordObj.getJSONObject("公民身份号码").isNull("words")) {
  84. info.idNum = wordObj.getJSONObject("公民身份号码").getString("words");
  85. }
  86. if (wordObj != null && !wordObj.isNull("出生") && !wordObj.getJSONObject("出生").isNull("words")) {
  87. info.birthday = wordObj.getJSONObject("出生").getString("words");
  88. }
  89. if (wordObj != null && !wordObj.isNull("性别") && !wordObj.getJSONObject("性别").isNull("words")) {
  90. info.sex = wordObj.getJSONObject("性别").getString("words");
  91. }
  92. LogUtils.d("getIDCard response parse IDCardInfo: " + info.toString());
  93. return info;
  94. }
  95. }
  96. } catch (Exception e) {
  97. LogUtils.d("getIDCard response parse exception: " + e.getMessage());
  98. e.printStackTrace();
  99. return null;
  100. }
  101. }
  102. return null;
  103. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/683003
推荐阅读
相关标签
  

闽ICP备14008679号