1

我正在 Android 中实现自定义摄像头。所有事情都以正确的方式进行,但是当我更改设备的方向时,我的应用程序 Force 关闭并给出错误:

08-29 10:50:31.368: D/AndroidRuntime(2099): Shutting down VM
08-29 10:50:31.368: W/dalvikvm(2099): threadid=1: thread exiting with uncaught exception (group=0x40a13300)
08-29 10:50:31.607: E/AndroidRuntime(2099): FATAL EXCEPTION: main
08-29 10:50:31.607: E/AndroidRuntime(2099):
08-29 10:50:31.607: E/AndroidRuntime(2099):     at com.example.customcamera.CameraPreview.surfaceCreated(CameraPreview.java:37)
08-29 10:50:31.607: E/AndroidRuntime(2099):     at android.view.SurfaceView.updateWindow(SurfaceView.java:543)
08-29 10:50:31.607: E/AndroidRuntime(2099):     at android.view.SurfaceView.access$000(SurfaceView.java:81)
08-29 10:50:31.607: E/AndroidRuntime(2099):     at android.view.SurfaceView$3.onPreDraw(SurfaceView.java:169)
08-29 10:50:31.607: E/AndroidRuntime(2099):     at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:671)
08-29 10:50:31.607: E/AndroidRuntime(2099):     at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1820)
08-29 10:50:31.607: E/AndroidRuntime(2099):     at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1000)
08-29 10:50:31.607: E/AndroidRuntime(2099):     at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4214)
08-29 10:50:31.607: E/AndroidRuntime(2099):     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
08-29 10:50:31.607: E/AndroidRuntime(2099):     at android.view.Choreographer.doCallbacks(Choreographer.java:555)

我的 CameraPreview 代码是:-

/** A basic Camera preview class */
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
    private SurfaceHolder mHolder;
    private Camera mCamera;
    private Size mPreviewSize; 



public CameraPreview(Context context, Camera camera) {
    super(context);
    mCamera = camera;

    // Install a SurfaceHolder.Callback so we get notified when the
    // underlying surface is created and destroyed.
    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) {
    // The Surface has been created, now tell the camera where to draw the preview.
    try {
        mCamera.setPreviewDisplay(holder);
        //mCamera.startPreview();
    } catch (IOException e) {
       // Log.d(TAG, "Error setting camera preview: " + e.getMessage());
    }
}

public void surfaceDestroyed(SurfaceHolder holder) {
    // empty. Take care of releasing the Camera preview in your activity.
}

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {

     Log.d("Function", "surfaceChanged iniciado");
    if (mHolder.getSurface() == null){
      // preview surface does not exist
      return;
    }

    // stop preview before making changes
    try {
        if(mCamera!=null){

        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

    try {
         if(mCamera!=null){
    //mCamera.setDisplayOrientation(90);




             DVCameraActivity a=new DVCameraActivity();





                if(a.display.getRotation() == Surface.ROTATION_0)
                {

                    mCamera.setDisplayOrientation(90);
                }

                if(a.display.getRotation() == Surface.ROTATION_90)
                {
                    //parameters.setPreviewSize(width, height);                           
                }

                if(a.display.getRotation() == Surface.ROTATION_180)
                {
                   // parameters.setPreviewSize(height, width);               
                }

                if(a.display.getRotation() == Surface.ROTATION_270)
                {
                    //parameters.setPreviewSize(width, height);
                    mCamera.setDisplayOrientation(180);
                }




        Camera.Parameters parameters = mCamera.getParameters();



    Camera.Size size = getBestPreviewSize(w, h);
    parameters.setPreviewSize(size.width, size.height);
    mCamera.setParameters(parameters);
    mCamera.startPreview();

         }

    } catch (Exception e){
       // Log.d(TAG, "Error starting camera preview: " + e.getMessage());
    }
}






private Camera.Size getBestPreviewSize(int width, int height)
{
        Camera.Size result=null;    
        Camera.Parameters p = mCamera.getParameters();
        for (Camera.Size size : p.getSupportedPreviewSizes()) {
            if (size.width<=width && size.height<=height) {
                if (result==null) {
                    result=size;
                } else {
                    int resultArea=result.width*result.height;
                    int newArea=size.width*size.height;

                    if (newArea>resultArea) {
                        result=size;
                    }
                }
            }
        }
    return result;

}


public static void setCameraDisplayOrientation(Activity activity,
        int cameraId, android.hardware.Camera camera) {
  android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
  android.hardware.Camera.getCameraInfo(cameraId, info);
  int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
  int degrees = 0;
  switch (rotation) {
        case Surface.ROTATION_0: degrees = 0; break;
        case Surface.ROTATION_90: degrees = 90; break;
        case Surface.ROTATION_180: degrees = 180; break;
        case Surface.ROTATION_270: degrees = 270; break;
  }

  int result;
  if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
      result = (info.orientation + degrees) % 360;
      result = (360 - result) % 360;  // compensate the mirror
  } else {  // back-facing
      result = (info.orientation - degrees + 360) % 360;
  }
  camera.setDisplayOrientation(result);
  }


}

我的主要活动是:-

   public class DVCameraActivity extends Activity {
 private Camera mCamera;
    private CameraPreview mCameraPreview;
    public static final int MEDIA_TYPE_IMAGE = 1;

    Display display;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dvcamera);

     display  = getWindowManager().getDefaultDisplay();


        mCamera = getCameraInstance();
        mCameraPreview = new CameraPreview(this, mCamera);



        FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
        preview.addView(mCameraPreview);


      //Adding listener
        Button captureButton = (Button) findViewById(R.id.button_capture);
        captureButton.setOnClickListener(
                new View.OnClickListener() {

                    @Override
                    public void onClick(View v) {
                        mCamera.takePicture(null, null, mPicture);

                    }
                });

    }

    /**
     * Helper method to access the camera returns null if
     * it cannot get the camera or does not exist
     * @return
     */
    private Camera getCameraInstance() {
        Camera camera = null;

        try {
            camera = Camera.open();
        } catch (Exception e) {
            // cannot get camera or does not exist
        }
        return camera;
    }


    PictureCallback mPicture = new PictureCallback() {

        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
             File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
                if (pictureFile == null){
                    return;
                }

                try {
                    FileOutputStream fos = new FileOutputStream(pictureFile);
                    fos.write(data);
                    fos.close();
                } catch (FileNotFoundException e) {

                } catch (IOException e) {

                }

        }

    };



    /** Create a File for saving the image */
    private static File getOutputMediaFile(int type){

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

        if (! mediaStorageDir.exists()){
            if (! mediaStorageDir.mkdirs()){
                Log.d("MyCameraApp", "failed to create directory");
                return null;
            }
        }

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

        return mediaFile;
    }






}
4

1 回答 1

0

当方向发生变化时,Activity 将重新加载,如果您不释放相机并尝试打开一个新相机,我认为可能会导致异常。

尝试在 onStop 或 onDestroy 方法中释放相机?或者你可以检查一下,尝试旋转屏幕而不重新启动活动。

于 2013-08-29T12:47:20.603 回答