Android相机 – 有时候拍照时,应用程序会冻结,相机无法使用

我已经构建了一个应用程序,当您触摸预览时拍摄照片.
我可以拍摄很多照片,但有时候,当我触摸预览拍摄照片时,没有快门音,整个应用程序冻结.此外,在此之后,如果我尝试启动内置相机应用程序,我会收到一条消息,指出相机不能使用.

我不知道这个行为的原因,它是随机发生的,当它发生时,我必须重新启动设备(Samsung 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

解决方法

我不知道是什么原因导致这个错误,如果从发生此错误的时间发布了loggcat输出,这将真的有帮助.

但是,我可以做一些gusesses.看起来相机被锁定(内置相机不起作用).如果您的应用程序强制关闭,相机锁定可能是由于Samsung相机HAL中的错误处理引起的.特别是在像galaxy S这样的老旧手机中,他们在处理错误或者不是标准的API调用时都没有做最好的工作.

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

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

添加一些布尔值isTakingPicture = false变量然后:

public boolean onTouch(View v,MotionEvent event) {
  if (!isTakingPicture) {
    camera.takePicture(shutterCallback,jpegCallback);
    isTakingPicture = true;
  }
  return false;
}
...
public void onPictureTaken(byte[] data,Camera camera) {
  isTakingPicture = false;
  ...

>你使用previewCallback做什么?我在这里没有任何有用的东西.有时候,预览回调有时会导致一些痛苦,尽管你的代码对我来说看起来不错.你可以试试删除它,并检查是否有帮助.

相关文章

Android性能优化——之控件的优化 前面讲了图像的优化,接下...
前言 上一篇已经讲了如何实现textView中粗字体效果,里面主要...
最近项目重构,涉及到了数据库和文件下载,发现GreenDao这个...
WebView加载页面的两种方式 一、加载网络页面 加载网络页面,...
给APP全局设置字体主要分为两个方面来介绍 一、给原生界面设...
前言 最近UI大牛出了一版新的效果图,按照IOS的效果做的,页...