Android 相机 - 有时当我拍照时,应用程序冻结并且相机无法使用 [英] Android Camera - Sometimes when i take photos, the app freezes and the camera is non-usable

查看:25
本文介绍了Android 相机 - 有时当我拍照时,应用程序冻结并且相机无法使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have built an application which takes photos when you touch the preview. I can take many photos, but sometimes when i touch the preview to take a photo, there is no shutter sound and the whole application freezes. Moreover, after that, if i try to launch launch the built-in camera application, i get a message that the camera can't be used.

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

I don't know the reason for that behavior, it happens randomly and when it happens i must restart the device (Samsung Galaxy S) to be able to use the camera again.

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

In the DDM, after the crash i can see the following line: keyDispatchingTimedOut

以下是相关代码:CameraActivity 类:

Here is the relevant code: CameraActivity Class:

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();
        }
    };

}

请帮忙,我正在尝试几天来了解问题出在哪里,但没有成功

Please help, i am trying a few days to understand where the problem is with no success

艾尔

推荐答案

我不知道是什么导致了这个错误,如果你从这个时间发布 loggcat 输出,它会真的帮助发生错误.

I don't know what causes that bug, it would really help if you posted the loggcat output from the time from when this error happened.

但是,我可以做一些猜测.看起来相机被锁定(内置相机不起作用).如果您的应用程序强制关闭,则相机锁定可能是由三星相机 HAL 中的错误处理引起的.尤其是在 Galaxy S 等较旧的手机中,它们在处理错误或不标准的 API 调用方面做得并不好.

But, I can make some gusesses. It looks like camera is locked (built-in camera does not work). If your app force closed, the camera lock might be caused by erroneus error handling in Samsung camera HAL. Especially in older phones, like Galaxy S, they did not do the best job at handling wrong, or not standard API calls.

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

Here are some suggestions of what may have caused this behaviour:

  1. 你应该为拍照添加一个警卫.现在,如果您触摸屏幕并拍照,您可以在拍照完成之前再次触摸屏幕.因此,camera.takePicture() 将被调用两次.第二个会失败.这是我最好的猜测.

  1. You should add a guard for picture taking. Right now, if you touch the screen and take picture, you can touch the screen again, before the picture finishes taking. So, camera.takePicture() will be called twice. The second one will fail. This is my best guess.

添加一些 boolean isTakingPicture = false 变量然后:

Add some boolean isTakingPicture = false variable and then:

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;
  ...

  • 你用 previewCallback 做什么?我在这里没有做任何有用的事情.预览回调有时会引起一些痛苦,尽管您的代码对我来说看起来不错.您可以随时尝试删除它并检查是否有帮助.

  • What do you use previewCallback for? I doesn't do anything useful here. Preview callbacks sometimes can sometimes cause some pain, although your code looks fine to me. You can alwys try to remove it and check if that helps.

    这篇关于Android 相机 - 有时当我拍照时,应用程序冻结并且相机无法使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