小工具知识网

当前位置: 首页 > 行业知识 > Android:身份证识别功能实现

行业知识

Android:身份证识别功能实现

2026-11-10 17:49:52 来源:互联网转载

说明:

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

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

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

1.AndroidManifest.xml添加权限:
 

2. 工程根目录build.gradle:

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

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

public class HWIDCardScanBiz {    private static HWIDCardScanBiz I;    public static HWIDCardScanBiz I() {        if (I == null) {            I = new HWIDCardScanBiz();        }        return I;    }    /**     * 打开身份证识别页,调用之前要申请蓝牙动态权限     */    public void startIDCardScanActivity(Context context, IDCardScanCallback callback) {        MLCnIcrCaptureConfig config = new MLCnIcrCaptureConfig.Factory()                .setFront(true)                .create();        MLCnIcrCapture icrCapture = MLCnIcrCaptureFactory.getInstance().getIcrCapture(config);        icrCapture.capture(new HWIDScanCallback(callback), context);    }    private class HWIDScanCallback implements MLCnIcrCapture.CallBack {        private IDCardScanCallback callback;        public HWIDScanCallback(IDCardScanCallback callback) {            this.callback = callback;        }        /**         * 识别成功回调         */        @Override        public void onSuccess(MLCnIcrCaptureResult result) {            if (result == null) {                Toast.makeText(XApp.Companion.getContext(), "识别失败", Toast.LENGTH_SHORT);                return;            }            if (callback != null) {                IDCardInfo info = new IDCardInfo(result.name, result.sex, result.nation, result.birthday, result.address, result.idNum, result.authority, result.validDate, result.sideType);                callback.onIDCardResult(info);            }        }        @Override        public void onCanceled() {        }        @Override        public void onFailure(int retCode, Bitmap bitmap) {            Toast.makeText(XApp.Companion.getContext(), "识别失败", Toast.LENGTH_SHORT);        }        @Override        public void onDenied() {        }    }    public interface IDCardScanCallback {        void onIDCardResult(IDCardInfo result);    }}

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

HWIDCardScanBiz.I().startIDCardScanActivity(context, new HWIDCardScanBiz.IDCardScanCallback() {    @Override    public void onIDCardResult(IDCardInfo result) {        /*result.name: 姓名result.sex:性别result.nation:国籍result.birthday:生日result.address:地址result.idNum:身份证号result.validDate:有效期         */    }});

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

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

1.添加配置:(1)AndroidManifest.xml添加权限:
 
