没有任何充分理由无法连接到摄像头服务(RuntimeException)

时间:2015-09-03 10:17:16

标签: java android camera android-camera runtimeexception

所以我的Manifest.xml是正确的:

<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus"/>
<application>
...

我还使用此功能在onPauseonDestroy功能中释放相机:

private void releaseCamera() {
    // stop and release camera
    if (mCamera != null) {
        mCamera.stopPreview();
        mCamera.release();
        mCamera = null;
    }
    //mPreview instance of CameraPreview (referenced below)
    if (mPreview != null) {
        mPreview.setCamera(null);
    }
}

我在mCamera = Camera.open();期间只拨打onResume一次。

即使我完成了我在Stack Overflow和其他来源上找到的每个示例所指定的所有内容,Camera.open() 偶尔会失败。

一些用例:

  • 启用WiFi时打开相机活动(相机工作
  • 在没有网络连接的情况下打开相机活动(相机失败//Bizarre
  • 在捕获RuntimeException,然后调用mCamera.takePicture()时,活动崩溃并重新加载。 (相机工作

所以我完全被难过......任何想法都会非常感激:D

根据要求,找到以下相关代码:

CameraPreiview

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
    private SurfaceHolder mHolder;
    private Camera mCamera;

    public CameraPreview(Context context, Camera camera) {
        super(context);
        mCamera = camera;
        mHolder = getHolder();
        mHolder.addCallback(this);
        // deprecated setting, but required on Android versions prior to 3.0
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public void surfaceCreated(SurfaceHolder holder) {
        try {
            // create the surface and start camera preview
            if (mCamera != null) {
                mCamera.setPreviewDisplay(holder);
                mCamera.startPreview();
            }
        } catch (IOException e) {
            Log.d(VIEW_LOG_TAG, "Error setting camera preview: " + e.getMessage());
        }
    }

    public void refreshCamera(Camera camera) {
        if (mHolder.getSurface() == null) {
            // preview surface does not exist
            return;
        }
        // stop preview before making changes
        try {
            mCamera.stopPreview();
        } catch (Exception e) {
            // ignore: tried to stop a non-existent preview
        }
        // set preview size and make any resize, rotate or
        // reformatting changes here
        // start preview with new settings
        setCamera(camera);
        try {
            mCamera.setPreviewDisplay(mHolder);
            mCamera.startPreview();
        } catch (Exception e) {
            Log.d(VIEW_LOG_TAG, "Error starting camera preview: " + e.getMessage());
        }
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        // If your preview can change or rotate, take care of those events here.
        // Make sure to stop the preview before resizing or reformatting it.
        refreshCamera(mCamera);
    }

    public void setCamera(Camera camera) {
        //method to set a camera instance
        mCamera = camera;
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.release();
        }

    }
}

SampleActivity

public class CameraActivity extends Activity {

    private static final String TAG = "CameraActivity";

    private Camera mCamera;
    private CameraPreview mPreview;
    private Camera.PictureCallback mPicture;
    private ImageButton capture;
    private Context myContext;
    private LinearLayout cameraPreview;

    // Required to remove the camera if onPause did not
    @Override
    public void onDestroy() {
        releaseCamera();
        super.onDestroy();
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera_test);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        myContext = this;
        initialize();
    }


    //Code to find the id for the traditional back facing camera
    private int findBackFacingCamera() {
        int cameraId = -1;
        //Search for the back facing camera
        //get the number of cameras
        int numberOfCameras = Camera.getNumberOfCameras();
        //for every camera check
        for (int i = 0; i < numberOfCameras; i++) {
            Camera.CameraInfo info = new Camera.CameraInfo();
            Camera.getCameraInfo(i, info);
            if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
                cameraId = i;
                cameraFront = false;
                break;
            }
        }
        return cameraId;
    }

    @Override
    public void onResume() {
        super.onResume();
        //If there is no camera on the device, inform the user.
        if (!hasCamera(myContext)) {
            Toast toast = Toast.makeText(myContext, "Sorry, your phone does not have a camera!", Toast.LENGTH_LONG);
            toast.show();
        }
        //release the camera if it's in use.
        releaseCamera();
        if (mCamera == null) {
            //if the back facing camera does not exist
            if (findBackFacingCamera() < 0) {
                Toast.makeText(this, "No back facing camera found.", Toast.LENGTH_LONG).show();
            } else {
                try {
                    //Open the back facing camera, note that Camera.open() gives the same error.
                    mCamera = Camera.open(findBackFacingCamera());
                    mCamera.setDisplayOrientation(90);  //Show in Portrait
                    mPicture = getPictureCallback();
                    mPreview.refreshCamera(mCamera);
                } catch (RuntimeException e) {
                    e.printStackTrace();
                    Toast.makeText(this, "Could not connect to camera.", Toast.LENGTH_LONG).show();
                }
            }
        }
    }


    public void initialize() {
        cameraPreview = (LinearLayout) findViewById(R.id.camera_preview);
        mPreview = new CameraPreview(myContext, mCamera);
        cameraPreview.addView(mPreview);

        capture = (ImageButton) findViewById(R.id.button_capture);
        capture.setOnClickListener(captureListener);
    }


    @Override
    protected void onPause() {
        super.onPause();
        //when on Pause, release camera in order to be used from other applications
        releaseCamera();
    }


    private void captureComplete() {
        //...
    }

    private Camera.PictureCallback getPictureCallback() {
        Camera.PictureCallback picture = new Camera.PictureCallback() {

            @Override
            public void onPictureTaken(byte[] data, Camera camera) {
                //make a new picture file
                mFile = ImageUtility.getOutputMediaFile(ImageUtility.MEDIA_TYPE_IMAGE);
                Log.i(TAG, (mFile == null) + ": ");
                if (mFile == null) {
                    return;
                }

                mPreview.refreshCamera(mCamera);
                mBackgroundHandler.post(new ImageUtility.ImageSaver(getApplicationContext(), data, mFile, new Callable() {
                    @Override
                    public Object call() throws Exception {
                        captureComplete();
                        return null;
                    }
                }));
            }
        };
        return picture;
    }

    View.OnClickListener captureListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (mCamera != null) {
                mCamera.autoFocus(new Camera.AutoFocusCallback() {
                    @Override
                    public void onAutoFocus(boolean success, Camera camera) {
                        mPicture = getPictureCallback();
                        mPreview.refreshCamera(camera);
                        camera.takePicture(null, null, mPicture);
                    }
                });
            } else {
                throw new NullPointerException();
            }
        }
    };

    private void releaseCamera() {
        // stop and release camera
        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
        }
        if (mPreview != null) {
            mPreview.setCamera(null);
        }
    }
}

1 个答案:

答案 0 :(得分:0)

您可以做一些更改,因为我自3个月以来一直在Camera api工作..

CameraPreview构造函数中,添加此行

    if(Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) // add this
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

surfaceDestroyed()中的CameraPreview方法中,您应该在释放相机资源后立即删除回调:

this.getHolder().removeCallback(this);

除了改变上述内容之外,由于您使用了自动对焦和其他功能,我无法从您的CameraActivity中获得更多信息....我使用FrameLayout作为运行预览的容器。