Visualizzazione post con etichetta Qrcode. Mostra tutti i post
Visualizzazione post con etichetta Qrcode. Mostra tutti i post

mercoledì 26 agosto 2020

Scansioni codici QR in Kotlin Android

Nel 2013 avevo fatto qualche esperimento con la lettura dei codici a barre tramite la libreria ZXing.

Ad oggi le funzioni di scansioni dei codici sono incluse nelle librerie di Google Play ma le trovo complicate mentre la libreria ZXing (https://github.com/zxing/zxing) e' in maintenance mode. Ho trovato una alternativa a questo link    https://github.com/yuriy-budiyev/code-scanner

build.gradle(app)

implementation 'com.budiyev.android:code-scanner:2.1.0'

Layout
=====================================================
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">

<com.budiyev.android.codescanner.CodeScannerView
android:id="@+id/scanner_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:autoFocusButtonColor="@android:color/white"
app:autoFocusButtonVisible="true"
app:flashButtonColor="@android:color/white"
app:flashButtonVisible="true"
app:frameColor="@android:color/white"
app:frameCornersSize="50dp"
app:frameCornersRadius="0dp"
app:frameAspectRatioWidth="1"
app:frameAspectRatioHeight="1"
app:frameSize="0.75"
app:frameThickness="2dp"
app:maskColor="#77000000"/>
</FrameLayout>

</androidx.constraintlayout.widget.ConstraintLayout>
=====================================================
codice

=====================================================

    val scannerView = findViewById<CodeScannerView>(R.id.scanner_view)

codeScanner = CodeScanner(this, scannerView)

// Parameters (default values)
codeScanner.camera = CodeScanner.CAMERA_BACK // or CAMERA_FRONT or specific camera id
codeScanner.formats = CodeScanner.ALL_FORMATS // list of type BarcodeFormat,
// ex. listOf(BarcodeFormat.QR_CODE)
codeScanner.autoFocusMode = AutoFocusMode.SAFE // or CONTINUOUS
codeScanner.scanMode = ScanMode.SINGLE // or CONTINUOUS or PREVIEW
codeScanner.isAutoFocusEnabled = true // Whether to enable auto focus or not
codeScanner.isFlashEnabled = false // Whether to enable flash or not

// Callbacks
codeScanner.decodeCallback = DecodeCallback {
runOnUiThread {
Toast.makeText(this, "Scan result: ${it.text}", Toast.LENGTH_LONG).show()
}
}
codeScanner.errorCallback = ErrorCallback { // or ErrorCallback.SUPPRESS
runOnUiThread {
Toast.makeText(this, "Camera initialization error: ${it.message}",
Toast.LENGTH_LONG).show()
}
}

scannerView.setOnClickListener {
codeScanner.startPreview()
}
}

override fun onResume() {
super.onResume()
codeScanner.startPreview()
}

override fun onPause() {
codeScanner.releaseResources()
super.onPause()
}

lunedì 1 aprile 2013

Zbar QRcode Scanner

Sulla base dell'esperienza di questo post sull'utilizzo della libreria zxing ha voluto provare la libreria ZBar piu' che altro per la necessita' di avere una maggiore velocita' di acquisizione

La principale differenza tra i due metodi e' che in Zxing si usa l'Intent ovvero si lancia una applicazione esterna e si attende il risultato mentre con ZBar si usa una libreria nativa inclusa nella propria applicazione


Il risultato e' una velocita' di elaborazione decisamente piu' veloce (ho dovuto creare una procedura apposita per impedire le acquisizione multiple su un stesso QrCode perche' il programma e' piu' veloce nel riconoscimento dello spostamento della mano)

Molto utile e' l'esempio compreso nella libreria che rende il tutto operativo in pochi minuti

Segue il codice di un programma che sto sviluppando per il riconoscimento dei pettorali delle corse podistiche
-----------------------------------------------------------------------

/*
 * Basic no frills app which integrates the ZBar barcode scanner with
 * the camera.
 * 
 * Created by lisah0 on 2012-02-24
 */
package net.sourceforge.zbar.android.CameraTest;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.Timer;
import java.util.TimerTask;

import net.sourceforge.zbar.android.CameraTest.CameraPreview;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.pm.ActivityInfo;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;

import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.Button;
import android.widget.Toast;

import android.hardware.Camera;
import android.hardware.Camera.PreviewCallback;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.Size;

import android.widget.TextView;

/* Import ZBar Class files */
import net.sourceforge.zbar.ImageScanner;
import net.sourceforge.zbar.Image;
import net.sourceforge.zbar.Symbol;
import net.sourceforge.zbar.SymbolSet;
import net.sourceforge.zbar.Config;

public class CameraTestActivity extends Activity
{
    private Camera mCamera;
    private CameraPreview mPreview;
    private Handler autoFocusHandler;

    TextView scanText;
    Button scanButton;

    ImageScanner scanner;

    private boolean previewing = true;
private long partenza;
private String old_pettorale;
private String pettorale;
private TextView pett;
private EditText man;
private int contatore;


    static {
        System.loadLibrary("iconv");
    } 

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        setContentView(R.layout.main);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        contatore = 0;
        pettorale = "";
        
        autoFocusHandler = new Handler();
        mCamera = getCameraInstance();

        /* Instance barcode scanner */
        scanner = new ImageScanner();
        scanner.setConfig(0, Config.X_DENSITY, 3);
        scanner.setConfig(0, Config.Y_DENSITY, 3);

        mPreview = new CameraPreview(this, mCamera, previewCb, autoFocusCB);
        FrameLayout preview = (FrameLayout)findViewById(R.id.cameraPreview);
        preview.addView(mPreview);
        scanText = (TextView)findViewById(R.id.scanText);
        pett = (TextView)findViewById(R.id.pettorale);
        man = (EditText)findViewById(R.id.editText1);

        //gestisce l'introduzione manuale del pettorale
        man.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
                    //Log.d("test","Premuto il tasto Done");
                pettorale = man.getText().toString();
                    long attuale = System.currentTimeMillis();
                    long x = (attuale-partenza) / 1000;
          long seconds = x % 60;
          x /= 60;
          long minutes = x % 60;
          x /= 60;
          long hours = x % 24;
          x /= 24;
          long days = x;
          contatore = contatore + 1;
          String ora_passaggio = new SimpleDateFormat("HH:mm:ss dd/MM/yyyy").format(new Date(System.currentTimeMillis()));
          String race_time = String.format("%02d:%02d:%02d", hours,minutes,seconds);
          String str3 = Integer.toString(contatore)+";"+pettorale + ";" + race_time +"\n";
          pett.setText(str3);
         
     
          
          playAlarm();
          scrivi(ora_passaggio+";"+str3);
          send_udp(str3);
                    man.setText("");
                    old_pettorale=pettorale;
                    
                    }

