Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Zbar with Android : Scanner camera viewport remain inactive and black after showing the url in browser

I need to have a QR scanner in my project. I use ZBar for doing this task. Mainly I did a very small change on the example code given by ZBar git example to do the job. I need to show the scanned result in a browser(if url) or in a dialog(if normal information).

Every thing working well with my code given bellow except if I try to show the url after scan a qr code in browser. When I come back to my app from the browser the camera viewport turns black and remain inactive. I tried to get back the camera active to scan another qr code but i failed. I tried to reopen the camera in my onResume() function but that causes error and forcefully exited from the app. Please help me on that issue.

    package com.myapp;
    import net.sourceforge.zbar.Config;
    import net.sourceforge.zbar.Image;
    import net.sourceforge.zbar.ImageScanner;
    import net.sourceforge.zbar.Symbol;
    import net.sourceforge.zbar.SymbolSet;
    import android.app.Activity;
    import android.app.AlertDialog;
    import android.content.DialogInterface;
    import android.content.Intent;
    import android.content.pm.ActivityInfo;
    import android.hardware.Camera;
    import android.hardware.Camera.AutoFocusCallback;
    import android.hardware.Camera.PreviewCallback;
    import android.hardware.Camera.Size;
    import android.net.Uri;
    import android.os.Bundle;
    import android.os.Handler;
    import android.webkit.URLUtil;
    import android.widget.FrameLayout;

    import com.myapp.CameraPreview;
    /* Import ZBar Class files */

    public class QRScannerActivity extends Activity
    {
        private Camera mCamera;
        private CameraPreview mPreview;
        private Handler autoFocusHandler;

        ImageScanner scanner;

        private boolean barcodeScanned = false;
        private boolean previewing = true;

        static {
            System.loadLibrary("iconv");
        } 

        @Override
        protected void onCreate(Bundle savedInstanceState) {

            super.onCreate(savedInstanceState);

            setContentView(R.layout.qr_scanner_main);

            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

            autoFocusHandler = new Handler();
            mCamera = getCameraInstance();

            /* Instance barcode scanner */
            scanner = new ImageScanner();
            scanner.setConfig(0, Config.X_DENSITY, 3);
            scanner.setConfig(0, Config.Y_DENSITY, 3);

            mPreview = new CameraPreview(this, mCamera, previewCb, autoFocusCB);
            FrameLayout preview = (FrameLayout)findViewById(R.id.cameraPreview);
            preview.addView(mPreview);
        }

        @Override
        protected void onPause() {
            super.onPause();
            releaseCamera();
            //finish();
        }

        /** A safe way to get an instance of the Camera object. */
        public static Camera getCameraInstance(){
            Camera c = null;
            try {
                c = Camera.open();
            } catch (Exception e){
            }
            return c;
        }

        private void releaseCamera() {
            //Toast.makeText(QRScannerActivity.this, "Paused State", Toast.LENGTH_SHORT).show();
            if (mCamera != null) {
                previewing = false;
                mCamera.setPreviewCallback(null);
                mPreview.getHolder().removeCallback(mPreview);
                mCamera.release();
                mCamera = null;
            }

        }

        private Runnable doAutoFocus = new Runnable() {
                public void run() {
                    if (previewing)
                        mCamera.autoFocus(autoFocusCB);
                }
            };

        PreviewCallback previewCb = new PreviewCallback() {
                public void onPreviewFrame(byte[] data, Camera camera) {
                    Camera.Parameters parameters = camera.getParameters();
                    Size size = parameters.getPreviewSize();

                    Image barcode = new Image(size.width, size.height, "Y800");
                    barcode.setData(data);

                    int result = scanner.scanImage(barcode);
                    String QRScannerResult;

                    if (result != 0) {
                        previewing = false;
                        mCamera.setPreviewCallback(null);
                        mCamera.stopPreview();

                        SymbolSet syms = scanner.getResults();
                        for (Symbol sym : syms) {
                            QRScannerResult = sym.getData();
                            showResultAction(QRScannerResult);
                            barcodeScanned = true;

                        }
                    }
                }
            };

        // Mimic continuous auto-focusing
        AutoFocusCallback autoFocusCB = new AutoFocusCallback() {
                public void onAutoFocus(boolean success, Camera camera) {
                    autoFocusHandler.postDelayed(doAutoFocus, 1000);
                }
            };

        private void showResultAction(String QRScannerResult){
                if (URLUtil.isValidUrl(QRScannerResult)) {

                    if (barcodeScanned) {
                        barcodeScanned = false;
                        mCamera.setPreviewCallback(previewCb);
                        mCamera.startPreview();
                        previewing = true;
                        mCamera.autoFocus(autoFocusCB);
                    }

                    Intent i = new Intent(Intent.ACTION_VIEW);
                    i.setData(Uri.parse(QRScannerResult));
                    startActivity(i);

                    }else {
                        new AlertDialog.Builder(this)
                        .setTitle("QR Data")
                        .setMessage(QRScannerResult)
                        .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) { 
                                if (barcodeScanned) {
                                    barcodeScanned = false;
                                    mCamera.setPreviewCallback(previewCb);
                                    mCamera.startPreview();
                                    previewing = true;
                                    mCamera.autoFocus(autoFocusCB);
                                }
                            }
                         })
                         .show();
                    }

        }
    }

Thanks in advance. Sakib

like image 522
Sakib Avatar asked Jul 24 '13 06:07

Sakib


1 Answers

At last I succeeded to find out the problem of my code and got the solution. When i try to reopen the camera in my onResume() method I missed a part. When I create/open a new camera in onResume(), the FrameLayout still has my previous camera. So All I do is remove my previous camera from FrameLayout on onPause() method and then recreate everything on onResume() method. That solve my problem and now it is working nicely without any error. Here is my onPause() and onResume() method with the fix. Hope this might help somebody in future.

    public void onPause() {
        super.onPause();
        releaseCamera();
        FrameLayout preview = (FrameLayout)findViewById(R.id.cameraPreview);
        preview.removeView(mPreview);
    }

    public void onResume(){
        super.onResume();

        try {
            if(mCamera==null){

            //setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            autoFocusHandler = new Handler();
            mCamera = getCameraInstance();
            this.getWindowManager().getDefaultDisplay().getRotation();

            scanner = new ImageScanner();
            scanner.setConfig(0, Config.X_DENSITY, 3);
            scanner.setConfig(0, Config.Y_DENSITY, 3);

            mPreview = new CameraPreview(this, mCamera, previewCb, autoFocusCB);
            FrameLayout preview = (FrameLayout)findViewById(R.id.cameraPreview);
            preview.addView(mPreview);
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block

        }
    }

    /** A safe way to get an instance of the Camera object. */
    public static Camera getCameraInstance(){
        Camera c = null;
        try {
            c = Camera.open();
        } catch (Exception e){
        }
        return c;
    }

    private void releaseCamera() {
        //Toast.makeText(QRScannerActivity.this, "Paused State", Toast.LENGTH_SHORT).show();
        if (mCamera != null) {
            previewing = false;
            mCamera.setPreviewCallback(null);
            mPreview.getHolder().removeCallback(mPreview);
            mCamera.release();
            mCamera = null;
            mPreview= null;
        }

    }

Thanks, Sakib

like image 161
Sakib Avatar answered Nov 14 '22 21:11

Sakib