35

I'm getting a Fail to connect to camera service exception when I run my Android app in the emulator. I've read the various existing posts but none have fixed this. It is clearly the Camera.open() call which is failing. I would eventually like to get the webcam going in the emulator, as many SO posts discuss, but right now just want the app to run without bombing. I do not care whether any camera video gets shown or not, since there are other features besides the camera that I need to test, and will primarily test the camera on my device anyway.

My manifest seems to be ok. The following lines are in it:

<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.CAMERA"></uses-permission>

In my AVD manager I have set both the front and back camera to be "Emulated" and the SD Card value to 64. These seem to be the recommended values. The full stack trace is now below. Solution has to be something straightforward, but what?

10-09 08:14:32.375    2628-2628/com.allinlearning.AILAndroidScanner E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.allinlearning.AILAndroidScanner, PID: 2628
java.lang.RuntimeException: Fail to connect to camera service
        at android.hardware.Camera.native_setup(Native Method)
        at android.hardware.Camera.<init>(Camera.java:350)
        at android.hardware.Camera.open(Camera.java:309)
        at com.allinlearning.AILAndroidScanner.AsynCamPreview.surfaceCreated(AsynCamPreview.java:104)
        at android.view.SurfaceView.updateWindow(SurfaceView.java:572)
        at android.view.SurfaceView.access$000(SurfaceView.java:86)
        at android.view.SurfaceView$3.onPreDraw(SurfaceView.java:175)
        at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:847)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1871)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1000)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5670)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761)
        at android.view.Choreographer.doCallbacks(Choreographer.java:574)
        at android.view.Choreographer.doFrame(Choreographer.java:544)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747)
        at android.os.Handler.handleCallback(Handler.java:733)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:136)
        at android.app.ActivityThread.main(ActivityThread.java:5017)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
        at dalvik.system.NativeStart.main(Native Method)

The code for the entire class is below. Again, it's the Camera.open() call that throws the exception:

import java.io.IOException;
import java.util.List;

import android.graphics.Bitmap;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.SurfaceHolder;
import android.webkit.MimeTypeMap;
import android.widget.ImageView;

public class AsynCamPreview extends MainActivity
        implements SurfaceHolder.Callback,  Camera.PreviewCallback
{

    private Camera mCamera;
    public Camera.Parameters params;
    private SurfaceHolder sHolder;
    private ImageView myCameraPreview = null;
    private Bitmap mBitmap = null;

    // data arrays
    private int[] pixels = null;
    private float[] floatpixels = null;
    private byte[] FrameData = null;

    // Camera params
    public float maxZoom;
    private int imageFormat;
    private int previewSizeWidth;
    private int previewSizeHeight;
    private int camId = 1;

    // flags and counts
    private boolean bProcessing = false;
    private int frameCount = 0;
    private boolean doProcessing = false;
    public boolean mProcessInProgress = false;

    public static final String TAG = "AsynCamPreview";

    private long mTiming[] = new long[50];
    private int mTimingSlot = 0;

    Handler mHandler = new Handler(Looper.getMainLooper());

    static {
//      System.loadLibrary("ImageProcessing");
        Log.i(TAG, "Native library loaded");
    }

    public AsynCamPreview(int previewLayoutWidth, int previewLayoutHeight, ImageView cameraPreview)
    {
        previewSizeWidth = previewLayoutWidth;
        previewSizeHeight = previewLayoutHeight;
        myCameraPreview =cameraPreview;
    }


    @Override
    public void onPreviewFrame(byte[] data, Camera camera)
    {
        // Do nothing for now
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        sHolder = holder;
        if (camId == 0) {
            mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
        }
        else {
            mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
        }

        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.setPreviewCallback(this);
        } catch (IOException e) {
            mCamera.release();
            mCamera= null;
        }

        params = mCamera.getParameters();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
                               int height) {
        // TODO Auto-generated method stub
        params = mCamera.getParameters();
        List<Camera.Size> sizes = params.getSupportedPictureSizes();
        this.params.setPreviewSize(previewSizeWidth, previewSizeHeight);

        mBitmap = Bitmap.createBitmap(previewSizeWidth, previewSizeHeight,
                Bitmap.Config.ARGB_8888);
        myCameraPreview.setImageBitmap(mBitmap);

        pixels = new int[previewSizeWidth * previewSizeHeight];
        //floatpixels = new float[previewSizeWidth * previewSizeHeight * 3];
        imageFormat = params.getPreviewFormat();
        mCamera.setParameters(params);
        mCamera.startPreview();

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        mCamera.setPreviewCallback(null);
        mCamera.stopPreview();
        mCamera.release();
        mCamera = null;
    }

    @Override
    public void onPause() {
        this.mCamera.stopPreview();
    }

}
Alyoshak
  • 2,696
  • 10
  • 43
  • 70
  • Could you post the Java code please? And also the whole stack trace? – aProperFox Oct 10 '14 at 17:45
  • Tyler, I've updated the question as per your request. – Alyoshak Oct 10 '14 at 18:11
  • Thanks, although we'll likely need more of the Java code. Can you post the whole class? I'm guessing it's the declaration of mCamera that's not done properly. – aProperFox Oct 10 '14 at 18:16
  • 1
    Doesn't seem like much is done once Camera var is set besides try to open it. But this code worked fine in my Eclipse project for a device (I'm now in IntelliJ on the emulator) – Alyoshak Oct 10 '14 at 18:25

