Android barcode scanner on Github

As written in the previous part of this story, I was looking for a simple Android barcode scanner application that allowed me to simply catch the barcodes of my comic magazine. Long story short, I stumbled upon the ZXing library and related example application, but, by default, it did not properly build with a recent Android Studio. Let’s see how I managed to solve this…

Android barcode

Building ZXing example app with Android Studio

The first step was obviously to clone the ZXing repository available at github. Then I let Android Studio look for something it could recognize as an Android project: it seemed to succeed, but, when building, there were many errors, the first ones related to the missing Resource class.

Googling a bit, I found a page in the Android developer website which seemed to me a very good starting point, so I tried following those instructions. The result is in the following paragraphs.

Start Android Studio and create a new project: Phone and Tablet with No Activity. Let’s call it “Barcode Scanner” and use “com.google.zxing.client.android” as the package name.

Phone and Tablet Application with No Activity
Application initial settings

After filling the remaining initial settings, click Finish and let Android Studio create the project tree. The important thing in this step is the package name, since using com.google.zxing.client.android allows us to keep the import statements for the Resource class unchanged.

We now need to load the project with the content available in the official zxing repo: let’s start with the resources.

Filling the project with content

Copy the content of

zxing/android/res/

into

BarcodeScanner/app/src/main/res/

making sure to avoid overwriting colors.xml and themes.xml, since they need to be merged instead of being overwritten.

Now copy the content of

android/src/com/google/zxing/client/android/

to

BarcodeScanner/app/src/main/java/com/google/zxing/client/android/

Create the directory

core

inside

BarcodeScanner/app/src/main/java/com/google/zxing/

and copy the content of

zxing/core/src/main/java/com/google/zxing/

Copy the file

zxing/android-core/src/main/java/com/google/zxing/client/android/camera/CameraConfigurationUtils.java

inside

BarcodeScanner/app/src/main/java/com/google/zxing/client/android/camera/open/

Open the file

CameraConfigurationUtils.java

and replace its package name with

package com.google.zxing.client.android.camera.open;

Then, open the file

CameraConfigurationManager.java

and add the following import:

import com.google.zxing.client.android.camera.open.CameraConfigurationUtils;

This will help us to avoid complicating the project directory structure, by removing the zxing/android-core part, since it has just a single file.

Reload the project from the disk and start building it. The build will fail due to multiple errors of type “Constant expression required”.

This error is found when using id from resources in switch/case constructs for ADT versions >= 14. A nice Android Studio Project page tells us what to do: simply refactor the code to use an if/else construct instead of the switch/case. Android Studio refactoring capabilities help for that: just highlight the switch statement and press Alt + Enter. Choose Replace ‘switch’ with ‘if’ in the menu and the code will be fixed. Repeat the procedure for each error reported.

Dealing with runtime errors

The build should now be fine, but, after editing the configuration for choosing module Barcode_Scanner.app.main, if you run the app in your phone or emulator you will notice the following error:

05/12 19:21:23: Launching 'app.zxingcore' on Google Pixel 4a.
Install successfully finished in 2 s 896 ms.
Could not identify launch activity: Default Activity not found
Error while Launching activity
Failed to launch an application on all devices

This error makes sense, since, so far, we did not indicate which activity is the default one. The original AndroidManifest.xml should be merged with the Android barcode scanner application one.

Copy all the uses-permission and uses-feature, but avoid uses-sdk, since this piece of information does not belong anymore to the manifest, but it’s instead in the gradle script. Merge the application tags icon and logo. Expand the application section with all the activities available in the original manifest and change the CaptureActivity tag “exported” to “true”, since the Activity can receive intents.

Let’s now build again the project and run it. Unfortunately, an error pop-up related to the camera will show, blocking the app: the on screen message box does not help much, but we can look at what the logcat is telling us:

W An error occurred while connecting to camera 0: Status(-8, EX_SERVICE_SPECIFIC): '1: validateClientPermissionsLocked:1292: Caller "com.google.zxing.client.android" (PID 10049, UID 30781) cannot open camera "0" without camera permission'
W Unexpected error initializing camera
java.lang.RuntimeException: Fail to connect to camera service

Looks like a permission issue, but in the manifest we do already have

<uses-permission android:name="android.permission.CAMERA"/>

Asking Google for another hint, it turns out that the runtime permission is required, and it should be granted by the user. We need to add some code for that and to me it seems that the a good place would be the main activity, i.e. the CaptureActivity.

Let’s add the following code snippet at the end of the method OnCreate:

if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA)
        != PackageManager.PERMISSION_GRANTED) {
    Log.d(TAG, "Asking for camera permission");
    ActivityCompat.requestPermissions((Activity) this,
    new String[] { android.Manifest.permission.CAMERA }, 100);
}

Then add also the following method:

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == 100 &&
            grantResults[0] == PermissionChecker.PERMISSION_GRANTED) {
        finish();
        overridePendingTransition(0, 0);
        startActivity(getIntent());
        overridePendingTransition(0, 0);
    } else {
        finish();
    }
}

Rebuild the project and start it again: the pop-up asking for the permission to use the camera should now show-up and, if granted, everything should be fine. There are still warnings/deprecated API usage that need to be fixed, but it’s enough to start playing with the app.

Android barcode scanner repo

You can find the BarcodeScanner code at github.

Is this the end?

No, there are at least two more things needed:

  • This application can’t still read my comics magazines barcodes
  • There are still errors found by Lint