2012-12-01 38 views
7

我创建一个摄像头应用程序,但我有startPreview问题,给我发:相机startPreview失败

java.lang.RuntimeException: startPreview failed 

这里是我的相机活动

public class CameraActivity extends Activity { 

private Camera mCamera; 
private CameraPreview mPreview; 
private Target_Frame targetFrame; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    // TODO Auto-generated method stub 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.camera_layout); 




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




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

} 




/** Check if this device has a camera only if not specified in the manifest */ 
public boolean checkCameraHardware(Context context) { 
    if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){ 
     // this device has a camera 
     return true; 
    } else { 
     // no camera on this device 
     return false; 
    } 
} 

/** A safe way to get an instance of the Camera object. */ 
public static Camera getCameraInstance(){ 
    Camera c = null; 
    try { 
     c = Camera.open(); // attempt to get a Camera instance 
    } 
    catch (Exception e){ 
     // Camera is not available (in use or does not exist) 
    } 
    return c; // returns null if camera is unavailable 
} 

/**Check if the device has flash*/ 
public boolean checkFlash(Context context){ 
    if(context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)){ 
     //the device has flash 
     return true; 
    }else{ 
     //no flash 
     return false; 
    } 

} 




@Override 
protected void onDestroy() { 
    // TODO Auto-generated method stub 
    super.onDestroy(); 
    releaseCamera(); 
} 




@Override 
protected void onPause() { 
    // TODO Auto-generated method stub 
    super.onPause(); 
    releaseCamera(); 
} 




@Override 
protected void onResume() { 
    // TODO Auto-generated method stub 
    super.onResume(); 

    //Test if i have to put all this code like in onCreate 
    if(mCamera!=null){ 
     return; 
    } 
    mCamera=getCameraInstance(); 

    if(mPreview!=null){ 
     return; 
    } 
    mPreview=new CameraPreview(this, mCamera); 
    FrameLayout preview=(FrameLayout)findViewById(R.id.camera_preview); 
    preview.addView(mPreview); 


} 


private void releaseCamera(){ 
    if (mCamera != null){ 
     mCamera.release();  // release the camera for other applications 
     mCamera = null; 
    } 
}} 

这里是我的SurfaceView code:

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { 
    private static final String TAG = "CameraPreview"; 
    private SurfaceHolder mHolder; 
    private Camera mCamera; 

    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) { 
     // If your preview can change or rotate, take care of those events here. 
     // Make sure to stop the preview before resizing or reformatting it. 

     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 
     Parameters parameters= mCamera.getParameters(); 
     parameters.setPreviewSize(w, h); 
     mCamera.setParameters(parameters); 

     // start preview with new settings 
     try { 
      mCamera.setPreviewDisplay(mHolder); 
      mCamera.startPreview(); 

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

这里是我的错误日志:

12-01 13:17:01.135: E/AndroidRuntime(1161): FATAL EXCEPTION: main 

12-01 13:17:01.135: E/AndroidRuntime(1161): java.lang.RuntimeException: startPreview 

12-01 13:17:01.135: E/AndroidRuntime(1161):  at com.example.prueba.CameraPreview.surfaceCreated(CameraPreview.java:36) 
+0

对不起,我觉得你的变量名称非常混乱。当mChanged中使用'mholder'而不是'holder',并且'preview'和'mPreview'是不同类的实例时,'mholder/holder/camera/mcamera/preview/mpreview'。我不得不放弃,我正要穿上衣服!我不能说没有任何错误,但是我认为,如果你更持久地使用名称,并且可能在其中有更多的描述,你会发现它更容易。祝你好运! – emrys57

+1

嗨变量名称是相同的android sdk示例,但也许我会hace来改变他们,如你所说。你没有看到任何错误?我已经检查了很多东西,但是我现在不知道该怎么做 – user1805792

+0

我从来没有将'SurfaceView'编程到'FrameLayout'中。这可能是完全正确的,但我会从简单的事情开始。像在xml文件中直接将'SurfaceView'添加到'camera_layout',一旦你有这个工作,改变布局到你在这里的方式。我不知道这是否能解决问题,但它会使调试变得更简单。 – emrys57

回答

4

我已经解决了删除在surfaceChanged

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. 
     Log.d("Function", "surfaceChanged iniciado"); 
     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 
     try { 
      mCamera.setPreviewDisplay(mHolder); 
      mCamera.startPreview(); 

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

一些线条所以误差必须在我这行之一:

Parameters parameters= mCamera.getParameters(); 
    parameters.setPreviewSize(w, h); 
    mCamera.setParameters(parameters); 

有人可以解释我在这些问题上出了什么问题?

+0

我已在下面发布了答案。 – hybrid

4

是(w,h)是否为您的相机有效的预览尺寸?

您可以使用mCamera.getParameters().getSupportedPreviewSizes()获取所有有效的预览大小。

+0

这很可能是'RuntimeException'的原因。对于某些设备,请使用不支持的预览大小调用[Camera.setParameters()](http://developer.android.com/reference/android/hardware/Camera.html#setParameters(android.hardware.Camera.Parameters))导致'RuntimeException'。对于其他人,[摄像机]引发异常。startPreview()](http://developer.android.com/reference/android/hardware/Camera.html#startPreview()) –

3

其后,但如果有人寻找答案

变量w和h不是最佳的预览大小。您可以使用功能

public static Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) { 
     final double ASPECT_TOLERANCE = 0.1; 
     double targetRatio=(double)h/w; 
     if (sizes == null) return null; 

     Camera.Size optimalSize = null; 
     double minDiff = Double.MAX_VALUE; 

     int targetHeight = h; 

     for (Camera.Size size : sizes) { 
      double ratio = (double) size.width/size.height; 
      if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue; 
      if (Math.abs(size.height - targetHeight) < minDiff) { 
       optimalSize = size; 
       minDiff = Math.abs(size.height - targetHeight); 
      } 
     } 

     if (optimalSize == null) { 
      minDiff = Double.MAX_VALUE; 
      for (Camera.Size size : sizes) { 
       if (Math.abs(size.height - targetHeight) < minDiff) { 
        optimalSize = size; 
        minDiff = Math.abs(size.height - targetHeight); 
       } 
      } 
     } 
     return optimalSize; 
    } 

获得最佳的预览尺寸,并且可以调用使用

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 
.. 
size=getOptimalPreviewSize(parameters.getSupportedPreviewSizes(), w, h); 
parameters.setPreviewSize(size.getWidth(), size.getHeight()); 
.. 

} 
0

我有这个错误的功能,这是因为我没有对的onPause调用releaseCamera第一次我开始我的应用程序。
重新启动之后,一切工作正常^^

0
public void surfaceCreated(SurfaceHolder holder) { 
    // The Surface has been created, now tell the camera where to draw the preview. 
    try { 
     mCamera.setPreviewDisplay(holder); 
     mCamera.getParameters().getSupportedPreviewSizes(); 
     mCamera.startPreview(); 
     Log.d(TAG, "Camera preview started."); 
    } catch (IOException e) { 
     Log.d(TAG, "Error setting camera preview: " + e.getMessage()); 
    } 
}