Перейти к содержанию
Fire Monkey от А до Я

Kast2k

Пользователи
  • Постов

    4
  • Зарегистрирован

  • Посещение

Достижения Kast2k

  1. Вследствие асинхронной обработки железным сканером вызовов TJNASC.Stop и TJNASC.Stop проблема была решена добавлением 2 TTimer выполняющих эти вызовы. Возможно решение кривое, но работает чётко.
  2. Добрый день! Пишу программу для обработки результатов работы сканера Honeywell CT50 (Android 6). Сразу прошу прощения за простыни кода, упрощал изо всех сил. Главная форма: TMainForm = class(TForm) Label1: TLabel; btnSaveToStore: TButton; procedure FormCreate(Sender: TObject); private { Private declarations } FAutomaticMode:Boolean; procedure ActivateScanner; public property AutomaticMode: Boolean read FAutomaticMode write FAutomaticMode; procedure onBarCodeCompleteThreadSwitcher; procedure onBarCodeFailThreadSwitcher; procedure ShowInformationMessage(const AText:string); { Public declarations } end; uses FMX.Helpers.Android, Androidapi.NativeActivity, Androidapi.JNI.Widget, formScanTakeOnStore, PSTypes, PSVars; procedure TMainForm.ActivateScanner; begin RegisterDelphiNativeMethods; TJNASC.Activate; Log.d('Scanner ready'); end; procedure TMainForm.btnSaveToStoreClick(Sender: TObject); begin Barcode.DelayInSeconds:=2; frmScanTakeOnStore:=TfrmScanTakeOnStore.Create(Application); //правильный ли вызов? надо ли Free при выходе? frmScanTakeOnStore.Show; end; procedure TMainForm.FormCreate(Sender: TObject); begin Barcode:=TBarcode.Create; Barcode.DelayInSeconds:=2; ActivateScanner; end; procedure TMainForm.onBarCodeCompleteThreadSwitcher; begin if AutomaticMode then TJNASC.Start else TJNASC.Stop; end; procedure TMainForm.onBarCodeFailThreadSwitcher; begin end; procedure TMainForm.ShowInformationMessage(const AText: string); begin CallInUiThread ( procedure begin TJToast.JavaClass.makeText (TAndroidHelper.Context, StrToJCharSequence(AText), TJToast.JavaClass.LENGTH_LONG).show; end ); end; PSTypes.pas unit PSTypes; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.ScrollBox, FMX.Memo, FMX.Controls.Presentation, FMX.StdCtrls, Androidapi.JNI.App, Androidapi.JNI, Androidapi.JNIBridge, Androidapi.JNI.JavaTypes, DateUtils, System.Character; type JNativeActivitySubclass = interface; JNativeActivitySubclassClass = interface(JActivityClass) ['{361C7073-E0A2-4A0D-B5E4-8403E5214275}'] {Methods} //function init: JFMXNativeActivity; cdecl; end; [JavaSignature('com/winarhi/nativeactivitysubclass/NativeActivitySubclass')] JNativeActivitySubclass = interface(JActivity) ['{7141B1C4-508D-46F3-A767-E0BFCE22C9CE}'] {Methods} // procedure WA_75e_DoScan(paramBoolean :JBoolean); procedure WA_75e_Create_aidcManager; procedure WA_75e_Destroy_aidcManager; procedure WA_75eStart; procedure WA_75eStop; end; TJNativeActivitySubclass = class(TJavaGenericImport<JNativeActivitySubclassClass, JNativeActivitySubclass>) public procedure Activate; procedure DeActivate; procedure Start; procedure Stop; end; TBarcodeData=record end; TBarcodeResult=procedure(const BarcodeData:TBarcodeData) of object; TBarcode=class private FBarcodeData : TBarcodeData; FOnBarcodeResult : TBarcodeResult; procedure SetReceivedBarcodeData(const Value: string); public property OnBarcodeResult: TBarcodeResult read FOnBarcodeResult write FOnBarcodeResult; end; procedure RegisterDelphiNativeMethods; implementation uses FMX.Helpers.Android, Androidapi.NativeActivity, PSVars, formMain; { TJNativeActivitySubclass } procedure onBarCodeCompleteNative(PEnv: PJNIEnv; This: JNIObject; BarCode: JNIString); cdecl; begin PSVars.Barcode.ReceivedBarcodeData := JNIStringToString(PEnv, BarCode); TThread.Synchronize(TThread.CurrentThread, MainForm.onBarCodeCompleteThreadSwitcher); end; procedure onBarCodeFailNative(PEnv: PJNIEnv; This: JNIObject; BarCode: JNIString); cdecl; begin // PSVars.Barcode.ReceivedBarcodeData := JNIStringToString(PEnv, BarCode); TThread.Synchronize(TThread.CurrentThread, MainForm.onBarCodeFailThreadSwitcher); end; procedure RegisterDelphiNativeMethods; var PEnv: PJNIEnv; ActivityClass: JNIClass; NativeMethods: array[0..1] of JNINativeMethod; begin Log.d('Starting the registration JNI stuff'); PEnv := TJNIResolver.GetJNIEnv; Log.d('Registering interop methods'); NativeMethods[0].Name := 'onBarCodeCompleteNative'; NativeMethods[0].Signature := '(Ljava/lang/String;)V'; NativeMethods[0].FnPtr := @onBarCodeCompleteNative; NativeMethods[1].Name := 'onBarCodeFailNative'; NativeMethods[1].Signature := '()V'; NativeMethods[1].FnPtr := @onBarCodeFailNative; ActivityClass := PEnv^.GetObjectClass( PEnv, PANativeActivity(System.DelphiActivity).clazz); PEnv^.RegisterNatives(PEnv, ActivityClass, @NativeMethods[0], 2); PEnv^.DeleteLocalRef(PEnv, ActivityClass); Log.d('Interop Methods Registered'); end; procedure TJNativeActivitySubclass.Activate; begin Wrap(PANativeActivity(System.DelphiActivity)^.clazz).WA_75e_Create_aidcManager; end; procedure TJNativeActivitySubclass.DeActivate; begin Wrap(PANativeActivity(System.DelphiActivity)^.clazz).WA_75e_Destroy_aidcManager; end; procedure TJNativeActivitySubclass.Start; begin Wrap(PANativeActivity(System.DelphiActivity)^.clazz).WA_75eStart; end; procedure TJNativeActivitySubclass.Stop; begin Wrap(PANativeActivity(System.DelphiActivity)^.clazz).WA_75eStop; end; end. PSVars unit PSVars; interface uses PSTypes ; var Barcode:TBarcode; TJNASC:TJNativeActivitySubclass; implementation end. formScanTakeOnStore unit formScanTakeOnStore; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Controls.Presentation, FMX.StdCtrls, FMX.ScrollBox, FMX.Memo, Androidapi.JNI.App, Androidapi.JNI, Androidapi.JNIBridge, Androidapi.JNI.JavaTypes, Androidapi.Helpers, FMX.DialogService, System.Rtti, FMX.Grid.Style, FMX.Grid, FMX.TextLayout, DateUtils, PSTypes, FMX.Objects; type TfrmScanTakeOnStore = class(TForm) Label1: TLabel; btnFinish: TButton; Panel1: TPanel; Panel2: TPanel; Panel3: TPanel; btnContinuous: TButton; btnManual: TButton; Panel4: TPanel; lblReceived: TLabel; StyleBook1: TStyleBook; btnTable: TButton; lblMaterial: TLabel; lblBankaCounts: TLabel; lblTotalLeft: TLabel; tmrSleep: TTimer; rectStatus: TRectangle; Button1: TButton; procedure btnFinishClick(Sender: TObject); procedure FormShow(Sender: TObject); procedure btnContinuousClick(Sender: TObject); procedure btnManualClick(Sender: TObject); procedure btnTableClick(Sender: TObject); procedure tmrSleepTimer(Sender: TObject); procedure Button1Click(Sender: TObject); private { Private declarations } FNewDataExist:Boolean; BarcodeData:TBarcodeData; procedure OnBarcodeResult(const ABarcodeData:TBarcodeData); procedure CloseFrm(Sender: TObject; const AResult: TModalResult); procedure MaterialAddedNG(Sender: TObject; const AResult: TModalResult); procedure MaterialAddedOK(Sender: TObject; const AResult: TModalResult); procedure StopScannerAndColor(CL:Cardinal); public { Public declarations } end; var frmScanTakeOnStore: TfrmScanTakeOnStore; implementation uses FMX.Helpers.Android, Androidapi.NativeActivity, formScanComplete, dmData, formAgreeAction, formScanTakeOnStoreTable, PSVars, formMain; {$R *.fmx} procedure TfrmScanTakeOnStore.btnContinuousClick(Sender: TObject); begin TJNASC.Start; btnContinuous.StyleLookup:='btnContinuousStyle1'; btnManual.StyleLookup:=''; MainForm.AutomaticMode:=True; MainForm.ShowInformationMessage('Automatic mode'); end; procedure TfrmScanTakeOnStore.btnFinishClick(Sender: TObject); begin // MainForm.SayTextToSpeech('Завершить приемку материалов на склад?'); TDialogService.MessageDialog( 'Завершить приемку материалов на склад?', TMsgDlgType.mtWarning, [TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo], TMsgDlgBtn.mbNo, 0, CloseFrm); end; procedure TfrmScanTakeOnStore.btnManualClick(Sender: TObject); begin TJNASC.Stop; btnManual.StyleLookup:='btnContinuousStyle1'; btnContinuous.StyleLookup:=''; MainForm.AutomaticMode:=False; end; procedure TfrmScanTakeOnStore.btnTableClick(Sender: TObject); begin CallInUIThread(procedure begin frmScanTakeOnStoreTable:=TfrmScanTakeOnStoreTable.Create(Application); //Free ??? frmScanTakeOnStoreTable.Show; end); end; procedure TfrmScanTakeOnStore.Button1Click(Sender: TObject); //simulation var bc: TBarcodeData; begin bc.Parsed:=True; bc.KPJCode:='80604358'; bc.LotName:='testlot'; OnBarcodeResult(bc); end; procedure TfrmScanTakeOnStore.CloseFrm(Sender: TObject; const AResult: TModalResult); begin if AResult = mrYes then begin TJNASC.Stop; MainForm.AutomaticMode:=False; Close; end; end; procedure TfrmScanTakeOnStore.FormShow(Sender: TObject); begin Log.d('Pre-activate'); tmrSleep.Interval:=Barcode.DelayInSeconds*1000; Barcode.LastScanTimeUnix:=DateTimeToUnix(Now); Barcode.OnBarcodeResult:=OnBarcodeResult; end; procedure TfrmScanTakeOnStore.MaterialAddedNG(Sender: TObject; const AResult: TModalResult); begin if AResult = mrYes then begin ///NG result parse end; end; procedure TfrmScanTakeOnStore.MaterialAddedOK(Sender: TObject; const AResult: TModalResult); begin end; procedure TfrmScanTakeOnStore.OnBarcodeResult(const ABarcodeData: TBarcodeData); begin if ABarcodeData.Parsed then begin StopScannerAndColor(TAlphaColors.Green); end else begin MainForm.ShowInformationMessage(ARNBarCode+' невозможно распознать.'); StopScannerAndColor(TAlphaColors.Red); end; end; procedure TfrmScanTakeOnStore.StopScannerAndColor(CL: Cardinal); begin rectStatus.Fill.Color:=CL; TJNASC.Stop; TJNASC.DeActivate; Log.d('Scanner DeActivate'); tmrSleep.Enabled:=True; end; procedure TfrmScanTakeOnStore.tmrSleepTimer(Sender: TObject); begin TJNASC.Activate; Log.d('Scanner ready'); if MainForm.AutomaticMode then begin MainForm.ShowInformationMessage('Starting scanner'); frmScanTakeOnStore.btnManual.OnClick(frmScanTakeOnStore.btnManual); Sleep(1000); frmScanTakeOnStore.btnContinuous.OnClick(frmScanTakeOnStore.btnContinuous); MainForm.ShowInformationMessage('Automatic mode'); end; rectStatus.Fill.Color:=StrToInt('$FFE0E0E0'); tmrSleep.Enabled:=False; end; end. Итак, при запуске основной формы сканер активируется и появляется возможность чтения. Для получения и обработки данных я открываю форму frmScanTakeOnStore и выставляю статус ручное сканирование. Процедуры TJNASC.Start, TJNASC.Stop отвечают за Автоматическое сканирование ВКЛ и Выкл соответственно. Автоматическое = сканер постоянно пытается считать баркод. Ручное = чтение по триггеру (кнопке на аппарате). Поступила задача, если сканер в Автоматическом режиме, то после каждого скнаирования надо делать паузу в 1-несколько секунд и выключать сканер, а потом активировать снова. Я решил сделать это через штатный таймер. Он отрабатывает нормально, но симуляция нажатия кнопок (знаю что так себе решение, но см дальше) не происходит. Т.е. если я закомментирую строку в OnTimer Sleep(1000); frmScanTakeOnStore.btnContinuous.OnClick(frmScanTakeOnStore.btnContinuous); то кнопка btnManual станет подсвеченной. Если раскомментирую, то автоматическое чтение не активируется. НО! Если просто нажать на кнопку btnContinuous, то сканер запускает постоянное чтение. Пробовал сделать так, но результат также был нулевой (постоянное чтение не запускается программно, только через клик по кнопке): TJNASC.Stop; MainForm.AutomaticMode:=False; TJNASC.Start; MainForm.AutomaticMode:=True; Пробовал через CallInUIThread() = тоже самое Коллеги, Подскажите, пожалуйста, что я делаю не так? Может быть необходимо методы по иному вызывать или я упускаю какие-то пункты? Спасибо!
  3. Простите за беспокойство, разобрался. Надо было в главной форме вместо такого var f:TfrmScanWindow; begin f:=TfrmScanWindow.Create(nil); try f.Show; finally // FreeAndNil(f); end; Указать как begin frmScanWindow:=TfrmScanWindow.Create(nil); try frmScanWindow.Show; finally end; И форму выкинуть из auto-create
  4. Добрый день! Delphi 10.2 Tokyo. С FMX разбираюсь всего пару-тройку недель и возможно пока не понимаю его принципов работы. Есть сканер на андроиде Honeywell. В FMX рисую для него приложение по получению и обработке штрих-кодов. Есть основная форма и вспомогательная (принимающая данные со сканера). Дочернюю форму вызываю так: procedure TMainForm.btnSaveToStoreClick(Sender: TObject); var f:TfrmScanWindow; begin f:=TfrmScanWindow.Create(Application); try f.Show; finally // FreeAndNil(f); end; end; Далее, в дочерней форме следующий код: type JNativeActivitySubclass = interface; JNativeActivitySubclassClass = interface(JActivityClass) ['{829C77FB-08F1-4D19-9782-3C58EECAAAAA}'] {Methods} //function init: JFMXNativeActivity; cdecl; end; [JavaSignature('com/winarhi/nativeactivitysubclass/NativeActivitySubclass')] JNativeActivitySubclass = interface(JActivity) ['{2FA559EC-D1D7-46AA-9C52-FEFC6B3AAAAA}'] {Methods} procedure WA_75e_DoScan; procedure WA_75e_Create_aidcManager; procedure WA_75e_Destroy_aidcManager; end; TJNativeActivitySubclass = class(TJavaGenericImport<JNativeActivitySubclassClass, JNativeActivitySubclass>) end; TfrmScanWindow = class(TForm) Label1: TLabel; MemoData: TMemo; btnAgree: TButton; btnCancel: TButton; btnFinish: TButton; Panel1: TPanel; Panel2: TPanel; Timer1: TTimer; procedure btnFinishClick(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure FormShow(Sender: TObject); procedure Timer1Timer(Sender: TObject); private { Private declarations } ARNBarCode : string; procedure MemoAddText(const AText:string); public { Public declarations } procedure ActivateScanner; procedure RegisterDelphiNativeMethods; procedure onBarCodeCompleteThreadSwitcher; procedure onBarCodeFailThreadSwitcher; end; var frmScanWindow: TfrmScanWindow; implementation uses FMX.Helpers.Android, Androidapi.NativeActivity, formScanComplete; {$R *.fmx} procedure onBarCodeCompleteNative(PEnv: PJNIEnv; This: JNIObject; BarCode: JNIString); cdecl; begin frmScanWindow.MemoAddText('onBarCodeCompleteNative start'); // НЕ работает TThread.Synchronize(TThread.CurrentThread, procedure() begin frmScanWindow.MemoData.Lines.Add('onBarCodeCompleteNative start'); frmScanWindow.MemoData.Repaint; end); // НЕ работает // Log.d('Thread (Main: %.8x, Current: %.8x, Java:%.8d (%2:.8x), POSIX:%.8x)', // [MainThreadID, TThread.CurrentThread.ThreadID, TJThread.JavaClass.currentThread.getId]); frmScanWindow.ARNBarCode := JNIStringToString(PEnv, BarCode); // работает TThread.Synchronize(TThread.CurrentThread, frmScanWindow.onBarCodeCompleteThreadSwitcher); // НЕ работает end; procedure onBarCodeFailNative(PEnv: PJNIEnv; This: JNIObject; BarCode: JNIString); cdecl; begin frmScanWindow.MemoAddText('onBarCodeFailNative start'); // НЕ работает // Log.d('Thread (Main: %.8x, Current: %.8x, Java:%.8d (%2:.8x), POSIX:%.8x)', // [MainThreadID, TThread.CurrentThread.ThreadID, TJThread.JavaClass.currentThread.getId]); frmScanWindow.ARNBarCode := JNIStringToString(PEnv, BarCode); // работает // Log.d('Calling Synchronize'); TThread.Synchronize(TThread.CurrentThread, frmScanWindow.onBarCodeFailThreadSwitcher); // НЕ работает end; procedure TfrmScanWindow.ActivateScanner; begin RegisterDelphiNativeMethods; TJNativeActivitySubclass.Wrap(PANativeActivity(System.DelphiActivity)^.clazz).WA_75e_Create_aidcManager; MemoAddText('Activated'); // работает end; procedure TfrmScanWindow.FormShow(Sender: TObject); begin MemoAddText('Pre-activate'); // работает ActivateScanner; end; procedure TfrmScanWindow.MemoAddText(const AText: string); begin MemoData.Lines.BeginUpdate; try MemoData.Lines.Add(AText); finally MemoData.Lines.EndUpdate; end; end; procedure TfrmScanWindow.onBarCodeCompleteThreadSwitcher; begin MemoAddText('onBarCodeCompleteThreadSwitcher'); // НЕ работает MemoAddText(ARNBarCode); // НЕ работает ShowMessage(ARNBarCode); // работает end; procedure TfrmScanWindow.onBarCodeFailThreadSwitcher; begin MemoAddText('onBarCodeFailThreadSwitcher'); // НЕ работает MemoAddText('Barcode Scan Failed ' + ARNBarCode); // НЕ работает end; procedure TfrmScanWindow.RegisterDelphiNativeMethods; var PEnv: PJNIEnv; ActivityClass: JNIClass; NativeMethods: array[0..1] of JNINativeMethod; begin Log.d('Starting the registration JNI stuff'); PEnv := TJNIResolver.GetJNIEnv; Log.d('Registering interop methods'); NativeMethods[0].Name := 'onBarCodeCompleteNative'; NativeMethods[0].Signature := '(Ljava/lang/String;)V'; NativeMethods[0].FnPtr := @onBarCodeCompleteNative; NativeMethods[1].Name := 'onBarCodeFailNative'; NativeMethods[1].Signature := '()V'; NativeMethods[1].FnPtr := @onBarCodeFailNative; ActivityClass := PEnv^.GetObjectClass( PEnv, PANativeActivity(System.DelphiActivity).clazz); PEnv^.RegisterNatives(PEnv, ActivityClass, @NativeMethods[0], 2); PEnv^.DeleteLocalRef(PEnv, ActivityClass); Log.d('Interop Methods Registered'); end; procedure TfrmScanWindow.Timer1Timer(Sender: TObject); begin MemoAddText(FormatDateTime('hh:nn:ss',Now)); // работает end; Поясните, пожалуйста, что я делаю не так. Если весь этот код вызывать в основной форме, то всё работает и в memo я вижу полученные данные баркода. При вызове из дочерней - нет. При попытке вызвать ShowModal я получаю ошибку Not implemented for this platform.
×
×
  • Создать...