QR code 생성 하기.
 2014/08/12 - [Android Study] - Android QR code

 이번에는 Scanner code 에 대해서 설명 해보도록 하겠음.
Camera preview 를 이용한 기법이므로 camera preview 정도는 가볍게 해결 해주셔야함.

 일단은 Camera preview callback 함수 부터.
     private Camera.PreviewCallback mPreviewCallback = new Camera.PreviewCallback() {
        // Frame 제한 시간
        private static final long FRAME_RATE_TIME = 200; // 200:5, 124:8, 100:10
        // Frame 체크용 시간 변수
        private long mCheckTime = 0;

        @Override
        public void onPreviewFrame(byte[] data, Camera camera) {
            boolean checkImage = false;
            // Frame 제한 시간을 넘는 경우에만 decode 작업을 수행
            if (mCheckTime == 0) {
                mCheckTime = System.currentTimeMillis();
                checkImage = true;
            } else {
                long current = System.currentTimeMillis();
                if (current - mCheckTime > FRAME_RATE_TIME) {
                    mCheckTime = current;
                    checkImage = true;
                }
            }

            if (checkImage == true) {
                mThread.insert(data, camera.getParameters().getPreviewSize());
            }
        }
    };


 코드 자체는 별 내용이 없고 Thread에 YUV 데이터를 전달 하는게 전부 인데, 시간 interval을 준 까닭은 Preview size가 너무 클 경우 YUV data 가 무지막지하게 커지는 경향이 있음.
 이럴 경우 decode에 과부하가 걸려서 Camera preview가 제대로 동작 안하고 버벅이는 현상이 발생함.

그다음 Thread 부분은.
    private class QRDecorderThread extends Thread {
        // Queue의 최대 값
        private static final int QUEUE_MAX = 3;
        // YUV data blocking queue
        private BlockingQueue<byte[]> mQueue;
        // UI 쪽에 data를 전달 할 Handler
        private Handler mHandler;
        // Preview size 변수
        private Camera.Size mSize;

        public QRDecorderThread(Handler handler) {
            mHandler = handler;
            mQueue = new ArrayBlockingQueue<byte[]>(QUEUE_MAX);
        }

        @Override
        public void run() {
            while (true) {
                try {
                    byte[] data = mQueue.take();

                    PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(
                            data, mSize.width, mSize.height, 0, 0, mSize.width,
                            mSize.height, false);

                    BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(
                            source));

                    QRCodeReader reader = new QRCodeReader();

                    try {
                        Result result = reader.decode(bitmap);
                        String resultData = result.getText();
                        // 결과물이 있을 경우 preview 정지 및 UI 쪽에 data 전달
                        if (resultData != null) {
                            mCamera.stopPreview();
                            mHandler.sendMessage(mHandler.obtainMessage(0,
                                    resultData));
                        }
                    } catch (Exception e) {
                    }
                } catch (InterruptedException e) {
                    break;
                }
            }
        }

        public void insert(byte[] data, Camera.Size size) {
            try {
                mSize = size;
                mQueue.put(data);
            } catch (InterruptedException e) {
            }
        }
    }

사실은 저기 Thread 내부에서 새로 생성하는 class 들도 어떻게 잘 조절하면 new를 안하고 재활용 할 수 있을 듯한데...
음 거기까진 잘 모르겠음.
그리고 하나더 Camera parameter를 setting 할때 분명 preview에 대한 FrameRate를 설정 할 수 있는 걸로 알고 있는데 이것 또한
시도 해보지 않음...
여하튼 이런식으로 하면 동작하긴 함. 

'Android' 카테고리의 다른 글

Android HTTPS SHA128 인증서 오류  (0) 2017.02.08
Sharedpreferences 에 관하여  (0) 2015.04.04
Android QR code  (0) 2014.08.12
Android AsyncTask 함정 카드  (1) 2014.08.03
Android Custom Widget 만들기 7편  (0) 2012.04.12

+ Recent posts