2012-06-28 39 views
5

嗨,大家好,我试图在显示相机预览的同时在设备的正面和背面相机之间切换。我正在关注通用软件提供的示例。下面是我正在使用的代码,每当我点击翻转按钮时,表面视图变黑,我不知道我哪里出错了。请帮我解决这个问题。我搜索了这个,我没有得到任何合适的答案,因为有些人试图重新启动当前的活动,但我不想那样。希望得到更好的回应。提前致谢。Android相机预览在相机之间切换

package com.commonsware.android.camera; 
import android.app.Activity; 
import android.hardware.Camera; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 
import android.widget.CompoundButton; 
import android.widget.CompoundButton.OnCheckedChangeListener; 
import android.widget.Toast; 
import android.widget.ToggleButton; 
public class PreviewDemo extends Activity { 
    private SurfaceView preview = null; 
    private SurfaceHolder previewHolder = null; 
    private Camera camera = null; 
    private boolean inPreview = false; 
    private boolean cameraConfigured = false; 
    private ToggleButton flipCamera; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    setContentView(R.layout.main); 
    flipCamera = (ToggleButton) findViewById(R.id.flip); 
    preview = (SurfaceView) findViewById(R.id.preview); 
    previewHolder = preview.getHolder(); 
    previewHolder.addCallback(surfaceCallback); 
    previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
    flipCamera.setOnCheckedChangeListener(new OnCheckedChangeListener() { 

     @Override 
     public void onCheckedChanged(CompoundButton buttonView, 
       boolean isChecked) { 
      // TODO Auto-generated method stub 
      restartPreview(isChecked); 
     } 
    }); 

} 

@Override 
public void onResume() { 
    super.onResume(); 

    // camera=Camera.open(); 
    int camId = Camera.CameraInfo.CAMERA_FACING_BACK; 
    if (Camera.getNumberOfCameras() > 1 
      && camId < Camera.getNumberOfCameras() - 1) { 
     // startCamera(camId + 1); 
     camera = Camera.open(camId + 1); 
    } else { 
     // startCamera(Camera.CameraInfo.CAMERA_FACING_BACK); 
     camera = Camera.open(camId); 
    } 
    startPreview(); 
} 

void restartPreview(boolean isFront) { 
    if (inPreview) { 
     camera.stopPreview(); 
    } 
    // 
    camera.release(); 

    // camera=null; 
    // inPreview=false; 
    // /*int camId = Camera.CameraInfo.CAMERA_FACING_BACK; 
    // if (Camera.getNumberOfCameras() > 1 && camId < 
    // Camera.getNumberOfCameras() - 1) { 
    // //startCamera(camId + 1); 
    // camera = Camera.open(camId + 1); 
    // } else { 
    // //startCamera(Camera.CameraInfo.CAMERA_FACING_BACK); 
    // camera = Camera.open(camId); 
    // }*/ 
    int camId = Camera.CameraInfo.CAMERA_FACING_BACK; 
    if (isFront) { 
     camera = Camera.open(camId); 
     camera.startPreview(); 

    } else { 
     camera = Camera.open(camId + 1); 
     camera.startPreview(); 

    } 
    // startPreview(); 
} 

@Override 
public void onPause() { 
    if (inPreview) { 
     camera.stopPreview(); 
    } 

    camera.release(); 
    camera = null; 
    inPreview = false; 

    super.onPause(); 
} 

private Camera.Size getBestPreviewSize(int width, int height, 
     Camera.Parameters parameters) { 
    Camera.Size result = null; 

    for (Camera.Size size : parameters.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); 
} 

private void initPreview(int width, int height) { 
    if (camera != null && previewHolder.getSurface() != null) { 
     try { 
      camera.setPreviewDisplay(previewHolder); 
     } catch (Throwable t) { 
      Log.e("PreviewDemo-surfaceCallback", 
        "Exception in setPreviewDisplay()", t); 
      Toast.makeText(PreviewDemo.this, t.getMessage(), 
        Toast.LENGTH_LONG).show(); 
     } 

     if (!cameraConfigured) { 
      Camera.Parameters parameters = camera.getParameters(); 
      Camera.Size size = getBestPreviewSize(width, height, parameters); 

      if (size != null) { 
       parameters.setPreviewSize(size.width, size.height); 
       camera.setParameters(parameters); 
       cameraConfigured = true; 
      } 
     } 
    } 
} 

private void startPreview() { 
    if (cameraConfigured && camera != null) { 

     camera.startPreview(); 
     inPreview = true; 
    } 
} 

SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback() { 
    public void surfaceCreated(SurfaceHolder holder) { 
     // no-op -- wait until surfaceChanged() 
    } 

    public void surfaceChanged(SurfaceHolder holder, int format, int width, 
      int height) { 
     initPreview(width, height); 
     startPreview(); 
    } 

    public void surfaceDestroyed(SurfaceHolder holder) { 
     // no-op 
     if (camera != null) { 
      /* 
      * Call stopPreview() to stop updating the preview surface. 
      */ 
      camera.stopPreview(); 

      /* 
      * Important: Call release() to release the camera for use by 
      * other applications. Applications should release the camera 
      * immediately in onPause() (and re-open() it in onResume()). 
      */ 
      camera.release(); 

      camera = null; 
     } 
    } 
}; 
} 
+0

使'camId'成为静态成员,并在检查更改时再次启动活动..就像开始自己并在下一行中调用完成一样......'递归活动'.. – Ronnie

+0

@ userSeven7s尽管这样可以解决问题它不是(在我看来)一个明智的设计选择。摄像机的一个常见模式是让它们返回捕获图像的路径。如果我从活动A启动相机并且相机自行启动,则从相机获取结果变得复杂。此外,将递归添加到Android的“特殊”生命周期听起来像是一个可怕的想法。 – TheCrafter

回答

12

你似乎从restartPreviev()方法调用startPreview()之前忘记调用setPreviewDisplay()(或者,你的情况,initPreview())。实际上,您正在尝试开始预览,而没有指定要渲染预览的曲面。