Logo

Navigation
  • Home
  • Android
  • Web
  • Raspberry Pi
  • PHP
  • Go

Android Barcode Scanner in Fragment

By Rajinder Deol | on December 11, 2016 | 16 Comments
Android Education Technology

I have received quite a few comments on my recent posts Android Barcode Scanner , Android Aadhaar Card Scanner and Android QR Code scanner about integrating the scanner inside a fragment instead of, directly in the activity.

 

So this post will cover full details of how to integrate barcode scanner into a fragment.

Step 1: create application and include dependency

We will use Zxing library for scanning the barcodes. There is an opensource project named ZXing Android Minimal which has embeded this library so we will use this project in our app.Create a blank project in android studio and add ZXing Android Minimal as dependency in your build.gradle file located in app folder.

 
// Added by raj
repositories {
    mavenCentral()

    maven {
        url "http://dl.bintray.com/journeyapps/maven"
    }
}
// Added by raj ends

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:21.0.3'
    // Added by raj
// Supports Android 4.0.3 and later (API level 15)
    compile 'com.journeyapps:zxing-android-embedded:[email protected]'

// Supports Android 2.1 and later (API level 7), but not optimal for later Android versions.
// If you only plan on supporting Android 4.0.3 and up, you don't need to include this.
    compile 'com.journeyapps:zxing-android-legacy:[email protected]'

// Convenience library to launch the scanning and encoding Activities.
// It automatically picks the best scanning library from the above two, depending on the
// Android version and what is available.
    compile 'com.journeyapps:zxing-android-integration:[email protected]'

// Version 3.0.x of zxing core contains some code that is not compatible on Android 2.2 and earlier.
// This mostly affects encoding, but you should test if you plan to support these versions.
// Older versions e.g. 2.2 may also work if you need support for older Android versions.
    compile 'com.google.zxing:core:3.0.1'
// Added by raj ends
}

Step 2 create scan fragment:

Create a new class in your project named ScanFragment extending Fragment.


public class ScanFragment extends Fragment {
}

We will use intent to launch the barcode scanner, so override the onCreate function of fragment and launch scan


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

    IntentIntegrator integrator = new IntentIntegrator(this.getActivity()).forSupportFragment(this);
    // use forSupportFragment or forFragment method to use fragments instead of activity
    integrator.setDesiredBarcodeFormats(IntentIntegrator.ONE_D_CODE_TYPES);
    integrator.setPrompt(this.getString(R.string.scan_bar_code));
    integrator.setResultDisplayDuration(0); // milliseconds to display result on screen after scan
    integrator.setCameraId(0);  // Use a specific camera of the device
    integrator.initiateScan();
}

The intent will require the fragment to have onActivityResult method so that scan result can be returned. Add method onActivityResult to the fragment. I have also declared two string variables codeContent and codeFormat to hold scan data and format


/**
 * function handle scan result
 * @param requestCode scanned code
 * @param resultCode  result of scanned code
 * @param intent intent
 */
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
    //retrieve scan result
    IntentResult scanningResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
    codeContent = scanningResult.getContents();
    codeFormat = scanningResult.getFormatName();
}

Step 3 Integrate fragment in activity:

After creating the scan fragment, we have to invoke this from activity. Create an activity class in your project named HomeActivity. Add a layout in the layout folder named activity_home.xml. Add a button in the layout to start the scan. Add two text views to display the scan data and barcode format. Also add a layout to add fragment programmatically.


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".HomeActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/tv_blog_url"
        android:text="@string/btn_scan_now"
        android:layout_centerHorizontal="true"
        android:onClick="scanNow"
        android:layout_marginBottom="@dimen/activity_vertical_margin"
        android:id="@+id/btn_scan_now" />

    <TextView
        android:id="@+id/scan_format"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textIsSelectable="true"
        android:layout_below="@+id/btn_scan_now"
        android:gravity="center_horizontal"
        android:layout_marginBottom="@dimen/activity_vertical_margin" />
    <TextView
        android:id="@+id/scan_content"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textIsSelectable="true"
        android:layout_below="@+id/scan_format"
        android:layout_marginBottom="@dimen/activity_vertical_margin"
        android:gravity="center_horizontal" />
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/scan_fragment"
        android:orientation="horizontal"></LinearLayout>
    </LinearLayout>
</RelativeLayout>

We have added scanNow function to the button in layout, now add this function to HomeActivity. This function will create and add the fragment to the current activity.


/**
 * event handler for scan button
 * @param view view of the activity
 */
