我正在修改Google针对Android的Camera2 API示例,可在此处找到:https://github.com/googlesamples/android-Camera2Basic
我正在将捕获的图像上传到Cloudinary,显然需要在后台线程中这样做,因此UI不会被阻止。
然而,我遇到的问题是,即使根据我的理解,也不应该在上传图像时阻止UI,因为Handler是使用后台线程中的Looper创建的像这样:
private void startBackgroundThread() {
mBackgroundThread = new HandlerThread("CameraBackground");
mBackgroundThread.start();
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
}
ImageSaver类负责将捕获的映像写入磁盘,如下所示:
private static class ImageSaver implements Runnable {
/**
* The JPEG image
*/
private final Image mImage;
/**
* The file we save the image into.
*/
private final File mFile;
public ImageSaver(Image image, File file ) {
mImage = image;
mFile = file;
}
@Override
public void run() {
ByteBuffer buffer = mImage.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
FileOutputStream output = null;
try {
output = new FileOutputStream(mFile);
output.write(bytes);
InputStream is = new ByteArrayInputStream(bytes);
Map uploadResult = CloudinaryManager.getInstance().uploader().upload(is, ObjectUtils.asMap(
"api_key", CloudinaryManager.CLOUDINARY_API_KEY,
"api_secret", CloudinaryManager.CLOUDINARY_SECRET_KEY
));
System.out.println("result");
} catch (IOException e) {
e.printStackTrace();
} finally {
mImage.close();
if (null != output) {
try {
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
此处将ImageSaver添加到处理程序:
private final ImageReader.OnImageAvailableListener mOnImageAvailableListener
= new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
mBackgroundHandler.post(new ImageSaver(reader.acquireNextImage(), mFile));
}
};
我希望得到任何帮助或建议,指出我正确的方向。
答案 0 :(得分:1)
我相信它是因为摄像机正在使用背景锁定...因为你从ImageReader获取一个Image,我怀疑它是在你完成资源之前一直锁定...所以作为一个建议,我会填充onImageAvailable中的字节数组,关闭你获得的图像,并将字节数组发送到AsyncTask来执行保存
答案 1 :(得分:0)
我有同样的问题,经过一些调查和测试,发现它实际上并没有冻结用户界面,它冻结了相机预览,在许多相机应用程序上给人的印象相同。
如果您查看方法unLockFocus(),您会发现它将相机设置回正常的预览状态。
查看调用它的位置,您可以看到它直到图像保存为止:
.
.
.
CameraCaptureSession.CaptureCallback CaptureCallback
= new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(@NonNull CameraCaptureSession session,
@NonNull CaptureRequest request,
@NonNull TotalCaptureResult result) {
showToast("Saved: " + mFile);
Log.d(TAG, mFile.toString());
unlockFocus();
}
};
通过在相机保存序列中的较早点调用此功能,可以启用预览,并且UI会在更早的时候再次解锁。
我已经进行了实验,如果在获取图像之后和保存之前调用它似乎有效 - 我还在captureCallback中删除了对unLockFocus的原始调用。请注意,我没有对竞争条件等进行任何正确的测试,因此我强烈建议您自己进行试验,以确保您的案例有效(如果我对其进行更多验证,我会更新此信息):
/**
* This a callback object for the {@link ImageReader}. "onImageAvailable" will be called when a
* still image is ready to be saved.
*/
private final ImageReader.OnImageAvailableListener mOnImageAvailableListener
= new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
Log.d(TAG,"onImageAvailable");
//Get the image
Image cameraImage = reader.acquireNextImage();
//Now unlock the focus so the UI does not look locked - note that this is a much earlier point than in the
//original Camera2Basic example from google as the original place was causing the preview to lock during any
//image manipulation and saving.
unlockFocus();
//Save the image file in the background - note check you have permissions granted by user or this will cause an exception.
mBackgroundHandler.post(new ImageSaver(getActivity().getApplicationContext(), cameraImage, outputPicFile);
}
};