【发布时间】:2019-03-15 15:10:30
【问题描述】:
我使用 camera2 api 实现了一个自定义的 Android 相机,当我点击捕获按钮时,我将捕获的图像保存到我的手机永久存储中。
现在我需要在保存之前显示一个弹出窗口来输入图片名称,并且这个弹出窗口有一个 imageView 来显示捕获的图像。
即使我从主线程加载图像,我也会收到此错误
"Only the original thread that created a view hierarchy can touch its views"
这里是代码
private void initPopup(final Bitmap bitmap) {
popAddName = new Dialog(this);
popAddName.setContentView(R.layout.popup_add_name);
popAddName.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
popAddName.getWindow().setLayout(Toolbar.LayoutParams.MATCH_PARENT, Toolbar.LayoutParams.WRAP_CONTENT);
popAddName.getWindow().getAttributes().gravity = Gravity.TOP;
popup_add = popAddName.findViewById(R.id.popup_add);
popup_img = popAddName.findViewById(R.id.popup_img);
popup_name = popAddName.findViewById(R.id.popup_name);
Thread thread = new Thread() {
@Override
public void run() {
runOnUiThread(new Runnable() {
@Override
public void run() {
Picasso.with(getApplicationContext()).load(getImageUri(getApplicationContext(), bitmap)).placeholder(R.drawable.placeholder).into(popup_img);
}
});
}
};
thread.start();
}
这是将Bitmap转换为Uri以进行Picasso加载的方法
public Uri getImageUri(Context inContext, Bitmap inImage) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, "Title", null);
return Uri.parse(path);
}
这是捕获方法
ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader imageReader) {
Image image = null;
try {
image = reader.acquireLatestImage();
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.capacity()];
buffer.get(bytes);
//CONVERTION BYTES[] TO BITMAP
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
//create a new folder in external storage directory
String lorealFolder = "coffretPics";
File f = new File(Environment.getExternalStorageDirectory(), lorealFolder);
if (!f.exists()) {
f.mkdirs();
}
initPopup(bitmap);
popAddName.show();
file = new File(Environment.getExternalStorageDirectory() + "/" + lorealFolder + "/" + UUID.randomUUID().toString() + ".jpg");
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 outputStream = null;
try {
outputStream = new FileOutputStream(file);
outputStream.write(bytes);
} finally {
if (outputStream != null) {
outputStream.close();
}
}*/
}
};
谁能告诉我这是什么问题?
【问题讨论】:
-
您必须向 UI 线程发布消息并从那里更改 UI。有多种方法可以做到这一点(如果您在活动中,则使用 runOnUIThread,对主线程使用 Handler 并向其发布消息,使用 rxjava 或类似库等)。选择你最喜欢的。
-
在您的情况下,回调正在另一个线程上运行,因为它是从它用于联网的线程中调用的。所以你需要在那里发布到 ui 线程。通常你不想在网络线程上做所有的处理,然后只在ui线程上做ui更改。
-
@GabeSechan 你能发布一个例子,我很乐意接受。还是谢谢你,先生。
-
@SamuelPhilipp 这不是因为我已经在尝试该解决方案但它不起作用。
标签: java android error-handling android-camera2