这段时间由于项目的原因,去了解了一点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) {
}`