Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Alternative for this project #184

Open
Artenes opened this issue May 5, 2021 · 1 comment
Open

Alternative for this project #184

Artenes opened this issue May 5, 2021 · 1 comment

Comments

@Artenes
Copy link

Artenes commented May 5, 2021

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();

        }

    }

}
@zhongjie-chen
Copy link

mark

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants