switch back/front camera on fly
Asked Answered
B

6

26

If I use only CAMERA_FACING_BACK or CAMERA_FACING_FRONT all works fine.

I have trouble with switch from CAMERA_FACING_BACK to CAMERA_FACING_FRONT.

My code snippet:

public class PhotoCameraActivity extends Activity implements OnClickListener {
private SurfaceView cameraView;
private Button turnButton;
private Camera camera = null;
private Callback listener;
private static int camId = Camera.CameraInfo.CAMERA_FACING_BACK;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.photo_camera_main);
    prepareActivity();
}

private void prepareActivity() {
    cameraView = (SurfaceView) findViewById(R.id.photo_camera_surface_view);

    turnButton = (ImageButton) findViewById(R.id.turn_button);
    turnButton.setOnClickListener(this);
}

@Override
public void onClick(View v) {
    if (v.equals(turnButton)) {
        if (Camera.getNumberOfCameras() > 1 && camId < Camera.getNumberOfCameras() - 1) {
            startCamera(camId + 1);
        } else {
            startCamera(Camera.CameraInfo.CAMERA_FACING_BACK);
        }
    } 
}

@Override
protected void onResume() {
    startCamera(camId);
    super.onResume();
}

@Override
protected void onPause() {
    stopCamera();
    super.onPause();
}

private void startCamera(int cameraId) {
    if (camera != null) {
        stopCamera();
    }       
    holder = cameraView.getHolder();
    listener = new Callback() {

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
        }

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            try {
                camera.setPreviewDisplay(holder);
                camera.startPreview();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int           width, int height) {}
    };
    holder.addCallback(listener);


    camId = cameraId;
    camera = Camera.open(cameraId);
    Camera.Parameters params = camera.getParameters();
    if (cameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {
        params.setPreviewSize(1280, 800);
    } else {
        params.setPreviewSize(640, 480);
    }
    camera.setParameters(params);

}

private void stopCamera(){
    System.out.println("stopCamera method");
    if (camera != null){
        camera.stopPreview();
        camera.setPreviewCallback(null);
        camera.release();
        camera = null;
        holder.removeCallback(listener);
        holder = null;
    }
}

}
Backwards answered 6/7, 2011 at 15:59 Comment(6)
What is the nature of the "trouble" that you're having?Dextrogyrate
If I try to stop camera, viewfinder freezes and do not display image from another camera. But if I press "Back" and then again start this Activity, camera switches to front and it work fine again. I think I have trouble with shutdown camera and release resources.Backwards
i have stuck with same problemCuritiba
you can have only one camera open at a time so if you want to switch camera first call camera.recycle()Wounded
This code is wrong: … camera facing is not neccessarily the same than the camera index. For example my tablet has only one camera (index: 0) but facing front (facing index: 1). Therefore using the simple code like Camera.open(CameraInfo.CAMERA_FACING_FRONT) is nonesenseKranz
enter link description here This worded for meKleenex
B
6

I restart Activity with cameraId = 2 and this is working.

Backwards answered 7/7, 2011 at 8:17 Comment(3)
@Dmitriy_Boichenko..I am also facing thne same issue.. Can you please share your code?Winne
How to restart activity on button clickSatiety
Anybody who tries this answer should remember that this probably worked on some unspecified device a few years ago. This is not the way cameraId was ever expected to behave.Kranz
O
23

In onCreate() of my activity I add the following onClick listener to a button overlayed on my Preview SurfaceView (there are numerous example on the web for previewing):

ImageButton useOtherCamera = (ImageButton) findViewById(R.id.useOtherCamera);
//if phone has only one camera, hide "switch camera" button
if(Camera.getNumberOfCameras() == 1){
    useOtherCamera.setVisibility(View.INVISIBLE);
}
else {
    useOtherCamera.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    if (inPreview) {
        camera.stopPreview();
    }
    //NB: if you don't release the current camera before switching, you app will crash
    camera.release();

    //swap the id of the camera to be used
    if(currentCameraId == Camera.CameraInfo.CAMERA_FACING_BACK){
        currentCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
    }
    else {
        currentCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
    }
    camera = Camera.open(currentCameraId);
    //Code snippet for this method from somewhere on android developers, i forget where
    setCameraDisplayOrientation(CameraActivity.this, currentCameraId, camera);
    try {
        //this step is critical or preview on new camera will no know where to render to
        camera.setPreviewDisplay(previewHolder);
    } catch (IOException e) {
        e.printStackTrace();
    }
    camera.startPreview();
}

On my test device the back camera has an ID of 0 and the front has an id of 1. I suggest using Camera.CameraInfo static variables for your camera id's rather than hard-coding values. I am sure that will only cause issues on other devices.

