我已经构建了一个应用程序,可以在您触摸预览时拍摄照片。 我可以拍很多照片,但有时当我触摸预览拍照时,没有快门声,整个应用都冻结了。此外,在此之后,如果我尝试启动内置相机应用程序,我会收到一条消息,说明相机无法使用。
我不知道这种行为的原因,它是随机发生的,当它发生时我必须重启设备(三星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
答案 0 :(得分:8)
我在三星Galaxy SII上测试我的应用程序时遇到了这个问题。您只需在拍照前删除预览回调:
mCamera.setPreviewCallback(null);
mCamera.takePicture(null, null, mPictureCallback);
答案 1 :(得分:6)
我不知道导致该错误的原因是,如果您从发生此错误的时间开始发布loggcat输出,它将真正帮助。
但是,我可以做一些保护。它看起来像相机被锁定(内置相机不起作用)。如果您的应用程序强制关闭,相机锁定可能是由三星相机HAL中的错误处理错误引起的。特别是在像Galaxy S这样的旧款手机中,他们在处理错误或非标准API调用时并没有做得最好。
以下是可能导致此行为的一些建议:
你应该为拍照添加一个警卫。现在,如果您触摸屏幕并拍照,您可以在照片完成拍摄之前再次触摸屏幕。因此,camera.takePicture()将被调用两次。第二个将失败。这是我最好的猜测。
添加一些boolean isTakingPicture = false
变量,然后:
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做什么?我这里没有做任何有用的事情。虽然你的代码看起来很好,但有时预览回调有时会引起一些痛苦。你可以尝试删除它并检查是否有帮助。
答案 2 :(得分:2)
我在这里报道过类似的问题。在LG p705和三星Galaxy Trend上拍照后,预览被冻结,相机在手机重启之前不再可用。但是,在Galaxy S3上,即使多次拍照后,预览仍会继续正常显示。
在调试时,我注意到当按下相机按钮拍照时,相关的侦听器类正在接收多个调用。我不确定为什么它被调用两次,即使按钮只点击一次。在任何情况下,由于Tomasz建议使用布尔变量,第二次调用会在第一次尝试进行时跳过拍照。并且还要感谢Eyal提出这个问题。 :)