如何将扫描到的实际条码图像传递至ImageView或Activity
我有一个Android Activity,支持两种条码扫描功能:
- 从相册选择图片扫描条码,将结果显示在TextView,选中的图片显示在ImageView
- 启动相机实时扫描条码,将结果显示到对应TextView
我通过第三方库间接使用Google Mobile Vision API,扫描速度很快,但现在遇到一个问题:无法将扫描到的实际条码图像传递到ImageView。我已经查阅了该库的示例、Google Mobile Vision文档和网络资料,都没找到解决方案。
我的核心回调代码如下:
@Override public void onRetrieved(final Barcode barcode) { Log.d(TAG, "Barcode read: " + barcode.displayValue); runOnUiThread(new Runnable() { @Override public void run() { AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this) .setTitle("code retrieved") .setMessage(barcode.displayValue); builder.show(); } }); } // 多条码回调 @Override public void onRetrievedMultiple(final Barcode closetToClick, final List<BarcodeGraphic> barcodeGraphics) { runOnUiThread(new Runnable() { @Override public void run() { String message = "Code selected : " + closetToClick.displayValue + "\n\nother codes in frame include : \n"; for (int index = 0; index < barcodeGraphics.size(); index++) { Barcode barcode = barcodeGraphics.get(index).getBarcode(); message += (index + 1) + ". " + barcode.displayValue + "\n"; } AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this) .setTitle("code retrieved") .setMessage(message); builder.show(); } }); } @Override public void onBitmapScanned(SparseArray<Barcode> sparseArray) { for (int i = 0; i < sparseArray.size(); i++) { Barcode barcode = sparseArray.valueAt(i); Log.e("value", barcode.displayValue); } } @Override public void onRetrievedFailed(String reason) { // 失败处理 }
代码运行正常,但我能否通过SparseArray<Barcode>获取到扫描到的实际条码图像?
首先明确一点:Google Mobile Vision的Barcode对象本身并不包含条码的原始图像数据,它只存储了条码的识别结果、位置边界框(boundingBox)等元数据。不过我们可以针对两种扫描场景,通过以下方案获取并显示条码图像:
1. 相册图片扫描场景(onBitmapScanned回调)
如果是从相册选择图片扫描,你需要先保留原始Bitmap的引用(在调用扫描API前保存),然后利用Barcode的boundingBox属性从原始Bitmap中裁剪出条码区域:
// 提前保存你从相册选中的原始Bitmap private Bitmap mSelectedAlbumBitmap; // 在调用扫描方法前赋值,比如从相册获取Bitmap后 // mSelectedAlbumBitmap = ...; @Override public void onBitmapScanned(SparseArray<Barcode> sparseArray) { if (sparseArray.size() > 0 && mSelectedAlbumBitmap != null) { Barcode barcode = sparseArray.valueAt(0); Rect barcodeRect = barcode.boundingBox; // 裁剪条码区域(注意:如果Bitmap有旋转,需要先调整Rect的坐标) Bitmap barcodeBitmap = Bitmap.createBitmap( mSelectedAlbumBitmap, barcodeRect.left, barcodeRect.top, barcodeRect.width(), barcodeRect.height() ); // 切换到UI线程显示到ImageView runOnUiThread(() -> { mBarcodeImageView.setImageBitmap(barcodeBitmap); Log.e("value", barcode.displayValue); }); } }
注意:如果相册图片存在方向旋转(比如带Exif旋转信息),需要先根据Exif数据旋转原始Bitmap,再进行裁剪,否则boundingBox的坐标会和实际图像不匹配。
2. 相机实时扫描场景(onRetrieved/onRetrievedMultiple回调)
这种情况相对复杂,取决于你使用的第三方库是否开放了相机预览帧的获取权限:
- 如果第三方库提供获取当前相机预览帧的API,直接拿到预览帧的Bitmap,再用
barcode.boundingBox裁剪出条码区域即可。 - 如果第三方库没有提供该API,你可能需要直接使用Google Mobile Vision的原生API,自己处理相机预览回调:
- 在相机预览的
onPreviewFrame回调中获取帧数据(通常是YUV格式),转换为Bitmap。 - 将Bitmap传给
BarcodeDetector进行识别。 - 识别到条码后,用
barcode.boundingBox从转换后的Bitmap中裁剪出条码区域,再显示到ImageView。
- 在相机预览的
另外,相机预览的坐标可能和屏幕坐标存在旋转/镜像差异,你需要根据设备的屏幕方向、相机的预览方向调整boundingBox的坐标,确保裁剪区域正确。
关于SparseArray<Barcode>的补充
SparseArray里的Barcode对象同样只包含位置和识别结果数据,没有图像信息,所以你必须依赖原始的图像源(相册Bitmap或相机预览帧)来裁剪出条码图像。
内容的提问来源于stack exchange,提问作者Hardik sharma

