Basic usage of Camera2 API

Basic usage of Camera2 API

refer to: https://developer.android.google.cn/reference/android/hardware/camera2/package-summary

request access camera permission

there need add permission declaration in AndroidManifest.xml

<!--    false means APP can run on device which has no camera -->
<uses-feature
        android:name="android.hardware.camera"
        android:required="false" />

<uses-permission android:name="android.permission.CAMERA" />

then, there need to dynamically request access camera permission

public static final int REQUEST_PERMISSION_CODE = 100;
public boolean permissionAccepted = false;

private void checkPermission() {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, REQUEST_PERMISSION_CODE);
    } else {
        permissionAccepted = true;
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_PERMISSION_CODE) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            permissionAccepted = true;
        } else {
            permissionAccepted = false;
            Toast.makeText(this, "this APP need to access CAMERA!!", Toast.LENGTH_SHORT).show();
        }
    }
}

get CameraManager:

CameraManager is a system service manager for detecting, characterizing, and connecting to CameraDevices.

private CameraManager cameraManager = (CameraManager) context.getSystemService(CAMERA_SERVICE);

open CameraDevide

Open a connection to a camera with the given ID.
Use getCameraIdList() to get the list of available camera devices. Note that even if an id is listed, open may fail if the device is disconnected between the calls to getCameraIdList() and openCamera(String, StateCallback, Handler), or if a higher-priority camera API client begins using the camera device.

function:

public void openCamera (String cameraId, CameraDevice.StateCallback callback,  Handler handler)

example:

public void openCamera(String cameraId, int frameRate) {
	try {
		// check permission
		if (ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
			this.frameRate = frameRate;
			imageReader = ImageReader.newInstance(640, 480, ImageFormat.YUV_420_888, 2);
			imageReader.setOnImageAvailableListener(onImageAvailableListener, cameraHandler);
			cameraManager.openCamera(cameraId, stateCallback, cameraHandler);
		} else {
			Toast.makeText(context, "can not access CAMERA, please give me permission!!", Toast.LENGTH_SHORT).show();
			ActivityCompat.requestPermissions(((MainActivity)context), new String[]{Manifest.permission.CAMERA}, REQUEST_PERMISSION_CODE);
		}
	} catch (CameraAccessException e) {
		e.printStackTrace();
	}
}

where, cameraHandler is created as follow:

private HandlerThread handlerThread;
handlerThread = new HandlerThread("camera2Thread");
handlerThread.start();
CameraHandler cameraHandler = new Handler(handlerThread.getLooper())

and stateCallback is used to listen the state of CameraDevice:

private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
	@Override
	public void onOpened(@NonNull CameraDevice camera) {
		// do something when camera opened.
		// here, when the camera opened, create a cameraCaptureSession to request to capture image
		cameraDevice = camera;
		createCameraPreviewSession(camera);
	}

	@Override
	public void onDisconnected(@NonNull CameraDevice camera) {
		camera.close();
		Log.d("vv", "onDisconnected: camera disconnected!");
	}

	@Override
	public void onError(@NonNull CameraDevice camera, int error) {
		camera.close();
		cameraDevice = null;
		Log.d("vv", "onDisconnected: camera error!");
	}
};

create cameraCaptureSession

A configured capture session for a CameraDevice, used for capturing images from the camera or reprocessing images captured from the camera in the same session previously.

