2011-11-15 61 views
0

这里是我的CameraView类:Android相机预览错误

public class CameraView extends SurfaceView implements SurfaceHolder.Callback, PreviewCallback { 
private Camera camera=null; 

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

    SurfaceHolder holder = this.getHolder(); 
    holder.addCallback(this); 
    holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
} 

public boolean isVisible(){ 
    return this.getVisibility()==View.VISIBLE; 
} 

public void show(){ 
    this.setVisibility(View.VISIBLE); 
} 

public void hide(){ 
    this.setVisibility(View.GONE); 
} 

public void surfaceCreated(SurfaceHolder holder) { 
    camera = Camera.open(); 
    camera.setPreviewCallback(this); 

    try { 
     camera.setPreviewDisplay(holder); 
    }catch (IOException e) { 
     Log.e("Preview Exception", e.getMessage()); 
    } 
} 

public void surfaceDestroyed(SurfaceHolder holder) {   
    if(camera!=null){ 
     camera.stopPreview(); 
     camera.setPreviewCallback(null); 
     camera.release(); 
     camera=null; 
    } 
} 

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {   
    if(camera==null || !(w>0&&h>0)) 
     return; 

    Camera.Parameters parameters = camera.getParameters(); 
    parameters.setPreviewSize(w, h); 

    camera.setParameters(parameters); 
    camera.startPreview(); 
} 

@Override 
public void onPreviewFrame(byte[] data, Camera camera) { 

} 
} 

在我的活动我有两个按钮 - 其中之一显示相机预览,并且第二隐藏它(使用CameraView.show()和CameraView.hide ()) 方法。

它工作得很好,除了一种情况: 如果我使用CameraView.hide()隐藏预览,请按HOME按钮(应用程序将分叉到背景)并将应用程序再次置于前面,我无法启动预览了。 当我调用CameraView.show()(通过按下按钮)时,CameraView出现,但预览不启动。

对我来说,它看起来像android bug,因为在其他情况下,一切工作正常 - 我运行android 2.1。

有人可以帮助我吗? 谢谢!

PS。下面是更新类,根据mmeyer的帖子(仍然没有工作):

public class CameraView extends SurfaceView implements SurfaceHolder.Callback, PreviewCallback { 
private Camera camera=null; 
private SurfaceHolder holder; 

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

public void initialize(){ 
    camera=Camera.open(); 

    holder = this.getHolder(); 
    holder.addCallback(this); 
    holder.setSizeFromLayout(); 
    holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
} 

public void release(){ 
    holder.removeCallback(this); 

    if(camera!=null){ 
     camera.stopPreview(); 
     camera.setPreviewCallback(null); 
     camera.release(); 
     camera=null; 
    } 
} 

public boolean isVisible(){ 
    return this.getVisibility()==View.VISIBLE; 
} 

public void show(){ 
    this.setVisibility(View.VISIBLE); 
} 

public void hide(){ 
    this.setVisibility(View.GONE); 
} 

public void surfaceCreated(SurfaceHolder holder) {  
} 

public void surfaceDestroyed(SurfaceHolder holder) { 
    if(camera!=null) 
     camera.stopPreview(); 
} 

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {   
    if(camera==null || !(w>0&&h>0)) 
     return; 


    try { 
     camera.setPreviewDisplay(holder); 
    }catch (IOException e) { 
     Log.e("Preview Exception", e.getMessage()); 
    } 

    Camera.Parameters parameters = camera.getParameters(); 
    parameters.setPreviewSize(w, h); 

    camera.setParameters(parameters); 
    camera.startPreview(); 
} 

@Override 
public void onPreviewFrame(byte[] data, Camera camera) { 

} 
} 

回答

2

我怀疑你需要释放相机中最小和的onDestroy理想中的onPause或你最终将摄像头驱动程序挂起。

我用相机预览东西的模式是:

onResume: 
    - get a ref to camera with Camera.open(); 
    - sv = (SurfaceView)this.findViewById(R.id.capture_SurfaceView); 
       mHolder = sv.getHolder(); 
       mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
       mHolder.setSizeFromLayout(); 
       mHolder.addCallback(this); 
    surfaceChanged: 
    - Camera.setPreviewDisplayHolder() 
    - Camera.startPreview() 
    onPause: 
    - Camera.stopPreview 
    - SurfaceHolder.removeCallback() 
    - Camera.release() 
+0

我修改了类如你所说,但问题仍然存在。 – user1011446

+0

如果您事先没有事先做好CameraView.hide()而回到家中,您会遇到同样的问题吗?如果隐藏似乎是问题,那么我会考虑让它也发布。 – mmeyer

+0

如果我在将应用程序分配到背景之前没有隐藏预览,那么一切正常。 – user1011446

0

我有一个工作版本:

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

    private SurfaceHolder surfaceHolder; 
    private Camera camera; 

    public CameraPreview(Context context) { 
     super(context); 

     // Install a SurfaceHolder.Callback so we get notified when the 
     // underlying surface is created and destroyed 

     surfaceHolder = getHolder(); 
     surfaceHolder.addCallback(this); 
    } 

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

    public void surfaceDestroyed(SurfaceHolder holder) { 
     camera.stopPreview(); 
    } 

    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 (surfaceHolder.getSurface() == null){ 
      // Preview surface does not exist 
      return; 
     } 

     // Stop preview before making changes 
     try { 
      camera.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 { 
      camera.setPreviewDisplay(surfaceHolder); 

      // Update the camera parameters 
      Camera.Parameters cameraParameters = camera.getParameters(); 
      cameraParameters.setPreviewSize(w, h); 

      camera.setParameters(cameraParameters); 
      camera.startPreview(); 

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

    public void setCamera(Camera camera) { 
     this.camera = camera; 
    } 
}