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

Пишу программу для обработки результатов работы сканера 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
18.07.2020, 00:09
    #39981157
white_nigger
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
FMX. Изменение типа чтения данных со cканера Android программно
Мало что понял, но... вызов btnContinuousClick в обработчике таймера срабатывает или нет? Помимо этого перенеси отключение таймера в его обработчиках из конца метода в самое начало.
...
Рейтинг: 0 / 0
18.07.2020, 05:50
    #39981192
Kast2K
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
FMX. Изменение типа чтения данных со cканера Android программно
white_nigger,

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

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

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

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

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

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

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

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

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

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


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