【问题标题】:Camera is being used after Camera.release was called android在 Camera.release 被称为 android 之后正在使用相机
【发布时间】:2016-07-02 12:04:21
【问题描述】:

我知道有一些与此相关的类似主题,但我无法解决我的问题。无论如何,我正在尝试制作一些带有“闪光灯”的前置摄像头,我在整个活动中只调用一次Camera.release,当时surfaceDestroyed()。所以这是我的 MainActivity:

@SuppressWarnings("deprecation")
public class MainActivity extends AppCompatActivity {
    private Camera mCamera = null;
    private CameraPreview mCameraView = null;
    private int cameraId = 0;

    private void addView() {
        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 {
                    mCamera = Camera.open(cameraId);
                } catch (Exception e) {
                    Log.d("ERROR", "Failed to get camera: " + e.getMessage());
                }
            }
        }
        if (mCamera != null) {
            mCameraView = new CameraPreview(this, mCamera);//create a SurfaceView to show camera data
            FrameLayout camera_view = (FrameLayout) findViewById(R.id.camera_view);
            camera_view.addView(mCameraView);//add the SurfaceView to the layout
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        addView();
        ImageButton imgCapture = (ImageButton) findViewById(R.id.imgCapture);
        imgCapture.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                WindowManager.LayoutParams layout = getWindow().getAttributes();
                layout.screenBrightness = 1F;
                getWindow().setAttributes(layout);
                setContentView(R.layout.whitescreen);
                new CountDownTimer(3000, 1000) {
                    public void onTick(long millisUntilFinished) {
                    }
                    public void onFinish() {
                        if (CameraPreview.safeToTakePicture) {
                            CameraPreview.safeToTakePicture = false;
                            mCamera.takePicture(null, null,
                                    new PhotoHandler(getApplicationContext()));
                        }
                            setContentView(R.layout.activity_main);
                        addView();
                    }
                }.start();
            }
        });
    }

    private int findFrontFacingCamera() {
        int cameraId = -1;
        // Search for the front facing camera
        int numberOfCameras = Camera.getNumberOfCameras();
        for (int i = 0; i < numberOfCameras; i++) {
            Camera.CameraInfo info = new Camera.CameraInfo();
            Camera.getCameraInfo(i, info);
            if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                Log.d("Camera", "Camera found");
                cameraId = i;
                break;
            }
        }
        return cameraId;
    }

}

当按下捕获按钮时,我将布局切换为空布局(白色布局),等待 3 秒拍照,然后再次添加相机视图,这是我的 CameraPreview 类:

@SuppressWarnings("deprecation")
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
    private SurfaceHolder mHolder;
    private Camera mCamera;
    public static boolean safeToTakePicture = false;

    public CameraPreview(Context context, Camera camera) {
        super(context);
        mCamera = camera;
        mCamera.setDisplayOrientation(90);
        mHolder = getHolder();
        mHolder.addCallback(this);
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_NORMAL);
    }

    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {
        try {
            mCamera.setPreviewDisplay(surfaceHolder);
            mCamera.startPreview();
        } catch (IOException e) {
            Log.d("ERROR", "Camera error on surfaceCreated " + e.getMessage());
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i2, int i3) {
        if (mHolder.getSurface() == null)
            return;
        try {
            mCamera.stopPreview();
        } catch (Exception e) {
            Log.d("ERROR", "Trying the camera and it's not running");
        }
        try {
            mCamera.setPreviewDisplay(mHolder);
            mCamera.startPreview();
            safeToTakePicture = true;
        } catch (IOException e) {
            Log.d("ERROR", "Camera error on surfaceChanged " + e.getMessage());
        }

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        mCamera.stopPreview();
        mCamera.release();
    }
}

我多次收到错误Camera is being used after Camera.release was called,例如拍照时:

07-02 14:49:35.561 19017-19017/davidandguy.com.selfielightcamera E/AndroidRuntime: FATAL EXCEPTION: main
                                                                                   Process: davidandguy.com.selfielightcamera, PID: 19017
                                                                                   java.lang.RuntimeException: Camera is being used after Camera.release() was called
                                                                                       at android.hardware.Camera.native_takePicture(Native Method)
                                                                                       at android.hardware.Camera.takePicture(Camera.java:1523)
                                                                                       at android.hardware.Camera.takePicture(Camera.java:1468)
                                                                                       at davidandguy.com.selfielightcamera.MainActivity$1$1.onFinish(MainActivity.java:65)
                                                                                       at android.os.CountDownTimer$1.handleMessage(CountDownTimer.java:127)
                                                                                       at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                                       at android.os.Looper.loop(Looper.java:158)
                                                                                       at android.app.ActivityThread.main(ActivityThread.java:7224)
                                                                                       at java.lang.reflect.Method.invoke(Native Method)
                                                                                       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
                                                                                       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

或者即使在调用onResume() 时,例如,最小化活动然后再次运行。我知道我需要放在某个地方 onPause()onResume() 但我不知道在哪里/如何实现它。谢谢

【问题讨论】:

    标签: android


    【解决方案1】:

    这真的是迟到了,但是当我在一分钟前设法解决了我的一个类似问题时,我想我会为你自己和其他任何可能正在拼命搜索 Stack 的人的利益做出贡献。

    我在这里看不到你的生命周期代码,但是这对我有用,在我的情况下,surfaceDestroyed 是空的

    首先是cameraPreview

    public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) {
    try {
        this.mCamera.setPreviewDisplay(surfaceHolder);
        this.mCamera.startPreview();
    } catch (Exception e) {
    }
    }
    
    
    public void surfaceCreated(SurfaceHolder surfaceHolder) {
    try {
        //TODO we need this here too because on SurfaceCreated we always need to open the camera, in case its released
    
        this.mCamera.setPreviewDisplay(surfaceHolder);
        this.mCamera.setDisplayOrientation(90);
        //this.mCamera.startPreview();
    } catch (IOException e) {
    }
    }
    

    接下来,CameraActivity

    @Override
    public void onResume() {
        super.onResume();
       try{
           mCamera = openFrontFacingCameraGingerbread();
          // Add to Framelayout
           this.mCameraPreview = new CameraPreview(this, this.mCamera);
            mImage.removeAllViews();
           this.mImage.addView(this.mCameraPreview);
    
       }catch (RuntimeException ex){
    
        }
    
    
    
    }
    
    
    @Override
    public void onPause() {
        super.onPause();
        captureButton.setText("Begin Capture");
        if(CameraActivity.this.timer !=null) {
            CameraActivity.this.timer.cancel();
            CameraActivity.this.timer.purge();
            CameraActivity.this.timer = null;
        }
        if (mCamera != null) {
            mCamera.setPreviewCallback(null);
            mCameraPreview.getHolder().removeCallback(mCameraPreview);
            mCamera.release();
            mCamera = null;
        }
    
    
    }
    
    
    @Override
    protected void onDestroy(){
        super.onDestroy();
        releaseCameraAndPreview();
    }
    
    private void releaseCameraAndPreview() {
    
        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
        }
        if(mCameraPreview != null){
            mCameraPreview.destroyDrawingCache();
            mCameraPreview.mCamera = null;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-09
      • 2013-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多