简体   繁体   中英

Camera is being used after Camera.release() was called when minimizing app and reopening

I am getting a RuntimeException "Camera is being used after Camera.release() was called", when I minimize the application and then reopen the app. The app doesn't crash, so I am wondering if it is something to be concerned about? If so, how do I resolve this issue? I couldn't find anything useful on the web. Also, when screen rotation is changed, there is no error. I am thinking that is because the camera rotation is handled in the surfaceCreated()...

    05-21 11:09:14.405 15474-15474/? I/zygote64: Late-enabling -Xcheck:jni
05-21 11:09:14.445 15474-15489/? E/zygote64: Failed writing handshake bytes (-1 of 14): Broken pipe
05-21 11:09:14.445 15474-15489/? I/zygote64: Debugger is no longer active
05-21 11:09:14.549 15474-15474/? I/InstantRun: starting instant run server: is main process
05-21 11:09:14.650 15474-15474/? D/TAG: onCreate() called
05-21 11:09:14.651 15474-15474/? D/TAG: onStart() called
05-21 11:09:14.656 15474-15474/? E/libc: Access denied finding property "camera.hal1.packagelist"
05-21 11:09:14.651 15474-15474/? W/ojectLightCycle: type=1400 audit(0.0:211090): avc: denied { read } for name="u:object_r:camera_prop:s0" dev="tmpfs" ino=22601 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:camera_prop:s0 tclass=file permissive=0 ppid=2713 pcomm="main" pgid=2713 pgcomm="main"
05-21 11:09:14.651 15474-15474/? D/TAG: onStart() called
05-21 11:09:14.656 15474-15474/? E/libc: Access denied finding property "camera.hal1.packagelist"
05-21 11:09:14.693 15474-15474/? D/getCameraInstance(): Camera is available
05-21 11:09:14.717 15474-15474/? D/TAG: onResume() called
05-21 11:09:14.728 15474-15586/? D/OpenGLRenderer: HWUI GL Pipeline
05-21 11:09:14.785 15474-15586/? I/Adreno: QUALCOMM build                   : 3953ab1, Ib515ec08c2
    Build Date                       : 09/27/17
    OpenGL ES Shader Compiler Version: EV031.20.00.04
    Local Branch                     : 
    Remote Branch                    : refs/tags/AU_LINUX_ANDROID_LA.UM.6.4.R1.08.00.00.309.032
    Remote Branch                    : NONE
    Reconstruct Branch               : NOTHING
05-21 11:09:14.785 15474-15586/? I/vndksupport: sphal namespace is not configured for this process. Loading /vendor/lib64/hw/gralloc.msm8998.so from the current namespace instead.
05-21 11:09:14.789 15474-15586/? I/Adreno: PFP: 0x005ff087, ME: 0x005ff063
05-21 11:09:14.792 15474-15586/? I/OpenGLRenderer: Initialized EGL, version 1.4
05-21 11:09:14.792 15474-15586/? D/OpenGLRenderer: Swap behavior 2
05-21 11:09:14.800 15474-15474/? D/Picture Size: Supported Size - Width: 5056 Height: 3792
    Supported Size - Width: 5504 Height: 3096
    Supported Size - Width: 4000 Height: 3000
    Supported Size - Width: 4608 Height: 2592
    Supported Size - Width: 3840 Height: 2160
    Supported Size - Width: 3264 Height: 2448
    Supported Size - Width: 2048 Height: 1536
    Supported Size - Width: 1920 Height: 1080
    Supported Size - Width: 1280 Height: 720
    Supported Size - Width: 720 Height: 480
    Supported Size - Width: 640 Height: 480
    Supported Size - Width: 480 Height: 320
    Supported Size - Width: 352 Height: 288
    Supported Size - Width: 320 Height: 240
    Supported Size - Width: 176 Height: 144
    Supported Size set to - Width: 5056 Height: 3792
