Scan a QR Code by using the front camera

TBMSamTBMSam Member ✭✭
edited February 20 in Xamarin.Android

Hello altogether,

I try to create a simple app that can scan a qr code and process its data.

I made it with the following tutorial: https://www.c-sharpcorner.com/article/xamarin-android-qr-code-reader-by-mobile-camera/

Now I have some questions concerning this:

1.) I tested it with several mobile devices, but the image quality seems to be extremly bad. Sometimes it works, sometimes not. But this has nothing to do with the device's camera quality, when installing an external qr-scanner-app, it always works. Is there a way to increase the quality? I read something about ZXing scanner, is this available for Xamarin.Android, too?
2.) Now it scans (or tries to scan^^) the qr code using the backside camera of the device. Is it somehow possible to use the front camera instead?

(Refering amongst others to https://forums.xamarin.com/discussion/22130/is-there-any-way-to-scan-qr-code-with-front-camera, but unfortunately the link provided there is broken).

Please let me share my code so far, maybe it's easier to help me:

QrCodeScanner.axml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <SurfaceView
        android:layout_width="480dp"
        android:layout_height="480dp"
        android:layout_centerInParent="true"
        android:id="@+id/cameraPreview" />
    <TextView
        android:layout_centerInParent="true"
        android:gravity="center_horizontal"
        android:text="Bitte fokussieren Sie den QR-Code"
        android:layout_below="@+id/cameraPreview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="20sp"
        android:layout_marginTop="20dp"
        android:id="@+id/resultTextView" />
</RelativeLayout>

QrCodeScannerActivity.cs:

[Activity(Label = "QrCodeScannerActivity", Theme ="@style/Theme.AppCompat.Light.NoActionBar")]
public class QrCodeScannerActivity : AppCompatActivity, ISurfaceHolderCallback, IProcessor
{
    SurfaceView cameraPreview;
    TextView resultTxt;
    BarcodeDetector barcodeDetector;
    CameraSource cameraSource;
    const int RequestCameraPermissionID = 1001;

    public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
    {
        switch (requestCode)
        {
            case RequestCameraPermissionID:
                {
                    if(grantResults[0] == Permission.Granted)
                    {
                        if (ActivityCompat.CheckSelfPermission(ApplicationContext, Manifest.Permission.Camera) != Android.Content.PM.Permission.Granted)
                        {
                            ActivityCompat.RequestPermissions(this, new string[]
                            {
                Manifest.Permission.Camera
                            }, RequestCameraPermissionID);
                            return;
                        }
                        try
                        {
                            cameraSource.Start(cameraPreview.Holder);
                        }
                        catch (InvalidOperationException)
                        {

                        }
                    }
                }
                break;
        }
    }
    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        SetContentView(Resource.Layout.QrCodeScanner);

        cameraPreview = FindViewById<SurfaceView>(Resource.Id.cameraPreview);
        resultTxt = FindViewById<TextView>(Resource.Id.resultTextView);

        barcodeDetector = new BarcodeDetector.Builder(this).SetBarcodeFormats(BarcodeFormat.QrCode).Build();
        cameraSource = new CameraSource.Builder(this, barcodeDetector).SetRequestedPreviewSize(640, 480).Build();

        cameraPreview.Holder.AddCallback(this);
        barcodeDetector.SetProcessor(this);
    }
    public void SurfaceChanged(ISurfaceHolder holder, [GeneratedEnum] Format format, int width, int height)
    {

    }
    public void SurfaceCreated(ISurfaceHolder holder)
    {
        if (ActivityCompat.CheckSelfPermission(ApplicationContext, Manifest.Permission.Camera) != Android.Content.PM.Permission.Granted)
        {
            ActivityCompat.RequestPermissions(this, new string[]
            {
                Manifest.Permission.Camera
            }, RequestCameraPermissionID);
            return;
        }
        try
        {
            cameraSource.Start(cameraPreview.Holder);
        }
        catch (InvalidOperationException)
        {

        }
    }
    public void SurfaceDestroyed(ISurfaceHolder holder)
    {
        cameraSource.Stop();
    }
    public void ReceiveDetections(Detections detections)
    {
        SparseArray qrcodes = detections.DetectedItems;
        if (qrcodes.Size() != 0)
        {
            resultTxt.Post(()=>
            {
                Vibrator vib = (Vibrator)GetSystemService(Context.VibratorService);
                vib.Vibrate(1000);
                resultTxt.Text = ((Barcode)qrcodes.ValueAt(0)).RawValue;
            });
        }
    }
    public void Release()
    {

    }
}

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.kling.klingonemobile" android:installLocation="preferExternal">
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="27" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.VIBRATE"/>
  <application android:label="KlingOnEMobile" android:theme="@android:style/Theme.Holo.Light.NoActionBar" android:windowActionBar="false" android:windowNoTitle="true" android:icon="@drawable/Joker_0256x0256">
    <meta-data android:name="com.google.android.gms.vision.DEPENDENCIES" android:value="barcode" />    
  </application>
</manifest>

I would be very thankful for every answer.

Best regards

Best Answer

Answers

  • jezhjezh Member, Xamarin Team Xamurai
    edited February 21

    For ZXing scanner in Xamarin Android, you can check ZXing.Net.Mobile
    The Nuget is this: https://www.nuget.org/packages/ZXing.Net.Mobile/

  • TBMSamTBMSam Member ✭✭
    edited February 21

    Thank you so much for answering and for your help.

    The usage of the front camera works, but unfortunately .SetAutoFocusEnabled(true) seems to have no effect :(

    I tested it again with several devices, sometimes it works, so the app can read/display the data read, sometimes not.

    What could be the problem here?

    Let me briefly describe the situation:
    Samsung Galaxy S4: own app (code above) works, so is able to read and process the qr code, external qr app as well
    Acer B3 A40: same own app, camera image displayed well (similar to the Samsung device), but holding the same qr code (which worked above) to scan over the camera, it has no effect. Regardless of its distance to the device. Nevertheless using an external qr app works always, so the quality of the camera itself isn't the problem.

  • TBMSamTBMSam Member ✭✭

    Hmm I think it is not the quality of the camera image which is the problem @jezh

    I found out that I can furthermore do .SetRequestedFps(). But this has no effect as well. And the display seems to be well, at least for my eye, but he can't detect the qr code when holding it into the camera on several devices.

    What can I do to increase the qr code detector quality?

Sign In or Register to comment.