Git Product home page Git Product logo

betterbarcodes's Introduction

BetterBarcodes

The best way to read and display barcodes.

  • Works on API level 14 and above: That's 99% of all Android devices. BetterBarcodes takes care backwards compatibility so you don't have to worry about a thing!
  • Extensive support of barcode formats: Read and display 1D or 2D barcodes in almost all common formats.
  • No lag, no loading times: Uses the newest API and most efficient implementation to ensure the best possible performance and user experience.

Build Status BCH compliance

How do I add it to my project?

Just add this to the dependencies closure in your build.gradle:

compile 'com.github.wrdlbrnft:better-barcodes:0.3.0.46'

Example App

There is an example app maintained for BetterBarcodes you can find it on GitHub here.

Or if you just want to test the library you can download the example app from the Play Store:

Get it on Google Play

How do I use it?

BetterBarcodes includes two ready to use Views which you can add to your layout:

  • BarcodeView: Displays a barcode in one or many different formats.
  • BarcodeReaderView: Reads a barcode by using the camera of the device.

BarcodeReaderView

Basic usage

The BarcodeReaderView can be used to read a barcode of a format of your choosing.

To use the BarcodeReaderView add it to your layout like this:

<com.github.wrdlbrnft.betterbarcodes.views.reader.BarcodeReaderView
    android:id="@+id/barcode_reader"
    android:layout_width="match_parent"
    android:layout_height="250dp"
    app:format="qr_code|code128"/>

The custom attribute format can be used to set the barcode formats you want to read. You can also do that at runtime by using the setFormat() method:

barcodeReaderView.setFormat(BarcodeFormat.QR_CODE, BarcodeFormat.CODE_128);

After that you need to start and stop the reading process by calling start() and stop().

  • start(): Starts the camera preview and immediately starts looking any barcodes in the cameras field of view.
  • stop(): Stops the camera preview and stops looking for barcodes.

Usually you would call start() in onResume() and stop() in onPause(). It is not recommended to leave the camera running while your app is in the background.

@Override
public void onResume() {
    super.onResume();
    barcodeReaderView.start();
}

@Override
public void onPause() {
    super.onPause();
    barcodeReaderView.stop();
}

You can also independently control preview and scanning by calling startPreview() and startScanning() as well as stopScanning() and stopPreview(). However you cannot scan for barcodes without the preview running so calling startScanning() will also start the camera preview. In the same way stopPreview() will also stop scanning for barcodes.

Runtime Permissions

On API levels 23 and above you need handle the runtime permission for the camera which the BarcodeReaderView has to use. There are two options:

  • Either you can handle them entirely on your own. In that case you need to make sure that start() is only called once the permission has been granted
  • However the preferable option is to use the permission request logic which is built into the BarcodeReaderView!

Using the built-in permission request logic is simple:

You have to set a PermissionHandler on the BarcodeReaderView. The PermissionHandler has callback methods to easily handle permission requests, show the permission rational when required and callbacks when the permission is granted or denied. To simplify implementing the PermissionHandler there is the PermissionHandler.Adapter class. The basic implementation - in this example in a Fragment - looks like this:

private PermissionRequest mPermissionRequest;

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    barcodeReaderView.setCameraPermissionHandler(new PermissionHandler.Adapter() {
        @Override
        public void onNewPermissionRequest(PermissionRequest request) {
            mPermissionRequest = request;
            request.start(ExampleFragment.this);
        }
    });
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    mPermissionRequest.onRequestPermissionsResult(requestCode, permissions, grantResults);
}

In the onNewPermissionRequest() method of the PermissionHandler you have to save the PermissionRequest instance that is passed in a field. By calling start() on the PermissionRequest with the current instance of your Fragment or Activity you start the actual permission request process. Later in the onRequestPermissionsResult() callback in your Fragment or Activty you have to call the method of the same name on the PermissionRequest and pass in the parameters. This implementation is enough to handle a complete request for the permission. However you can also override additional methods to show a rationale and to handle cases where the permission is granted or denied:

