Android 调用UVCCamera 采集UVC摄像头数据,并调用zxing 扫码库扫码

zxing 提供的sample都是原生camera采集摄像头数据,而android上使用UVCCamera采集摄像头的情况比较多,那么怎么在uvccamera采集到摄像头数据,并调用zxing扫码呢。直接上代码。

DecodeHandle.java

package com.baidu.idl.face.main.decode;

import android.content.Context;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.PlanarYUVLuminanceSource;
import com.google.zxing.ReaderException;
import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer;

import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.EnumMap;
import java.util.EnumSet;

public class DecodeHandler {

    private final DecodeListener mListener;
    private boolean isAvailable = true;
    private static final int DECODE_BITMAP = 0;
    private static final int DECODE_YUV = 1;
    //private QrDecoder mDecoder;
    private DecodeThread mDecodThread;
    private int mTimeout;
    Context mContext;
    private int mWidth;
    private int mHeight;

    private final Map<DecodeHintType, Object> hints;
    private Collection<BarcodeFormat> decodeFormats;
    private final MultiFormatReader multiFormatReader;

    public DecodeHandler(Context context, DecodeListener listener,final int width, final int height) {
        mWidth = width;
        mHeight = height;
        mListener = listener;
        mContext = context;
        //mDecoder = new QrDecoder(context);
        HandlerThread thread = new HandlerThread("qr_decode_thread");
        thread.start();
        mDecodThread = new DecodeThread(thread.getLooper());

        //扫码初始化
        multiFormatReader = new MultiFormatReader();

        decodeFormats = EnumSet.of(BarcodeFormat.QR_CODE, BarcodeFormat.CODE_128);
        hints = new EnumMap<>(DecodeHintType.class);
        hints.put(DecodeHintType.POSSIBLE_FORMATS, decodeFormats);
        String characterSet = "utf-8";
        if (characterSet != null) {
            hints.put(DecodeHintType.CHARACTER_SET, characterSet);
        }
        hints.put(DecodeHintType.TRY_HARDER, true);

        multiFormatReader.setHints(hints);
    }

    public void release() {
        setAvailable(false);
        mDecodThread.getLooper().quit();
    }

    public void pushYuv(byte[] yuv) {
        Log.d("MainActivity","pushYuv()");
        if (isAvailable()) {
            setAvailable(false);
            mDecodThread.obtainMessage(DECODE_YUV, yuv).sendToTarget();
        }
    }

    private boolean isAvailable() {
        return isAvailable;
    }

    private void setAvailable(boolean b) {
        isAvailable = b;
    }

    private class DecodeThread extends Handler {
        DecodeThread(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case DECODE_YUV:
                {
                    decode((byte[])msg.obj,mWidth,mHeight);
                    setAvailable(true);

                }
                break;
            }
        }
    }

    /**
     * @param data   A preview frame.
     * @param width  The width of the image.
     * @param height The height of the image.
     * @return A PlanarYUVLuminanceSource instance.
     */
    public PlanarYUVLuminanceSource buildLuminanceSource(byte[] data, int width, int height) {
        return new PlanarYUVLuminanceSource(data, width, height, 0, 0,
                width, height, false);
    }

    /**
     * @param data   The YUV preview frame.
     * @param width  The width of the preview frame.
     * @param height The height of the preview frame.
     */
    private void decode(byte[] data, int width, int height) {

        long start = System.currentTimeMillis();
        Result rawResult = null;
        PlanarYUVLuminanceSource source = buildLuminanceSource(data, width, height);
        if (source != null) {
            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
            try {
                rawResult = multiFormatReader.decodeWithState(bitmap);

  
                BarcodeFormat format = rawResult.getBarcodeFormat();
                //类型
                String type = format.toString();
                String strScan = rawResult.getText();

                String content = new String(strScan.trim());

                if (!TextUtils.isEmpty(content)) {
                    mListener.onDecodeSuccess(content);
                }
            } catch (ReaderException re) {
                // continue
                mListener.onDecodeFailed(-1);
            } finally {
                multiFormatReader.reset();
            }
        }

    }

}

 

DecodeListener.java

package com.baidu.idl.face.main.decode;


public interface DecodeListener {

    public void onDecodeSuccess(final String content);

    public void onDecodeFailed(final int error);
}

 

### UVCCamera 应用点击预览时崩溃的解决方案 当遇到UVCCamera应用在点击预览时发生奔溃的情况,通常可能是由于多种原因引起的。以下是几种可能的原因以及相应的解决方法: #### 1. USB权限未授予 如果应用程序尝试访问USB设备而没有获得必要的权限,则可能会导致异常终止。确保已请求获得了USB权限。 ```java UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE); HashMap<String, UsbDevice> deviceList = manager.getDeviceList(); Iterator<UsbDevice> deviceIterator = deviceList.values().iterator(); while(deviceIterator.hasNext()){ UsbDevice usbDevice = deviceIterator.next(); if (!manager.hasPermission(usbDevice)) { PendingIntent pi = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0); manager.requestPermission(usbDevice, pi); } } ``` #### 2. 预览分辨率设置不当 某些特定分辨率可能导致硬件不兼容或性能瓶颈从而引发错误。可以先测试较低分辨率来验证是否稳定工作,逐步调整至所需的最佳配置[^3]。 对于高分辨率如`2064 * 1548`,建议降低到更常见的尺寸比如720p或者VGA级别再做进一步优化。 #### 3. 线程管理问题 图像采集过程应当放在后台线程执行而不是主线程中完成,以免阻塞UI响应造成ANR(Application Not Responding)[^1]。 使用HandlerThread或其他异步机制处理耗时操作: ```java private HandlerThread mBackgroundThread; private Handler mHandler; mBackgroundThread = new HandlerThread("CameraPreview"); mBackgroundThread.start(); mHandler = new Handler(mBackgroundThread.getLooper()); // 将相机初始化和其他重载任务放入此handler中运行 ``` #### 4. 资源释放不足 每次关闭预览之前都应该正确清理资源,防止内存泄漏或者其他潜在风险。这包括停止视频流、断开与外设连接等措施[^4]。 ```java @Override protected void onDestroy(){ super.onDestroy(); if(camera != null){ camera.close(); // 关闭摄像机实例 camera = null; } if(textureView!=null && textureView.isAvailable()) textureView.release(); // 清理纹理视图资源 if(mBackgroundThread!=null){ mBackgroundThread.quitSafely(); try{ mBackgroundThread.join(); mBackgroundThread=null; mHandler=null; }catch(final InterruptedException e){ Log.e(TAG,"Exception",e); } } } ``` 通过以上几个方面的排查和改进,应该能够有效减少甚至消除UVCCamera应用启动预览功能时发生的崩溃现象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值