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

Андрей Рулин

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

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

  • Посещение

  • Победитель дней

    1

Сообщения, опубликованные Андрей Рулин

  1.  

    Buf1,Buf2 : Array[0..13100] of byte;
    FileByte        : File of byte;
    Len : array[0..7] of integer
                  = (26,20,26,131,13100,36,36,36);

     

    Цитата

    а что за конструкция while true do suspend там вообще?? 

     

    В отдельном потоке читаем файл.  После каждого чтения поток "засыпает". Если у нас осталось меньше 13100 байт, опять будим поток.

    Вот ещё вариант, накодил сегодня.

    procedure TThreadSignal.Execute;
    begin
      inherited;
      while True do
        begin
          fCompleted := False;
          Task[fi].Solve;
          fCompleted := True;
          Suspend;
        end;
    end;

    Тут вообще андройдовская версия намертво повисает. А под win32 всё исправно работает, производит вычисления. 

    Тут идея тоже самая почти. Надо провести 4 вычисления параллельно. Потом дождаться , пока все 4 выполнятся и идти дальше. 

     

  2. В ходи анализа обнаружилось, что первый раз приложение открывается в любом положении экрана. Потом , если нажать кнопку "Выход", в которой выполняется метод Close; , то потом эта проблема и возникает. 

  3. Очередная "чуча" от fmx(Delphi 10 Seattle)

    Если просто читать без потока , кода работает на обоих платформах

    begin
            if ThreadFile.BytesReady<=ThreadFile.Counter then
            begin
              BlockRead(FileByte,ThreadFile.Buf1,Len[4]);
              ThreadFile.Counter := 0;
              ThreadFile.BytesReady :=Len[4];
            end;
            Move(ThreadFile.Buf1[ThreadFile.Counter],GetHidBufPointer^,Len[3]);
            ThreadFile.Counter := ThreadFile.Counter + Len[3];
          end;

     

    Если использовать потоки 

    begin
            if ThreadFile.BytesReady=0 then
              begin
                BlockRead(FileByte,ThreadFile.Buf1,Len[4]);
                ThreadFile.BackBuf := False;
                ThreadFile.BytesReady := Len[4];
                ThreadFile.Resume;
              end;
            if ThreadFile.Counter=ThreadFile.BytesReady then
              begin
                ThreadFile.Counter := 0;
                ThreadFile.BytesReady :=0;
                ThreadFile.BackBuf := not ThreadFile.BackBuf;
                ThreadFile.Resume;
              end;
            if  ThreadFile.BackBuf then  Move(ThreadFile.Buf2[ThreadFile.Counter],GetHidBufPointer^,Len[3])
                                   else  Move(ThreadFile.Buf1[ThreadFile.Counter],GetHidBufPointer^,Len[3]);
            ThreadFile.Counter := ThreadFile.Counter + Len[3];
          end;
    
    //-------------
    
    procedure TThreadFile.Execute;
    begin
      inherited;
      while True do
        begin
          if BackBuf then BlockRead(FileByte,Buf1,Len[4])
                     else BlockRead(FileByte,Buf2,Len[4]);
          BytesReady := BytesReady + Len[4];
          Suspend;
         // Self.
        end;
    end;

    То в этом случае всё работает только в fmx в версии win32 . В Андройде , увы читаются нули.

     

    В принципе ошибка не критичная, т.к. второй вариант в итоге не даёт приросто производительности, но в общей случае настораживает. 

  4. Стоит Delphi 10.0

    Разрешены две ориентации экрана LandscapeHomeright и LandscapeHomeleft. При открытии в одной ориентации приложения чаще всего вылетает, когда форма показывается. При открытии во второй всё перевёрнутое, но зато не вылетает . Можно перевернуть экран и тогда тоже не вылетает.  Ну и естественно в Windows всё нормальное работате, программа никогда не вылетает . 

     

    Вопрос, что собственно это такое. 

  5. При обновление приложении иногда обновляется иногда рандомно пишет "приложение не установлено". Остановка приложение не всегда помогает.  Устройство Samsung Galaxy Tab 8 , Android 9 . Но было с другими устройствами и другими системами тоже. 

  6. Допустим идут вычисления, мне надо в Label выводить, что они закончились на 10%...20%...100%

    После изменения текста я делаю

    Label1.Repaint;
    Invalidate;

    При этом текст не изменяется, пока не окончатся вычисления.  Хотя в Vcl версии хватает Repaint для формы. 

  7. Да, у меня на телефоне API 33.

    Я вот почитал https://developer.android.com/training/data-storage/use-cases#opt-out-scoped-storage , что теперь только Downloads получается открыта? 

     

    Цитата
    1. Move any shared non-media files to an app-dedicated subdirectory of the Downloads/ directory.

     

  8. Раньше у меня в директории  assets она  же android/data ,она же получаемая по TPath.GetSharedDocumentsPath располагался конфигурационный файл, который я мог править из файлового менеджера. Туда же скидывались логи и т.д. 

    Начиная с версии 10.0 Android эту возможность прикрыли.  Теперь android/data пуста, конфигурационный файл я не вижу. В 10-й версии причём как-то "через раз" работает.  В 11-м уже железно не работает. 

    Есть какая-это папка , которая доступна и для программы и для файлового менеджера?  Или можно в assets как-то доступ из файлового менеджера получить? 

  9. Решил я загрузить на Samsung Galaxy Store своё приложение. При этом на Google Play Store аккаунта не имеют.  Мне приложение заморозили  по причине "Play Protect pop-up appears during installation." - то есть , что ругается защитник.  Как показало гугление, для того, чтобы он не ругался надо загрузить приложение сначала на  Google Play Store.

    Вопрос , кто-то работал с  а Samsung Galaxy Store? Можно к ним загружать уникальные приложения. Или только те, что на Google Play Store уже загрузил(тогда непонятно зачем они вообще нужны). 

  10. krapotkin   - может вы и правы.  Потестирую на других устройствах пока тестировал на Samsung A71. Вот ещё что есть интересного. Я протестировал в режиме портретном, там угол экрана всё-таки ровно по центру пальца оказывается.  А в ланшафтном - увы.

    Slym - я пробовал нажимать стандартные иконки. Там именно реакция на нажатие именно по центру пальца. Что в портретном режиме, что в ландшафтном. 

    ---

    UPD   - на планшете Galaxy Tab 8a  всё работает, левый верхний угол именно по центру. 

    UPD2 - на Galaxy A6+ тоже работает. 

    UPD3 - на A71 фронтальная камера расположена прямо на экране. При клике на фронтальную камеру ничего не происходит.  При клике сверху или снизу камеры(если держать в ландшафтной ориентации)  тоже никакой реакции.  Если кликнуть чуть правее камеры, то левая часть прямоугольника устанавливается ровно слева от экрана. То есть сдвиг идёт ровно на ширину этой фронтальной камеры. 

  11. С помощью старших товарищей на этом форуме я научился отображать прямоугольники.  Вот код, который мне подсказали.

    procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
    begin
      FCrd := PointF(X,Y);
    end;
    
    procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Single);
    begin
      Invalidate;
    end;
    
    procedure TForm1.FormPaint(Sender: TObject; Canvas: TCanvas;
      const ARect: TRectF);
    begin
      Canvas.Fill.Color := TAlphaColorRec.Wheat;
      Canvas.FillRect(rectf(FCrd.X, FCrd.Y, FCrd.X+100, FCrd.Y+100), 0,0,[], 1);
    end;

    Так вот в Windows , если нажать курсор, то как мы и ожидаем, левый верхний угол прямоугольника будет установлен именно туда , куда мы нажали. В Andoroid же левый верхний угол устанавливается где-то по левой верхней части пальца. А ожидается, что он будет установлен в центр пальца.  В связи с этим вопросы.

    1) X,Y -это координаты центра пальца или левой верхней его части?

    2) Как получить координаты именно куда нажал центр пальца? Ведь я не знаю ни размера устройства ни размера пальца, поэтому просто прибавлять к X,Y какое-то значение, это такое себе.. 

    В справке удалось нарыть только это - http://docwiki.embarcadero.com/Libraries/Sydney/en/FMX.Controls.TControl.MouseDown  . Так никак не описывается поведение на планшетах. 

     

     

     

    20200723_173738.jpg

  12. Увы,  и это не работает.

     


     

     InvalidateRect(WinRect);
     //FormPaint(Sender,Canvas,TestRect);

    WinRect - посылается размер окна.

    Естественно на win32 работает и этот вариант.

    Цитата

    По мне, так то, что в Windows это работает - это скорее упущение, баг, а не фича ))

    Ну на VCL - это был скорее фича , можно было всё без танцев с бубном делать.  Но на FMX на разных платформах должно работать единообразно - или везде или нигде.   ПОтому , что любую программу надо будет тестировать на win32/64 , потом так же тщательно на Android , а потом ещё и на IoS. Вот у меня устойств с IOS нет , я уже понял, то доступ раз в недёлю "отца русской демократии" не спасёт. 

  13. Да , так работает лучше, но всё же всё-рано что-то не так. 

    Вот я отрабатываю клик мышкой.

     

     TestRect.Left := XToEtalon(X)-50;
     TestRect.Top :=  XToEtalon(Y)-50;
     FormPaint(Sender,Canvas,TestRect);
     WriteToLog(report,FloatToStr(X)+' , '+ FloatToStr(Y));

    И соотвественно,

    redraw(0,0,1,false);
    redraw(Round(ARect.Left),Round(ARect.Top),1,true);

    В итоге в Win32 всё работает отлично - куда я щёлкаю мышкой, появляются прямоугольники.

    В Android - нулевая реакция. 

    При этом в логе записывается , что клик произошёл. 

     

    Test2.rar

  14. Данный код работает в windows-32 , но не хочет работать в Android.

      Form1.Canvas.BeginScene;
      Form1.Canvas.Fill.Kind := TBrushKind.bkSolid;
      Form1.Canvas.Fill.Color :=  TAlphaColorRec.Red;
      form1.Canvas.FillRect(fs,0,0,AllCorners,1);
      Form1.Canvas.EndScene;

    Просто ничего не отрисовывается. В чём может быть причина? 

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

    Test.rar

  15. Я вот кстати пробовал реализовать более простой пример подключения , чем в этой библиотеке. 

     

    
       //NewUSB:=TUSB.Create;
       FEpOut:=nil;
       Memo1.Lines.Append('Begin');
       if UsbManager=nil then UsbManager:= TJvHidDeviceController.Create(Self); //usbManager = context.getSystemService(Context.USB_SERVICE) as UsbManager
       DeviceList := UsbManager.FUsbManager.getDeviceList;
       iter := DeviceList.values.iterator;
       while iter.hasNext do
        begin
          LocalUSBDevice := TJUSBDevice.Wrap((iter.next as ILocalObject).GetObjectID);
          if (LocalUSBDevice.getVendorId <> VENDOR) or (LocalUSBDevice.getproductId <> PRODUCT) then continue;//continue;
          Memo1.Lines.Append('Stage 1');
          for i:=0 to LocalUsbDevice.getInterfaceCount-1 do
            begin
              Memo1.Lines.Append('Stage 2');
              LocalUsbInterface := LocalUsbDevice.getInterface(0);
              if LocalUsbInterface.getInterfaceClass=3 then break;
            end;
    
          //Open
        end;
        if NOT UsbManager.UsbManager.hasPermission(LocalUSBDevice) then
        begin
    
          PermissionIntent:=TJPendingIntent.JavaClass.getBroadcast(SharedActivityContext, 0, TJIntent.JavaClass.init(StringToJString(ACTION_USB_PERMISSION)), 0);
          Filter := TJIntentFilter.JavaClass.init;
          Filter.addAction(StringToJString(ACTION_USB_PERMISSION));
          FBroadcastReceiverListener := TBroadcastReceiverListener.Create(UsbManager);
          FReceiver := TJFMXBroadcastReceiver.JavaClass.init(FBroadcastReceiverListener);
          SharedActivityContext.getApplicationContext.registerReceiver(
              FReceiver,
              Filter);
    
          UsbManager.UsbManager.requestPermission(LocalUSBDevice,PermissionIntent);
          exit;
        end;
    
    
       if LocalUsbInterface=nil then exit
       else Memo1.Lines.Append('Stage 3');
       for I := 0 to LocalUsbInterface.getEndpointCount-1 do
            begin
              FUsbEP := LocalUsbInterface.getEndpoint(i);
              if FUsbEP.getType=3 then
                begin
                  if FUsbEP.getDirection = TJUsbConstantsUSB_DIR_OUT then
                    begin
                      if FEpOut=nil then FEpOut := FUsbEP;
                    end
                  else if FUsbEP.getDirection = TJUsbConstantsUSB_DIR_IN then
                    begin
                      if FEpIn=nil then FEpIn := FUsbEP;
                    end;
                end;
            end;
          if {(EpIn=nil) AND} (FEpOut=nil) then  exit;
          Memo1.Lines.Append('Stage 4');
    
          // Open device
          FUsbDeviceConnection := UsbManager.UsbManager.openDevice(LocalUSBDevice);
          if not assigned( FUsbDeviceConnection) then exit;
          Memo1.Lines.Append('Stage 5');
          if not FUsbDeviceConnection.claimInterface(LocalUsbInterface, True) then exit;
          Memo1.Lines.Append('Stage 6');
          btnHIDEnable.Enabled := True;
          btnGetSerial.Enabled := True;
          //FUsbDeviceConnection.

    Соотвественно, передача делается через

    S:=IntToStr(FUsbDeviceConnection.bulkTransfer(FEpOut, Buffer, {Buffer.Length}3, 0));  //можно 0
      Memo1.Lines.Append('Retval = '+S);

    Он кстати при подключении пишет, что всё нормально. Но при попытке отправки данных увы, ничего не передаёт. Даже более того, другие программы на Java , запущенные параллельно тоже после моей не могут ничего передать. 

     

  16. В итоге для определеления имени продукта изменил код на

    FProductName := JStringToString(FUsbDevice.getProductName); 

    Вместо

    Цитата
    
     FProductName := GetDeviceString(2);
        //FProductName := JStringToString(FUsbDevice.getDeviceName);

    Серийный номер так и не получилось получать. 

  17. Приведу куски кода, которые , собственно эту хрень и вызывают.

    function THidServer.DeviceName(HidDev: TJvHidDevice): string;
    begin
      if HidDev.ProductName <> '' then
        Result := HidDev.ProductName
      else
        Result := Format('Device VID=%.4x PID=%.4x',
          [HidDev.Attributes.VendorID, HidDev.Attributes.ProductID]);
      if HidDev.SerialNumber <> '' then
        Result := Result + Format(' (Serial=%s)', [HidDev.SerialNumber]);
    end;


    Соотвественно HidDev.ProductName и HidDev.SerialNumber  получаем так

    function TJvHidDevice.GetProductName: String;
    begin
      if FProductName = '' then
      begin
        FProductName := GetDeviceString(2);
        //FProductName := JStringToString(FUsbDevice.getDeviceName);
      end;
      Result := FProductName;
    end;
    
    function TJvHidDevice.GetSerialNumber: String;
    begin
      if FSerialNumber = '' then
      begin
        FSerialNumber:=GetDeviceString(3);
        //if Openfile then FSerialNumber:=JStringToString(FUsbDeviceConnection.getSerial);
      end;
      Result := FSerialNumber;
    end;

     

    Наконец GetDeviceString - это вот что:

    
    function TJvHidDevice.GetDeviceString(Idx: Byte): string;
    const
      STD_USB_REQUEST_GET_DESCRIPTOR = $06;
      STD_USB_REQUEST_GET_REPORT = $01;
      LIBUSB_FEATURE_REPORT = $0301; //Feature report, ID = 1
      LIBUSB_DT_STRING = $03;
    var
      i,rdo:integer;
      rawDescs,buffer : TJavaArray<Byte>;
      requestidx:integer;
      S : String;
    begin
    
      if Openfile then
      begin
        rawDescs := FUsbDeviceConnection.getRawDescriptors;
    
        if (13+Idx)>rawDescs.Length then
        begin
          result:='';
          exit;
        end;
    
        requestidx := rawDescs[13+Idx];
    
        rawDescs.Free;
    
        buffer := TJavaArray<Byte>.Create(255);
    
        rdo := FUsbDeviceConnection.controlTransfer(
               (TJUsbConstantsUSB_DIR_IN	OR TJUsbConstantsUSB_TYPE_STANDARD),
               STD_USB_REQUEST_GET_DESCRIPTOR,
               ((LIBUSB_DT_STRING SHL 8) OR requestidx),
               0,
               buffer,
               $FF,
               0);
    
        if rdo>100 then rdo:=100;
    
        if rdo<3 then
        begin
          result:='';
          exit;
        end;
    
        S:='';
        for i:=1 to (rdo-2) do
        begin
          S:=S+Char(buffer.Items[i+1]);
        end;
        result:=S;
        buffer.Free;
      end
      else result:='';
    end;


     

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

    Arrival of  #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 (Serial= #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0 #0)

     

     

  18. Устанавливая в device_filter.xml устройство, с которым хочу работать. Например для PicKIT3  ставлю

    <usb-device vendor-id="1240" product-id="36874"/> 

    После этого при подключении данного устройства он предлагает выполнить мою программу.  Это было ожидаемый результат.  Неожидаемый результат, что если не прописать это устройство, то например выдаётся

    Device VID=04D8 PID=900

    А если устройство прописать, то выдаётся хрень вида

                      (Serial=                        )

     

    Это что, особенность планшета? Или это потому, что я к нему не правильно подключился? Или я как-то в лог могу неправильно записывать то, что он прислал? 

     

  19. Мне надо установить две версии своей программы на один планшет.  Но при установке система говорит, что это я старую пытаюсь обновить. И по итогу установлена оказывается одна(которую я последней установил).  Переименование проекта не спасает, он всё равно считает, что это одна и та же программа.  Как заставить систему их различать? 

×
×
  • Создать...