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;
    }
}

}
Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
Dmytro Boichenko
  • 5,217
  • 3
  • 28
  • 31
  • 1
    What is the nature of the "trouble" that you're having? – Estel Jul 06 '11 at 18:24
  • 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. – Dmytro Boichenko Jul 06 '11 at 19:08
  • i have stuck with same problem – himanshu Jun 26 '12 at 10:43
  • you can have only one camera open at a time so if you want to switch camera first call camera.recycle() – Illegal Argument May 22 '14 at 08:51
  • 2
    **This code is [wrong](http://stackoverflow.com/questions/2779002/how-to-open-front-camera-on-android-platform/4767832#comment33410134_4767832)**: *… 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 nonesense* – Alex Cohn Dec 02 '15 at 08:41
  • [enter link description here](http://stackoverflow.com/a/38267032/4448757) This worded for me – Shailendra Yadav Jul 08 '16 at 12:52

6 Answers6

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.

Derek
  • 255
  • 2
  • 3
  • +1 I was missing the camera.setPreviewDisplay(previewHolder); – X.Y. Apr 05 '14 at 01:32
  • 5
    **This code is [wrong](http://stackoverflow.com/questions/2779002/how-to-open-front-camera-on-android-platform/4767832#comment33410134_4767832)**: *… 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 nonesense* – Alex Cohn Dec 02 '15 at 08:40
  • 1
    @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. – Merlevede Jun 30 '16 at 07:00
  • 1
    @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). – Alex Cohn Jun 30 '16 at 07:43
  • @Alex Cohn, can you also please specify what is the right way of doing this ? – Raja Apr 11 '17 at 17:11
  • @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**](https://developer.android.com/reference/android/hardware/camera2/package-summary.html) API. – Alex Cohn Apr 12 '17 at 15:30
  • @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; }} – Raja Apr 21 '17 at 17:30
  • @Raja 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. – Alex Cohn Apr 21 '17 at 19:22
6

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

Dmytro Boichenko
  • 5,217
  • 3
  • 28
  • 31
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));
        }
    }
}
Saksham
  • 9,037
  • 7
  • 45
  • 73
  • i did actually forgot to remove the view so i was not able to see the switched camera view.thanks this helped – Sagar G. Aug 07 '14 at 07:13
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
MobileMon
  • 8,341
  • 5
  • 56
  • 75
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(); } 
Ingo
  • 5,239
  • 1
  • 30
  • 24
  • 3
    **This code is [wrong](http://stackoverflow.com/questions/2779002/how-to-open-front-camera-on-android-platform/4767832#comment33410134_4767832)**: *… 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 nonesense* – Alex Cohn Dec 02 '15 at 08:37
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(); }