05-21 11:09:15.050 15474-15586/? I/vndksupport: sphal namespace is not configured for this process. Loading /vendor/lib64/hw/gralloc.msm8998.so from the current namespace instead.
05-21 11:09:30.906 15474-15474/com.example.saili.ProjectLightCycle D/TAG: onPause() called
05-21 11:09:30.940 15474-15474/com.example.saili.ProjectLightCycle D/TAG: onStop() called
05-21 11:09:32.033 15474-15474/com.example.saili.ProjectLightCycle D/TAG: onStart() called
05-21 11:09:32.037 15474-15474/com.example.saili.ProjectLightCycle E/libc: Access denied finding property "camera.hal1.packagelist"
05-21 11:09:32.099 15474-15474/com.example.saili.ProjectLightCycle D/getCameraInstance(): Camera is available
05-21 11:09:32.125 15474-15474/com.example.saili.ProjectLightCycle D/TAG: onResume() called
05-21 11:09:32.146 15474-15474/com.example.saili.ProjectLightCycle E/SurfaceView: Exception configuring surface
    java.lang.RuntimeException: Camera is being used after Camera.release() was called
        at android.hardware.Camera.native_getParameters(Native Method)
        at android.hardware.Camera.getParameters(Camera.java:2027)
        at com.example.saili.ProjectLightCycle.ShowCamera.surfaceCreated(ShowCamera.java:43)
        at android.view.SurfaceView.updateSurface(SurfaceView.java:664)
        at android.view.SurfaceView.setFrame(SurfaceView.java:344)
        at android.view.View.layout(View.java:19587)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:19590)
        at android.view.ViewGroup.layout(ViewGroup.java:6053)
        at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1080)
        at android.view.View.layout(View.java:19590)
        at android.view.ViewGroup.layout(ViewGroup.java:6053)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:19590)
        at android.view.ViewGroup.layout(ViewGroup.java:6053)
        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1791)
        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1635)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1544)
        at android.view.View.layout(View.java:19590)
        at android.view.ViewGroup.layout(ViewGroup.java:6053)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:19590)
        at android.view.ViewGroup.layout(ViewGroup.java:6053)
        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1791)
        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1635)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1544)
        at android.view.View.layout(View.java:19590)
        at android.view.ViewGroup.layout(ViewGroup.java:6053)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at com.android.internal.policy.DecorView.onLayout(DecorView.java:768)
        at android.view.View.layout(View.java:19590)
        at android.view.ViewGroup.layout(ViewGroup.java:6053)
        at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2488)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2204)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1390)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6754)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:966)
        at android.view.Choreographer.doCallbacks(Choreographer.java:778)
        at android.view.Choreographer.doFrame(Choreographer.java:713)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:952)
        at android.os.Handler.handleCallback(Handler.java:789)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:251)
        at android.app.ActivityThread.main(ActivityThread.java:6572)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
05-21 11:09:32.168 15474-15474/com.example.saili.ProjectLightCycle D/Picture Size: Supported Size - Width: 5056 Height: 3792
    Supported Size - Width: 5504 Height: 3096
    Supported Size - Width: 4000 Height: 3000
    Supported Size - Width: 4608 Height: 2592
    Supported Size - Width: 3840 Height: 2160
    Supported Size - Width: 3264 Height: 2448
    Supported Size - Width: 2048 Height: 1536
    Supported Size - Width: 1920 Height: 1080
    Supported Size - Width: 1280 Height: 720
    Supported Size - Width: 720 Height: 480
    Supported Size - Width: 640 Height: 480
    Supported Size - Width: 480 Height: 320
    Supported Size - Width: 352 Height: 288
    Supported Size - Width: 320 Height: 240
05-21 11:09:32.169 15474-15474/com.example.saili.ProjectLightCycle D/Picture Size: Supported Size - Width: 176 Height: 144
    Supported Size set to - Width: 5056 Height: 3792
05-21 11:09:38.611 15474-15474/com.example.saili.ProjectLightCycle D/TAG: onPause() called
05-21 11:09:38.640 15474-15474/com.example.saili.ProjectLightCycle D/TAG: onStop() called
05-21 11:09:39.737 15474-15474/com.example.saili.ProjectLightCycle D/TAG: onDestroy() called

Here is my main activity

package com.example.saili.ProjectLightCycle;


import android.content.Context;
import android.content.Intent;
import android.hardware.Camera;
import android.net.Uri;
import android.os.Environment;
import android.support.v4.view.GestureDetectorCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.Toast;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import static android.provider.MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE;

