Skip to content

Alternative for this project #184

@Artenes

Description

@Artenes

This is an old project that no longer receives support nor works 100% as expected.

For anyone looking for a simple solution to read QR codes you can use both Android CameraX library and Google ML Kit Barcode library as such:

build.gradle

android {
   compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    implementation 'com.google.mlkit:barcode-scanning:16.1.1'
    implementation "androidx.camera:camera-camera2:1.0.0-beta07"
    implementation "androidx.camera:camera-lifecycle:1.0.0-beta07"
    implementation "androidx.camera:camera-view:1.0.0-alpha14"
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

    <uses-feature android:name="android.hardware.camera.any" />
    <uses-permission android:name="android.permission.CAMERA" />

    <application
        ....
    </application>

</manifest>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    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"
    tools:context=".MainActivity">

    <androidx.camera.view.PreviewView
        android:id="@+id/viewFinder"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

MainActivity.java

package com.example.cameraapptest;

import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
import android.util.Size;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.ImageAnalysis;
import androidx.camera.core.ImageProxy;
import androidx.camera.core.Preview;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.camera.view.PreviewView;

import com.google.common.util.concurrent.ListenableFuture;
import com.google.mlkit.vision.barcode.Barcode;
import com.google.mlkit.vision.barcode.BarcodeScanner;
import com.google.mlkit.vision.barcode.BarcodeScannerOptions;
import com.google.mlkit.vision.barcode.BarcodeScanning;
import com.google.mlkit.vision.common.InputImage;

import java.nio.ByteBuffer;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MainActivity extends AppCompatActivity {

    private static final int REQUEST_CODE_PERMISSIONS = 10;
    private static final String TAG = MainActivity.class.getSimpleName();

    private ExecutorService cameraExecutor;
    private PreviewView viewFinder;

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

        //this view displays camera preview
        viewFinder = findViewById(R.id.viewFinder);

        //checks for permission to either start camera or request permission
        if (hasCameraPermission()) {
            startCamera();
        } else {
            requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CODE_PERMISSIONS);
        }

        //executor where qr code evaluation will happen
        cameraExecutor = Executors.newSingleThreadExecutor();
    }

    private boolean hasCameraPermission() {
        return checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED;
    }

    private void startCamera() {

        ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this);

        cameraProviderFuture.addListener(() -> {

            //this will provide for us the frames from the camera
            ProcessCameraProvider cameraProvider;

            try {

                cameraProvider = cameraProviderFuture.get();

            } catch (ExecutionException | InterruptedException exception) {

                Log.e(TAG, "Unable to get camera provider instance", exception);
                return;

            }

            //set the view where preview will be shown
            Preview preview = new Preview.Builder().build();
            preview.setSurfaceProvider(viewFinder.createSurfaceProvider());

            //use back camera
            CameraSelector cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA;

            //set up QR code analysis
            ImageAnalysis imageAnalysis = new ImageAnalysis.Builder().setTargetResolution(new Size(1280, 720)).build();
            imageAnalysis.setAnalyzer(cameraExecutor, new QRCodeAnalyzer());

            try {

                cameraProvider.unbindAll();

                cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageAnalysis);

            } catch (Exception exception) {

                Log.e(TAG, "Use case binding failed", exception);

            }

        }, getMainExecutor());

    }

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

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == REQUEST_CODE_PERMISSIONS) {
            if (hasCameraPermission()) {
                startCamera();
            } else {
                finish();
            }
        }
    }

    private static class QRCodeAnalyzer implements ImageAnalysis.Analyzer {

        //this is from ml kit
        private BarcodeScanner scanner;

        QRCodeAnalyzer() {
            BarcodeScannerOptions options = new BarcodeScannerOptions.Builder().setBarcodeFormats(Barcode.FORMAT_QR_CODE).build();
            scanner = BarcodeScanning.getClient(options);
        }

        @Override
        public void analyze(@NonNull ImageProxy image) {

            //this analyze method will be called about every second and will provide a camera frame
            //this API is from camerax library, so with this frame we will pass along ml kit library
            //for it to tell us if there is any qr code in the image
            ByteBuffer imageBuffer = image.getPlanes()[0].getBuffer();

            InputImage inputImage = InputImage.fromByteBuffer(
                    imageBuffer,
                    image.getWidth(),
                    image.getHeight(),
                    image.getImageInfo().getRotationDegrees(),
                    InputImage.IMAGE_FORMAT_NV21
            );

            scanner.process(inputImage)
                    .addOnSuccessListener(barcodes -> {
                        //here we receive response from ml kit with the qr codes evaluated
                        for (Barcode barcode : barcodes) {
                            Log.i(TAG, "Read QR code: " + barcode.getDisplayValue());
                        }
                        if (barcodes.isEmpty()) {
                            Log.i(TAG, "No QR codes found");
                        }
                    })
                    .addOnFailureListener(e -> Log.e(TAG, "Failed to read QR code"));

            image.close();

        }

    }

}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions