之所以是(1),是因为还有第二个方案,这个方案在适配上被淘汰了,先记录代码,后面再详细来分拆说明

  • 百度的Maven库,修改为Gradle依赖的方式
    implementation 'com.baidu.aip:java-sdk:4.4.1'

这是一个java库,用于服务器端的,所以当中会配置到一些log4j之类的东西,可以自己配制成Android路径,也可以置之不理

public class EntranceActivity extends BaseActivity {

@BindView(R.id.surfaceView_entrance_act)
SurfaceView mSurfaceView;
@BindView(R.id.iv_head_entrance_act)
ImageView iv_head_entrance_act;

//设置APPID/AK/SK
public static final String APP_ID = "XXXXXXXXXXX";
public static final String API_KEY = "XXXXXXXXXXXXXXXXXXXX";
public static final String SECRET_KEY = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
private Camera camera;
private Camera.Size cameraPreviewSize;
private Camera.PreviewCallback previewCallback;
private Camera.AutoFocusCallback autoFocusCallback;
private SurfaceHolder surfaceHolder;
private ExecutorService singleThreadExecutor;
private AipFace client;
private RectF mRect;
boolean one = true;
int faceSize;

@Override
protected int getContentViewId() {
    return R.layout.activity_entrance;
}

@Override
protected void initLayout(@Nullable Bundle savedInstanceState) {

    camera = Camera.open();

    Logger.e("MaxNumDetectedFaces: " + camera.);

    singleThreadExecutor = Executors.newSingleThreadExecutor();

    surfaceHolder = mSurfaceView.getHolder();

    surfaceHolder.addCallback(new SurfaceHolder.Callback() {
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            setFaceDetectionListenerV2();
            try {
                camera.setPreviewDisplay(surfaceHolder);
                camera.startPreview();
                camera.startFaceDetection();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            if (camera != null) {
                camera.release();
                camera = null;
            }
        }
    });

    autoFocusCallback = new Camera.AutoFocusCallback() {
        @Override
        public void onAutoFocus(boolean success, Camera camera) {
            Logger.e("success: " + success);
        }
    };

    previewCallback = new Camera.PreviewCallback() {
        @Override
        public void onPreviewFrame(byte[] data, Camera camera) {
            if (mRect == null) {
                return;
            }
            YuvImage image = new YuvImage(data, ImageFormat.NV21, cameraPreviewSize.width, cameraPreviewSize.height, null);
            ByteArrayOutputStream baos = new ByteArrayOutputStream(8192);
            // 转换成JPEG
            image.compressToJpeg(new Rect(0, 0, cameraPreviewSize.width, cameraPreviewSize.height), 30, baos);

            Bitmap bitmapOriginal = BitmapFactory.decodeByteArray(baos.toByteArray(), 0, baos.size());
            Bitmap bitmap = Bitmap.createBitmap(bitmapOriginal, (int) mRect.left, (int) mRect.top, (int) mRect.width(), (int) mRect.height());
            iv_head_entrance_act.setImageBitmap(bitmap);
            search(bitmapToBase64(bitmap));
            mRect = null;
        }
    };

    // 初始化一个AipFace
    client = new AipFace(APP_ID, API_KEY, SECRET_KEY);

    // 可选:设置网络连接参数
    client.setConnectionTimeoutInMillis(2000);
    client.setSocketTimeoutInMillis(60000);

    // 可选:设置代理服务器地址, http和socket二选一,或者均不设置
    //client.setHttpProxy("proxy_host", proxy_port);  // 设置http代理
    //client.setSocketProxy("proxy_host", proxy_port);  // 设置socket代理

    // 可选:设置log4j日志输出格式,若不设置,则使用默认配置
    // 也可以直接通过jvm启动参数设置此环境变量
    //System.setProperty("aip.log4j.conf", "path/to/your/log4j.properties");

    // 调用接口
    //String path = "test.jpg";
    //JSONObject res = client.detect(path, new HashMap<String, String>());
    //System.out.println(res.toString(2));
}

private void setFaceDetectionListenerV2() {
    cameraPreviewSize = camera.getParameters().getPreviewSize();

    // 人脸识别
    camera.setFaceDetectionListener(new Camera.FaceDetectionListener() {
        @Override
        public void onFaceDetection(Camera.Face[] faces, Camera camera) {
            int length = faces.length;
            Logger.e("faceNum: " + length);
            // 思路:faces的size不变的情况下一定是同一个人,切换人物一定会出现数量的变化,人物的变化一定快不过毫秒级的检测,如果快过了。那么丢弃一两个也无所谓
            if (length != faceSize) {
                faceSize = length;
                if (length != 0) {
                    camera.autoFocus(autoFocusCallback);
                    for (int i = 0; i < length; i++) {
                        Camera.Face face = faces[i];
                        Logger.e("score: " + face.score + "   id: " + face.id);
                        // score 一直是0
                        /*if (face.score < 50) {
                            faceSize -= 1;
                            return;
                        }*/

                        singleThreadExecutor.submit(new Runnable() {
                            @Override
                            public void run() {
                                checkFace(face);
                                camera.setOneShotPreviewCallback(previewCallback);
                            }
                        });
                    }
                }
            }
        }
    });
}

private void checkFace(Camera.Face face) {
    Rect rect = face.rect;
    RectF rectF = new RectF();
    rectF.set(rect);
    Matrix matrix = new Matrix();
    // 转换坐标系
    prepareMatrix(matrix, false, 0, cameraPreviewSize.width, cameraPreviewSize.height);
    matrix.mapRect(rectF);
    mRect = rectF;
}

private void search(String imageBase64) {
    HashMap<String, String> options = new HashMap<>();
    options.put("quality_control", "NONE");
    options.put("liveness_control", "NONE");
    options.put("max_user_num", "1");

    //String image = "取决于image_type参数,传入BASE64字符串或URL字符串或FACE_TOKEN字符串";
    String imageType = "BASE64";
    String groupIdList = "TEACHER,STUDENT,PARENT,FAMILY,TEMPORARY";

    // 人脸搜索,网络操作不可以在主线程
    new Thread(new Runnable() {
        @Override
        public void run() {
            JSONObject res = client.search(imageBase64, imageType, groupIdList, options);
            Logger.e("res: " + res);
            // 得分低于70的丢掉,高于的记录
            // TODO: 2018/6/29 记录
        }
    }).start();
}

public static String bitmapToBase64(Bitmap bitmap) {

    // 要返回的字符串
    String reslut = null;

    ByteArrayOutputStream baos = null;

    try {

        if (bitmap != null) {

            baos = new ByteArrayOutputStream();
            /**
             * 压缩只对保存有效果bitmap还是原来的大小
             */
            bitmap.compress(Bitmap.CompressFormat.JPEG, 30, baos);

            baos.flush();
            baos.close();
            // 转换为字节数组
            byte[] byteArray = baos.toByteArray();

            // 转换为字符串
            reslut = Base64.encodeToString(byteArray, Base64.DEFAULT);
            //Log.e("base64", reslut);
        } else {
            return null;
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {

        try {
            if (baos != null) {
                baos.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
    return reslut;

}

public static Bitmap base64ToBitmap(String base64String) {

    byte[] decode = Base64.decode(base64String, Base64.DEFAULT);

    Bitmap bitmap = BitmapFactory.decodeByteArray(decode, 0, decode.length);

    return bitmap;
}

public static void prepareMatrix(Matrix matrix, boolean mirror, int displayOrientation, int viewWidth, int viewHeight) {
    // Need mirror for front camera.
    matrix.setScale(mirror ? -1 : 1, 1);
    // This is the value for android.hardware.Camera.setDisplayOrientation.
    matrix.postRotate(displayOrientation);
    // Camera driver coordinates range from (-1000, -1000) to (1000, 1000).
    // UI coordinates range from (0, 0) to (width, height).
    matrix.postScale(viewWidth / 2000f, viewHeight / 2000f);
    matrix.postTranslate(viewWidth / 2f, viewHeight / 2f);
}

}