源码下载地址:注:源码里没有腾讯优图的账号需要填写自己的 下载地址

先讲几下.首先我们需要去腾讯优图申请一个账号,因为身份证识别需要用到第三方接口如图所示

我申请的是扫描身份证,当然还有其他的功能,比如扫描银行卡,营业执照,车牌等等  ,大家可以去研究一下

1.记得配权限,需要读写SD卡 ,还需要网络的权限   记得引入第三方库,本人很懒,反正能少些代码的,绝对不手打,能用第三库解决的,绝不自己动手,哈哈

    //网络请求库compile 'org.xutils:xutils:3.3.36'//图片选择器库compile 'com.github.LuckSiege.PictureSelector:picture_library:v2.2.3'//解析库compile 'com.google.code.gson:gson:2.7'

还有,记得在allprojects添加下代码

allprojects {repositories {maven { url 'https://jitpack.io' }maven { url 'https://maven.google.com' }//图片选择器库maven {url "http://dl.bintray.com/nuptboyzhb/maven"}google()jcenter()}
}

下面配置好权限

    <!-- 读写 --><uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /><!-- 用于申请调用照相机 --><uses-permission android:name="android.permission.CAMERA" />

然后新建一个Application配置下网络请求吧

public class MyApplication extends Application {@Overridepublic void onCreate() {super.onCreate();
//网络请求x.Ext.init(this);}
}

记得在Manifests中设置一下name=.MyApplication

 <applicationandroid:name=".MyApplication"android:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/AppTheme">

接下来是布局文件来,等会上代码了

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@color/white"android:orientation="vertical"><ScrollViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:fillViewport="true"android:scrollbars="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><ImageViewandroid:id="@+id/activity_autonym_certification_iv_positive"android:layout_width="match_parent"android:layout_height="180dp"android:layout_marginRight="30dp"android:layout_marginLeft="30dp"android:layout_marginTop="20dp"android:background="@drawable/autonym_certification_iv_line"android:padding="20dp"android:src="@mipmap/idcard_positive" /><ImageViewandroid:id="@+id/activity_autonym_certification_iv_reverse"android:layout_width="match_parent"android:layout_height="180dp"android:layout_marginTop="25dp"android:layout_marginRight="30dp"android:layout_marginLeft="30dp"android:background="@drawable/autonym_certification_iv_line"android:padding="20dp"android:src="@mipmap/idcard_reverse" /><LinearLayoutandroid:layout_marginRight="30dp"android:layout_marginLeft="30dp"android:layout_marginTop="20dp"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:layout_width="90dp"android:layout_height="wrap_content"android:text="姓名:"android:textColor="@color/black"/><EditTextandroid:enabled="false"android:id="@+id/activity_autonym_certification_et_name"android:layout_width="match_parent"android:layout_height="wrap_content"android:textColor="@color/black"android:gravity="center"android:background="@drawable/autonym_certification_iv_line"android:text=""/></LinearLayout><LinearLayoutandroid:layout_marginTop="10dp"android:layout_marginLeft="30dp"android:layout_marginRight="30dp"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:layout_width="90dp"android:layout_height="wrap_content"android:text="有效日期:"android:textColor="@color/black"/><EditTextandroid:enabled="false"android:id="@+id/activity_autonym_certification_et_effective_date"android:layout_width="match_parent"android:layout_height="wrap_content"android:textColor="@color/black"android:gravity="center"android:background="@drawable/autonym_certification_iv_line"android:text=""/></LinearLayout><LinearLayoutandroid:layout_marginLeft="30dp"android:layout_marginRight="30dp"android:layout_marginTop="10dp"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:layout_width="90dp"android:layout_height="wrap_content"android:text="身份证号码:"android:textColor="@color/black"/><EditTextandroid:id="@+id/activity_autonym_certification_et_id_card"android:layout_width="match_parent"android:layout_height="wrap_content"android:textColor="@color/black"android:gravity="center"android:enabled="false"android:background="@drawable/autonym_certification_iv_line"android:text=""/></LinearLayout></LinearLayout></ScrollView></LinearLayout>

然后是两个实体类用来存放身份证 正反两面的数据,先是正面

package com.example.aa.demo.entity;import java.io.Serializable;
import java.util.List;/*** 识别结果实体*/
public class IdentifyResult implements Serializable {/*** errorcode : 0* errormsg : OK* name : xxx* name_confidence_all : [50,60,53]* sex : xx* sex_confidence_all : [41]* nation : xx* nation_confidence_all : [38]* birth : xxxx/xx/xx* birth_confidence_all : [69,43,46,46,44,53,50]* address : xxxxxxxxx* address_confidence_all : [43,36,34,17,25,24,21,31,45,36,23,62,12,30,9,1,39,34,24,19,16,30,30,4]* id : xxxxxxxxxxxxxxxxxx* id_confidence_all : [52,58,59,73,54,56,61,63,50,63,60,49,72,50,62,57,63,53]* frontimage : xxx* frontimage_confidence_all : []* watermask_confidence_all : []* valid_date_confidence_all : []* authority_confidence_all : []* backimage_confidence_all : []* detail_errorcode : []* detail_errormsg : []*/private int errorcode;private String errormsg;private String name;private String sex;private String nation;private String birth;private String address;private String id;private String frontimage;private List<Integer> name_confidence_all;private List<Integer> sex_confidence_all;private List<Integer> nation_confidence_all;private List<Integer> birth_confidence_all;private List<Integer> address_confidence_all;private List<Integer> id_confidence_all;private List<?> frontimage_confidence_all;private List<?> watermask_confidence_all;private List<?> valid_date_confidence_all;private List<?> authority_confidence_all;private List<?> backimage_confidence_all;private List<Integer> detail_errorcode;private List<String> detail_errormsg;public int getErrorcode() {return errorcode;}public void setErrorcode(int errorcode) {this.errorcode = errorcode;}public String getErrormsg() {return errormsg;}public void setErrormsg(String errormsg) {this.errormsg = errormsg;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public String getNation() {return nation;}public void setNation(String nation) {this.nation = nation;}public String getBirth() {return birth;}public void setBirth(String birth) {this.birth = birth;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getFrontimage() {return frontimage;}public void setFrontimage(String frontimage) {this.frontimage = frontimage;}public List<Integer> getName_confidence_all() {return name_confidence_all;}public void setName_confidence_all(List<Integer> name_confidence_all) {this.name_confidence_all = name_confidence_all;}public List<Integer> getSex_confidence_all() {return sex_confidence_all;}public void setSex_confidence_all(List<Integer> sex_confidence_all) {this.sex_confidence_all = sex_confidence_all;}public List<Integer> getNation_confidence_all() {return nation_confidence_all;}public void setNation_confidence_all(List<Integer> nation_confidence_all) {this.nation_confidence_all = nation_confidence_all;}public List<Integer> getBirth_confidence_all() {return birth_confidence_all;}public void setBirth_confidence_all(List<Integer> birth_confidence_all) {this.birth_confidence_all = birth_confidence_all;}public List<Integer> getAddress_confidence_all() {return address_confidence_all;}public void setAddress_confidence_all(List<Integer> address_confidence_all) {this.address_confidence_all = address_confidence_all;}public List<Integer> getId_confidence_all() {return id_confidence_all;}public void setId_confidence_all(List<Integer> id_confidence_all) {this.id_confidence_all = id_confidence_all;}public List<?> getFrontimage_confidence_all() {return frontimage_confidence_all;}public void setFrontimage_confidence_all(List<?> frontimage_confidence_all) {this.frontimage_confidence_all = frontimage_confidence_all;}public List<?> getWatermask_confidence_all() {return watermask_confidence_all;}public void setWatermask_confidence_all(List<?> watermask_confidence_all) {this.watermask_confidence_all = watermask_confidence_all;}public List<?> getValid_date_confidence_all() {return valid_date_confidence_all;}public void setValid_date_confidence_all(List<?> valid_date_confidence_all) {this.valid_date_confidence_all = valid_date_confidence_all;}public List<?> getAuthority_confidence_all() {return authority_confidence_all;}public void setAuthority_confidence_all(List<?> authority_confidence_all) {this.authority_confidence_all = authority_confidence_all;}public List<?> getBackimage_confidence_all() {return backimage_confidence_all;}public void setBackimage_confidence_all(List<?> backimage_confidence_all) {this.backimage_confidence_all = backimage_confidence_all;}public List<Integer> getDetail_errorcode() {return detail_errorcode;}public void setDetail_errorcode(List<Integer> detail_errorcode) {this.detail_errorcode = detail_errorcode;}public List<String> getDetail_errormsg() {return detail_errormsg;}public void setDetail_errormsg(List<String> detail_errormsg) {this.detail_errormsg = detail_errormsg;}
}

再是反面

package com.example.aa.demo.entity;import java.io.Serializable;
import java.util.List;/*** Created by aa on 2018/10/30.*/public class cardReverseRusult implements Serializable {/*** errorcode : 0* errormsg : OK* session_id :* name_confidence_all : []* sex_confidence_all : []* nation_confidence_all : []* birth_confidence_all : []* address_confidence_all : []* id_confidence_all : []* frontimage_confidence_all : []* watermask_confidence_all : []* valid_date : 2010.07.21-2020.07.21* valid_date_confidence_all : [99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,95,99,99,99,99]* authority : 赵县公安局* authority_confidence_all : [100]* backimage : .....* backimage_confidence_all : []* detail_errorcode : []* detail_errormsg : []* card_type : 1* recognize_warn_code : []* recognize_warn_msg : []*/private int errorcode;private String errormsg;private String session_id;private String valid_date;private String authority;private String backimage;private int card_type;private List<?> name_confidence_all;private List<?> sex_confidence_all;private List<?> nation_confidence_all;private List<?> birth_confidence_all;private List<?> address_confidence_all;private List<?> id_confidence_all;private List<?> frontimage_confidence_all;private List<?> watermask_confidence_all;private List<Integer> valid_date_confidence_all;private List<Integer> authority_confidence_all;private List<?> backimage_confidence_all;private List<?> detail_errorcode;private List<?> detail_errormsg;private List<?> recognize_warn_code;private List<?> recognize_warn_msg;public int getErrorcode() {return errorcode;}public void setErrorcode(int errorcode) {this.errorcode = errorcode;}public String getErrormsg() {return errormsg;}public void setErrormsg(String errormsg) {this.errormsg = errormsg;}public String getSession_id() {return session_id;}public void setSession_id(String session_id) {this.session_id = session_id;}public String getValid_date() {return valid_date;}public void setValid_date(String valid_date) {this.valid_date = valid_date;}public String getAuthority() {return authority;}public void setAuthority(String authority) {this.authority = authority;}public String getBackimage() {return backimage;}public void setBackimage(String backimage) {this.backimage = backimage;}public int getCard_type() {return card_type;}public void setCard_type(int card_type) {this.card_type = card_type;}public List<?> getName_confidence_all() {return name_confidence_all;}public void setName_confidence_all(List<?> name_confidence_all) {this.name_confidence_all = name_confidence_all;}public List<?> getSex_confidence_all() {return sex_confidence_all;}public void setSex_confidence_all(List<?> sex_confidence_all) {this.sex_confidence_all = sex_confidence_all;}public List<?> getNation_confidence_all() {return nation_confidence_all;}public void setNation_confidence_all(List<?> nation_confidence_all) {this.nation_confidence_all = nation_confidence_all;}public List<?> getBirth_confidence_all() {return birth_confidence_all;}public void setBirth_confidence_all(List<?> birth_confidence_all) {this.birth_confidence_all = birth_confidence_all;}public List<?> getAddress_confidence_all() {return address_confidence_all;}public void setAddress_confidence_all(List<?> address_confidence_all) {this.address_confidence_all = address_confidence_all;}public List<?> getId_confidence_all() {return id_confidence_all;}public void setId_confidence_all(List<?> id_confidence_all) {this.id_confidence_all = id_confidence_all;}public List<?> getFrontimage_confidence_all() {return frontimage_confidence_all;}public void setFrontimage_confidence_all(List<?> frontimage_confidence_all) {this.frontimage_confidence_all = frontimage_confidence_all;}public List<?> getWatermask_confidence_all() {return watermask_confidence_all;}public void setWatermask_confidence_all(List<?> watermask_confidence_all) {this.watermask_confidence_all = watermask_confidence_all;}public List<Integer> getValid_date_confidence_all() {return valid_date_confidence_all;}public void setValid_date_confidence_all(List<Integer> valid_date_confidence_all) {this.valid_date_confidence_all = valid_date_confidence_all;}public List<Integer> getAuthority_confidence_all() {return authority_confidence_all;}public void setAuthority_confidence_all(List<Integer> authority_confidence_all) {this.authority_confidence_all = authority_confidence_all;}public List<?> getBackimage_confidence_all() {return backimage_confidence_all;}public void setBackimage_confidence_all(List<?> backimage_confidence_all) {this.backimage_confidence_all = backimage_confidence_all;}public List<?> getDetail_errorcode() {return detail_errorcode;}public void setDetail_errorcode(List<?> detail_errorcode) {this.detail_errorcode = detail_errorcode;}public List<?> getDetail_errormsg() {return detail_errormsg;}public void setDetail_errormsg(List<?> detail_errormsg) {this.detail_errormsg = detail_errormsg;}public List<?> getRecognize_warn_code() {return recognize_warn_code;}public void setRecognize_warn_code(List<?> recognize_warn_code) {this.recognize_warn_code = recognize_warn_code;}public List<?> getRecognize_warn_msg() {return recognize_warn_msg;}public void setRecognize_warn_msg(List<?> recognize_warn_msg) {this.recognize_warn_msg = recognize_warn_msg;}
}

然后需要几个工具类

第一个bitmap编解码工具类

package cn.vonce.doer.utils;import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Matrix;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Base64;
import android.widget.Toast;import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;/*** bitmap编解码工具类*/
public class BitMapUtils {/*** bitmap转为base64** @param bitmap* @return*/public static String bitmapToBase64(Bitmap bitmap) {String result = null;ByteArrayOutputStream baos = null;try {if (bitmap != null) {baos = new ByteArrayOutputStream();bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);baos.flush();baos.close();byte[] bitmapBytes = baos.toByteArray();result = Base64.encodeToString(bitmapBytes, Base64.DEFAULT);}} catch (IOException e) {return "";} finally {try {if (baos != null) {baos.flush();baos.close();}} catch (IOException e) {return "";}}return result;}/*** 从SD卡上获取图片。如果不存在则返回null</br>* @return 代表图片的Bitmap对象*/public static Bitmap getBitmapFromSDCard(String url) {InputStream inputStream = null;try {inputStream = new FileInputStream(new File(url));if (inputStream != null && inputStream.available() > 0) {Bitmap bitmap = BitmapFactory.decodeStream(inputStream);return bitmap;}} catch (Exception e) {e.printStackTrace();}return null;}// 分享单张图片public static void shareSingleImage(Context context, Bitmap copy) {if(copy != null){File appDir = new File(Environment.getExternalStorageDirectory(), "demo");if (!appDir.exists()) {appDir.mkdir();}String fileName = System.currentTimeMillis() + ".jpg";File file = new File(appDir, fileName);try {FileOutputStream fos = new FileOutputStream(file);copy.compress(Bitmap.CompressFormat.JPEG, 100, fos);fos.flush();fos.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}String path = file.getAbsolutePath();// 由文件得到uriUri imageUri = Uri.fromFile(new File(path));Intent shareIntent = new Intent();shareIntent.setAction(Intent.ACTION_SEND);shareIntent.putExtra(Intent.EXTRA_STREAM, imageUri);shareIntent.setType("image/*");context.startActivity(Intent.createChooser(shareIntent, "分享到"));}else {Toast.makeText(context, "请先从图库选择一张图片", Toast.LENGTH_SHORT).show();}}/*** 保存图片到本地图库** @param context       上下文* @param bmp           要保存的bitmap*/public static void saveImageToGallery(Context context, Bitmap bmp) {// 首先保存图片File appDir = new File(Environment.getExternalStorageDirectory(), "demo");if (!appDir.exists()) {appDir.mkdir();}String fileName = System.currentTimeMillis() + ".jpg";File file = new File(appDir, fileName);try {FileOutputStream fos = new FileOutputStream(file);bmp.compress(Bitmap.CompressFormat.JPEG, 100, fos);fos.flush();fos.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}String path = file.getAbsolutePath();// 其次把文件插入到系统图库try {MediaStore.Images.Media.insertImage(context.getContentResolver(),file.getAbsolutePath(), fileName, null);} catch (FileNotFoundException e) {e.printStackTrace();}Toast.makeText(context, "图片已保存至" + path, Toast.LENGTH_SHORT).show();// 最后通知图库更新context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + path)));}/*** 选择图片后压缩展示*/public static Bitmap onSelected(String local_path) {Bitmap bitmap = BitmapFactory.decodeFile(local_path);ByteArrayOutputStream out = new ByteArrayOutputStream();bitmap.compress(Bitmap.CompressFormat.JPEG, 85, out);int size = bitmap.getWidth() * bitmap.getHeight();float zoom = (float) Math.sqrt(size * 1024 / (float)out.toByteArray().length);Matrix matrix = new Matrix();matrix.setScale(zoom, zoom);Bitmap result = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);out.reset();result.compress(Bitmap.CompressFormat.JPEG, 85, out);while(out.toByteArray().length > size * 1024){System.out.println(out.toByteArray().length);matrix.setScale(0.9f, 0.9f);result = Bitmap.createBitmap(result, 0, 0, result.getWidth(), result.getHeight(), matrix, true);out.reset();result.compress(Bitmap.CompressFormat.JPEG, 85, out);}bitmap = result;return bitmap;}/*** 获取压缩后的图片** @param srcPath       要压缩的图片路径* @return              压缩后的bitmap*/public static Bitmap getImage(String srcPath) {BitmapFactory.Options newOpts = new BitmapFactory.Options();// 开始读入图片,此时把options.inJustDecodeBounds 设回true了newOpts.inJustDecodeBounds = true;Bitmap bitmap = BitmapFactory.decodeFile(srcPath,newOpts);// 此时返回bm为空newOpts.inJustDecodeBounds = false;int w = newOpts.outWidth;int h = newOpts.outHeight;// 现在主流手机比较多是800*480分辨率,所以高和宽我们设置为float hh = 800f;// 这里设置高度为800ffloat ww = 480f;// 这里设置宽度为480f// 缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可int be = 1;// be=1表示不缩放if (w > h && w > ww) {// 如果宽度大的话根据宽度固定大小缩放be = (int) (newOpts.outWidth / ww);} else if (w < h && h > hh) {// 如果高度高的话根据宽度固定大小缩放be = (int) (newOpts.outHeight / hh);}if (be <= 0)be = 1;newOpts.inSampleSize = be;// 设置缩放比例// 重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了bitmap = BitmapFactory.decodeFile(srcPath, newOpts);return compressImage(bitmap);// 压缩好比例大小后再进行质量压缩}public static Bitmap compressImage(Bitmap image) {ByteArrayOutputStream baos = new ByteArrayOutputStream();image.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中int options = 100;while (baos.toByteArray().length / 1024 > 100) {  // 循环判断如果压缩后图片是否大于100kb,大于继续压缩baos.reset();// 重置baos即清空baosimage.compress(Bitmap.CompressFormat.JPEG, options, baos);// 这里压缩options%,把压缩后的数据存放到baos中options -= 10;// 每次都减少10}ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);// 把ByteArrayInputStream数据生成图片return bitmap;}/*** 处理指定的图片*/public static Bitmap handlePicture(Bitmap bitmap){int width = bitmap.getWidth();int height = bitmap.getHeight();Bitmap copy = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);int[] before = new int[width * height];int[] after = new int[width * height];bitmap.getPixels(before, 0, width, 0, 0, width, height);int pixelsA, pixelsR, pixelsG, pixelsB;for(int i = 0;i < width * height;i++){int color = before[i];// ∂获取RGB分量pixelsA = Color.alpha(color);pixelsR = Color.red(color);pixelsG = Color.green(color);pixelsB = Color.blue(color);if(pixelsA >= 1) {// 转换pixelsR = (255 - pixelsR);pixelsG = (255 - pixelsG);pixelsB = (255 - pixelsB);// 均小于等于255大于等于0if (pixelsR > 255) {pixelsR = 255;} else if (pixelsR < 0) {pixelsR = 0;}if (pixelsG > 255) {pixelsG = 255;} else if (pixelsG < 0) {pixelsG = 0;}if (pixelsB > 255) {pixelsB = 255;} else if (pixelsB < 0) {pixelsB = 0;}}// 根据新的RGB生成新像素after[i] = Color.argb(pixelsA, pixelsR, pixelsG, pixelsB);}copy.setPixels(after, 0, width, 0, 0, width, height);return copy;}/*** 处理指定的图片为黑白照片*/public static Bitmap colored(Bitmap bitmap){int width = bitmap.getWidth();int height = bitmap.getHeight();Bitmap copy = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);int[] before = new int[width * height];int[] after = new int[width * height];bitmap.getPixels(before, 0, width, 0, 0, width, height);int pixelsA, pixelsR, pixelsG, pixelsB;for(int i = 0;i < width * height;i++){int color = before[i];// 获取RGB分量pixelsA = Color.alpha(color);pixelsR = Color.red(color);pixelsG = Color.green(color);pixelsB = Color.blue(color);if(pixelsA >= 1) {pixelsR = pixelsG = pixelsB = (pixelsR + pixelsG + pixelsB) / 3;}// 根据新的RGB生成新像素after[i] = Color.argb(pixelsA, pixelsR, pixelsG, pixelsB);}copy.setPixels(after, 0, width, 0, 0, width, height);return copy;}/*** 处理指定的图片为半透明照片*/public static Bitmap halfTrans(Bitmap bitmap){int width = bitmap.getWidth();int height = bitmap.getHeight();Bitmap copy = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);int[] before = new int[width * height];int[] after = new int[width * height];bitmap.getPixels(before, 0, width, 0, 0, width, height);int pixelsA, pixelsR, pixelsG, pixelsB;for(int i = 0;i < width * height;i++){int color = before[i];// 获取RGB分量pixelsA = Color.alpha(color);pixelsR = Color.red(color);pixelsG = Color.green(color);pixelsB = Color.blue(color);// 根据新的RGB生成新像素after[i] = Color.argb(pixelsA / 2, pixelsR, pixelsG, pixelsB);}copy.setPixels(after, 0, width, 0, 0, width, height);return copy;}}

第二个网络请求工具类  请求腾讯的接口

package cn.vonce.doer.utils;import android.util.Log;import org.xutils.common.Callback;
import org.xutils.http.RequestParams;
import org.xutils.x;import java.io.File;import cn.vonce.doer.sign.Constant;
import cn.vonce.doer.sign.YoutuSign;/*** 网络请求工具类*/
public class TecentHttpUtil {public static void uploadIdCard(String bitmap, String card_type, final SimpleCallBack callback) {StringBuffer mySign = new StringBuffer("");YoutuSign.appSign(Constant.AppID, Constant.SecretID, Constant.SecretKey,System.currentTimeMillis() / 1000 + Constant.EXPIRED_SECONDS,Constant.QQNumber, mySign);RequestParams params = new RequestParams("http://api.youtu.qq.com/youtu/ocrapi/idcardocr");params.setAsJsonContent(true);params.addHeader("accept", "*/*");params.addHeader("Host", "api.youtu.qq.com");params.addHeader("user-agent", "youtu-java-sdk");params.addHeader("Authorization", mySign.toString());params.addHeader("Content-Type", "text/json");params.addParameter("card_type", Integer.valueOf(card_type));params.addBodyParameter("image", bitmap);params.addBodyParameter("app_id", Constant.AppID);x.http().post(params, new Callback.CommonCallback<String>() {@Overridepublic void onSuccess(String result) {Log.d("onSuccess",result);callback.Succ(result);}@Overridepublic void onError(Throwable ex, boolean isOnCallback) {Log.d("onError",ex.getMessage());}@Overridepublic void onCancelled(CancelledException cex) {Log.d("onCancelled", cex.getMessage());}@Overridepublic void onFinished() {}});}public interface SimpleCallBack {void Succ(String result);void error();}}

在网络请求工具类里面会用到你申请的id了   需要几个类

package com.example.aa.demo.sign;import java.util.Random;public class YoutuSign {/***app_sign    时效性签名*@param  appId       http://open.youtu.qq.com/上申请的业务ID*@param  secret_id   http://open.youtu.qq.com/上申请的密钥id*@param  secret_key  http://open.youtu.qq.com/上申请的密钥key*@param  expired     签名过期时间*@param  userid      业务账号系统,没有可以不填*@param  mySign      生成的签名*@return 0表示成功*/public static int appSign(String appId, String secret_id, String secret_key,long expired, String userid, StringBuffer mySign) {return appSignBase(appId, secret_id, secret_key, expired, userid, null, mySign);}private static int appSignBase(String appId, String secret_id,String secret_key, long expired, String userid, String url,StringBuffer mySign) {if (empty(secret_id) || empty(secret_key)){return -1;}String puserid = "";if (!empty(userid)){if (userid.length() > 64){return -2;}puserid = userid;}long now = System.currentTimeMillis() / 1000;int rdm = Math.abs(new Random().nextInt());String plain_text = "a=" + appId + "&k=" + secret_id + "&e=" + expired + "&t=" + now + "&r=" + rdm + "&u=" + puserid ;//+ "&f=" + fileid.toString();byte[] bin = hashHmac(plain_text, secret_key);byte[] all = new byte[bin.length + plain_text.getBytes().length];System.arraycopy(bin, 0, all, 0, bin.length);System.arraycopy(plain_text.getBytes(), 0, all, bin.length, plain_text.getBytes().length);mySign.append(Base64Util.encode(all));return 0;}private static byte[] hashHmac(String plain_text, String accessKey) {try {return HMACSHA1.getSignature(plain_text, accessKey);} catch (Exception e) {e.printStackTrace();return null;}}public static boolean empty(String s){return s == null || s.trim().equals("") || s.trim().equals("null");}}
package com.example.aa.demo.sign;public class Base64Util {private static final char last2byte = (char) Integer.parseInt("00000011", 2);private static final char last4byte = (char) Integer.parseInt("00001111", 2);private static final char last6byte = (char) Integer.parseInt("00111111", 2);private static final char lead6byte = (char) Integer.parseInt("11111100", 2);private static final char lead4byte = (char) Integer.parseInt("11110000", 2);private static final char lead2byte = (char) Integer.parseInt("11000000", 2);private static final char[] encodeTable = new char[] { 'A', 'B', 'C', 'D','E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q','R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd','e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q','r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3','4', '5', '6', '7', '8', '9', '+', '/' };/*** Base64 encoding.* * @param from*            The src data.* @return cryto_str*/public static String encode(byte[] from) {StringBuilder to = new StringBuilder((int) (from.length * 1.34) + 3);int num = 0;char currentByte = 0;for (int i = 0; i < from.length; i++) {num = num % 8;while (num < 8) {switch (num) {case 0:currentByte = (char) (from[i] & lead6byte);currentByte = (char) (currentByte >>> 2);break;case 2:currentByte = (char) (from[i] & last6byte);break;case 4:currentByte = (char) (from[i] & last4byte);currentByte = (char) (currentByte << 2);if ((i + 1) < from.length) {currentByte |= (from[i + 1] & lead2byte) >>> 6;}break;case 6:currentByte = (char) (from[i] & last2byte);currentByte = (char) (currentByte << 4);if ((i + 1) < from.length) {currentByte |= (from[i + 1] & lead4byte) >>> 4;}break;}to.append(encodeTable[currentByte]);num += 6;}}if (to.length() % 4 != 0) {for (int i = 4 - to.length() % 4; i > 0; i--) {to.append("=");}}return to.toString();}
}
package com.example.aa.demo.sign;import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;public class HMACSHA1 {private static final String HMAC_SHA1 = "HmacSHA1";public static byte[] getSignature(String data, String key) throws Exception {Mac mac = Mac.getInstance(HMAC_SHA1);SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(),mac.getAlgorithm());mac.init(signingKey);return mac.doFinal(data.getBytes());}
}
package com.example.aa.demo.sign;/*** 优图账号*这里填大家自己申请的*/
public class Constant {public static String QQNumber = "";// 腾讯优图开发者账号(QQ号)public static String AppID = "";public static String SecretID = "";public static String SecretKey = "";public static int EXPIRED_SECONDS = ;// 过期时间戳
}

然后就是主类了

package com.example.aa.demo;import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;import com.example.aa.demo.entity.IdentifyResult;
import com.example.aa.demo.entity.cardReverseRusult;
import com.example.aa.demo.utils.BitMapUtils;
import com.example.aa.demo.utils.TecentHttpUtil;
import com.google.gson.Gson;
import com.luck.picture.lib.PictureSelector;
import com.luck.picture.lib.config.PictureConfig;
import com.luck.picture.lib.config.PictureMimeType;
import com.luck.picture.lib.entity.LocalMedia;import java.util.ArrayList;
import java.util.List;public class AutonymCertificationActivity extends AppCompatActivity implements View.OnClickListener {/*** 身份证正面*/private ImageView activity_autonym_certification_iv_positive;/*** 身份证反面*/private ImageView activity_autonym_certification_iv_reverse;/*** 选择身份证正面*/private List<LocalMedia> cardPositive = new ArrayList<>();/*** 选择身份证反面*/private List<LocalMedia> cardReverse = new ArrayList<>();/*** 选择模式:全部.PictureMimeType.ofAll()、图片.ofImage()、视频.ofVideo()、音频.ofAudio()*/private int chooseMode = PictureMimeType.ofImage();/*** 主题id:R.style.picture_default_style、R.style.picture_white_style、R.style.picture_QQ_style、R.style.picture_Sina_style*/private int themeId = R.style.picture_default_style;/*** 最多可选择1张图片*/private int maxSelectNum = 1;/*** 正反图片路径*/private String cardPositivePath = null, cardReversePath = null;/*** 保存图片,正反*/private Bitmap cardPositiveBitMap, cardReverseBitMap;/*** 自动识别姓名  有效日期   身份证号码*/private EditText activity_autonym_certification_et_name;private EditText activity_autonym_certification_et_effective_date;private EditText activity_autonym_certification_et_id_card;/*** 存放正面识别数据的类*/IdentifyResult result;/*** 存放反面识别数据的类*/cardReverseRusult cardReverseRusult;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_autonym_certification);//初始化找idinitViews();}private void initViews() {activity_autonym_certification_iv_positive=findViewById(R.id.activity_autonym_certification_iv_positive);activity_autonym_certification_iv_reverse=findViewById(R.id.activity_autonym_certification_iv_reverse);activity_autonym_certification_et_name=findViewById(R.id.activity_autonym_certification_et_name);activity_autonym_certification_et_effective_date=findViewById(R.id.activity_autonym_certification_et_effective_date);activity_autonym_certification_et_id_card=findViewById(R.id.activity_autonym_certification_et_id_card);activity_autonym_certification_iv_positive.setOnClickListener(this);activity_autonym_certification_iv_reverse.setOnClickListener(this);//简单的申请两个权限if (ContextCompat.checkSelfPermission(AutonymCertificationActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1);}}@Overridepublic void onClick(View v) {switch (v.getId()) {//身份证正面点击事件case R.id.activity_autonym_certification_iv_positive://0表示正面OpenPhotoAlbum(cardPositive, 0);break;//身份证反面的点击事件  1表示反面case R.id.activity_autonym_certification_iv_reverse:OpenPhotoAlbum(cardReverse, 1);break;}}/*** @param list 相片返回的地方* @param i    判断返回的是正反    0是正面  1是反面*/private void OpenPhotoAlbum(List list, int i) {// 进入相册 以下是例子:不需要的api可以不写PictureSelector.create(this).openGallery(chooseMode)// 全部.PictureMimeType.ofAll()、图片.ofImage()、视频.ofVideo()、音频.ofAudio().theme(themeId)// 主题样式设置 具体参考 values/styles   用法:R.style.picture.white.style.maxSelectNum(maxSelectNum)// 最大图片选择数量.minSelectNum(1)// 最小选择数量.imageSpanCount(4)// 每行显示个数.selectionMode(PictureConfig.MULTIPLE)// PictureConfig.MULTIPLE多选 or 单选PictureConfig.SINGLE.previewImage(true)// 是否可预览图片//.previewVideo(true)// 是否可预览视频//.enablePreviewAudio(ture) // 是否可播放音频//.compressGrade(Luban.THIRD_GEAR)// luban压缩档次,默认3档 Luban.FIRST_GEAR、Luban.CUSTOM_GEAR.isCamera(true)// 是否显示拍照按钮.isZoomAnim(true)// 图片列表点击 缩放效果 默认true//.setOutputCameraPath("/CustomPath")// 自定义拍照保存路径//.enableCrop(false)// 是否裁剪.compress(true)// 是否压缩// .compressMode(PictureConfig.SYSTEM_COMPRESS_MODE)//系统自带 or 鲁班压缩 PictureConfig.SYSTEM_COMPRESS_MODE or LUBAN_COMPRESS_MODE//.sizeMultiplier(0.5f)// glide 加载图片大小 0~1之间 如设置 .glideOverride()无效.glideOverride(160, 160)// glide 加载宽高,越小图片列表越流畅,但会影响列表图片浏览的清晰度//.withAspectRatio(0, 0)// 裁剪比例 如16:9 3:2 3:4 1:1 可自定义//.hideBottomControls(false)// 是否显示uCrop工具栏,默认不显示//.isGif(false)// 是否显示gif图片//.freeStyleCropEnabled(false)// 裁剪框是否可拖拽//.circleDimmedLayer(false)// 是否圆形裁剪//.showCropFrame(false)// 是否显示裁剪矩形边框 圆形裁剪时建议设为false//.showCropGrid(false)// 是否显示裁剪矩形网格 圆形裁剪时建议设为false.openClickSound(false)// 是否开启点击声音.selectionMedia(list)// 是否传入已选图片
//                        .videoMaxSecond(15)
//                        .videoMinSecond(10)//.previewEggs(false)// 预览图片时 是否增强左右滑动图片体验(图片滑动一半即可看到上一张是否选中)//.cropCompressQuality(90)// 裁剪压缩质量 默认100//.compressMaxKB()//压缩最大值kb compressGrade()为Luban.CUSTOM_GEAR有效//.compressWH() // 压缩宽高比 compressGrade()为Luban.CUSTOM_GEAR有效//.cropWH()// 裁剪宽高比,设置如果大于图片本身宽高则无效//.rotateEnabled() // 裁剪是否可旋转图片//.scaleEnabled()// 裁剪是否可放大缩小图片//.videoQuality()// 视频录制质量 0 or 1//.videoSecond()//显示多少秒以内的视频or音频也可适用//.recordVideoSecond()//录制视频秒数 默认60s.forResult(i);//结果回调onActivityResult code(这里自己设置了0.1 目的区分是正反)}//选择完照片的回调@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);//选择图片回调if (resultCode == RESULT_OK) {switch (requestCode) {case 0:/*** 正面识别*/// 图片选择结果回调cardPositive = PictureSelector.obtainMultipleResult(data);// 例如 LocalMedia 里面返回三种path// 1.media.getPath(); 为原图path// 2.media.getCutPath();为裁剪后path,需判断media.isCut();是否为true// 3.media.getCompressPath();为压缩后path,需判断media.isCompressed();是否为true// 如果裁剪并压缩了,以取压缩路径为准,因为是先裁剪后压缩的//首先获取图片地址if (cardPositive.size() > 0) {//首先确保大于0LocalMedia localMedia = cardPositive.get(0);cardPositivePath = localMedia.getPath();//正常的地址,看具体的业务,如果需要压缩,则获取压缩地址//拿到了地址,那么就加载图片cardPositiveBitMap = BitMapUtils.getImage(cardPositivePath);
//                        //设置图片activity_autonym_certification_iv_positive.setImageBitmap(cardPositiveBitMap);//设置完成自动识别TecentHttpUtil.uploadIdCard(BitMapUtils.bitmapToBase64(cardPositiveBitMap), "0", new TecentHttpUtil.SimpleCallBack() {@Overridepublic void Succ(String res) {result = new Gson().fromJson(res, IdentifyResult.class);if (result != null) {if (result.getErrorcode() == 0) {// 识别成功设置姓名activity_autonym_certification_et_name.setText(result.getName());//设置身份证号码activity_autonym_certification_et_id_card.setText(result.getId());} else {Toast.makeText(AutonymCertificationActivity.this, "识别错误", Toast.LENGTH_SHORT).show();/*switch (result.getErrorcode()){case -7001:Toast.makeText(MainActivity.this, "未检测到身份证,请对准边框(请避免拍摄时倾角和旋转角过大、摄像头)", Toast.LENGTH_SHORT).show();break;case -7002:Toast.makeText(MainActivity.this, "请使用第二代身份证件进行扫描", Toast.LENGTH_SHORT).show();break;case -7003:Toast.makeText(MainActivity.this, "不是身份证正面照片(请使用带证件照的一面进行扫描)", Toast.LENGTH_SHORT).show();break;case -7004:Toast.makeText(MainActivity.this, "不是身份证反面照片(请使用身份证反面进行扫描)", Toast.LENGTH_SHORT).show();break;case -7005:Toast.makeText(MainActivity.this, "确保扫描证件图像清晰", Toast.LENGTH_SHORT).show();break;case -7006:Toast.makeText(MainActivity.this, "请避开灯光直射在证件表面", Toast.LENGTH_SHORT).show();break;default:Toast.makeText(MainActivity.this, "识别失败,请稍后重试", Toast.LENGTH_SHORT).show();break;}*/}}}@Overridepublic void error() {Log.i("识别错误", "error: ");}});}break;case 1:/*** 反面识别*/cardReverse = PictureSelector.obtainMultipleResult(data);if (cardReverse.size() > 0) {//首先确保大于0LocalMedia localMedia = cardReverse.get(0);cardReversePath = localMedia.getPath();//正常的地址,看具体的业务,如果需要压缩,则获取压缩地址//拿到了地址,那么就加载图片cardReverseBitMap = BitMapUtils.getImage(cardReversePath);
//                        //设置图片activity_autonym_certification_iv_reverse.setImageBitmap(cardReverseBitMap);TecentHttpUtil.uploadIdCard(BitMapUtils.bitmapToBase64(cardReverseBitMap), "1", new TecentHttpUtil.SimpleCallBack() {@Overridepublic void Succ(String res) {Log.e("===========success", res);cardReverseRusult = new Gson().fromJson(res, cardReverseRusult.class);if (cardReverseRusult != null) {if (cardReverseRusult.getErrorcode() == 0) {//反面识别成功设置有效日期activity_autonym_certification_et_effective_date.setText(cardReverseRusult.getValid_date());} else {Toast.makeText(AutonymCertificationActivity.this, "识别错误", Toast.LENGTH_SHORT).show();}}}@Overridepublic void error() {Log.i("识别错误", "error: ");}});}break;}}}@Overridepublic void onPointerCaptureChanged(boolean hasCapture) {}
}

到这来项目基本就跑起来了,代码不好,仅供参考,声明,里面有一些代码是参考了网络上的。

安卓识别身份证,自动提取身份证信息功能实现(附源码)相关推荐

  1. Java 实现人脸识别登录、注册等功能【附源码】

    点击下方"Java编程鸭"关注并标星 更多精彩 第一时间直达 来源: blog.csdn.net/Gaowumao?type=blog 前言 想自己搞一个人脸识别玩玩,随着开始查找 ...

  2. JAVA计算机毕业设计美容院信息管理系统(附源码、数据库)

    JAVA计算机毕业设计美容院信息管理系统(附源码.数据库) 目运行 环境项配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX(Webstorm也行)+ Eclispe ...

  3. Java毕设项目家政服务公司管理信息计算机(附源码+系统+数据库+LW)

    Java毕设项目家政服务公司管理信息计算机(附源码+系统+数据库+LW) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX(Webstorm也行)+ ...

  4. java人脸识别教程_用 Java 实现人脸识别功能(附源码)

    > 整理了一些Java方面的架构.面试资料(微服务.集群.分布式.中间件等),有需要的小伙伴可以关注公众号[程序员内点事],无套路自行领取 更多优选 引言 远程在家办公的第N天,快要闲出屁了,今 ...

  5. 集成Android 科大讯飞免费在线语音合成播报功能(附源码)

    概述 开篇先介绍一下'科大讯飞',毕竟是我家乡合肥的科技公司,我感到骄傲,更重要的是它在语音识别行业也是佼佼者,在如今人工智能横飞的时代,依然能够保持着较高水准的技术优势.在此,希望科大在AI之战中能 ...

  6. 用 Java 实现人脸识别功能(附源码)

    远程在家办公的第N天,快要闲出屁了,今天突然有个小学弟加我VX说要咨询我点技术问题(终于可以装X了). 看了他的需求描述,大概是要做一个Java web版本的人脸识别功能,然后存储人物的特征,再扫脸比 ...

  7. 人脸特性提取java_基于 Java 实现的人脸识别功能(附源码)

    引言 远程在家办公的第N天,快要闲出屁了,今天突然有个小学弟加我VX说要咨询我点技术问题(终于可以装X了).看了他的需求描述,大概是要做一个Java web版本的人脸识别功能,然后存储人物的特征,再扫 ...

  8. 安卓mysql导出excel_Android开发实现的导出数据库到Excel表格功能【附源码下载】...

    本文实例讲述了Android开发实现的导出数据库到Excel表格功能.分享给大家供大家参考,具体如下: 之前一直在电脑上用Excel表格记录家庭帐单,不久前重装系统不小心干掉了,伤心了好久,那可是我记 ...

  9. 计算机毕业设计SSM本科培训班学员信息管理系统【附源码数据库】

    项目运行 环境配置: Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclis ...

  10. Springboot+高考志愿填报信息管理系统 毕业设计-附源码251922

    Springboot高考志愿填报信息管理系统 摘 要 高中教育的普及使得每年高考人数攀升,与此同时,信息不对称会使部分考生处于劣势,造成获录学校或专业性价比不高.报录比偏低.复读率增高.考研热等问题. ...

最新文章

  1. 亚信安全服务器深度安全防护系统中标“世界最长”的城轨网络
  2. RDIFramework.NET ━ 9.8 用户权限管理 ━ Web部分
  3. PrintWriter用法简析
  4. NeHe教程Qt实现——lesson12
  5. LeetCode:Two Sum
  6. Maximum.TV 发布西班牙语Silverlight TV网站
  7. 8口PoE网口供电交换机适用环境介绍
  8. a4b5笔记本大小对比_天津订做笔记本*价格多少【广通印务】
  9. 说说设计模式~桥梁模式(Bridge)
  10. c# oracle异常,C# 连接Oracle数据库异常总结
  11. 一个关于偷书贼的故事
  12. Java Reference Objects or How I Learned to Stop Worrying and Love OutOfMemoryError
  13. less日常容易忘记的知识记录
  14. AT2401C功放PA完美替代RFX2401C
  15. pyspark:RDD和DataFrame
  16. 如何实现QQ的登入界面
  17. 什么是java线程_Java多线程是什么意思?
  18. java-常量和变量
  19. c语言中void *的使用
  20. 五大列级庄_1855列级庄分级

热门文章

  1. QGroundControl 提示 Power redundancy not met: 0 instead of 1
  2. 【NOIP普及组】1919:【02NOIP普及组】选数
  3. [设备驱动] 最简单的内核设备驱动--字符驱动
  4. 贝叶斯统计——基础篇
  5. openresty ngx_lua重定向
  6. oracle集群crs,oracle rac集群 crs常用命令(转)
  7. 《Real-Time Rendering 4th Edition》全文翻译 - 第6章 纹理化(上)6.1 ~ 6.3
  8. 常用动画特效 - CSS实现
  9. unity 动画控制器
  10. 轻松打造xfce4轻快桌面