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

не отрабатывает TThread.synchronize


Kast2k

Вопрос

Добрый день!

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.

 

Изменено пользователем Kast2k
Ссылка на комментарий

Рекомендуемые сообщения

  • 0

Простите за беспокойство, разобрался.

Надо было в главной форме вместо такого

 

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

Изменено пользователем Kast2k
Ссылка на комментарий
  • 1

ну, есть идеи, как бы модифицировать код, но и так сойдет

я бы перефразировал

if frmScanWindow = nil then
  frmScanWindow := TFrmScanWindow.Create(NIL);
frmScanwindow.showModal(
            procedure (const AResult:TModalResult) 
            begin 
               if AResult = mrOK then 
               begin
                  ....... 
                  и может быть даже
					FreeAndNil(frmScanwindow);
               end; 
            end);

 

Изменено пользователем krapotkin
Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...