barcodeReaderView.setCameraPermissionHandler(new PermissionHandler.Adapter() {

    @Override
    public void onNewPermissionRequest(PermissionRequest request) {
        mPermissionRequest = request;
        request.start(ReaderFragment.this);
    }

    @Override
    public boolean onShowRationale() {

        final AlertDialog rationaleDialog = new AlertDialog.Builder(getContext())
                .setTitle(R.string.rationale_title)
                .setMessage(R.string.rationale_message)
                .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int button) {
                        dialogInterface.dismiss();
                        
                        // Call this to continue the request process after showing your rationale in whatever way you want.
                        mPermissionRequest.continueAfterRationale(ExampleFragment.this);
                    }
                })
                .create();

        rationaleDialog.show();
        
        // Return true here if you show a rationale
        return true;
    }

    @Override
    public void onPermissionGranted() {
        // Called when the permission is granted
    }

    @Override
    public void onPermissionDenied() {
        // Called when the permission is denied
    }
});

BarcodeView

The BarcodeView can be used to display barcodes in one or more formats. How the barcodes are displayed on the screen is controlled by a BarcodeLayoutManager instance. BetterBarcodes comes with a few predefined, ready to use BarcodeLayoutManagers.

To use the BarcodeView add it to your layout like this:

<com.github.wrdlbrnft.betterbarcodes.views.writer.BarcodeView
    android:id="@+id/barcode_view"
    android:layout_width="match_parent"
    android:layout_height="250dp"
    app:format="qr_code|code128"
    app:text="@string/barcode_text">

The custom attribute format can be used to set the formats you want to display your barcode in. The custom attribute text is used to set the text the barcode should display, this can be a string or a string resource.

Of course you can also set both of those things at runtime:

barcodeView.setFormat(BarcodeFormat.QR_CODE, BarcodeFormat.CODE_128);
barcodeView.setText("Some Text");

Per default the BarcodeView uses the HorizontalRotatingLayoutManager. BetterBarcodes includes the following BarcodeLayoutManager implementations:

  • SimpleVerticalBarcodeLayoutManager
  • LinearBarcodeLayoutManager
  • HorizontalRotatingLayoutManager

If you want to use one of these you can set it using the setLayoutManager() method. Of course you can always implement your own BarcodeLayoutManager! To simplify this BetterBarcodes includes the AbsBarcodeLayoutManager class which you should use if you want to implement your own one.

Usage without the Views

If you just want to create a barcode image without using the BarcodeView you can do that like this:

final BarcodeWriter writer = BarcodeWriters.forFormat(BarcodeFormat.QR_CODE);
final Bitmap barcodeImage = writer.write("Some Text", someWidth, someHeight);

You can also read barcodes without using the BarcodeReaderView.

You can either place an AspectRatioTextureView in your layout and then create a BarcodeReader instance from it to read barcodes using them camera:

final BarcodeReader reader = BarcodeReaders.get(context, aspectRatioTextureView);
reader.setFormat(BarcodeFormat.QR_CODE, BarcodeFormat.CODE_128);

reader.startPreview();
reader.startScanning();
...
reader.stopScanning();
reader.stopPreview();

The BarcodeReader object works in principle the same way as the BarcodeReaderView does - including the way you can handle runtime permissions.

However you can also read barcodes in bitmaps and images from other sources by using a BarcodeImageDecoder. It is recommended to use a try/catch/finally block like below to reliably read barcodes:

final BarcodeImageDecoder decoder = BarcodeImageDecoders.forFormat(context, BarcodeFormat.QR_CODE, BarcodeFormat.CODE_128);

try {
    final String text = decoder.decode(someImageAsByteArray, imageWidth, imageHeight);
    // Barcode found and decoded
} catch (FormatException | ChecksumException | NotFoundException e) {
    // No Barcode found in the image or barcode is invalid.
} finally {
    // Every time a barcode is decoded you have to reset the BarcodeImageDecoder
    decoder.reset();
}

Based on ZXing

BetterBarcodes is using ZXing for encoding and decoding barcodes, check out their GitHub page here.

betterbarcodes's People

Contributors

wrdlbrnft avatar xaverkapeller avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

betterbarcodes's Issues

BarcodeView does not display PDF417 barcodes.

When using the BarcodeView, it does not display the PDF_417 barcode type.
When debugging, the error in found on line 18 of the FormatUtils.java.

In a nutshell, the FORMAT_MAP does not contain an entry for PDF_417, in which the format returns null when trying to display this type of barcode.

