10

I have implemented to record audio in background using Android MediaRecorder if the audio recording is in progress and user open's the native camera to record video, it gives

Camera Error "Can't Connect to the Camera"

or on some phones, the error appears as

Your camera is in use by another application

enter image description here

If I stop mediarecorder then the native camera video recording works fine, I searched for events to know when Camera is going to start video so then in my app I stop the mediarecorder, I found the BroadcastReceiver with filters

        <receiver android:name=".receiver.CameraReceiver">
            <intent-filter android:priority="10000">
            <action android:name="android.Medintent.action.CAMERA_BUTTON" />
            <action android:name="android.hardware.action.NEW_PICTURE" />
            <action android:name="android.hardware.action.NEW_VIDEO" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:mimeType="image/*" />
            <data android:mimeType="video/*" />
        </intent-filter>
    </receiver>

NEW_VIDEO and NEW_PICTURE events fired when picture or video is captured and saved in the directory. Anyone knows how can this issue be solved? I want to know in my app the event when Native/Camera Apps going to record video. Thanks in advance

Naveed Ahmad
  • 6,627
  • 2
  • 58
  • 83

2 Answers2

0

Even i had the same issue. Once camera resource is being used by an application,untill it is released, you can use them in some other app or even a service. If any service is using the camera resource, untill it releases the same we cannot use camera hardware. You can doublecheck if camera hardware is being used using this code :-

 private boolean isCameraInUse() {
    Log.v(TAG, "isCameraInUse()");
    boolean isCameraInUse = false;
    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)//Use Camera Api for Version Code < 23 and mCamera manager above it.
    {
        String cameraId = null;
        CameraManager camManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
        // Usually front mCamera is at 0 position.
        try {
            cameraId = camManager.getCameraIdList()[0];
        } catch (CameraAccessException e) {
            Log.e(TAG, Log.getStackTraceString(e));
            isCameraInUse = true;
        }
        try {
            camManager.setTorchMode(cameraId, true);
            camManager.setTorchMode(cameraId, false);
        } catch (CameraAccessException e) {
            Log.e(TAG, Log.getStackTraceString(e));
            isCameraInUse = true;
        }
    } else {
        Camera c = null;
        try {
            c = Camera.open();
        } catch (RuntimeException e) {
            Log.e(TAG, Log.getStackTraceString(e));
            turnFlashOff(mContext);
            isCameraInUse = true;
        } finally {
            if (c != null) c.release();
        }
    }
    return isCameraInUse;
}
GAGAN BHATIA
  • 591
  • 5
  • 17
  • Yes, you are right but I don't want to know whether the camera is in use or not, I want to know if Device Camera is needed by another app so I stop the recorder. Thanks for your time to look into this issue. – Naveed Ahmad Aug 03 '17 at 12:03
  • Unfortunately, i dont think if there is any way to detect if any other app wants camera hardware resource. – GAGAN BHATIA Aug 03 '17 at 12:09
  • Nothing is impossible @GAGAN if this API is not available then we will put in front of google guys to add this thing to their SDK – Naveed Ahmad Aug 03 '17 at 12:11
  • @NaveedAhmad, until process doesn't release resource, it means it needs that resource. – Uddhav P. Gautam Aug 12 '17 at 14:47
  • @UddhavGautam thanks for your message, basically without knowing that which resource is needed by another app, we can't know when to release. there should be a broadcast receiver message for requesting app which holds that resource. – Naveed Ahmad Aug 12 '17 at 15:19
0

CameraManager.AvailabilityCallback provides onCameraAvailable(String cameraId) method to detect whether a camera is available or not. https://developer.android.com/reference/android/hardware/camera2/CameraManager.AvailabilityCallback.html

Getting all camera IDs is the same as the above as shown by @GAGAN.

CameraManager camManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
        // Usually front mCamera is at position 0.
        try {
            cameraId = camManager.getCameraIdList()[0];
        }  catch (CameraAccessException e) {
            Log.e(TAG, Log.getStackTraceString(e));
            Log.cat("Error: ", e.getReason() + "");
            if (e.CAMERA_DISABLED) { /* ENABLE CAMERA */ }
            else if ( /* ... you can go to the link below to do various logic */ ) {
                //...
            }
            else { /* do nothing */ }
        }

https://developer.android.com/reference/android/hardware/camera2/CameraAccessException.html#CAMERA_IN_USE

Note: Until other applications use your camera hardware, they are using purposefully used by them. So until these apps don't free your hardware, you can't use that, it's clear. You can't know whether these apps actually need the camera. We believe process reserves hardware when it needs.

But, we can setup the listener on when camera becomes available (free) so that you can use it immediately.

CameraManager.AvailabilityCallback availabilityCallback = new CameraManager.AvailabilityCallback() {
    @Override 
    public void onCameraAvailable(String cameraId) {
        // your further stuffs. You must put all of your camera related logic here. 
    }

    public void onCameraUnavailable(String cameraId) {
        //you can logcat camera not available 
    }
};

The use of CameraManager.AvailabilityCallback abstract class is when you instantiate object, you do anonymous instantiation implementing callbacks like onCameraAvailable(), which is actually a listener that you are getting from the Camera Observer.

Answer: If you would have put your camera processing commands inside onCameraAvailable() callback, I guarantee, you wouldn't have got the error that you showed.

If the camera is used by other apps in the background, it means, those other apps are kind of buggy, because the camera needs foreground preview; they are not releasing the camera even after they are done with it. Nobody uses camera in background. Even in this case also, you are not supposed to kill camera process forcefully, because memory leaks can happen. Because you don't know how other processes are using the camera.

Stacky
  • 875
  • 9
  • 24
Uddhav P. Gautam
  • 7,362
  • 3
  • 47
  • 64
  • Bro, I am holding the MediaRecorder right? now if someone open native camera app to record video, then error appears on that app can't connect to the camera. – Naveed Ahmad Aug 12 '17 at 15:21
  • @NaveedAhmad Why don't you show your MediaRecorder implementation code? – Uddhav P. Gautam Aug 13 '17 at 23:22
  • You have to call `yourCamera.unlock()` **before** `yourMediaPlayer.pause() `method, and `yourCamera.lock()` after `yourMediaPlayer.resume()`. I advice you to puse yourCamera.unlock() and yourCamera.relase() inside try-catch block so that you can / can't lock/unlock then you don't do further operation. – Uddhav P. Gautam Aug 13 '17 at 23:30
  • @NaveedAhmad, I am waiting for your codes so that I can help you. – Uddhav P. Gautam Aug 13 '17 at 23:41
  • I am checking Camera while recording audio with MediaRecorder in my app, I just need to know the event when android starting video, so far I didnot found anything regarding this. – Naveed Ahmad Aug 14 '17 at 10:00