启动时,Android相机startPreview失败

时间:2016-03-03 08:46:43

标签: android android-camera surfaceview

我有一个自定义SurfaceView for Camera预览版。当我用它启动一个Activity时,应用程序崩溃了RuntimeException,它表示:startPreview failed和surfaceChanged方法中的Camera Error 1。怎么了?下面是我的表面视图和活动。

public class CameraView extends SurfaceView implements SurfaceHolder.Callback {

    private Path mClipPath;
    private Camera mCamera;
    private Context mContext;
    private SurfaceHolder mHolder;

    public CameraView(Context context) {
        super(context);
        init(context);
    }

    public CameraView(Context context, Camera camera) {
        super(context);
        mCamera = camera;
        mHolder = getHolder();
        mHolder.addCallback(this);
        init(context);
    }

    public CameraView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public CameraView(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
         init(context);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public CameraView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context);
    }

    private void init(Context context) {
        mContext = context;
        WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        Display display = manager.getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
        float radius;
        float center;
        if (display.getRotation() == Surface.ROTATION_0 || display.getRotation() == Surface.ROTATION_180) {
            radius = size.x / 2;
            center = size.x / 2;
        } else {
            radius = size.y / 2;
            center = size.y / 2;
        }
        mClipPath = new Path();
        mClipPath.addCircle(center, center, radius, Path.Direction.CW);
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        canvas.clipPath(mClipPath);
        super.dispatchDraw(canvas);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        if (mHolder.getSurface() == null) {
            return;
        }
        try {
            mCamera.stopPreview();
        } catch (Exception e) {
            e.printStackTrace();
        }
        Camera.Parameters parameters = mCamera.getParameters();
        Display display = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
        if (display.getRotation() == Surface.ROTATION_0) {
            parameters.setPreviewSize(height, width);
            mCamera.setDisplayOrientation(90);
        }
        if (display.getRotation() == Surface.ROTATION_90) {
            parameters.setPreviewSize(width, height);
        }
        if (display.getRotation() == Surface.ROTATION_180) {
            parameters.setPreviewSize(height, width);
        }
        if (display.getRotation() == Surface.ROTATION_270) {
            parameters.setPreviewSize(width, height);
            mCamera.setDisplayOrientation(180);
        }
        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {

    }
}

活动

public class CameraActivity extends AppCompatActivity {

    public static final String EXTRA_PICTURE = "com.rcd.perfecto.extra.PICTURE";

    @Bind(R.id.btn_photo_capture) Button mPhotoCaptureButton;
    @Bind(R.id.fl_camera_preview) FrameLayout mCameraPreviewFrameLayout;
    @Bind(R.id.btn_choose_from_gallery) Button mChooseFromGalleryButton;
    @Bind(R.id.iv_avatar) RoundedImageView mAvatarImageView;

    private Camera mCamera;
    private CameraView mCameraView;
    private boolean mCaptured = false;
    private byte[] mData;