public class MainActivity extends AppCompatActivity implements GestureDetector.OnGestureListener
{
    Camera camera;
    FrameLayout frameLayout;
    ShowCamera showCamera;
    String toastString;
    private GestureDetectorCompat detector;


    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d("TAG", "onCreate() called");


    }

    @Override
    protected void onStart()
    {
        super.onStart();
        Log.d("TAG", "onStart() called");

        frameLayout = (FrameLayout) findViewById(R.id.frameLayout);

        // open the camera
        camera = getCameraInstance();
        // create a showCamera object
        showCamera = new ShowCamera(this, camera);
        // add the view to the frameLayout to diplay the camera's view on the screen
        frameLayout.addView(showCamera);

        // Auto focus the camera preview
        Camera.Parameters parameters = camera.getParameters();
        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
        camera.setParameters(parameters);

        detector = new GestureDetectorCompat(this, this);
    }

    @Override
    protected void onResume()
    {
        super.onResume();
        Log.d("TAG", "onResume() called");
    }

    @Override
    protected void onPause()
    {
        camera.setPreviewCallback(null);
        releaseCamera();

        super.onPause();
        Log.d("TAG", "onPause() called");
    }

    @Override
    protected void onStop()
    {
        super.onStop();
        Log.d("TAG", "onStop() called");
    }

    @Override
    protected void onDestroy()
    {
        super.onDestroy();
        Log.d("TAG", "onDestroy() called");
    }

    Camera.ShutterCallback mShutterCallback = new Camera.ShutterCallback()
    {
        @Override
        public void onShutter()
        {
            toastString = "Picture Captured!";
            toast(toastString);
        }
    };

    // saves the image to the external storage
    Camera.PictureCallback mPictureCallback = new Camera.PictureCallback()
    {


        @Override
      public void onPictureTaken(byte[] data, Camera camera)
      {

          File picture_file = getOutputMediaFile(MEDIA_TYPE_IMAGE);

          if (picture_file == null)
          {
              Log.d("MainActivity", "Picture_file == null");

              return;
          }
          else
          {
              Log.d("MainActivity", "Picture_file != null");

              try
              {
                  FileOutputStream fileOutputStream = new FileOutputStream(picture_file);
                  fileOutputStream.write(data);

                  Log.d("MainActivity", "Data written!");

                  fileOutputStream.close();

                  Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
                  intent.setData(Uri.fromFile(picture_file));
                  sendBroadcast(intent);

                  // this commented out method would resume camera live preview
                  //camera.startPreview();
              }
              catch (FileNotFoundException e)
              {
                  Log.d("MainActivity", "File not Found");
              }
              catch (IOException e)
              {
                  Log.d("MainActivity", "Write IOException thrown!");

                  e.printStackTrace();
              }

          }
      }
    };

    private File getOutputMediaFile(int type)
    {
        String state = Environment.getExternalStorageState();
        if (!state.equals(Environment.MEDIA_MOUNTED))
        {
            Log.d("MainActivity", "Media Not Mounted!");

            return null;
        }
        else
        {
            Log.d("MainActivity", "Media Mounted!");

            File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "WhatsThisApp");

            String picDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + File.separator + "WhatsThisApp";
            Log.d("MainActivity", picDir);

            //create the storage directory if it does not exist
            if (!mediaStorageDir.exists())
            {
                if (!mediaStorageDir.mkdirs())
                {
                    Log.d("MainActivity", "Failed to create directory");

                    return null;
                }

            }

            // create a media file name
            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
            File mediaFile;
            if (type == MEDIA_TYPE_IMAGE)
            {
                mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg");

                Log.d("MainActivity", "File name created!");
            }
            else
            {
                Log.d("MainActivity", "File name not created!");

                return null;
            }
            return mediaFile;
        }
    }

    public void captureImage(View v)
    {
        if(camera != null)
        {
            camera.takePicture(mShutterCallback,null,mPictureCallback);

            Log.d("MainActivity", "Picture Taken!");
        }
    }

    public static Camera getCameraInstance()
    {
        Camera c = null;
        try
        {
            c = Camera.open(); // Camera.open() method will open the first back facing camera on the device
                                // to access a different camera use Camera.open(int)
            Log.d("getCameraInstance()", "Camera is available");
        }
        catch (Exception e)
        {
            // Camera is not available (in use or does not exist)
            Log.d("getCameraInstance()", "Camera is not available (in use or does not exist)");
        }
        return c;
    }

    // toast method
    public void toast(String toastString)
    {
        Context context = getApplicationContext();
        CharSequence text = toastString;
        int duration = Toast.LENGTH_LONG;

        Toast toast = Toast.makeText(context, text, duration);
        toast.show();
    }

    // swip funtionality
    @Override
    public boolean onDown(MotionEvent e)
    {
        return false;
    }

    @Override
    public void onShowPress(MotionEvent e)
    {

    }

    @Override
    public boolean onSingleTapUp(MotionEvent e)
    {
        return false;
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
    {
        return false;
    }

    @Override
    public void onLongPress(MotionEvent e)
    {

    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
    {
        //Intent intent = new Intent(this, Main2Activity.class);
       // startActivity(intent);
        return true; // which says that I handled this event
    }

    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        detector.onTouchEvent(event);
        return super.onTouchEvent(event);
    }

    private void releaseCamera()
    {
        if (camera != null)
        {
            camera.release();
            camera = null;
        }
    }
}