// TODO Auto-generated method stub
return false;
}
});
        
    }

    public void onPause() {
        super.onPause();
        releaseCamera();
    }

    /** A safe way to get an instance of the Camera object. */
    public static Camera getCameraInstance(){
        Camera c = null;
        try {
            c = Camera.open();
        } catch (Exception e){
        }
        return c;
    }

    private void releaseCamera() {
        if (mCamera != null) {
            previewing = false;
            mCamera.setPreviewCallback(null);
            mCamera.release();
            mCamera = null;
        }
    }

    private Runnable doAutoFocus = new Runnable() {
            public void run() {
                if (previewing)
                    mCamera.autoFocus(autoFocusCB);
            }
        };

    PreviewCallback previewCb = new PreviewCallback() {
            private long attuale;
private String race_time;
private String ora_passaggio;
private String str3;
private String chk;

public void onPreviewFrame(byte[] data, Camera camera) {
                Camera.Parameters parameters = camera.getParameters();
                Size size = parameters.getPreviewSize();

                Image barcode = new Image(size.width, size.height, "Y800");
                barcode.setData(data);

                int result = scanner.scanImage(barcode);
                
                if ((result != 0) && (!start)) 
            {
            pett.setText("Partenza non effettuata");
            }
                
                if ((result != 0) && (start)) {
                    SymbolSet syms = scanner.getResults();
                    for (Symbol sym : syms) {
                        pettorale = sym.getData();        
                    }
                        attuale = System.currentTimeMillis();
                        if (!pettorale.equals(old_pettorale)) //evita le immissioni multiple di un pettorale
                       {
              long x = (attuale-partenza) / 1000;
          long seconds = x % 60;
          x /= 60;
          long minutes = x % 60;
          x /= 60;
          long hours = x % 24;
          x /= 24;
          long days = x;
          contatore = contatore + 1;
          chk ="Arrivo";
          race_time = String.format("%02d:%02d:%02d", hours,minutes,seconds);
          ora_passaggio = new SimpleDateFormat("HH:mm:ss dd/MM/yyyy").format(new Date(System.currentTimeMillis()));
          str3 =  Integer.toString(contatore)+";"+pettorale + ";" + race_time +"\n";
          pett.setText(str3);
          
          playAlarm();
          old_pettorale = pettorale;
          //pettorale = "";
          scrivi(ora_passaggio+";"+str3);
          send_udp(str3);
                   }
                        else
                        {// se il pettorale e' gia' stato battuto fai un suono differente
               //scanText.setText("Gia' acquisito");
                                               
                        }
                        
                        
        } //if result
            } // preview Frame
        }; //termina il callback
        
        
 private void playAlarm() {
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);
r.play();
 }     
        

 private void scrivi(String testo)
{
File sdcard = Environment.getExternalStorageDirectory();
    if (sdcard.canWrite()) 
     {
     File localFile2 = new File(sdcard, "passaggi.txt");
         FileWriter localFileWriter1 = null;
 try {
localFileWriter1 = new FileWriter(localFile2, true);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
 BufferedWriter localBufferedWriter = new BufferedWriter(localFileWriter1);
 try {
localBufferedWriter.write(testo);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
 try {
localBufferedWriter.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
 }// chiude la scrittura su file
 }


 private void send_udp(String testo)
 {
DatagramSocket socket = null;
//testo = "luca";
try {
socket = new DatagramSocket();
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
    InetAddress serverIP = null;
try {
serverIP = InetAddress.getByName("192.168.0.100");
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
     byte[] outData = testo.getBytes();
     DatagramPacket out = new DatagramPacket(outData,outData.length, serverIP,55000);
     try {
socket.send(out);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
     socket.close();
 }

    public void onBackPressed() {
   new AlertDialog.Builder(this)
          .setMessage("Vuoi uscire?")
          .setCancelable(false)
          .setPositiveButton("Si", new DialogInterface.OnClickListener() {
              public void onClick(DialogInterface dialog, int id) {
                   finish();
              }
          })
          .setNegativeButton("No", null)
          .show();
}

    // Mimic continuous auto-focusing
    AutoFocusCallback autoFocusCB = new AutoFocusCallback() {
            public void onAutoFocus(boolean success, Camera camera) {
                autoFocusHandler.postDelayed(doAutoFocus, 1000);
            }
        };
private boolean start;
        
    @Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(1,1,0,"Partenza");
menu.add(1,2,1,"Annulla passaggio");
return true;
}
    
    public boolean onOptionsItemSelected(MenuItem item)
    {
    
switch(item.getItemId())
{
case 1:
if (!start) 
{
  start = true;
      partenza = System.currentTimeMillis();
      long x2 = (partenza) / 1000;
  long seconds2 = x2 % 60;
  x2 /= 60;
  long minutes2 = x2 % 60;
  x2 /= 60;
  long hours2 = x2 % 24;
  x2 /= 24;
  //long days = x;
      send_udp("Partenza   "+String.format("%02d:%02d:%02d", hours2,minutes2,seconds2));
          pett.setText("Partenza effettuata");
          scrivi("Partenza   "+String.format("%02d:%02d:%02d", hours2,minutes2,seconds2)+"\n");
          playAlarm();
}

else
{
Toast.makeText(this, "Partenza gia' effettuata",Toast.LENGTH_SHORT).show();
return false;
}


   Timer ti = new Timer();
   ti.scheduleAtFixedRate(new TimerTask() {
           public void run() {
            runOnUiThread(new Runnable() {
          private long attuale;
private String race_time;

@Override
          public void run() {
           //String tempo = new SimpleDateFormat("HH:mm:ss dd/MM/yyyy").format(new Date(System.currentTimeMillis()));
           if (partenza > 0)
           {
            attuale = System.currentTimeMillis();
    long x = (attuale-partenza) / 1000;
    long seconds = x % 60;
    x /= 60;
    long minutes = x % 60;
    x /= 60;
    long hours = x % 24;
    x /= 24;
    //long days = x;
    race_time = String.format("%02d:%02d:%02d", hours,minutes,seconds);
    scanText.setText(race_time);
           }
    }});}}, 0, 1000);
 //fa partire il cronometro della corsa
 partenza = System.currentTimeMillis();
   return true;
   
case 2:
send_udp("Annullato pettorale " + pettorale);
      pett.setText("Annullato pettorale " + pettorale);
      scrivi("Annullato pettorale " + pettorale+"\n");
      contatore = contatore - 1;
return true;

}

return false;
}
   
}

giovedì 7 marzo 2013

Creazione automatica QrCode in Java/Netbeans

Per generare QrCode in modo automatico in modo semplice si puo' utilizzare il metodo presentato a questo indirizzo

 Si deve scaricare la libreria XZing e si devono aggiungere al progetto le librerie core e javase contenute nelle sottodirectory del file zip


il codice e' stato modificato in modo da accettare in input sulla riga di comando (nella variabile args) il contenuto del QrCode. Questa motiva permette mediante una procedura batch di creare in automatico quanti QrCode si desiderino

-----------------------------------------
package qrcode;


import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.util.Hashtable;

import com.google.zxing.client.j2se.MatrixToImageWriter;


/**
 *
 * @author l.innocenti
 */
public class QrCode {

    public static void main(String[] args) {
        Charset charset = Charset.forName("UTF-8");
        CharsetEncoder encoder = charset.newEncoder();
        byte[] b = null;
            try {
                // Convert a string to UTF-8 bytes in a ByteBuffer
                ByteBuffer bbuf = encoder.encode(CharBuffer.wrap(args[0]));
                b = bbuf.array();
            } catch (CharacterCodingException e) {
                System.out.println(e.getMessage());
            }

            String data;
            try {
                data = new String(b, "UTF-8");
                // get a byte matrix for the data
                BitMatrix matrix = null;
                int h = 100;
                int w = 100;
                com.google.zxing.Writer writer = new MultiFormatWriter();
                try {
                    Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>(2);
                    hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
                    matrix = writer.encode(data,
                    com.google.zxing.BarcodeFormat.QR_CODE, w, h, hints);
                } catch (com.google.zxing.WriterException e) {
                    System.out.println(e.getMessage());
                }

                // change this path to match yours (this is my mac home folder, you can use: c:\\qr_png.png if you are on windows)
                        String filePath = args[0]+".png";
                File file = new File(filePath);
                try {
                    MatrixToImageWriter.writeToFile(matrix, "PNG", file);
                    System.out.println("printing to " + file.getAbsolutePath());
                } catch (IOException e) {
                    System.out.println(e.getMessage());
                }
            } catch (UnsupportedEncodingException e) {
                System.out.println(e.getMessage());
            }
            }
}
-----------------------------------------
Il risultato e' una immagine Png con nome uguale al contenuto del QrCode 
Per creare in automatico 1000 numeri QrCode di numeri progressivi si puo' creare un file batch su Windows con la seguente linea
-------------------------------------------------------------

FOR /L %%A IN (1,1,1000) DO java -jar Qrcode.jar %%A
-------------------------------------------------------------

mentre in Linux
-------------------------------------------------------------

#!/bin/bash
for i in {1..1000}
do
   java -jar Qrcode.jar $i
done
--------------------------------------------------------------


Debugger integrato ESP32S3

Aggiornamento In realta' il Jtag USB funziona anche sui moduli cinesi Il problema risiede  nell'ID USB della porta Jtag. Nel modulo...