I am developing a webRTC app using opentok. The app was working fine. I converted the app to library and launching the library activity by adding it to another project. The app is connecting to server but camera not opening. I am getting camera error as follows
E/opentok-videocapturer: The camera is in use by another app
java.lang.RuntimeException: Fail to connect to camera service
at android.hardware.Camera.<init>(Camera.java:518)
at android.hardware.Camera.open(Camera.java:360)
at com.opentok.android.DefaultVideoCapturer.init(DefaultVideoCapturer.java:110)
at com.opentok.android.BaseVideoCapturer.initTrap(BaseVideoCapturer.java:223)
public boolean isCameraUsebyApp() {
Camera camera = null;
try {
camera = Camera.open();
}
catch (RuntimeException e)
{
return true;
}
finally
{
if (camera != null)
{
camera.release();
}
}
return false;
}
Related
I am trying to resume my Camera preview with android after putting the app to sleep or changing between apps. Or even starting a different app which uses the camera feature but the Camera crashed with getParameters() being null.
Is there a way to retrieve the control other the camera preview when resuming using the Xamarin forms application.
I have tried to use Camera.Restart() and didn't work.
public void SurfaceCreated(ISurfaceHolder holder)
{
try
{
if (Preview != null)
{
Preview.StopPreview();
Preview.Reconnect();
Preview.SetPreviewDisplay(holder);
Preview.EnableShutterSound(true);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(#" ERROR: ", ex.Message);
}
}
public void SurfaceDestroyed(ISurfaceHolder holder)
{
Preview.StopPreview();
Preview.Release();
}
public void SurfaceChanged(ISurfaceHolder holder, Android.Graphics.Format format, int width, int height)
{
Camera.Parameters parameters = Preview.GetParameters();
parameters.FocusMode = Camera.Parameters.FocusModeContinuousPicture;
IList<Camera.Size> previewSizes = parameters.SupportedPreviewSizes;
// You need to choose the most appropriate previewSize for your app
Camera.Size previewSize = previewSizes[0];
parameters.SetPreviewSize(previewSize.Width, previewSize.Height);
Preview.SetParameters(parameters);
Preview.StartPreview();
}
I was able to get it to work by reading more thoroughly about the behaviour of the Android camera(Camera1) hardware.
If you are working on Xamarin and trying to create camera view within the app the best way to do it is making a custom renderer and create a camera view in each platform. Like shown here:
https://learn.microsoft.com/en-ca/xamarin/xamarin-forms/app-fundamentals/custom-renderer/view
but this example only shows how to create the camera preview, there is no camera hardware lifecycle or taking a pictures included.
To solve the issue for the question above I had simply to do Camera.Open(0) to gain control over the camera again within the lifecycle of Xamarin forms pages.
Here is what I did(in CameraPreview class in Xamarin Forms):
Created Camera open event handler:
public event EventHandler CloseCameraRequest;
Created a method to invoke the event:
public void OpenCamera()
{
OpenCameraRequest?.Invoke(this, EventArgs.Empty);
}
Registered the handler in the android camera native class:
protected override void OnElementChanged(ElementChangedEventArgs<CameraPreview> e)
{
base.OnElementChanged(e);
if (Control == null)
{
_nativeCameraPreview = new NativeCameraPreview(Context);
_nativeCameraPreview.PhotoCaptured += OnPhotoCaptured;
SetNativeControl(_nativeCameraPreview);
}
Control.Preview = Camera.Open(0);
if (e.OldElement != null)
{
e.NewElement.OpenCameraRequest -= OnOpenCameraRequest;
}
if (e.NewElement != null)
{
e.NewElement.OpenCameraRequest += OnOpenCameraRequest;
}
}
private void OnOpenCameraRequest(object sender, EventArgs e)
{
Control.Preview = Camera.Open(0);
}
Invoked the request all the way from Xamarin forms page OnAppearing method:
protected override void OnAppearing()
{
base.OnAppearing();
CameraPreview.OpenCamera();
}
This fixed the issue of resuming camera preview after opening other application which uses the camera or putting the app to sleep where camera preview will timeout.
How to save the state of the camera so when i close the screen and turn it on again the camera gets back to its previous state.Should i bundle it?
public void getCamera() {
if (camera == null) {
try {
camera = Camera.open();
params = camera.getParameters();
} catch (RuntimeException e) {
Log.e(e.getMessage(), "Camera Error. Failed to Open. Error:Application will close! ");
finish();
}
}
}
Generally you don't want to do this- you want to release the camera in onPause and recapture it in onResume so other apps can use it as well.
I'm writing a program that accesses the camera. It worked for a while, but now it is the Camera API is throwing exceptions because the camera is still in use when I try to open it. I think this is because I am not handling it correctly in my onPause, onResume, and where I use it. Here is my code:
#Override
protected void onResume(){
if (!getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
Toast.makeText(this, "No camera on this device", Toast.LENGTH_LONG)
.show();
} else {
cameraId = findFrontFacingCamera();
if (cameraId < 0) {
Toast.makeText(this, "No front facing camera found.",
Toast.LENGTH_LONG).show();
} else {
try {
if (camera != null) {
camera.release();
camera = null;
}
camera = Camera.open(cameraId);
try {
camera.setPreviewTexture(cameraTexture);
}
catch(IOException e){
Log.i("CameraHome", "could not set camera preview");
}
}
catch (Exception e){
}
}
}
super.onResume();}
Pause:
#Override
public void onPause(){
stopLocationUpdates();
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putLong("timeLeft", timeLeft);
editor.putBoolean("lockedOut", lockedOut);
editor.apply();
if (camera != null) {
camera.release();
camera = null;
}
super.onPause();
}
In use:
//Take picture
camera.startPreview();
camera.takePicture(null, null,
new PhotoHandler(getApplicationContext()));
camera.stopPreview();
camera.release();
Got any ideas what I'm doing wrong? Every time I relaunch the application, it throws an exception saying that the camera is in use, even if I launch the default camera app and close it.
EDIT: The camera is being accessed, but my callback (onPictureTaken in PhotoHandler) is never being called, as if the picture isn't being captured properly.
Turns out this code works. Had to uninstall, restart, and reinstall. Then my onPictureTaken callback wasn't being called. I believe this was because I was calling stopPreview too soon. I moved that to my onPause and took away the release call after the takePicture call. Works fine now
I know it is possible as the camera app that comes with my droid phone does it, but for the life of me, I don't seem to be able to switch cameras on the fly either for video or a standard camera (which leads me to suspect I'm not doing it right!)
Currently, I have an event for the button
btnSwitchCamera.Click += new EventHandler(btnSwitchCamera_Click);
prior to that, I check for the number of cameras - if there is only one camera, the event is not enabled.
The switch code looks like this
private void btnSwitchCamera_Click(object s, EventArgs e)
{
if (isBackCamera == false)
{
try
{
RunOnUiThread(delegate
{
camera.Release();
camera = Android.Hardware.Camera.Open(1);
});
}
catch (Java.Lang.RuntimeException)
{
alertMsg(context, Application.Context.Resources.GetString(Resource.String.videoErrorTitle),
Application.Context.Resources.GetString(Resource.String.videoFailToConnect));
return;
}
isBackCamera = true;
}
else
{
try
{
RunOnUiThread(delegate
{
camera.Release();
camera = Android.Hardware.Camera.Open(0);
});
}
catch (Java.Lang.RuntimeException)
{
alertMsg(context, Application.Context.Resources.GetString(Resource.String.videoErrorTitle),
Application.Context.Resources.GetString(Resource.String.videoFailToConnect));
return;
}
isBackCamera = false;
}
}
If I click the button, the app dies claiming that I cannot connect to the service.
The video record code is nothing special - it's a bog standard set the surface, do the holder, and start/stop recording.
Am I doing this right? From the docs, I need to release the camera then open the camera with the appropriate camera number (Android.Hardware.Camera.NumberOfCameras - 1)
The manifest is correctly set.
Thanks
Paul
I wanted to make use of the zxing library to detect qrcodes in my app. But for the apps viewing purpose, i had to change the custom display orientation to portrait. Hence i had to integrate the whole zxing library into my app and addded camera.setDisplayOrientation(90) to the openDriver() method.
After doing this, the program works, but I get "Runtime exceptions : Fail to connect to camera service" randomly.
public void openDriver(SurfaceHolder holder) throws IOException {
if (camera == null) {
camera = Camera.open();
camera.setDisplayOrientation(90);
if (camera == null) {
throw new IOException();
}
}
camera.setPreviewDisplay(holder);
if (!initialized) {
initialized = true;
configManager.initFromCameraParameters(camera);
}
configManager.setDesiredCameraParameters(camera);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
reverseImage = prefs.getBoolean(PreferencesActivity.KEY_REVERSE_IMAGE, false);
if (prefs.getBoolean(PreferencesActivity.KEY_FRONT_LIGHT, false)) {
FlashlightManager.enableFlashlight();
}
}
public void closeDriver() {
if (camera != null) {
FlashlightManager.disableFlashlight();
camera.release();
camera = null;
framingRect = null;
framingRectInPreview = null;
}
}
/**
* Asks the camera hardware to begin drawing preview frames to the screen.
*/
public void startPreview() {
if (camera != null && !previewing) {
camera.startPreview();
previewing = true;
}
}
/**
* Tells the camera to stop drawing preview frames.
*/
public void stopPreview() {
if (camera != null && previewing) {
if (!useOneShotPreviewCallback) {
camera.setPreviewCallback(null);
}
camera.stopPreview();
previewCallback.setHandler(null, 0);
autoFocusCallback.setHandler(null, 0);
previewing = false;
}
}
I doubt that the orientation change is causing that. I have found you will get that error whenever an activity stops but fails to call Camera.release in their onPause. The result is that the next time you try to do Camera.open you get that runtime error since the driver still considers it open regardless of the app/activity that opened it being gone.
You can easily get this to happen while debugging/testing stuff when something throws an exception and brings the activity down. You need to be very diligent about catching all exceptions and being sure to release the camera before finishing the activity.
BTW, are you finding you need to power cycle the device in order to be able to open the camera again?