powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / FMX. Изменение типа чтения данных со cканера Android программно
9 сообщений из 9, страница 1 из 1
FMX. Изменение типа чтения данных со cканера Android программно
    #39981060
Фотография Kast2K
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый день!

Пишу программу для обработки результатов работы сканера Honeywell CT50 (Android 6).

Сразу прошу прощения за простыни кода, упрощал изо всех сил.

Главная форма:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
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
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
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

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
unit PSVars;

interface

uses
  PSTypes ;

var
  Barcode:TBarcode;
  TJNASC:TJNativeActivitySubclass;

implementation

end.



formScanTakeOnStore
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
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');
//// не работает
      TJNASC.Stop;
      MainForm.AutomaticMode:=False;
      TJNASC.Start;
      MainForm.AutomaticMode:=True;
//// не работает
      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 и выставляю статус либо ручное сканирование (btnManual) либо Автоматическое (btnContinuous) .

Процедуры TJNASC.Start, TJNASC.Stop отвечают за Автоматическое сканирование ВКЛ и Выкл соответственно. Автоматическое = сканер постоянно пытается считать баркод. Ручное = чтение по триггеру (кнопке на аппарате).

Поступила задача, если сканер в Автоматическом режиме, то после каждого сканирования надо делать паузу в 1-несколько секунд и выключать сканер, а потом активировать его снова.

Я решил сделать это через штатный таймер. Он отрабатывает нормально, но ни TJNASC.Start, TJNASC.Stop ни симуляция нажатия кнопок в процедуре OnTimer не запускают режим автоматического скана. НО! Если просто нажать на кнопку btnContinuous, то сканер запускает постоянное чтение.

Проблема: постоянное чтение не запускается программно, только через клик по кнопке.

Коллеги,
Подскажите, пожалуйста, что я делаю не так? Может быть необходимо методы по иному вызывать или я упускаю какие-то пункты?
...
Рейтинг: 0 / 0
FMX. Изменение типа чтения данных со cканера Android программно
    #39981157
white_nigger
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мало что понял, но... вызов btnContinuousClick в обработчике таймера срабатывает или нет? Помимо этого перенеси отключение таймера в его обработчиках из конца метода в самое начало.
...
Рейтинг: 0 / 0
FMX. Изменение типа чтения данных со cканера Android программно
    #39981192
Фотография Kast2K
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
white_nigger,

Спасибо за идею, но не помогает :(

Может станет понятнее:
1. Открыл форму formScanTakeOnStore,
2.нажал кнопку btnContinuos, хардварный сканер включился и светит своим лазером, выполняется TJASC.Start
3. Считываю баркод
4. Программа деактивирует сканер, чтобы
а) автоматический режим выключился
б) не было возможности нажать железную кнопку для сканирования.
5. Запускается Timer
6. По прошествии 3 секунд отрабатывает OnTimer
7. Если в п.2. был активирован режим Автоматического сканирования, то должна отработать процедура TJASC.Start или симулироваться нажатие кнопки btnContinuous.

Проблема: в П.7 происходит вход и якобы выполнение данных процедур, но хардварный сканер не включается. Он включится если пальцем нажать на кнопку btnContinuous.
...
Рейтинг: 0 / 0
FMX. Изменение типа чтения данных со cканера Android программно
    #39981228
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kast2K,

сканер скорее всего выполняет команды асинхронно и не берется за следующую, пока предыдущая не выполнена. Потому кнопками работает, а в коде - нет.
И sleep в основном потоке - дурной тон.
...
Рейтинг: 0 / 0
FMX. Изменение типа чтения данных со cканера Android программно
    #39981267
Фотография Kast2K
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
wadman,

Спасибо.
Sleep было просто для теста.
...
Рейтинг: 0 / 0
FMX. Изменение типа чтения данных со cканера Android программно
    #39981268
Фотография Kast2K
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kast2K,
TThread.synchronize?
...
Рейтинг: 0 / 0
FMX. Изменение типа чтения данных со cканера Android программно
    #39981375
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kast2K
Kast2K,
TThread.synchronize?

Это-то тут при чем? В коде потоков нет.

Нужно выяснить какой период нужен сканеру для выполнения команд. Хотя-бы с теми же таймерами. Начни с задержки 100мс. То есть серия нужных команд с такой задержкой.
Не получится, увеличивай.
...
Рейтинг: 0 / 0
FMX. Изменение типа чтения данных со cканера Android программно
    #39981403
Cobalt747
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
wadman
Нужно выяснить какой период нужен сканеру для выполнения команд. Хотя-бы с теми же таймерами. Начни с задержки 100мс.

Или можно начать с чтения документации на оборудование )))
...
Рейтинг: 0 / 0
FMX. Изменение типа чтения данных со cканера Android программно
    #39981667
Фотография Kast2K
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
wadman,

Спасибо.
Идея с таймерами (100 мс) помогла, всё работает без проблем.

Cobalt747,
В документации всё нормально расписано и работает в FMX. Вопрос был в подходе.
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / FMX. Изменение типа чтения данных со cканера Android программно
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]