实现预览的步骤
- Get permission to use camera device
- Using CameraManager open connection to a camera
- Have prepared Surface for preview
- Using opened camera device and desired surfaces (it can include not only preview surface) create CaptureSession
- After CaptureSession created you need to create and configure CaptureRequest and submit it to CaptureSession
对surface的处理过程:
findViewById:(SurfaceView) -> getHolder(SurfaceHold) -> getSurface(Surface);
this.mSurfaceView = (SurfaceView) findViewById(R.id.SurfaceViewPreview);
this.mSurfaceHolder = this.mSurfaceView.getHolder();
this.mSurfaceHolder.addCallback(this);
mCameraSurface = holder.getSurface();
提交CaputreRequest的过程
mCameraManager = (CameraManager) this.getSystemService(Context.CAMERA_SERVICE);
mCameraManager.openCamera(mCameraIDsList[1], mCameraStateCB, new Handler());
赋值mCameraDevice: onOpened(CameraDevice);
通过CameraDevice配置Camera: mCameraDevice.createCaptureSession
通过CameraCaptureSession.StateCallback的onConfigured生成CameraCaptureSession
通过CameraDevice的createCaptureRequest创建CaptureRequest
最后调用CameraCaptureSession提交CaptureRequest。
SurfaceHold callback and CameraDevice StateCallback
@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/*怎样得到SurfaceView*/
this.mSurfaceView = (SurfaceView) findViewById(R.id.SurfaceViewPreview);
/*从SurfaceView得到SurfaceHold*/
this.mSurfaceHolder = this.mSurfaceView.getHolder();
/*赋值SurfaceHolder的Callbak:*/
this.mSurfaceHolder.addCallback(this);
/*获得SystemService: CAMERA_SERVICE,使用其中的getCameraIdList*/
try {
mCameraIDsList = this.mCameraManager.getCameraIdList();
for (String id : mCameraIDsList) {
Log.v(TAG, "CameraID: " + id);
}
}
/*赋值APP实现的StateCallback*/
@Override
public void onOpened(CameraDevice camera) {
Toast.makeText(getApplicationContext(), "onOpened", Toast.LENGTH_SHORT).show();
/*CameraDevice的赋值是通过回调函数的参数*/
mCameraDevice = camera;mHandler.sendEmptyMessage(MSG_CAMERA_OPENED);
}
@Override
public void onDisconnected(CameraDevice camera) {
Toast.makeText(getApplicationContext(), "onDisconnected", Toast.LENGTH_SHORT).show();
}
@Override
public void onError(CameraDevice camera, int error) {
Toast.makeText(getApplicationContext(), "onError", Toast.LENGTH_SHORT).show();
}
};
}
访问Camera的权限申请及openCamera的调用
@Override
protected void onStart() {
super.onStart();
//requesting permission
int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
} else {
ActivityCompat.requestPermissions
(this, new String[]{Manifest.permission.CAMERA}, MY_PERMISSIONS_REQUEST_CAMERA);
Toast.makeText(getApplicationContext(), "request permission", Toast.LENGTH_SHORT).show();}
} else {
Toast.makeText(getApplicationContext(), "PERMISSION_ALREADY_GRANTED", Toast.LENGTH_SHORT).show();
try {
mCameraManager.openCamera(mCameraIDsList[1], mCameraStateCB, new Handler());
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_CAMERA:
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
== PackageManager.PERMISSION_GRANTED)
try {mCameraManager.openCamera(mCameraIDsList[1], mCameraStateCB, new Handler());
} catch (CameraAccessException e) {
e.printStackTrace();
}
break;
}
}
SurfaceHolder Callback
/** * A client may implement this interface to receive information about * changes to the surface. */ public interface Callback { /** * This is called immediately after the surface is first created. */ public void surfaceCreated(SurfaceHolder holder); /** * This is called immediately after any structural changes (format or * size) have been made to the surface. You should at this point update * the imagery in the surface. This method is always called at least * once, after {@link #surfaceCreated}. */ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height); /** * This is called immediately before a surface is being destroyed. After * returning from this call, you should no longer try to access this * surface. If you have a rendering thread that directly accesses * the surface, you must ensure that thread is no longer touching the * Surface before returning from this function. * * @param holder The SurfaceHolder whose surface is being destroyed. */ public void surfaceDestroyed(SurfaceHolder holder); }@Override
public void surfaceCreated(SurfaceHolder holder) {
/*从holder的得到Surface*/
mCameraSurface = holder.getSurface();}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mCameraSurface = holder.getSurface();
mSurfaceCreated = true;
mHandler.sendEmptyMessage(MSG_SURFACE_READY);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mSurfaceCreated = false;
}
configureCamera: createCaptureSession
@Override
public boolean handleMessage(Message msg) {switch (msg.what) {
case MSG_CAMERA_OPENED:
case MSG_SURFACE_READY:
// if both surface is created and camera device is opened
// - ready to set up preview and other things
if (mSurfaceCreated && (mCameraDevice != null)
&& !mIsCameraConfigured) {
configureCamera();
}
break;
}
return true;
}
private void configureCamera() {
// prepare list of surfaces to be used in capture requests
List<Surface> sfl = new ArrayList<Surface>();
sfl.add(mCameraSurface); // surface for viewfinder preview
// configure camera with all the surfaces to be ever used
try {
mCameraDevice.createCaptureSession(sfl,
new CaptureSessionListener(), null);
}
mIsCameraConfigured = true;
}
CameraCaptureSession.StateCallback and request submit
private class CaptureSessionListener extends
CameraCaptureSession.StateCallback {@Override
public void onConfigureFailed(final CameraCaptureSession session) {
Log.d(TAG, "CaptureSessionConfigure failed");
}
/*当onConfigured时 得到CameraCaptureSession*/
@Override
public void onConfigured(final CameraCaptureSession session) {
Log.d(TAG, "CaptureSessionConfigure onConfigured");
mCaptureSession = session;
try { /*构建Request并提交到session */
CaptureRequest.Builder previewRequestBuilder = mCameraDevice
.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
previewRequestBuilder.addTarget(mCameraSurface);
mCaptureSession.setRepeatingRequest(previewRequestBuilder.build(),
null, null);
}
}
}
Create a CaptureRequest.Builder for new capture requests
从上面的mSurfaceSet可以看出需要赋值surface.
CaptureRequest.java: addTarget(@NonNull Surface outputTarget)
Add a surface to the list of targets for this request
addTarget: mRequest.mSurfaceSet.add(outputTarget)setRepeatingRequest:
camera 拍照
1.根据不同的View等使用callback 或listener调用CameraManger接口:openCamera,
2.由CameraDevice.StateCallback: onPened创建 createCaptureRequest, 进而创建CreateCaptureSession
3. 由CameraCaptureSession.StateCallback: onConfigured:提交Request
4. 当提交的request返回image到提交的surface: ImageReader.OnImageAvailableListener: onImageAvailable保存image到文件
5. 由CameraCaptureSession.CaptureCallback: onCaptureProgressed