(2)proguard-rules.pro添加混淆例外:
-keep class com.baidu.ocr.sdk.**{*;}-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模块工程:
//...省略之前配的其他地址repositories {    flatDir {        dirs 'libs'    }}dependencies {    //...省略之前配的其他地址    implementation(name: 'ocrsdk', ext: 'aar')    implementation project(path: ':ocr_ui')}
2.调用代码实现身份证识别:第1步:调用SDK方法获取token;第2步:调用SDK方法打开身份证识别界面;第3步,在调用的Activity的onActivityResult中调用SDK识别图片中的身份信息。身份证SDK业务类:
public class IDCardScanBiz {    public static final int REQUEST_CODE_CAMERA = 100;    private boolean mHasGotToken;    private static IDCardScanBiz I;    public static IDCardScanBiz I() {        if (I == null) {            I = new IDCardScanBiz();        }        return I;    }    /**     * 第1步,调用此方法获取token     */    public void initToken() {        OCR.getInstance(ExampleApplication.Companion.getContext()).initAccessTokenWithAkSk(new OnResultListener() {            @Override            public void onResult(Object o) {                Log.i("BDIDCard", "getAccessToken onResult >>> o: " + o.toString());                mHasGotToken = true;                init();            }            @Override            public void onError(OCRError error) {                Log.i("BDIDCard", "getAccessToken onError >>> error: " + error.toString());                // 调用失败,返回OCRError子类SDKError对象            }        }, ExampleApplication.Companion.getContext(), "gPxzwMwJVfENiggqd6csyE85", "hcTVlJYj8sKGEgWngy8Qmp83mNxVqp8O");    }    /**     * 初始化本地质量控制模型     */    private void init() {        Context context = ExampleApplication.Companion.getContext();        CameraNativeHelper.init(context, OCR.getInstance(context).getLicense(), (errorCode, e) -> Log.i("BDIDCard", "init onError >>> errorCode: " + errorCode));    }    /**     * 第2步:调用此方法打开身份证识别界面     */    public void startIDCardScanActivity(Activity act) {        if (!mHasGotToken) return;        Intent intent = new Intent(act, CameraActivity.class);        intent.putExtra(CameraActivity.KEY_OUTPUT_FILE_PATH, getSaveFile().getAbsolutePath());        intent.putExtra(CameraActivity.KEY_NATIVE_ENABLE, true);        intent.putExtra(CameraActivity.KEY_NATIVE_MANUAL, true);        intent.putExtra(CameraActivity.KEY_CONTENT_TYPE, CameraActivity.CONTENT_TYPE_ID_CARD_FRONT);        act.startActivityForResult(intent, REQUEST_CODE_CAMERA);    }    /**     * 第3步,在onActivityResult中调此方法,调用百度云API获取照片中的身份证信息     */    public void readIDCard() {        if (!mHasGotToken) return;        String filePath = getSaveFile().getAbsolutePath();        IDCardParams param = new IDCardParams();        param.setImageFile(new File(filePath));        // 设置身份证正反面        param.setIdCardSide(IDCardParams.ID_CARD_SIDE_FRONT);        // 设置方向检测        param.setDetectDirection(true);        // 设置图像参数压缩质量0-100, 越大图像质量越好但是请求时间越长。 不设置则默认值为20        param.setImageQuality(20);        param.setDetectRisk(true);        OCR.getInstance(ExampleApplication.Companion.getContext()).recognizeIDCard(param, new OnResultListener() {            @Override            public void onResult(IDCardResult result) {                Log.i("BDIDCard", "recIDCard result >>> result: " + result.toString());                if (result != null) {//获取身份信息                }            }            @Override            public void onError(OCRError error) {                Log.i("BDIDCard", "recIDCard result >>> error: " + error.toString());            }        });    }    public static File getSaveFile() {        File file = new File(ExampleApplication.Companion.getContext().getFilesDir(), "pic.jpg");        return file;    }}

调用业务类的Activity:

class MainActivity : Activity() {    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(R.layout.activity_main)        var ps = arrayOf(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE)        ActivityCompat.requestPermissions(this, ps, 100);        IDCardScanBiz.I().initToken()    }    fun onScanClick(v: View) {        IDCardScanBiz.I().startIDCardScanActivity(this)    }    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {        super.onActivityResult(requestCode, resultCode, data)        if (requestCode == IDCardScanBiz.REQUEST_CODE_CAMERA && resultCode == RESULT_OK) {            IDCardScanBiz.I().readIDCard()        }    }}

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

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

1.AndroidManifest.xml添加权限:

同上面两种

2.调用代码实现身份证识别:

第1步,调用百度API获取token:

public static String getToken() {        String url = "https://aip.baidubce.com/oauth/2.0/token?client_&client_secret=" + Config.CLIENT_SECRET + "&grant_type=client_credentials";        if (!NetHelp.getCurConnectStatus()) {            return null;        }        Response response = null;        try {            Request request = new Request.Builder().url(url).get().build();            LogUtils.d("getToken request url :" + url);            response = httpClient.newCall(request).execute();        } catch (IOException e) {            LogUtils.d("getToken request exception: " + e.getMessage());            e.printStackTrace();            return null;        }        LogUtils.d("getToken response isSuccessful: " + response.isSuccessful());        if (response != null && response.isSuccessful()) {            try {                String strRecData = response.body().string();                LogUtils.d("getToken response body: " + strRecData);                if (strRecData != null && strRecData.length() > 2) {                    JSONObject jsonObj = new JSONObject(strRecData);                    if (jsonObj != null && !jsonObj.isNull("access_token")) {                        return jsonObj.getString("access_token");                    }                }                return response.body().string();            } catch (Exception e) {                LogUtils.d("getToken response parse exception: " + e.getMessage());                e.printStackTrace();                return null;            }        }        return null;    }

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

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

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

    /**     * 解析身份证图片,获取身份信息     */    public void handlerData(Activity act, Intent data, IDCardScanCallback callback) {        new Thread() {            @Override            public void run() {                Bundle bundle = data.getExtras();                Log.i("IDCard", "IDCard handlerData bundle >>> : " + bundle);                if (bundle == null) return;                Bitmap bitmap = (Bitmap) bundle.get("data");                Log.i("IDCard", "IDCard handlerData bitmap >>> : " + bitmap);                if (bitmap == null) return;                File file = new File(App.getContext().getCacheDir(), System.currentTimeMillis() + ".jpeg");                if (!file.getParentFile().exists()) file.mkdirs();                try {                    FileOutputStream out = new FileOutputStream(file);                    bitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);                    out.flush();                    out.close();                    Log.i("IDCard", "IDCard saveBitmap  filePath: " + file.getAbsolutePath() + "  fileLen: " + file.length());                } catch (IOException ex) {                    ex.printStackTrace();                }                String filePath = file.getAbsolutePath();                Log.i("IDCard", "IDCard parseImage >>>  filePath: " + filePath);                final IDCardInfo info = HttpHelp.getIDCard(new File(filePath));                if (info != null && callback != null) {                    act.runOnUiThread(() -> callback.onIDCardResult(info));                }            }        }.start();    }    public static IDCardInfo getIDCard(File file){        if (!NetHelp.getCurConnectStatus() || file == null || file.length()  2) {                    JSONObject rootObj = new JSONObject(strRecData);                    if (rootObj != null && !rootObj.isNull("words_result")) {                        JSONObject wordObj = rootObj.getJSONObject("words_result");                        IDCardInfo info = new IDCardInfo();                        if (!wordObj.isNull("姓名") && !wordObj.getJSONObject("姓名").isNull("words")) {                            info.name = wordObj.getJSONObject("姓名").getString("words");                        }                        if (wordObj != null && !wordObj.isNull("民族") && !wordObj.getJSONObject("民族").isNull("words")) {                            info.nation = wordObj.getJSONObject("民族").getString("words");                        }                        if (wordObj != null && !wordObj.isNull("住址") && !wordObj.getJSONObject("住址").isNull("words")) {                            info.address = wordObj.getJSONObject("住址").getString("words");                        }                        if (wordObj != null && !wordObj.isNull("公民身份号码") && !wordObj.getJSONObject("公民身份号码").isNull("words")) {                            info.idNum = wordObj.getJSONObject("公民身份号码").getString("words");                        }                        if (wordObj != null && !wordObj.isNull("出生") && !wordObj.getJSONObject("出生").isNull("words")) {                            info.birthday = wordObj.getJSONObject("出生").getString("words");                        }                        if (wordObj != null && !wordObj.isNull("性别") && !wordObj.getJSONObject("性别").isNull("words")) {                            info.sex = wordObj.getJSONObject("性别").getString("words");                        }                        LogUtils.d("getIDCard response parse IDCardInfo: " + info.toString());                        return info;                    }                }            } catch (Exception e) {                LogUtils.d("getIDCard response parse exception: " + e.getMessage());                e.printStackTrace();                return null;            }        }        return null;    }

上一篇:服务器的硬盘怎么判断好坏?

下一篇:AJAX 学习笔记(Day4)