问题描述
我正在尝试使用相机api2捕获图像.该代码在MOTO g4上运行良好,但是当我在NEXUS 6上测试该代码时,在session.capture之后不会调用onImageAvailable,并且没有保存任何图像.真的很沮丧,如果有人可以帮助,我们将不胜感激!非常感谢.
I am trying to use camera api2 to capture images. The code worked fine on MOTO g4, but when I test the code on NEXUS 6, the onImageAvailable is not invoked after session.capture, and no image has been saved. Really frustrated, greatly appreciated if someone could help! Thanks so much.
ImageReader reader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 1);
List<Surface> outputSurfaces = new ArrayList<Surface>(2);
outputSurfaces.add(reader.getSurface());
outputSurfaces.add(new Surface(textureView.getSurfaceTexture()));
final CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureBuilder.addTarget(reader.getSurface());
captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
// Orientation
int rotation = getWindowManager().getDefaultDisplay().getRotation();
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
sendUri = getImageUri();
final File file = new File(Environment.getExternalStorageDirectory()+"/" + sendUri +".jpg");
ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
Image image = null;
try {
image = reader.acquireLatestImage();
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.capacity()];
buffer.get(bytes);
save(bytes);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (image != null) {
image.close();
}
}
}
private void save(byte[] bytes) throws IOException {
OutputStream output = null;
try {
output = new FileOutputStream(file);
output.write(bytes);
} finally {
if (null != output) {
output.close();
}
}
}
};
reader.setOnImageAvailableListener(readerListener, mBackgroundHandler);
final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
//Toast.makeText(MainActivity.this, "Saved:" + file, Toast.LENGTH_SHORT).show();
toast1("Saved:"+file);
//createCameraPreview();
}
};
cameraDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(CameraCaptureSession session) {
try {
session.capture(captureBuilder.build(), captureListener, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onConfigureFailed(CameraCaptureSession session) {
}
}, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
下面是运行相机功能时nexus 6的完整logcat输出,似乎没什么用...
Below is the full logcat output from nexus 6 when run the camera function, seems nothing useful...
03-07 13:04:34.526 1838-1838/examples.hello E/AndroidCameraApi: is camera open
03-07 13:04:34.527 1838-1838/examples.hello I/CameraManagerGlobal: Connecting to camera service
03-07 13:04:34.659 1838-1838/examples.hello E/AndroidCameraApi: openCamera X
03-07 13:04:34.694 1838-1838/examples.hello E/AndroidCameraApi: onOpened
03-07 13:04:34.722 1838-1883/examples.hello D/OpenGLRenderer: endAllActiveAnimators on 0x931bee80 (RippleDrawable) with handle 0x92c2cea0
03-07 13:04:43.952 1838-1838/examples.hello E/AndroidCameraApi: onPause
推荐答案
如果包括故障设备的完整logcat输出,将会很有帮助,但我怀疑问题是这样的:
It'd be helpful if you included full logcat output from the failing device, but I suspect the problem is this:
ImageReader reader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 1);
您正在创建本地ImageReader对象,而不是将其保存以备将来使用.您确实可以从中获得一个Surface,但是Surface很像一个弱指针.如果没有任何引用,它不会阻止ImageReader获得GC(请参见开发人员参考资料中的注释)
You're creating a local ImageReader object, and not saving it for further use. You do get a Surface from it, but a Surface is much like a weak pointer; it will not keep the ImageReader from getting GC'd if nothing references it (see the note in the developer references)
所以我怀疑如果您只是创建一个类成员mReader变量,然后将reader存储在其中,那么一切都会正常运行.
So I suspect if you just create a class member mReader variable, and store reader in that, everything will work OK.
由于GC算法的差异,它可能在Moto手机上运行;运行时尚未完全清除读者对象,因此有时间调用回调.
It may be working on the Moto phone due to differences in the GC algorithm; the runtime just hadn't gotten around to clearing out the reader object quite yet, so it has time to invoke the callback.
这篇关于android camera2 api-在session.capture之后不会调用onImageAvailable的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!