0

I am implementing a camera function directly in an app, as I do not want to use Intent to open the default camera application. I have followed the code provided here:

The app crashes as soon as the photo gets taken, with the following error message:

Java.Lang.RuntimeException: Fail to connect to camera service

Here is how I set it up. I have ommited the unneccessary code.

namespace camera_test
    {
        [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true, Icon = "@drawable/icon")]
        public class MainActivity : Android.Support.V7.App.AppCompatActivity, Android.Hardware.Camera.IPictureCallback, Android.Hardware.Camera.IPreviewCallback,
            Android.Hardware.Camera.IShutterCallback, ISurfaceHolderCallback
        {
    static Android.Hardware.Camera camera = null;
    Button btnStart;
    Button btnEnd;

    protected override void OnCreate(Bundle savedInstanceState)
    { 
        base.OnCreate(savedInstanceState);

        // Set our view from the "main" layout resource

        SetContentView(Resource.Layout.activity_main);

        SurfaceView surface = (SurfaceView)FindViewById(Resource.Id.surface);
        var holder = surface.Holder;
        holder.AddCallback(this);
        holder.SetType(Android.Views.SurfaceType.PushBuffers);

        btnStart = FindViewById<Button>(Resource.Id.buttonStart);
        btnEnd = FindViewById<Button>(Resource.Id.buttonEnd);

        btnStart.Click += BtnStart_Click;
        btnEnd.Click += BtnEnd_Click;

        StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder(); StrictMode.SetVmPolicy(builder.Build());

    }


    private void BtnStart_Click(object sender, EventArgs e)
    {
        camera.StartPreview();



    private void BtnEnd_Click(object sender, EventArgs e)
    {

        Android.Hardware.Camera.Parameters p = camera.GetParameters();
        p.PictureFormat = Android.Graphics.ImageFormatType.Jpeg;
        camera.SetParameters(p);
        camera.TakePicture(this, this, this);
        StartActivity(typeof(MainActivity));

    }
    void Android.Hardware.Camera.IPictureCallback.OnPictureTaken(byte[] data, Android.Hardware.Camera camera)
    {
        Java.IO.FileOutputStream outStream = null;
        Java.IO.File dataDir = Android.OS.Environment.ExternalStorageDirectory;
        DateTime DT = DateTime.Now;
        String DateTimeStamp = DT.Year.ToString("D4") + "-" + DT.Month.ToString("D2") + "-" + DT.Day.ToString("D2") + "-" + DT.Hour.ToString("D2") + DT.Minute.ToString("D2") + DT.Second.ToString("D2");
        String PictureFilename = "Photo-" + DateTimeStamp + ".jpg";

        if (data != null)
        {
            try
            {
                outStream = new Java.IO.FileOutputStream(dataDir + "/" + PictureFilename);
                outStream.Write(data);
                outStream.Close();
            }
            catch (FileNotFoundException e)
            {
                System.Console.Out.WriteLine(e.Message);
            }
            catch (IOException ie)
            {
                System.Console.Out.WriteLine(ie.Message);
            }
        }
    }

    void Android.Hardware.Camera.IPreviewCallback.OnPreviewFrame(byte[] b, Android.Hardware.Camera c)
    {

    }

    void Android.Hardware.Camera.IShutterCallback.OnShutter()
    {

    }


    public void SurfaceCreated(ISurfaceHolder holder)
    {


        try
        {
            camera = Android.Hardware.Camera.Open();
            Android.Hardware.Camera.Parameters p = camera.GetParameters();
            p.PictureFormat = Android.Graphics.ImageFormatType.Jpeg;
            camera.SetParameters(p);
            camera.SetPreviewCallback(this);
            camera.Lock();
            camera.SetPreviewDisplay(holder);
            // camera.StartPreview();
        }
        catch (IOException e)
        {
        }
    }

    public void SurfaceDestroyed(ISurfaceHolder holder)
    {

        camera.Unlock();
        camera.StopPreview();
        camera.SetPreviewCallback(null);
        camera.Release();
        camera = null;
    }

    public void SurfaceChanged(ISurfaceHolder holder, Android.Graphics.Format f, int i, int j)
    {
    }
}

}

I am guessing it has something to do with the way in which the camera is opened and closed, but I can't figure out how to solve this problem. Note that the start button correctly starts the camera viewer. It is only when the end button is clicked does the app crash. Any help or suggestions would be appreciated. Also, I know that camera has been depreciated. Thanks.

UPDATE:

The error occurs when:

  • the device changes orientation

  • or when I call this line: StartActivity(typeof(MainActivity));.

I.e, the error occurs when the acitvity gets restarted (I think that if the orientation changes then it restarts the activity as well). I have no idea how else to restart my activity because I need to. Interestingly, if I switch to a different activity then switch back to my main activity that has the camera function, the error does not occure. I am very puzzled.

user3451660
  • 447
  • 8
  • 17
  • Have you declared the permissions in the manifest?. Also if your os version is 6.0 or later version then you may have to implement the runtime permission model. – Sunil Sunny Sep 19 '18 at 10:09
  • Yes I have declared the permissions. If it was a permision error, I wouldn't be able to view the camera (it shows correclty in my surface view). I have verified that I have access to external storage (read and write) and the camera. – user3451660 Sep 19 '18 at 10:14
  • I was talking about the read and write permissions forgot to mention that. Check if those permissions are toggled on or off in the apps permission list in the settings page. – Sunil Sunny Sep 19 '18 at 10:20
  • Yes I definitly have read and write permissions . – user3451660 Sep 19 '18 at 10:25
  • Please check out [this SO post](https://stackoverflow.com/a/33798448/2590375) - is this a duplicate? – nilsK Sep 19 '18 at 10:55
  • No, my error is not caused by permission issues. I can take photos and the photos get saved, my error occurs after it has already been saved. – user3451660 Sep 19 '18 at 11:04

1 Answers1

1

Is there a reason why you use the deprecated camera api?

You should use camera2: https://developer.android.com/reference/android/hardware/camera2/package-summary

Xamarin also provides a basic example for this: https://developer.xamarin.com/samples/monodroid/android5.0/Camera2Basic/

eugstman
  • 978
  • 2
  • 15
  • 18