基於SnapdragonBoard410c開發板自定義相機

這段時間由於項目的原因,去了解了一點Android Camera2的APi和Android Framework的架構.接下來我先和大家講解下API的流程:

調用流程圖:
這裏寫圖片描述

實現的代碼如下:

` public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(Build.VERSION.SDK_INT>22) {
this.requestPermissions(new String[]{Manifest.permission.CAMERA}, 0);
}
Log.i(“Build_version”,Build.VERSION.SDK_INT+”“);
initview();
mThreadHandler = new HandlerThread(“CAMERA2”);
mThreadHandler.start();
mHandler = new Handler(mThreadHandler.getLooper());
iniicallback();
autoFocus();
}

private void autoFocus() {

}

private void iniicallback() {
    stateCallback = new CameraDevice.StateCallback() {
        @Override
        public void onOpened(@NonNull CameraDevice cameraDevice) {
            try {
                startprew(cameraDevice);
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onDisconnected(@NonNull CameraDevice cameraDevice) {

        }

        @Override
        public void onError(@NonNull CameraDevice cameraDevice, int i) {

        }
    };

    session = new CameraCaptureSession.CaptureCallback() {
        @Override
        public void onCaptureStarted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, long timestamp, long frameNumber) {
            super.onCaptureStarted(session, request, timestamp, frameNumber);
        }

        @Override
        public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
            super.onCaptureCompleted(session, request, result);
            previewbuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO);// set camera's focus model CONTINUOUS Focus after captured;
        }
    };

    capturestateCallback = new CameraCaptureSession.StateCallback() {
        @Override
        public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {

                    try {//點擊focus
                        Session = cameraCaptureSession;
                        cameraCaptureSession.setRepeatingRequest(previewbuilder.build(), session, mHandler);
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }
        }


        @Override
        public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {

        }
    };

}

private void startprew(CameraDevice device) throws CameraAccessException {
    SurfaceTexture surface = textureView.getSurfaceTexture();
    surface.setDefaultBufferSize(textureView.getWidth(), textureView.getHeight());
    Surface surfaceview = new Surface(surface);
    previewbuilder = device.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
    previewbuilder.addTarget(surfaceview);
    device.createCaptureSession(Arrays.asList(surfaceview), capturestateCallback, mHandler);
}

public void initview() {
    textureView = findViewById(R.id.preview);
    button = findViewById(R.id.capture);
    textureView.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            Boolean x1 = touchToFocus(view, motionEvent);
            if (x1 != null) return x1;

            return true;

        }
         /*
          * touch to focus  
          */
        @Nullable
        private Boolean touchToFocus(View view, MotionEvent motionEvent) {
            final int actionMasked = motionEvent.getActionMasked();
            if (actionMasked != MotionEvent.ACTION_DOWN) {
                return false;
            }
            if (mManualFocusEngaged) {
                return true;
            }
            final Rect sensorArraySize = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
            //TODO: here I just flip x,y, but this needs to correspond with the sensor orientation (via SENSOR_ORIENTATION)
            final int y = (int)((motionEvent.getX() / (float)view.getWidth())  * (float)sensorArraySize.height());
            final int x = (int)((motionEvent.getY() / (float)view.getHeight()) * (float)sensorArraySize.width());
            final int halfTouchWidth  = 150; //(int)motionEvent.getTouchMajor(); //TODO: this doesn't represent actual touch size in pixel. Values range in [3, 10]...
            final int halfTouchHeight = 150; //(int)motionEvent.getTouchMinor();
            MeteringRectangle focusAreaTouch = new MeteringRectangle(Math.max(x - halfTouchWidth,  0),
                    Math.max(y - halfTouchHeight, 0),
                    halfTouchWidth  * 2,
                    halfTouchHeight * 2,
                    MeteringRectangle.METERING_WEIGHT_MAX - 1);

            CameraCaptureSession.CaptureCallback captureCallbackHandler = new CameraCaptureSession.CaptureCallback() {
                @Override
                public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
                    super.onCaptureCompleted(session, request, result);
                    mManualFocusEngaged = false;

                    if (request.getTag() == "FOCUS_TAG") {
                        //the focus trigger is complete -
                        //resume repeating (preview surface will get frames), clear AF trigger
                        previewbuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, null);
                        if (Session!=null) {
                            try {
                                Session.setRepeatingRequest(previewbuilder.build(), null, null);
                            } catch (CameraAccessException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
                @Override
                public void onCaptureFailed(CameraCaptureSession session, CaptureRequest request, CaptureFailure failure) {
                    super.onCaptureFailed(session, request, failure);
                   // Log.e(TAG, "Manual AF failure: " + failure);
                    mManualFocusEngaged = false;
                }
            };
            //first stop the existing repeating request
            if (Session!=null) {
                try {
                    Session.stopRepeating();
                } catch (CameraAccessException e) {
                    e.printStackTrace();
                }
            }
            //cancel any existing AF trigger (repeated touches, etc.)
            previewbuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
            previewbuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_OFF);
              if (Session!=null) {
            try {
                Session.capture(previewbuilder.build(), captureCallbackHandler, mHandler);
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
              }

            //Now add a new AF trigger with focus region
            if (isMeteringAreaAFSupported()) {
                previewbuilder.set(CaptureRequest.CONTROL_AF_REGIONS, new MeteringRectangle[]{focusAreaTouch});
            }
            previewbuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
            previewbuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO);
            previewbuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
            previewbuilder.setTag("FOCUS_TAG"); //we'll capture this later for resuming the preview

            //then we ask for a single request (not repeating!)
            try {
                Session.capture(previewbuilder.build(), captureCallbackHandler, mHandler);
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
            mManualFocusEngaged = true;
            return null;
        }
    });

    textureView.setSurfaceTextureListener(this);

    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            //oneshot to preview

            final Rect sensorArraySize = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
            //TODO: here I just flip x,y, but this needs to correspond with the sensor orientation (via SENSOR_ORIENTATION)
            final int y = (int)(0.5  * (float)sensorArraySize.height());
            final int x = (int)(0.5 * (float)sensorArraySize.width());
            final int halfTouchWidth  = 150; //(int)motionEvent.getTouchMajor(); //TODO: this doesn't represent actual touch size in pixel. Values range in [3, 10]...
            final int halfTouchHeight = 150; //(int)motionEvent.getTouchMinor();
            MeteringRectangle focusAreaTouch = new MeteringRectangle(Math.max(x - halfTouchWidth,  0),
                    Math.max(y - halfTouchHeight, 0),
                    halfTouchWidth  * 2,
                    halfTouchHeight * 2,
                    MeteringRectangle.METERING_WEIGHT_MAX - 1);

            CameraCaptureSession.CaptureCallback captureCallbackHandler = new CameraCaptureSession.CaptureCallback() {
                @Override
                public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
                    super.onCaptureCompleted(session, request, result);
                    mManualFocusEngaged = false;

                    if (request.getTag() == "FOCUS_TAG") {
                        //the focus trigger is complete -
                        //resume repeating (preview surface will get frames), clear AF trigger
                        previewbuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, null);
                        if (Session!=null) {
                            try {
                                Session.setRepeatingRequest(previewbuilder.build(), null, null);
                            } catch (CameraAccessException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
                @Override
                public void onCaptureFailed(CameraCaptureSession session, CaptureRequest request, CaptureFailure failure) {
                    super.onCaptureFailed(session, request, failure);
                   // Log.e(TAG, "Manual AF failure: " + failure);
                    mManualFocusEngaged = false;
                }
            };
            //first stop the existing repeating request
            if (Session!=null) {
                try {
                    Session.stopRepeating();
                } catch (CameraAccessException e) {
                    e.printStackTrace();
                }
            }
            //cancel any existing AF trigger (repeated touches, etc.)
            previewbuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
            previewbuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_OFF);
              if (Session!=null) {
            try {
                Session.capture(previewbuilder.build(), captureCallbackHandler, mHandler);
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
              }

            //Now add a new AF trigger with focus region
            if (isMeteringAreaAFSupported()) {
                previewbuilder.set(CaptureRequest.CONTROL_AF_REGIONS, new MeteringRectangle[]{focusAreaTouch});
            }
            previewbuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
            previewbuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO);
            previewbuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
            previewbuilder.setTag("FOCUS_TAG"); //we'll capture this later for resuming the preview

            //then we ask for a single request (not repeating!)
            try {
                Session.capture(previewbuilder.build(), captureCallbackHandler, mHandler);
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
            mManualFocusEngaged = true;


        }
    });


}
private boolean isMeteringAreaAFSupported() {
    if (characteristics!=null){
        return characteristics.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AF) >= 1;
    }
   return  false;
}

@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) {
    String[] cameraId = null;

    CameraManager cameraManager = (CameraManager) getSystemService(CAMERA_SERVICE);
    try {
        cameraId = cameraManager.getCameraIdList();
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
    try {
        characteristics = cameraManager.getCameraCharacteristics(cameraId[0]);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
   characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);

    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
        try {
            cameraManager.openCamera(cameraId[0], stateCallback, mHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
        return;
    }

}

@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {

}

@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
    return false;
}

@Override
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {

}`
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章