While using the IntentIntegrator from the ZXing library, can I add a flash button to the barcode scanner via the Intent?

允我心安 提交于 2021-01-28 23:05:33

问题


I am scanning barcodes and QR codes from an Android app via Intent using the ZXing Library and its port of the Android Application. I added the following two lines in my Gradle dependencies to use the android-integration code without modification:

compile 'com.journeyapps:zxing-android-embedded:3.2.0@aar'
compile 'com.google.zxing:core:3.2.1'

And I am using IntentIntegrator in my Activity to scan a barcode in the onCreate() like this:

integrator = new IntentIntegrator(this);
integrator.setOrientationLocked(false);
integrator.setPrompt(getString(R.string.scanner_text)); // Set the text of the scanner
integrator.setCameraId(0);  // Use a specific camera of the device
integrator.setBeepEnabled(true); // Enable beep in the scanner
integrator.setBarcodeImageEnabled(false); // Do not fetch image from the camera
integrator.initiateScan();

Everything works and I get correct scanned result, but I want a flash button in the lower right corner of the scanner like this:

I can already control the flash using the volume up and down keys because I override the CaptureActivity. Is a flash button like the one above already there in the barcode scanner which can switch between AUTO, ON and OFF mode? If there is, can I use the addExtra() method of the IntentIntegrator to activate it? Or is the only way to implement this would be to modify the entire code according to my needs?


回答1:


I had overlooked this page on Embedding BarcodeView and these sample activities which show how to customise the Barcode Scanner according to your needs. The example activity that helped me was CustomScannerActivity.

There isn't a option in the IntentIntegrator class to implement a flash button natively. Instead I should make a custom layout for the Barcode Scanner, use it in a custom activity and call this activity from the IntentIntegrator.

I have two activities. One is the ScannerActivity and other one is the CallingActivity. A mistake that confused me for a while was that I created an instance of IntentIntegrator in the onCreate() method of ScannerActivity. It should be in the CallingActivity.

In the example given a Button is used and the text of the Button is changed according to the flash. I created a new Android Layout called activity_custom_scanner where I replaced the Button with a ToggleButton and used images for the button instead to get my desired Flash On/Off Button.

So my ScannerActivity looks like this:

public class CustomScannerActivity extends Activity implements
        CompoundBarcodeView.TorchListener {

    private static final int BarCodeScannerViewControllerUserCanceledErrorCode = 99991;

    private static final String TAG = CustomScannerActivity.class.getSimpleName();

    private CaptureManager capture;
    private CompoundBarcodeView barcodeScannerView;
    private ToggleButton switchFlashlightButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_custom_scanner);

        barcodeScannerView = (CompoundBarcodeView)findViewById(R.id.zxing_barcode_scanner);
        barcodeScannerView.setTorchListener(this);

        switchFlashlightButton = (ToggleButton)findViewById(R.id.switch_flashlight);

        switchFlashlightButton.setText(null);
        switchFlashlightButton.setTextOn(null);
        switchFlashlightButton.setTextOff(null);

        // if the device does not have flashlight in its camera,
        // then remove the switch flashlight button...
        if (!hasFlash()) {
            switchFlashlightButton.setVisibility(View.GONE);
        }

        switchFlashlightButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                // Save the state here
                if (isChecked) {
                    barcodeScannerView.setTorchOn();
                } else {
                    barcodeScannerView.setTorchOff();
                }
            }
        });

        capture = new CaptureManager(this, barcodeScannerView);
        capture.initializeFromIntent(getIntent(), savedInstanceState);
        capture.decode();
    }

    @Override
    protected void onResume() {
        super.onResume();
        capture.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        capture.onPause();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        capture.onDestroy();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        capture.onSaveInstanceState(outState);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        return barcodeScannerView.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event);
    }

    /**
     * Check if the device's camera has a Flashlight.
     * @return true if there is Flashlight, otherwise false.
     */
    private boolean hasFlash() {
        return getApplicationContext().getPackageManager()
                .hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
    }

    @Override
    public void onTorchOn() {
        // necessary override..
    }


    @Override
    public void onTorchOff() {
        // necessary override..
    }

}

And the CallingActivity looks like this:

public class CallingActivity extends Activity {

    private static final String TAG = CallingActivity.class.getSimpleName();

    private static final int BarCodeScannerViewControllerUserCanceledErrorCode = 99991;

    String uuid;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        uuid = getIntent().getStringExtra("uuid");
        new IntentIntegrator(this).setOrientationLocked(false).setCaptureActivity(CustomScannerActivity.class).initiateScan();
    }



    public void onActivityResult(int requestCode, int resultCode, Intent intent) {

        IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);

        if (resultCode == RESULT_OK) {
            if (scanResult != null) {

                // handle scan result
                Log.i(TAG, "Text from Barcode Scanner: " + scanResult.getContents());
                getIntent().putExtra("data", scanResult.getContents());
                getIntent().putExtra("uuid", uuid);
            }
        }
        else if (resultCode == RESULT_CANCELED) {
            getIntent().putExtra("error", "User canceled");
            getIntent().putExtra("error_code", BarCodeScannerViewControllerUserCanceledErrorCode);
        }
        else
        {
            getIntent().putExtra("error", getString(R.string.scanner_error));
            getIntent().putExtra("error_code", BarCodeScannerViewControllerUserCanceledErrorCode);
        }

        setResult(resultCode, this.getIntent());

        this.finish();
    }

}

I am not sure if it's the perfect way, but that's how I did it.

Hope it helps someone!




回答2:


There is a setTorchOn method in CompoundBarcodeView so you can check that method out and try to implement it for your needs. Hope it helps.




回答3:


This question is probably too old, but you can use the Volume buttons to turn on/off the torch while scanning.



来源:https://stackoverflow.com/questions/35993253/while-using-the-intentintegrator-from-the-zxing-library-can-i-add-a-flash-butto

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!