我正在尝试使用Camera2 API使用Zbar读取QR码。不幸的是,当我在成功扫描QR码后尝试完成活动时,我收到以下错误:
Handler (android.os.Handler) {282a7034} sending message to a Handler on a dead thread
java.lang.IllegalStateException: Handler (android.os.Handler) {282a7034} sending message to a Handler on a dead thread
at android.os.MessageQueue.enqueueMessage(MessageQueue.java:325)
at android.os.Handler.enqueueMessage(Handler.java:631)
at android.os.Handler.sendMessageAtTime(Handler.java:600)
at android.os.Handler.sendMessageDelayed(Handler.java:570)
at android.os.Handler.post(Handler.java:326)
at android.hardware.camera2.dispatch.HandlerDispatcher.dispatch(HandlerDispatcher.java:61)
at android.hardware.camera2.dispatch.MethodNameInvoker.invoke(MethodNameInvoker.java:88)
at android.hardware.camera2.dispatch.DuckTypingDispatcher.dispatch(DuckTypingDispatcher.java:53)
at android.hardware.camera2.dispatch.ArgumentReplacingDispatcher.dispatch(ArgumentReplacingDispatcher.java:74)
at android.hardware.camera2.dispatch.BroadcastDispatcher.dispatch(BroadcastDispatcher.java:54)
at android.hardware.camera2.dispatch.MethodNameInvoker.invoke(MethodNameInvoker.java:88)
at android.hardware.camera2.impl.CallbackProxies$DeviceCaptureCallbackProxy.onCaptureCompleted(CallbackProxies.java:120)
at android.hardware.camera2.impl.CameraDeviceImpl$CameraDeviceCallbacks$4.run(CameraDeviceImpl.java:1362)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.os.HandlerThread.run(HandlerThread.java:61)
这些是相关的代码片段:
private CameraCaptureSession.CaptureCallback mCaptureCallback
= new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
TotalCaptureResult result) {
Bitmap barcodeBmp = mTextureView.getBitmap();
if(barcodeBmp == null)
return;
int width = barcodeBmp.getWidth();
int height = barcodeBmp.getHeight();
Image mQRCode = new Image(width, height, "RGB4");
final ImageScanner scanner = new ImageScanner();
scanner.setConfig(0, Config.X_DENSITY, 3);
scanner.setConfig(0, Config.Y_DENSITY, 3);
scanner.setConfig(0, Config.ENABLE, 0); //Disable all the Symbols
scanner.setConfig(Symbol.QRCODE, Config.ENABLE, 1); //Only QRCODE is enable
int[] pixels = new int[(width * height)];
barcodeBmp.getPixels(pixels, 0, width, 0, 0, width, height);
mQRCode.setData(pixels);
int scanResult = scanner.scanImage(mQRCode.convert("Y800"));
Log.i(TAG, "Result = " + scanResult);
if(scanResult != 0) {
Log.i(TAG, "Getting results");
SymbolSet syms = scanner.getResults();
Log.i(TAG, "Have results");
for(Symbol sym : syms) {
Intent returnIntent = new Intent();
returnIntent.putExtra("Result", sym.getData());
setResult(RESULT_OK, returnIntent);
closeCamera();
stopBackgroundThread();
mActivity.finish();
}
}
}
};
private void closeCamera() {
try {
mCameraOpenCloseLock.acquire();
if (null != mCaptureSession) {
mCaptureSession.close();
mCaptureSession = null;
}
if (null != mCameraDevice) {
mCameraDevice.close();
mCameraDevice = null;
}
if (null != mImageReader) {
mImageReader.close();
mImageReader = null;
}
} catch (InterruptedException e) {
throw new RuntimeException("Interrupted while trying to lock camera closing.", e);
} finally {
mCameraOpenCloseLock.release();
}
}
private void stopBackgroundThread() {
if(mBackgroundThread != null) {
mBackgroundThread.quitSafely();
try {
mBackgroundThread.join(1);
mBackgroundThread = null;
mBackgroundHandler = null;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
如何停止调用CaptureCallback并将结果干净地返回到我的主要活动?
答案 0 :(得分:5)
您正在呼叫CameraDevice#close()
,但这不会立即关闭相机。您应该保持线程运行,直到设备完成。
您的代码可能基于Google’s Camera2 sample app。要完整地完成所有操作,请通过覆盖CameraDevice.StateCallback
方法停止#onClosed(CameraDevice)
中的主题:
private CameraDevice.StateCallback mStateCallback
= new CameraDevice.StateCallback() {
// ...
@Override
public void onClosed(CameraDevice camera) {
// Keep the thread alive until the camera is closed.
stopBackgroundThread();
}
};
看起来当前行为可能是一个错误,因为documentation for CameraDevice#close()
说:
此次通话结束后,除了最后
onClosed(CameraDevice)
次来电之外,不会再发生来自设备或活动会话的回调,并且任何剩余的已提交捕获请求都将被丢弃,就好像已调用abortCaptures()
,但不会调用成功或失败的回调。
答案 1 :(得分:0)
这可能是因为您将Camera2Basic代码&{39}更改为mBackgroundThread.join();
。
即使你调用了mBackgroundThread.join(1);
,仍然可能会有一些请求的捕获"在飞行中"在相机管道中,因此在关闭捕获会话后它们仍会出现并调用mCaptureSession.close()
。
原始代码允许在关闭线程之前解析这些延迟调用,但是仅在1ms之后关闭它,这还不足以确保它们被解析。你应该让它先完成它的业务。