7 Answers7

43

From the Android Developers Docs:

Calling Camera.open() throws an exception if the camera is already in use by another application, so we wrap it in a try block.

Try wrapping that code in a try catch block like so:

try {
    releaseCameraAndPreview();
    if (camId == 0) {
        mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
    }
    else {
        mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
    }
} catch (Exception e) {
    Log.e(getString(R.string.app_name), "failed to open Camera");
    e.printStackTrace();
}

Then add this function somewhere:

private void releaseCameraAndPreview() {
    myCameraPreview.setCamera(null);
    if (mCamera != null) {
        mCamera.release();
        mCamera = null;
    }
}
T.Todua
  • 53,146
  • 19
  • 236
  • 237
aProperFox
  • 2,114
  • 2
  • 20
  • 21
  • Looks to me that calling releaseCameraAndPreview() is what actually fixed things. Camera must have been in use somehow, though I couldn't see how. Anyhow, why the myCameraPreview.setCamera(null) call? I had to comment it out. No setCamera() method on myCameraPreview, which is an ImageView object. – Alyoshak Oct 10 '14 at 19:17
  • I just grabbed that from the Android Dev Docs. I think it might have been the need to initialize the camera with mcamera = null; My research showed that most people needed to add this. Either that or just that the camera was in use by another application :P – aProperFox Oct 10 '14 at 19:20
  • 1
    I just want to note that this error can also occur if the camera on the device does not work. – Automatico Mar 10 '16 at 19:12
  • @Alyoshak: One scenario where this can happen: Facebook video call on minimising creates a smaller video call dialog and doesn't release the camera. When from another app you use camera, you will get this error. – Harish Vishwakarma May 10 '17 at 05:09
  • what is myCameraPreview? – AlexS Nov 20 '18 at 06:20
9

OP mentions this in his question, but my issue was I forgot to enable camera emulation in my AVD emulator settings:

enter image description here

Adam Johns
  • 35,397
  • 25
  • 123
  • 176
9

With Android 6.0, this error can appened if you don't check for manifest authorisation :

    //If authorisation not granted for camera
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)
        //ask for authorisation
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 50);
    else
        //start your camera
        this.startCamera();
Kevin ABRIOUX
  • 16,507
  • 12
  • 93
  • 99
5

Using

if (ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
  ActivityCompat.requestPermissions(CodeScanner.this, new String[]{android.Manifest.permission.CAMERA}, 50);
}

worked for me

Arnyminer Z
  • 5,784
  • 5
  • 18
  • 32
3

1.Use below permissions in manifest file and always put permissions above Application tag.

<uses-permission android:name="android.permission.CAMERA" />
<uses-feature
    android:name="android.hardware.camera"
    android:required="false" />
<uses-feature android:name="android.hardware.camera.autofocus" />

2.Use Unlock while camera used by other service like MediaRecorder.

camera.unlock();
recorder.setCamera(camera);

2.Released camera properly, I prefer to use lock so become safely accessible for other application and second time use (In case if we reopen).

if (camera != null) {
        camera.lock();
        camera.stopPreview();
        camera.release();
        camera = null;
    }
Dattatray Nande
  • 139
  • 1
  • 2
2

If you periodically got a white screen instead your view of camera - use:

private void releaseCameraAndPreview() {
        if (mCamera != null) {
            mCamera.setPreviewCallback(null);
            mCameraView.getHolder().removeCallback(mCameraView);
            mCamera.release();
            mCamera = null;
        }
    }

and put it here

try {
            releaseCameraAndPreview();
            mCamera = getCameraInstance();
        }...

and here

@Override
    protected void onPause() {
        super.onPause();
        releaseCameraAndPreview();
    }
nicolas asinovich
  • 3,201
  • 3
  • 27
  • 37
-1

If you are using surface View and using code like this`

 Observable.create(CameraUtils.getCameraOnSubscribe())
                    .subscribeOn(Schedulers.newThread())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(camera -> {

                 mCamera = camera.open();
...    
}};

Then replace mCamera=camera;