public void scanNow(View view){
    // add fragment
    FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    ScanFragment scanFragment = new ScanFragment();
    fragmentTransaction.add(R.id.scan_fragment,scanFragment);
    fragmentTransaction.commit();
}

Step 4 Return scan data from fragment to activity:

The advantage of using barcode scanner in a fragment is to re-use it with any activity. However we still need a way to send scanned data back to the parent activity. We can add a public method in the activity and call this method from fragment but this will make our fragment dependent on the activity class. So to make our fragment not dependent on the activity class we will create an interface with method scanResultData. Our activity will implement this interface and override this method.

Create a new interface in your project folder named ScanResultReceiver


public interface ScanResultReceiver {
    /**
     * function to receive scanresult
     * @param codeFormat format of the barcode scanned
     * @param codeContent data of the barcode scanned
     */
    public void scanResultData(String codeFormat, String codeContent);

    public void scanResultData(NoScanResultException noScanData);
}

Now update HomeActivity to implement this interface and override scanResultData method. We will use the data received in this method to populate our text views.


@Override
public void scanResultData(String codeFormat, String codeContent){
    // display it on screen
    formatTxt.setText("FORMAT: " + codeFormat);
    contentTxt.setText("CONTENT: " + codeContent);
}

Now update the ScanFragment to use this method and send scanned data back to activity. Updated onActivityResult method will look like:


/**
 * function handle scan result
 * @param requestCode scanned code
 * @param resultCode  result of scanned code
 * @param intent intent
 */
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
    //retrieve scan result
    IntentResult scanningResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
    ScanResultReceiver parentActivity = (ScanResultReceiver) this.getActivity();

    if (scanningResult != null) {
        //we have a result
        codeContent = scanningResult.getContents();
        codeFormat = scanningResult.getFormatName();
        // send received data
        parentActivity.scanResultData(codeFormat,codeContent);

    }else{
        // send exception
        parentActivity.scanResultData(new NoScanResultException(noResultErrorMsg));
    }
}

Step 5 Handle no scan data error:

There will be a case when we will not receive scan result in onActivityResult we need to handle this case and let the parent activity decide what to do. So I have created a custom exception NoScanResultException which will be returned back to the activity. I have used method overloading and added scanResultData twice in interface ScanResultReceiver

Exception class


public class NoScanResultException extends Exception {
    public NoScanResultException() {}
    public NoScanResultException(String msg) { super(msg); }
    public NoScanResultException(Throwable cause) { super(cause); }
    public NoScanResultException(String msg, Throwable cause) { super(msg, cause); }
}

Lets update HomeActivity to implement the second scanResultData. Just for simplicity I am displaying a toast with the error message.


@Override
public void scanResultData(NoScanResultException noScanData) {
    Toast toast = Toast.makeText(this,noScanData.getMessage(), Toast.LENGTH_SHORT);
    toast.show();
}

This is a very basic implementation of barcode scanner in fragment. As always the full source code can be found on my github profile under android-barcode-scanner-in-fragment

Related

Share this story:
  • tweet

Recent Posts

  • RaspberryPi with PiHole to block ads everywhere

    September 22, 2021 - 2 Comments
  • Reviving RaspberryPi 1 Model B in 2021 After 7 years

    September 13, 2021 - 1 Comment
  • NodeJS Consumer for AWS SQS using Docker

    November 10, 2018 - 3 Comments

Author Description