Observation answered 25/1, 2013 at 3:48 Comment(8)
+1 I was missing the camera.setPreviewDisplay(previewHolder);Trichromatism
This code is wrong: … camera facing is not neccessarily the same than the camera index. For example my tablet has only one camera (index: 0) but facing front (facing index: 1). Therefore using the simple code like Camera.open(CameraInfo.CAMERA_FACING_FRONT) is nonesenseKranz
@AlexCohn I wouldn't say this code is wrong, in fact it works pretty good and shows how to stop the camera and start a new one. It's up to the programmer to understand the code and adapt it to their own needs.Legendre
@Merlevede: this code is wrong in a very specific sense. Please read my comment to the end, I don't object the way the camera is stopped and restarted (even though this is not optimal, so if you want to learn best practices, feel free to search or ask).Kranz
@Alex Cohn, can you also please specify what is the right way of doing this ?Rubric
@Raja, is your question about choosing the front/back camera or about the correct way to open the camera? Please note that this is a very old discussion, and the API has been deprecated for a while. These days, you should use the camera2 API.Kranz
@Alex Cohn: I have the following code, which is different from the ones you disapprove. Is this correct: for (int n=0; n < Camera.getNumberOfCameras(); n++) { CameraInfo info = new CameraInfo(); Camera.getCameraInfo(n, info); if (info.facing == CameraInfo.CAMERA_FACING_FRONT) { cam = Camera.open(n); break; }}Rubric
@Rubric yes, this is the right way to do it. Don't forget that on some devices, your loop may find no front-facing camera. In rear cases, such loop will not find a bac-facing camera.Kranz
B
6

I restart Activity with cameraId = 2 and this is working.

Backwards answered 7/7, 2011 at 8:17 Comment(3)
@Dmitriy_Boichenko..I am also facing thne same issue.. Can you please share your code?Winne
How to restart activity on button clickSatiety
Anybody who tries this answer should remember that this probably worked on some unspecified device a few years ago. This is not the way cameraId was ever expected to behave.Kranz
B
4

I removed and re-added SurfaceView in my layout and so it worked.

public void switchCamera(int cameraType)
{
    if(context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT))
    {
        if(Camera.getNumberOfCameras() > cameraType)
        {
            // Set selected camera
            this.cameraType = cameraType;
        }
        else
        {
            // Set default camera (Rear)
            this.cameraType = Camera.CameraInfo.CAMERA_FACING_BACK;
        }

        if(mCamera != null)
        {
            // Destroy previuos Holder
            surfaceDestroyed(holder);
            holder.removeCallback(this);

            // Remove and re-Add SurfaceView
            ViewGroup rootLayout = (ViewGroup) surface.getParent();
            rootLayout.removeView(surface);
            surface = new SurfaceView(context);
            holder = surface.getHolder();
            holder.addCallback(this);
            rootLayout.addView(surface, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        }
    }
}
Bluebill answered 25/9, 2013 at 13:34 Comment(1)
i did actually forgot to remove the view so i was not able to see the switched camera view.thanks this helpedOpera
J
2

I have to remove the surface preview before adding a new one:

if (mPreview != null) {
        mPreview.surfaceDestroyed(mPreview.getHolder());
        mPreview.getHolder().removeCallback(mPreview);
        mPreview.destroyDrawingCache();
        FrameLayout preview = (FrameLayout) view.findViewById(R.id.camera_frame);
        preview.removeView(mPreview);
        mPreview.mCamera = null;
        mPreview = null;

    }

//then add your preview
Justinejustinian answered 6/6, 2015 at 21:41 Comment(0)
J
0

Use this code:

if (mCamera != null) {
      mCamera.stopPreview();                  
      mCamera.release();
      mCamera = null;
}

//swap the id of the camera to be used
if (currentCameraId == Camera.CameraInfo.CAMERA_FACING_BACK)
  currentCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
else 
  currentCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;         

try {                
       mCamera = Camera.open(currentCameraId);   

       mCamera.setDisplayOrientation(90);

       mCamera.setPreviewDisplay(surfaceHolder);               

       mCamera.startPreview();

     } 
catch (Exception e) { e.printStackTrace(); } 
Jeramie answered 22/11, 2013 at 18:31 Comment(1)
This code is wrong: … camera facing is not neccessarily the same than the camera index. For example my tablet has only one camera (index: 0) but facing front (facing index: 1). Therefore using the simple code like Camera.open(CameraInfo.CAMERA_FACING_FRONT) is nonesenseKranz
S
0

try using this:

camera.stopPreview();
if(camera != null)
    camera.release();
try {
    camera = Camera.open(/*new id*/);
    camera.setPreviewDisplay(holder);
    camera.startPreview();
} catch (Exception ex) { ex.printStackTrace(); }
Signalment answered 22/12, 2021 at 14:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.