private void createCameraPreviewSession(CameraDevice camera) {
	try {
		captureRequestBuilder = camera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                previewSurface.setFrameRate(frameRate, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT);
		}
		captureRequestBuilder.addTarget(previewSurface); // for preview on SurfaceView or TextureView
		captureRequestBuilder.addTarget(imageReader.getSurface()); // get frame by a imageReader
		// set frame rate by new Range<>(60, 60)
		captureRequestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, new Range<>(60, 60));
		camera.createCaptureSession(Arrays.asList(previewSurface, imageReader.getSurface()), new CameraCaptureSession.StateCallback() {
		@Override
		public void onConfigured(@NonNull CameraCaptureSession session) {
			cameraCaptureSession = session;
			try {
				captureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
				if (turnOnFlash) {
					captureRequestBuilder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_TORCH);
				}
				cameraCaptureSession.setRepeatingRequest(captureRequestBuilder.build(), captureCallback, cameraHandler);
			} catch (CameraAccessException e) {
				e.printStackTrace();
			}
		}

			@Override
			public void onConfigureFailed(@NonNull CameraCaptureSession session) {
                    Toast.makeText(context, "Failed to create camera capture session \n camera " + camera.getId() + " may not exist", Toast.LENGTH_SHORT).show();
			}
		}, cameraHandler);
	} catch (CameraAccessException e) {
            e.printStackTrace();
	}
}

where, previewSurface can be SurfaceView, need use it in layout.xml first. Then, get Surface object like:

SurfaceView surfaceView = findViewById(R.id.surfaceView);
SurfaceHolder surfaceHolder = surfaceView.getHolder();
surfaceHolder.setFormat(PixelFormat.TRANSPARENT);
surfaceHolder.setFixedSize(640, 480);
surfaceHolder.addCallback(surfaceCallBack);

Surface previewSurface = surfaceHolder.getSurface();

private final SurfaceHolder.Callback surfaceCallBack = new SurfaceHolder.Callback() {
	@Override
	public void surfaceCreated(@NonNull SurfaceHolder holder) {

	}

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

	}

	@Override
	public void surfaceDestroyed(@NonNull SurfaceHolder holder) {

	}
};

imageReader is created as follow:

ImageReader imageReader = ImageReader.newInstance(640, 480, ImageFormat.YUV_420_888, 2);
imageReader.setOnImageAvailableListener(onImageAvailableListener, cameraHandler);

where, onImageAvailableListener is refer to ImageReader

private final ImageReader.OnImageAvailableListener onImageAvailableListener = new ImageReader.OnImageAvailableListener() {
	@Override
	public void onImageAvailable(ImageReader reader) {
		Image image = reader.acquireLatestImage();
		if (image != null) {
			// process image
			if (dataFile == null) {
				filePath = context.getExternalFilesDir(null).getAbsolutePath();
				@SuppressLint("SimpleDateFormat") SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_hh-mm-ss");
				filename = filename + "_(" + sdf.format(new Date(System.currentTimeMillis())) + ").txt";
				String mFilePath = filePath + "/" + filename;
				dataFile = new File(mFilePath);
			}
			int red = DataProcess.process(image, dataFile);
			Message msg = Message.obtain();
			msg.what = 1;
			msg.arg1 = red;
			((MainActivity) context).handler.sendMessage(msg);
			image.close();
		}
	}
};

captureRequestBuilder is instance of CaptureRequest.Builder

A builder for capture requests.

To obtain a builder instance, use the CameraDevice#createCaptureRequest method, which initializes the request fields to one of the templates defined in CameraDevice.

captureCallback is a callback object for tracking the progress of a CaptureRequest submitted to the camera device.

This callback is invoked when a request triggers a capture to start, and when the capture is complete. In case on an error capturing an image, the error method is triggered instead of the completion method.

int count = 0;

private final CameraCaptureSession.CaptureCallback captureCallback = new CameraCaptureSession.CaptureCallback() {
	@Override
	public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
		super.onCaptureCompleted(session, request, result);
		// I calculate frame rate here.
		count++;
		if (count == 30) {
			long currFrameTime = System.currentTimeMillis();
			float frameRate = (float) (1000.0 / ((currFrameTime - lastFrameTime) / 30.0));
			lastFrameTime = currFrameTime;
			count = 0;
			((MainActivity)context).runOnUiThread(new Runnable() {
				@Override
				public void run() {
					((MainActivity)context).updateFrameRate(frameRate);
				}
			});
		}
		if (!((MainActivity)context).timerStarted) {
			((MainActivity)context).runTimer();
		}
	}
};
  • 18
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值