16 Responses to “Android Barcode Scanner in Fragment”

  1. March 15, 2017

    Don Reply

    I am getting the following runtime error relating to camera… Do you have any suggestions? Thanks!

    3-15 00:17:29.821 16782-16782/in.whomeninja.android_barcode_scanner I/com.google.zxing.client.android.camera.open.OpenCameraInterface: Opening camera #0
    03-15 00:17:29.821 16782-16782/in.whomeninja.android_barcode_scanner W/CameraBase: An error occurred while connecting to camera: 0
    03-15 00:17:29.821 16782-16782/in.whomeninja.android_barcode_scanner W/CaptureActivity: Unexpected error initializing camera
    java.lang.RuntimeException: Fail to connect to camera service
    at android.hardware.Camera.(Camera.java:568)

    • March 16, 2017

      Rajinder Deol Reply

      Hi Don,

      try to connect a real device to deploy and test. Emulators sometimes does not work for cameras.

      Also please check the API version of your app in your build.gradle file check: https://github.com/rajdeol/android-barcode-scanner-in-fragment/blob/master/app/build.gradle

      • March 16, 2017

        Don Reply

        Thanks for the quick reply, I have the app working now. I’m not exactly sure what was causing the issue originally but I was testing the app on a Samsung Tab A, not an emulator. I originally upgraded the Gradle build files and commented out the one dependency since this app will only run on lollipop and later. Ultimately I started with the clean slate, exactly as you zipped it and then slowly worked through updating the build. I ended up with everything working now. I did make other change and switched to a new version, com.journeyapps:zxing-android-embedded:3.4.0
        The only issue I came across with that version is that integrator.setResultDisplayDuration(0) was removed from this build due to redundancy and coding issues. As far as I can tell, everything functions fine. Now I just need to integrate into the app I am building.
        Thanks again.

        • March 17, 2017

          Rajinder Deol Reply

          glad to know that the issue is resolved, all the best for your app. Let me know if you need any help.

  2. April 13, 2017

    Bozo Reply

    The problem I have is : scanner does not work in fragment and that was the point. It runs in full screen. It scans but I need it in fragment, not in full screen, since I need to place other things on the same screen. Actually the fragment id=”@+id/scan_fragment” is totally ignored and scanner runs in its own space somehow. It works exactly the same like when I run it with
    fragmentTransaction.add (scanFragment, “”);

    • April 18, 2017

      Rajinder Deol Reply

      Hi Bozo,

      the default zxing implementation is not that extendable so it ignores ui changes. I have used another implementation in my post Android Barcode Scanner vertical orientation (portrait mode) which allow you to modify the view.

      Have a look at it and let me know if it works.

    • April 22, 2017

      Don Reply

      Did you have any luck running the barcode within a fragment?

      • April 24, 2017

        Rajinder Deol Reply

        Hi Don,

        it works in fragment but in full screen mode, checkout my post Android Barcode Scanner in Fragment

  3. October 6, 2017

    ajay Reply

    after scaning barcode camera is not stop

    • October 7, 2017

      Rajinder Deol Reply

      Hi Ajay,

      are you getting any error in the error logs ? can you explain a bit more.

  4. November 5, 2017

    Santiago Reply

    Hi, im trying to use your code but i cant pass this as parametre in this line
    IntentIntegrator integrator = new IntentIntegrator(getActivity()).forFragment(this);
    Please i hope that you can help me, regards from Colombia.

    • November 6, 2017

      Rajinder Deol Reply

      Hi Santiago,

      can you please share the error you are getting.

  5. March 6, 2020

    YongWook Kim Reply

    Thank you brother!! This helped to complete the task. T_T

  6. November 9, 2020

    Thomas Reply

    Hello Rajinder,

    I’ve written a little android app including SQLite and I want to integrate the barcode scanner.But I have some headache regarding the implemtation in a fragment. So I need some help (payment via paypal?). Please let me know, if you have a little bit time for me…

    Thanks a lot and kind regards
    Thomas

    • November 9, 2020

      Rajinder Deol Reply

      Hi Thomas,

      sure I can help, what is the issue you are facing ?

  7. November 9, 2020

    Thomas Reply

    Hello Rajinder, first thanks for your fast reply. The application is for a logistic company. On the main activity there is an EditView and a container, where the barcode scanner should be shown.When I click a button, the barcode scanner (ZXing) should be opened in a fragment, and this fragment should be shown in a container on the main activity. As soon as the barcode is recognised, the barcode should be written into the EditView on the main activity. If the bark on scanner can’t recognise the barcode, this would be a possibility to stop the process. Maybe it’s easier to explain, if I can send you a little video or some screenshots.Is there any email address, where I can send it to? Thanks a lot and best regards, Thomas

Leave a Reply Cancel Reply

Your email address will not be published. Required fields are marked *


*
*

Recent Posts

  • RaspberryPi with PiHole to block ads everywhere
  • Reviving RaspberryPi 1 Model B in 2021 After 7 years
  • NodeJS Consumer for AWS SQS using Docker
  • Laravel development using docker-compose with nginx and Mysql
  • Writing Your First Service in Golang Go-Micro

Subscribe to Blog via Email

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Join 9 other subscribers

Categories

  • Android (7)
  • Education (9)
  • Go (2)
  • PHP (5)
  • Raspberry Pi (4)
  • Technology (17)
  • Web (8)

Author details:

Raj Deol

Raj Deol

Traveller, Foodie and electronics enthusiast.

View Full Profile →

© 2016. All Rights Reserved.