0

I'm making an Android app using the Camera2 api.

I want to be able to switch between the front and back camera, but it takes an awful lot of time to do so no matter how i try to implement it.

After what i understand, you can't open both cameras at once(i've tried that also), so you have to stop the first one before opening the second.

The problem is it takes me 1.5seconds to stop the first camera.

How does for instance snapchat manage to swap the cameras in a few hundred milliseconds?


The code i'm using is the camera2basic from google that can be found here:

https://github.com/googlesamples/android-Camera2Basic/blob/master/Application/src/main/java/com/example/android/camera2basic/Camera2BasicFragment.java

I've added a simple method to stop the camera:

public void stopCamera(){
    Log.i("yoyo","Stopcamera() begin");
    mCameraDevice.close();
    //stopBackgroundThread();
    Log.i("yoyo","Stopcamera() end");
}

Android Monitor:

08-01 15:13:01.478 10020-10020/com.example.android.camera2basic I/yoyo: Stopcamera() begin 08-01 15:13:02.852 10020-10020/com.example.android.camera2basic I/yoyo: Stopcamera() end 08-01 15:13:02.853 10020-10020/com.example.android.camera2basic I/Choreographer: Skipped 81 frames! The application may be doing too much work on its main thread. 08-01 15:13:02.855 10020-10207/com.example.android.camera2basic I/yoyo: Cameradevice - onClosed() callback running


-UPDATE 07 aug 2017-

It seems that the camera2 api just takes longer to shut down than the old camera api.

I tried using the old camera api and I achieved the same speed as snapchat/instagram, so i'm guessing they are using the old camera api.

  • Some devices [support](https://stackoverflow.com/questions/11419940/using-both-front-and-back-cameras-simultaneously-android) simultaneous operation on two cameras; then, switch may be instant. Other devices may have glitches with camera2 implementation (especially if camera characteristics reports [Legacy](https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) support level), but more often the deprecated Camera API is slower. – Alex Cohn Aug 07 '17 at 12:01
  • Yes it seems strange to me that the camera2 api is slower. I tried downloading a bunch of camera2 apps from the play store, and they all seem to have this 1.5ish second lag between switching cameras. The phone i was using for my tests was the galaxy s7 – Richard Slettevoll Aug 08 '17 at 09:56
  • It should not be hard find which camera API instagram are using. Usually you can see the trace in logcat. I won't be surprised if they choose one or another per device model based on A/B testing. – Alex Cohn Aug 08 '17 at 11:33
  • Do you find the solution for this? – nhoxbypass Mar 28 '18 at 09:41
  • Yes i used the old camera api. I checked the manifest file for snapchat and instagram, and they both use the old api – Richard Slettevoll Apr 03 '18 at 09:00

2 Answers2

0

You should be able to run both capture sessions concurrently. You can even have both "previews" on the UI at the same time.

Here's what you have to do:

  • create device 1 (i.e. back camera) with cameraManager.openCamera("1", ...)
  • create device 2 (i.e. front camera) cameraManager.openCamera("2", ...)
  • Once you have a CameraDevice instance for each camera, start their capture session
  • cameraDevice1.createCaptureSession(surface1, ...)
  • cameraDevice1.createCaptureSession(surface2, ...)
  • When the capture sessions are created successfully, you should be at to call captureSession.setRepeatingRequest(...).

As you've noticed, there's a huge overhead in switching cameras from "scratch". If you only want to show one preview at a time. You can still call openCamera() for each camera, call createCaptureRequest for each camera, and use setRepeatingRequest or stopRepeating to control when the captureSession is actually processing frames.

Hope this helps!

0

William Guedes

Here's what you have to do:

create device 1 (i.e. back camera) with cameraManager.openCamera("1", ...)

create device 2 (i.e. front camera) cameraManager.openCamera("2", ...)

I've written some simple code below for opening both cameras using manager.openCamera().

The monitor only logs "camera 0 onOpened() callback" though, and i assumed this ment you could only open one camera at the time?

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.e("yoyo", "onCreate() begin");
        CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
           
        try {

            String[] cameraIdList = manager.getCameraIdList();

            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 123);
                return;
            }
            manager.openCamera(cameraIdList[0], new CameraDevice.StateCallback() {
                @Override
                public void onOpened(@NonNull CameraDevice cameraDevice) {
                    Log.e("yoyo", "camera 0 onOpened() callback");
                }

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

                }

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

                }
            }, null);

            manager.openCamera(cameraIdList[1], new CameraDevice.StateCallback() {
                @Override
                public void onOpened(@NonNull CameraDevice cameraDevice) {
                    Log.e("yoyo", "camera 1 onOpened() callback");
                }

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

                }

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

                }
            }, null);


        }catch (CameraAccessException e) {e.printStackTrace();}


    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == 123) {
            if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
                // close the app
                Toast.makeText(this, "Sorry!!!, you can't use this app without granting permission", Toast.LENGTH_LONG).show();
                finish();
            }
        }
    }
}
Community
  • 1
  • 1
  • int he onError() calback i get errocode 2 wich means: ERROR_MAX_CAMERAS_IN_USE added in API level 21 int ERROR_MAX_CAMERAS_IN_USE An error code that can be reported by onError(CameraDevice, int) indicating that the camera device could not be opened because there are too many other open camera devices. The system-wide limit for number of open cameras has been reached, and more camera devices cannot be opened until previous instances are closed. This error can be produced when opening the camera fails. – Richard Slettevoll Aug 02 '17 at 09:47