Here is my SHowCamera class

package com.example.saili.ProjectLightCycle;

import android.content.Context;
import android.content.res.Configuration;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.hardware.Camera;

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

public class ShowCamera extends SurfaceView implements SurfaceHolder.Callback
{
    Camera camera;
    SurfaceHolder holder;

    public ShowCamera(Context context, Camera camera)
    {
        super(context);
        this.camera = camera;
        holder = getHolder();
        holder.addCallback(this);

    }


    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
    {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder)
    {

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder)
    {
        Camera.Parameters parameters = camera.getParameters();

        // finds the supported picture sizes
        List<Camera.Size> supportedPictureSizes = parameters.getSupportedPictureSizes();
        Camera.Size mSize = null;

        for (Camera.Size size : supportedPictureSizes)
        {
            mSize = size;
            Log.d("Picture Size", "Supported Size - Width: " + mSize.width + " Height: " + mSize.height);
        }

        // sets the picture size to the first available picture size higher than width 720 and height 480
        for (Camera.Size size : supportedPictureSizes)
        {
            mSize = size;
            if (mSize.width > 720 && mSize.height > 480)
            {
                break;
            }
        }
        Log.d("Picture Size", "Supported Size set to - Width: " + mSize.width + " Height: " + mSize.height);

        if(this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE)
        {
            parameters.set("orientation", "portrait");
            camera.setDisplayOrientation(90);
            parameters.setRotation(90);
        }
        else
        {
            parameters.set("Orientation", "landscape");
            camera.setDisplayOrientation(0);
            parameters.setRotation(0);
        }

        parameters.setPictureSize(mSize.width, mSize.height);
        camera.setParameters(parameters);
        try
        {
            camera.setPreviewDisplay(holder);

            camera.startPreview();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }
}

According to Activity Reference when another activity comes into foreground the onPause method will be called. After it when user returns to your activity the onResume method will be called but not the onCreate . This way you should setup the camera on onResume instead of onCreate .

Acquire/Release of any kind of resources should always be symmetric. If acquire at onStart then realease at onStop . If acquire at onResume then release at onPause .

Hope it works!

活动的生命周期

So for the original problem that I posted about, RuntimeException "Camera is being used after Camera.release() was called", the solution was spelled out in the Logcat logs (see logs above). I happened to notice that I was getting that error after onStart() and onResume() was already called. I said well, of course, the camera is being used after Camera.release was called! So, I just needed to un-call the Camera.release for onResume().

Here is what I ended up doing and as of right now I no longer get the error when I minimize the app and unminimize it. There may be another or better way to do accomplish this, but this is working so far for me.

@Override
protected void onResume()
{
    super.onResume();
    if (camera == null)
    {
        showCameraMethod();
    }
    detector = new GestureDetectorCompat(this, this);
    Log.d("TAG", "onResume() called");
}

@Override
protected void onPause()
{
    super.onPause();
    if (camera != null)
    {
        showCamera.getHolder().removeCallback(showCamera);
        camera.release(); // release the camera for other applications
        camera = null;
    }
    Log.d("TAG", "onPause() called");
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM