Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   QR-Code scannen (https://www.delphipraxis.net/216430-qr-code-scannen.html)

DaCoda 27. Dez 2024 18:33

QR-Code scannen
 
Hallo,

da ZXing veraltet ist und unter aktuellen Android nicht mehr geht, suche ich eine Alternative die ich unter FMX nutzen kann.

Amanda 27. Dez 2024 19:56

AW: QR-Code scannen
 
Das kann ich nicht bestätigen. Ich verwende ZXing unter Android (neueste Version), IOS neueste Version und Windows ohne Probleme.

DaCoda 27. Dez 2024 20:23

AW: QR-Code scannen
 
Mir wird im Playstore gesagt das es für meine Version kein ZXing gibt.

Wie machst du das mit QR-Code in Android genau ?

Ich habe Android V13 und bekomme immer eine Fehlermeldung:

[PAClient Fehler] Fehler: E8712 android:exported needs to be explicitly specified for element <activity#com.embarcadero.firemonkey.FMXNativeActi vity>. Apps targeting Android 12 and higher are required to specify an explicit value for `android:exported` when the corresponding component has an intent filter defined. See https://developer.android.com/guide/...ement#exported for details.

Neumann 28. Dez 2024 10:49

AW: QR-Code scannen
 
Das muss man im Manifest eingeben. Da gab's hier schon mal was; bitte suchen habe das jetzt nicht parat.

Amanda 28. Dez 2024 15:07

AW: QR-Code scannen
 
Du hast die aktuelle Version Delphi 12.2 ?

DaCoda 28. Dez 2024 16:10

AW: QR-Code scannen
 
Ja, Delphi 12.2

Ich habe nun mal ein Demo in ein neues Projekt kopiert, funktioniert "fast". Nur QR-Code liest er nicht :-(
Manche Barcodes aber schon (?)

Source:
Code:
unit MainForm;

interface

uses
  System.SysUtils,
  System.Types,
  System.UITypes,
  System.Classes,
  System.Variants,
  System.Math.Vectors,
  System.Actions,
  System.Threading,
  System.Permissions,

  FMX.Types,
  FMX.Controls,
  FMX.Forms,
  FMX.Graphics,
  FMX.Dialogs,
  FMX.Objects,
  FMX.StdCtrls,
  FMX.Media,
  FMX.Platform,
  FMX.MultiView,
  FMX.ListView.Types,
  FMX.ListView,
  FMX.Layouts,
  FMX.ActnList,
  FMX.TabControl,
  FMX.ListBox,
  FMX.Controls.Presentation,
  FMX.ScrollBox,
  FMX.Memo,
  FMX.Memo.Types,
  FMX.Controls3D,

  ZXing.BarcodeFormat,
  ZXing.ReadResult,
  ZXing.ScanManager;

type
  TfrmMain = class(TForm)
    Rectangle1: TRectangle;
    Camera: TCameraComponent;
    btnStartStop: TButton;
    lblScanStatus: TLabel;
    Memo1: TMemo;
    imgCamera: TImage;
    procedure btnStartStopClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure CameraSampleBufferReady(Sender: TObject;
      const ATime: TMediaTime);
  private
  { Private declarations }
    fPermissionCamera: string;
    fScanInProgress: Boolean;
    fFrameTake: Integer;
    fScanBitmap: TBitmap;

    procedure ParseImage();
{$IF CompilerVersion >= 35.0}
    // after Delphi 11 Alexandria
    procedure CameraPermissionRequestResult(Sender: TObject;
      const APermissions: TClassicStringDynArray;
      const AGrantResults: TClassicPermissionStatusDynArray);
    procedure ExplainReason(Sender: TObject; const APermissions: TClassicStringDynArray;
      const APostRationaleProc: TProc);
{$ELSE}
    // before Delphi 11 Alexandria
    procedure CameraPermissionRequestResult(Sender: TObject;
      const APermissions: TArray<string>;
      const AGrantResults: TArray<TPermissionStatus>);
    procedure ExplainReason(Sender: TObject; const APermissions: TArray<string>;
      const APostRationaleProc: TProc);
{$ENDIF}

  public

  end;

var
  frmMain: TfrmMain;

implementation

{$R *.fmx}
{$R *.NmXhdpiPh.fmx ANDROID}
{$R *.LgXhdpiPh.fmx ANDROID}

uses
{$IFDEF ANDROID}
  Androidapi.Helpers,
  Androidapi.JNI.JavaTypes,
  Androidapi.JNI.Os,
{$ENDIF}
  FMX.DialogService;

procedure TfrmMain.btnStartStopClick(Sender: TObject);
begin
  if btnStartStop.Tag = 0 then begin
    PermissionsService.RequestPermissions([fPermissionCamera], CameraPermissionRequestResult, ExplainReason);

    btnStartStop.Text := 'Stop';
    btnStartStop.Tag := 1;
  end else begin
    Camera.Active := False;

    btnStartStop.Text := 'Start';
    btnStartStop.Tag := 0;
  end;

end;

procedure TfrmMain.CameraSampleBufferReady(Sender: TObject; const ATime: TMediaTime);
begin
  TThread.Synchronize(TThread.CurrentThread,
  procedure
  begin
    Camera.SampleBufferToBitmap(imgCamera.Bitmap, True);

    if (fScanInProgress) then
    begin
      exit;
    end;

    { This code will take every 4 frame. }
    inc(fFrameTake);
    if (fFrameTake mod 4 <> 0) then
    begin
      exit;
    end;

    if Assigned(fScanBitmap) then
      FreeAndNil(fScanBitmap);

    fScanBitmap := TBitmap.Create();
    fScanBitmap.Assign(imgCamera.Bitmap);

    ParseImage();
  end);
end;

procedure TfrmMain.FormCreate(Sender: TObject);
var
  AppEventSvc: IFMXApplicationEventService;
begin
  lblScanStatus.Text := '';
  fFrameTake := 0;
  fScanBitmap := nil;

{$IFDEF ANDROID}
  fPermissionCamera := JStringToString(TJManifest_permission.JavaClass.CAMERA);
{$ENDIF}
end;

procedure TfrmMain.FormDestroy(Sender: TObject);
begin
    Camera.Active := False;
  if Assigned(fScanBitmap) then
    FreeAndNil(fScanBitmap);
end;

{$IF CompilerVersion >= 35.0}
    // after Delphi 11 Alexandria
procedure TfrmMain.CameraPermissionRequestResult(Sender: TObject;
  const APermissions: TClassicStringDynArray;
  const AGrantResults: TClassicPermissionStatusDynArray);

{$ELSE}
    // before Delphi 11 Alexandria
procedure TMainForm.CameraPermissionRequestResult(Sender: TObject;
  const APermissions: TArray<string>;
  const AGrantResults: TArray<TPermissionStatus>);
{$ENDIF}
begin
  if (Length(AGrantResults) = 1) and
  (AGrantResults[0] = TPermissionStatus.Granted) then begin
    Camera.Active := false;
    Camera.Quality := FMX.Media.TVideoCaptureQuality.MediumQuality;
    Camera.Kind := FMX.Media.TCameraKind.BackCamera;
    Camera.FocusMode := FMX.Media.TFocusMode.ContinuousAutoFocus;
    Camera.Active := True;
    lblScanStatus.Text := '';
    Memo1.Lines.Clear;
  end else
    TDialogService.ShowMessage('Cannot scan for barcodes because the required permissions is not granted');
end;

{$IF CompilerVersion >= 35.0}
    // after Delphi 11 Alexandria
procedure TfrmMain.ExplainReason(Sender: TObject;
  const APermissions: TClassicStringDynArray; const APostRationaleProc: TProc);

{$ELSE}
    // before Delphi 11 Alexandria
procedure TMainForm.ExplainReason(Sender: TObject;
  const APermissions: TArray<string>; const APostRationaleProc: TProc);
{$ENDIF}
begin
  TDialogService.ShowMessage('The app needs to access the camera to scan codes ...', procedure(const AResult: TModalResult)
    begin
      APostRationaleProc;
    end);
end;

procedure TfrmMain.ParseImage();
begin

  TThread.CreateAnonymousThread(
    procedure
    var
      ReadResult: TReadResult;
      ScanManager: TScanManager;

    begin
      fScanInProgress := True;
      ScanManager := TScanManager.Create(TBarcodeFormat.Auto, nil);

      try

        try
          ReadResult := ScanManager.Scan(fScanBitmap);
        except
          on E: Exception do
          begin
            TThread.Synchronize(TThread.CurrentThread,
              procedure
              begin
                lblScanStatus.Text := E.Message;
              end);
            exit;
          end;
        end;

        TThread.Synchronize(TThread.CurrentThread,
          procedure
          begin

            if (Length(lblScanStatus.Text) > 10) then
            begin
              lblScanStatus.Text := '*';
            end;

            lblScanStatus.Text := lblScanStatus.Text + '*';
            if (ReadResult <> nil) then
            begin
              Memo1.Lines.Insert(0, ReadResult.Text);
            end;

          end);

      finally
        if ReadResult <> nil then
          FreeAndNil(ReadResult);

        ScanManager.Free;
        fScanInProgress := false;
      end;

    end).Start();

end;

end.

Rollo62 28. Dez 2024 18:01

AW: QR-Code scannen
 
Hilft vielleicht nicht direkt für deine letzte Frage, aber ich würde den Guard etwas früher vorziehen,
so dass es nicht erst in den Thread laufen muss, um dann da rauszufliegen.

Siehe Kommentare
Delphi-Quellcode:

procedure TfrmMain.CameraSampleBufferReady(Sender: TObject; const ATime: TMediaTime);
begin

  // Direkt hier abblocken, sollte alle Frames ignorieren, bis der Image-Process abgeschlossen wurde
  if (fScanInProgress) then
  begin
      exit;
  end;


  TThread.Synchronize(TThread.CurrentThread,
  procedure
  begin
    Camera.SampleBufferToBitmap(imgCamera.Bitmap, True);

//    if (fScanInProgress) then
//    begin
//      exit;
//    end;

    { This code will take every 4 frame. }
    inc(fFrameTake);
    if (fFrameTake mod 4 <> 0) then
    begin
      exit;
    end;

    if Assigned(fScanBitmap) then
      FreeAndNil(fScanBitmap);

    fScanBitmap := TBitmap.Create();
    fScanBitmap.Assign(imgCamera.Bitmap);

    ParseImage();
  end);
end;

...

procedure TfrmMain.ParseImage();
begin

  TThread.CreateAnonymousThread(
    procedure
    var
      ReadResult: TReadResult;
      ScanManager: TScanManager;

    begin
//Das wird hier dann nicht mehr benötigt    
//      fScanInProgress := True;
      ScanManager := TScanManager.Create(TBarcodeFormat.Auto, nil);

      try

        try
          ReadResult := ScanManager.Scan(fScanBitmap);
        except
          on E: Exception do
          begin
            TThread.Synchronize(TThread.CurrentThread,
              procedure
              begin
                lblScanStatus.Text := E.Message;
              end);
            exit;
          end;
        end;

        TThread.Synchronize(TThread.CurrentThread,
          procedure
          begin

            if (Length(lblScanStatus.Text) > 10) then
            begin
              lblScanStatus.Text := '*';
            end;

            lblScanStatus.Text := lblScanStatus.Text + '*';
            if (ReadResult <> nil) then
            begin
              Memo1.Lines.Insert(0, ReadResult.Text);
            end;

          end);

      finally
        if ReadResult <> nil then
          FreeAndNil(ReadResult);

        ScanManager.Free;

        //Das sollte OK sein, und den ganzen Scan-Prozess wieder freigeben, ab dem nächsten Frame
        //aber sicherheitshalber auch in einem Queue      
        TThread.Queue(TThread.CurrentThread,
          procedure
          begin
              fScanInProgress := false;
          end);



      end;

    end).Start();

end;

Amanda 28. Dez 2024 18:05

AW: QR-Code scannen
 
constructor TfQRScanThread.create;
begin
inherited create(false);

starten := TEvent.create(nil, false, false, '');
fertig := TEvent.create(nil, true, true, '');
qrcode := TEvent.create(nil, true, false, '');

iBMP := TBitmap.Create;

iScanmanager := TScanManager.Create(TBarcodeFormat.QR_CODE, nil);

FreeOnTerminate := true;
end;

procedure TfQRScanThread.Execute ;
var
ReadResult : TReadResult;
str : string;
begin
while not Terminated do begin

if (starten.WaitFor(INFINITE) = wrSignaled) and assigned(iBMP) then begin
try
ReadResult := iScanManager.Scan(iBmp);
if assigned(readResult)then begin
qrcode.SetEvent;

str := readResult.Text;
freeAndNil(ReadResult);

queue(
procedure
begin
fQRCode.CameraComponent1.OnSampleBufferReady := nil;
fQRCode.CameraComponent1.Active := false;
fQRCode.imgCamera.Visible := false;
fQRCode.aScan.Checked := false;

pruefeQRCode(str);
//fQRCode.bild(iBMP, TAlphaColors.Green);
end);

end; // if

except
end; // try
end; // if

fertig.SetEvent;
end; // while

end;

DaCoda 28. Dez 2024 18:49

AW: QR-Code scannen
 
Vielen Dank für Eure Vorschläge :-)

Ich habe nun rausgefunden, das wenn ich weissen Hintergrund habe und schwarzen QR-Code, dann geht es. Wenn aber schwarzer Hintergrund und weissen QR-Code, dann nicht (warum weiss ich nun nicht)

TurboMagic 28. Dez 2024 20:21

AW: QR-Code scannen
 
Was machen andere QRCode apps aus dem Fall weißer QR Code auf schwarzem Grund?
Können die das?


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:21 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz