user3451660
user3451660

Reputation: 477

Implementing a camera directly in the application

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:

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.

Upvotes: 0

Views: 847

Answers (1)

eugstman
eugstman

Reputation: 1048

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/

Upvotes: 1

Related Questions