Due to business requirements, two physical cameras need to be opened at the same time. According to Camera2 api, SdkVersion 28 supports this function. But I have to say that api documents are not friendly, or that I am really a dish.
Let's take a picture of the structure of Camera2, which I don't know its name.
From this picture, we need to know what camera0 and Camera1... In HAL layer are and what they contain. From the official documents, it can be understood as
These cameras are logical cameras. What is a logic Camera? That's the software level Camera. No matter what your physical Camera (the real Camera on your mobile phone) looks like, you don't need to think about it. All you get is this logical Camera.
Here comes the question. Now I want to open two physical cameras at the same time. What's the use of giving me a bunch of logical cameras?
Don't worry.. Go on..
This logical camera is a package of physical cameras. This means that the logical camera will contain one or more physical cameras. The camera client can call getPhysicalCameraIds() You can get the physical camera under the logical camera (of course, it may not be available, that is, it is not provided). When this getPhysicalCameraIds() The number of returned physical camera IDS is greater than 2. That is to say, there are more than two physical cameras under this logical camera, which means there is an opportunity to open these two physical cameras together. It can only be measured if there is a chance.
No more bullshit. Let's go through the process
1, Select logical cameras with multiple physical cameras
Binoculars
public class DualCamera { //Logical camera ID (assigned by manufacturer) private String logicCameraId; //Camera physical id 1 private String physicsCameraId1; //Camera physical id 2 private String physicsCameraId2; public String getLogicCameraId() { return logicCameraId; } public void setLogicCameraId(String logicCameraId) { this.logicCameraId = logicCameraId; } public String getPhysicsCameraId1() { return physicsCameraId1; } public void setPhysicsCameraId1(String physicsCameraId1) { this.physicsCameraId1 = physicsCameraId1; } public String getPhysicsCameraId2() { return physicsCameraId2; } public void setPhysicsCameraId2(String physicsCameraId2) { this.physicsCameraId2 = physicsCameraId2; } }
Get a camera with two mirrors
public static DualCamera getDualCamera(Context context){ DualCamera dualCamera = new DualCamera(); //Get management class CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE); assert manager != null; try { //Get all logical ID S String[] cameraIdList = manager.getCameraIdList(); //Obtain the class with multiple physical cameras under the logic camera as the double mirror class for (String id : cameraIdList) { try { CameraCharacteristics cameraCharacteristics = manager.getCameraCharacteristics(id); Set<String> physicalCameraIds = cameraCharacteristics.getPhysicalCameraIds(); Log.d(TAG, "logic ID: " + id + " Physics under ID: " + Arrays.toString(physicalCameraIds.toArray())); if (physicalCameraIds.size() >= 2) { dualCamera.setLogicCameraId(id); Object[] objects = physicalCameraIds.toArray(); //Take the first two physical cameras as two lenses dualCamera.setPhysicsCameraId1(String.valueOf(objects[0])); dualCamera.setPhysicsCameraId2(String.valueOf(objects[1])); return dualCamera; } } catch (CameraAccessException e) { e.printStackTrace(); } } } catch (CameraAccessException e) { e.printStackTrace(); } return null; }
2, Turn on multiple physical cameras
First, turn on the corresponding logic camera
//Turn on the camera public void openCamera(){ HandlerThread thread = new HandlerThread("DualCamera"); thread.start(); handler = new Handler(thread.getLooper()); CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE); try { //Authority check if (ActivityCompat.checkSelfPermission(context, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { //Otherwise, ask for camera permission ActivityCompat.requestPermissions(context,new String[]{Manifest.permission.CAMERA},PERMISSIONS_REQUEST_CODE); return; } manager.openCamera(dualCamera.getLogicCameraId(),AsyncTask.SERIAL_EXECUTOR, cameraOpenCallBack); } catch (CameraAccessException e) { e.printStackTrace(); } }
Step 2: specify to open the corresponding physical camera in the open callback
//When the camera is turned on, the listener can get an instance of the camera, which can be used to create a request builder private CameraDevice.StateCallback cameraOpenCallBack = new CameraDevice.StateCallback() { @Override public void onOpened(CameraDevice cameraDevice) { Log.d(TAG, "Camera is on"); //When the logic camera is on, configure the parameters of the physical camera config(cameraDevice); } @Override public void onDisconnected(@NonNull CameraDevice cameraDevice) { Log.d(TAG, "Camera disconnected"); } @Override public void onError(@NonNull CameraDevice cameraDevice, int i) { Log.d(TAG, "Camera open failed"); } }; /** * Configure camera parameters * @param cameraDevice */ public void config(CameraDevice cameraDevice){ try { //Build output parameters set physical camera in parameters List<OutputConfiguration> configurations = new ArrayList<>(); CaptureRequest.Builder mPreViewBuidler = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); //Configure the first physical camera SurfaceTexture texture = textureView1.getSurfaceTexture(); OutputConfiguration outputConfiguration = new OutputConfiguration(new Surface(texture)); outputConfiguration.setPhysicalCameraId(dualCamera.getPhysicsCameraId1()); configurations.add(outputConfiguration); mPreViewBuidler.addTarget(Objects.requireNonNull(outputConfiguration.getSurface())); //Configure 2nd physical camera SurfaceTexture texture2 = textureView2.getSurfaceTexture(); OutputConfiguration outputConfiguration2 = new OutputConfiguration(new Surface(texture2)); outputConfiguration2.setPhysicalCameraId(dualCamera.getPhysicsCameraId2()); configurations.add(outputConfiguration2); mPreViewBuidler.addTarget(Objects.requireNonNull(outputConfiguration2.getSurface())); //Register camera SessionConfiguration sessionConfiguration = new SessionConfiguration( SessionConfiguration.SESSION_REGULAR, configurations, AsyncTask.SERIAL_EXECUTOR, new CameraCaptureSession.StateCallback() { @Override public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) { try { cameraSession = cameraCaptureSession; cameraCaptureSession.setRepeatingRequest(mPreViewBuidler.build(), null, handler); } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) { } } ); cameraDevice.createCaptureSession(sessionConfiguration); } catch (CameraAccessException e) { e.printStackTrace(); } }
After completing the above operation, you can basically use camera2 to open two cameras. The article is rough.
Finally, I'll give you a picture of Huawei mate 30's open double mirror