    private Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            mData = data;
        }
    };

    public CameraActivity() {
    }

    @OnClick(R.id.btn_photo_capture)
    void takePicture() {
        mCameraView.setVisibility(View.VISIBLE);
        mAvatarImageView.setVisibility(View.GONE);
        if (!mCaptured) {
            mCamera.takePicture(null, null, mPictureCallback);
            mPhotoCaptureButton.setText(R.string.reshoot);
        }
        else {
            mCamera.startPreview();
            mPhotoCaptureButton.setText(R.string.btn_photo_capture);
        }
        mCaptured = !mCaptured;
    }

    @OnClick(R.id.btn_choose_from_gallery)
    void chooseFromGallery() {
        Intent intent = new Intent();
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(intent, 0);
    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera);
        ButterKnife.bind(this);
        if (checkCameraHardware()) {
            if (Camera.getNumberOfCameras() > 1) {
                mCamera = getCameraInstance(Camera.CameraInfo.CAMERA_FACING_FRONT);
            } else mCamera = getCameraInstance();
        }
        mCameraView = new CameraView(CameraActivity.this, mCamera);
        mCameraPreviewFrameLayout.addView(mCameraView, 0);

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mCamera.release();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
         getMenuInflater().inflate(R.menu.menu_camera, menu);
         return super.onCreateOptionsMenu(menu);
    } 

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.me_done:
                Intent intent = new Intent();
                if (mData != null) {
                    intent.putExtra(EXTRA_PICTURE, mData);
                }
                setResult(RESULT_OK, intent);
                finish();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }

    }

    private static Camera getCameraInstance() {
        Camera c = null;
        try {
            c = Camera.open();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return c;
    }

    private static Camera getCameraInstance(int id) {
         Camera c = null;
         try {
            c = Camera.open(id);
         } catch (Exception e) {
            e.printStackTrace();
         }
         return c;
     }

    private boolean checkCameraHardware() {
        return getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK) {
            Uri imageUri = data.getData();
            try {
                Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), imageUri);
                mCameraView.setVisibility(View.GONE);
                mAvatarImageView.setVisibility(View.VISIBLE);
                mAvatarImageView.setImageBitmap(bitmap);
                mCaptured = true;
                mPhotoCaptureButton.setText(R.string.reshoot);
                ByteArrayOutputStream stream = new ByteArrayOutputStream();
                bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
                mData = stream.toByteArray();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

编辑:添加了完整的堆栈跟踪:

03-03 12:03:28.158 29399-29399/com.rcd.perfecto W/System.err: java.lang.RuntimeException: startPreview failed
03-03 12:03:28.158 29399-29399/com.rcd.perfecto W/System.err:     at android.hardware.Camera.startPreview(Native Method)
03-03 12:03:28.158 29399-29399/com.rcd.perfecto W/System.err:     at com.rcd.perfecto.ui.custom.CameraView.surfaceChanged(CameraView.java:122)
03-03 12:03:28.158 29399-29399/com.rcd.perfecto W/System.err:     at android.view.SurfaceView.updateWindow(SurfaceView.java:594)
03-03 12:03:28.159 29399-29399/com.rcd.perfecto W/System.err:     at android.view.SurfaceView$3.onPreDraw(SurfaceView.java:177)
03-03 12:03:28.159 29399-29399/com.rcd.perfecto W/System.err:     at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:944)
03-03 12:03:28.159 29399-29399/com.rcd.perfecto W/System.err:     at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2055)
03-03 12:03:28.159 29399-29399/com.rcd.perfecto W/System.err:     at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1107)
03-03 12:03:28.159 29399-29399/com.rcd.perfecto W/System.err:     at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6013)
03-03 12:03:28.159 29399-29399/com.rcd.perfecto W/System.err:     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858)
03-03 12:03:28.159 29399-29399/com.rcd.perfecto W/System.err:     at android.view.Choreographer.doCallbacks(Choreographer.java:670)
03-03 12:03:28.159 29399-29399/com.rcd.perfecto W/System.err:     at android.view.Choreographer.doFrame(Choreographer.java:606)
03-03 12:03:28.159 29399-29399/com.rcd.perfecto W/System.err:     at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844)
03-03 12:03:28.159 29399-29399/com.rcd.perfecto W/System.err:     at android.os.Handler.handleCallback(Handler.java:739)
03-03 12:03:28.159 29399-29399/com.rcd.perfecto W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:95)
03-03 12:03:28.159 29399-29399/com.rcd.perfecto W/System.err:     at android.os.Looper.loop(Looper.java:148)
03-03 12:03:28.159 29399-29399/com.rcd.perfecto W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:5417)
03-03 12:03:28.159 29399-29399/com.rcd.perfecto W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
03-03 12:03:28.159 29399-29399/com.rcd.perfecto W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
03-03 12:03:28.159 29399-29399/com.rcd.perfecto W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
03-03 12:03:28.207 29399-29399/com.rcd.perfecto E/Camera: Error 1

1 个答案:

答案 0 :(得分:0)

你不能使用surfaceview的宽度和高度作为参数的输入参数.setPreviewSize(height,width);

因为相机可能不支持宽度和高度。 相反,您应该使用相机支持的宽度和高度。

像这样:



        List<Camera.Size> supportedPreviewSizes = parameters.getSupportedPreviewSizes();
        Camera.Size optimalPreviewSize = getOptimalPreviewSize(supportedPreviewSizes, w, h);
        
        f (optimalPreviewSize != null) {
            parameters.setPreviewSize(optimalPreviewSize.width, optimalPreviewSize.height);
            camera.setParameters(parameters);
        }
&#13;
&#13;
&#13;