Proposed fix would be to include this entry- ".put(BarcodeFormat.PDF_417, com.google.zxing.BarcodeFormat.PDF_417)"

Thanks!

Tapping the preview area a few times causes autofocus force close for me 100%

2018-11-18 00:12:23.895 11729-11729/com.ideal.Audacy E/Camera: Error 2
2018-11-18 00:12:23.905 11729-11729/com.ideal.Audacy E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.ideal.Audacy, PID: 11729
java.lang.RuntimeException: autoFocus failed
at android.hardware.Camera.native_autoFocus(Native Method)
at android.hardware.Camera.autoFocus(Camera.java:1312)
at com.github.wrdlbrnft.betterbarcodes.reader.a.a$3.run(Unknown Source:28)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6665)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:772)

NPE happened

Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.os.Handler.post(java.lang.Runnable)' on a null object reference
at com.github.wrdlbrnft.betterbarcodes.reader.base.a.a(Unknown Source)
at com.github.wrdlbrnft.betterbarcodes.reader.a.a.a(Unknown Source)
at com.github.wrdlbrnft.betterbarcodes.reader.a.b.onPreviewFrame(Unknown Source)
at android.hardware.Camera$EventHandler.handleMessage(Camera.java:1272)
at android.os.Handler.dispatchMessage(Handler.java:111)
at android.os.Looper.loop(Looper.java:210)
at android.app.ActivityThread.main(ActivityThread.java:5839)
at java.lang.reflect.Method.invoke(Method.java)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1113)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:879)

Unable on/off flash

something like this

camera = Camera.open();
Camera.Parameters parameters = camera.getParameters();
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
camera.setParameters(parameters);

Fail to connect to camera service

Fatal Exception: java.lang.RuntimeException: Fail to connect to camera service
       at android.hardware.Camera.(Camera.java:653)
       at android.hardware.Camera.open(Camera.java:512)
       at com.github.wrdlbrnft.betterbarcodes.reader.a.a.a(Unknown Source)
       at com.github.wrdlbrnft.betterbarcodes.reader.a.a.a(Unknown Source)
       at com.github.wrdlbrnft.betterbarcodes.reader.base.a.startPreview(Unknown Source)
       at com.github.wrdlbrnft.betterbarcodes.views.reader.BarcodeReaderView.start(Unknown Source)
       at com.kfit.fave.fragment.QRScannerFragment.onResume(QRScannerFragment.java:132)
       at android.support.v4.app.Fragment.performResume(Fragment.java:2390)
       at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1474)
       at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1759)
       at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1827)
       at android.support.v4.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3244)
       at android.support.v4.app.FragmentManagerImpl.dispatchResume(FragmentManager.java:3212)
       at android.support.v4.app.FragmentController.dispatchResume(FragmentController.java:217)
       at android.support.v4.app.FragmentActivity.onResumeFragments(FragmentActivity.java:509)
       at android.support.v4.app.FragmentActivity.onPostResume(FragmentActivity.java:498)
       at android.support.v7.app.AppCompatActivity.onPostResume(AppCompatActivity.java:171)
       at android.app.Activity.performResume(Activity.java:6276)
       at android.app.ActivityThread.performNewIntents(ActivityThread.java:2772)
       at android.app.ActivityThread.handleNewIntent(ActivityThread.java:2779)
       at android.app.ActivityThread.access$1700(ActivityThread.java:188)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1602)
       at android.os.Handler.dispatchMessage(Handler.java:111)
       at android.os.Looper.loop(Looper.java:210)
       at android.app.ActivityThread.main(ActivityThread.java:5839)
       at java.lang.reflect.Method.invoke(Method.java)
       at java.lang.reflect.Method.invoke(Method.java:372)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1113)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:879)

This cause only happen on Android 4.4 and 5. Above those version, it was fine

License of this project

Hello,

the project looks very promising and I would like to use it for an Android app of mine. What are the terms and conditions for incorporating the code into my own project? Is an explicit stating of one of the usual open source licenses just missing or do some special conditions apply here?

Best regards

Providing the library via mavenCentral

Hi,

I know last time I asked about the license in #10 you mentioned that this library is not actively worked on any more. Despite this, is it possible to make it available as it is via mavenCentral to include it via this channel into build.gradle files?

Best regards

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.