Android相机 – 有时当我拍照时,应用程序冻结,相机不可用

我build立了一个应用程序,当你触摸预览时拍照。 我可以拍很多照片,但有时当我触摸预览拍照时,没有快门声,整个应用程序冻结。 此外,之后,如果我尝试启动内置的相机应用程序,我得到的消息,相机不能使用。

我不知道这种行为的原因,它是随机发生的,当它发生时,我必须重新启动设备(三星Galaxy S)才能够再次使用相机。

在DDM中,崩溃后,我可以看到下面这行:keyDispatchingTimedOut

这里是相关的代码:CameraActivity类:

public class CameraActivity extends Activity { private static final String TAG = "CameraDemo"; Preview preview; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); preview = new Preview(this); ((FrameLayout) findViewById(R.id.preview)).addView(preview); ((FrameLayout) findViewById(R.id.preview)).setOnTouchListener(preview); Log.d(TAG, "Camera Activity Created."); } } 

预览类:

  class Preview extends SurfaceView implements SurfaceHolder.Callback, OnTouchListener { private static final String TAG = "Preview"; SurfaceHolder mHolder; public Camera camera; Context ctx; boolean previewing = false; Preview(Context context) { super(context); ctx = context; // Install a SurfaceHolder.Callback so we get notified when the // underlying surface is created and destroyed. mHolder = getHolder(); mHolder.addCallback(this); mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } // Called once the holder is ready public void surfaceCreated(SurfaceHolder holder) { // The Surface has been created, acquire the camera and tell it where // to draw. camera = Camera.open(); } // Called when the holder is destroyed public void surfaceDestroyed(SurfaceHolder holder) { if (camera != null) { camera.setPreviewCallback(null); camera.stopPreview(); camera.release(); camera = null; } previewing = false; } // Called when holder has changed public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { if(previewing){ camera.stopPreview(); previewing = false; } if (camera != null){ try { camera.setDisplayOrientation(90); camera.setPreviewDisplay(holder); camera.setPreviewCallback(new PreviewCallback() { // Called for each frame previewed public void onPreviewFrame(byte[] data, Camera camera) { Log.d(TAG, "onPreviewFrame called at: " + System.currentTimeMillis()); Preview.this.invalidate(); } }); camera.startPreview(); previewing = true; } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public boolean onTouch(View v, MotionEvent event) { camera.takePicture(shutterCallback, rawCallback, jpegCallback); return false; } // Called when shutter is opened ShutterCallback shutterCallback = new ShutterCallback() { public void onShutter() { Log.d(TAG, "onShutter'd"); } }; // Handles data for raw picture PictureCallback rawCallback = new PictureCallback() { public void onPictureTaken(byte[] data, Camera camera) { Log.d(TAG, "onPictureTaken - raw"); } }; // Handles data for jpeg picture PictureCallback jpegCallback = new PictureCallback() { public void onPictureTaken(byte[] data, Camera camera) { FileOutputStream outStream = null; try { // Write to SD Card outStream = new FileOutputStream(String.format("/sdcard/TVguide/Detection/detected.jpg", System.currentTimeMillis())); // <9> outStream.write(data); outStream.close(); Log.d(TAG, "onPictureTaken - wrote bytes: " + data.length); } catch (FileNotFoundException e) { // <10> //Toast.makeText(ctx, "Exception #2", Toast.LENGTH_LONG).show(); e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally {} Log.d(TAG, "onPictureTaken - jpeg"); Toast.makeText(ctx, "SAVED", Toast.LENGTH_SHORT).show(); camera.startPreview(); } }; } 

请帮忙,我想了解几天没有成功的问题

的Eyal

我不知道是什么原因导致了这个bug,如果你从这个错误发生的时间开始发布loggcat的输出,那真的会有所帮助。

但是,我可以做出一些猜测。 它看起来像相机被locking(内置相机不工作)。 如果您的应用程序部队closures,相机锁可能是由三星相机HAL错误的error handling引起的。 特别是在像Galaxy S这样的旧手机中,他们在处理错误的,或不标准的API调用方面做得不是最好的。

以下是可能导致此行为的一些build议:

  1. 你应该加一个卫兵照相。 现在,如果您触摸屏幕并拍摄照片,则可以在完成拍摄之前再次触摸屏幕。 所以,camera.takePicture()将被调用两次。 第二个将失败。 这是我最好的猜测。

    添加一些boolean isTakingPicture = falsevariables,然后:

     public boolean onTouch(View v, MotionEvent event) { if (!isTakingPicture) { camera.takePicture(shutterCallback, rawCallback, jpegCallback); isTakingPicture = true; } return false; } ... public void onPictureTaken(byte[] data, Camera camera) { isTakingPicture = false; ... 
  2. 你用什么previewCallback? 我在这里没有做任何有用的事情。 预览callback有时可能会导致一些痛苦,虽然你的代码看起来很好。 你可以尝试删除它,并检查是否有帮助。

我在三星Galaxy SII上testing我的应用程序时遇到了这个问题。 拍照之前,您只需删除预览callback:

 mCamera.setPreviewCallback(null); mCamera.takePicture(null, null, mPictureCallback); 

我遇到过类似的问题。 在LG p705和三星Galaxy Trend上,拍照后,预览被冻结,相机不再可用,直到手机重新启动。 然而,在Galaxy S3上,即使在多张照片捕捉之后,预览仍能正常显示。

在debugging过程中,我注意到相关button被按下时,相关的监听器类正在接收多个呼叫。 我不确定为什么它被调用两次,即使button只是点击一次。 在任何情况下,由于Tomaszbuild议使用布尔variables,第二次呼叫将在第一次尝试进行时跳过拍照。 也感谢Eyal的问题。 🙂