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

Евгений Корепов

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

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

  • Посещение

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

    100

Сообщения, опубликованные Евгений Корепов

  1. Я написал класс для демонизации приложения в linux. Класс форкает процесс, обрабатывает поступающие сигналы и передает их в основной поток через потокобезопасную очередь.

    Исходники https://github.com/EvgeniyKorepov/LinuxDaemon

    Для использования просто подключите модуль UnitDaemon в свое консольное приложение:

    program DaemonTest;
    
    {$APPTYPE CONSOLE}
    
    uses
      System.SysUtils,
      System.IOUtils,
      System.SyncObjs,
      Posix.Stdlib,
      Posix.SysStat,
      Posix.SysTypes,
      Posix.Unistd,
      Posix.Signal,
      Posix.Fcntl,
      Posix.Syslog in 'Posix.Syslog.pas',
      UnitDaemon in 'UnitDaemon.pas';
    
    var
      AEventType : TEventType;
    
    begin
      syslog(LOG_NOTICE, 'main START');
      while True do
      begin
        syslog(LOG_NOTICE, 'main LOOP');
        if UnitDaemon.QueueEvent.PopItem(AEventType) = System.SyncObjs.TWaitResult.wrSignaled then
        begin
          syslog(LOG_NOTICE, 'main UnitDaemon.QueueEvent.PopItem');
          case AEventType of
            TEventType.StopProcess :
            begin
              syslog(LOG_NOTICE, 'main Event StopProcess');
              ExitCode := EXIT_SUCCESS;
              exit;
            end;
            TEventType.Start :
            begin
              syslog(LOG_NOTICE, 'main Event START');
            end;
            TEventType.Reload :
            begin
              // Reload config
              syslog(LOG_NOTICE, 'main Event RELOAD');
            end;
            TEventType.Stop :
            begin
              syslog(LOG_NOTICE, 'main Event STOP');
              ExitCode := EXIT_SUCCESS;
              exit;
            end;
          end;
        end;
        Sleep(50);
      end;
    end.

    Так же поддерживается systemd - для этого положите  DaemonTest.service в /etc/systemd/system/ и используйте :

    systemctl start DaemonTest.service 
    systemctl reload DaemonTest.service 
    systemctl stop DaemonTest.service

     

  2. И еще вариант похожий, источник https://stackoverflow.com/questions/44415054/execute-external-program-from-linux-delphi-10-2-console-application

    uses
      ...
      System.SysUtils,
      Posix.Base,
      Posix.Fcntl,
      ...;
    
    type
      TStreamHandle = pointer;
    
    function popen(const command: MarshaledAString; const _type: MarshaledAString): TStreamHandle; cdecl;
          external libc name _PU + 'popen';
    function pclose(filehandle: TStreamHandle): int32; cdecl; external libc name _PU + 'pclose';
    function fgets(buffer: pointer; size: int32; Stream: TStreamHandle): pointer; cdecl; external libc name _PU + 'fgets';
    
    function runCommand(const acommand: MarshaledAString): String;
    // run a linux shell command and return output
    // Adapted from http://chapmanworld.com/2017/04/06/calling-linux-commands-from-delphi/
    var
      handle: TStreamHandle;
      data: array [0 .. 511] of uint8;
    
      function bufferToString(buffer: pointer; maxSize: uint32): string;
      var
        cursor: ^uint8;
        endOfBuffer: nativeuint;
      begin
        if not assigned(buffer) then
          exit;
        cursor := buffer;
        endOfBuffer := nativeuint(cursor) + maxSize;
        while (nativeuint(cursor) < endOfBuffer) and (cursor^ <> 0) do
        begin
          result := result + chr(cursor^);
          cursor := pointer(succ(nativeuint(cursor)));
        end;
      end;
    
    begin
      result := '';
      handle := popen(acommand, 'r');
      try
        while fgets(@data[0], sizeof(data), handle) <> nil do
        begin
          result := result + bufferToString(@data[0], sizeof(data));
        end;
      finally
        pclose(handle);
      end;
    end;
    
    function createQRCode(id, fn: string): string;
    // Create qr-code using qrencode package
    begin
      deletefile(fn);
      if fileExists(fn) then
        raise Exception.create('Old file not deleted!');
      // I am targeting rhel for now, so I know the path for sure
      result := runCommand(MarshaledAString(UTF8STring('/usr/bin/qrencode -o ' + fn + ' ''' + id + '''')));
      if not fileExists(fn) then
        raise Exception.create('New file not created!');
    end;
    
    function testqr: String;
    // Test QR Code creation with error handling
    // QREncode does not output anything but who knows ;-)
    begin
      try
        result := createQRCode('08154711', '/tmp/myqrcode.png');
      except
        on e: Exception do
        begin
          result := 'Error: ' + e.message;
        end;
      end;
    end;

     

  3. Отсюда https://chapmanworld.com/2017/04/06/calling-linux-commands-from-delphi/

    program myls;
    {$APPTYPE CONSOLE}
    {$R *.res}
    
    uses
      System.SysUtils,
      Posix.Base,
      Posix.Fcntl;
    
    type
      TStreamHandle = pointer;
    
    ///  <summary>
    ///    Man Page: http://man7.org/linux/man-pages/man3/popen.3.html
    ///  </summary>
    function popen(const command: MarshaledAString; const _type: MarshaledAString): TStreamHandle; cdecl; external libc name _PU + 'popen';
    
    ///  <summary>
    ///    Man Page: http://man7.org/linux/man-pages/man3/pclose.3p.html
    ///  </summary>
    function pclose(filehandle: TStreamHandle): int32; cdecl; external libc name _PU + 'pclose';
    
    ///  <summary>
    ///    Man Page: http://man7.org/linux/man-pages/man3/fgets.3p.html
    ///  </summary>
    function fgets(buffer: pointer; size: int32; Stream: TStreamHAndle): pointer; cdecl; external libc name _PU + 'fgets';
    
    ///  <summary>
    ///    Utility function to return a buffer of ASCII-Z data as a string.
    ///  </summary>
    function BufferToString( Buffer: pointer; MaxSize: uint32 ): string;
    var
      cursor: ^uint8;
      EndOfBuffer: nativeuint;
    begin
      Result := '';
      if not assigned(Buffer) then begin
        exit;
      end;
      cursor := Buffer;
      EndOfBuffer := NativeUint(cursor) + MaxSize;
      while (NativeUint(cursor)<EndOfBuffer) and (cursor^<>0) do begin
        Result := Result + chr(cursor^);
        cursor := pointer( succ(NativeUInt(cursor)) );
      end;
    end;
    
    var
      Handle: TStreamHandle;
      Data: array[0..511] of uint8;
    
    begin
      try
        Handle := popen('/bin/ls -lart','r');
        try
          while fgets(@data[0],Sizeof(Data),Handle)<>nil do begin
            Write(BufferToString(@Data[0],sizeof(Data)));
          end;
        finally
          pclose(Handle);
        end;
      except
        on E: Exception do
          Writeln(E.ClassName, ': ', E.Message);
      end;
    end.

     

  4. А вот я и не прав! Теперь я тоже проклят и напоролся на точно такую же проблему. 

    Действительно, PopItem в непредсказуемый момент изменяет поведение - любой таймаут (от 1 до INFINITE) превращается в 0.

    И похоже проблеме уже 2 года, но Эмбаркадера делает вид что в " я в домике". Т.е. полностью игнорирует проблему. Дело похоже как обычно в злощастном TMonitor - то одна проблема, то другая, то опять внедряют предыдущую проблему.

    Вот найденные ссылки по этой проблеме:

    https://forums.embarcadero.com/thread.jspa?messageID=941762

    https://quality.embarcadero.com/browse/RSP-19993

    А вот тут речь тоже о той же самой проблеме, дата 2012 год

    https://delphihaven.wordpress.com/2012/01/30/fixing-tthreadedqueue-or-in-other-words-tmonitor-again/

  5. Вам нужно провести чистый эксперимент на простом приложении и простых условиях. И не использовать Double для условий - лучше использовать целочисленные переменные, чтоб быть уверенным в отсутствии накопления ошибки.

    Еще важный момент - создание очереди

    TThreadedQueue<TBytes>.Create(100, 1, 1)

    не совсем корректно. Вы ставите одинаковый и минимально возможный таймаут на pop и push, и рискуете словить взаимную блокировку. Пока идет push невозможен pop, и наоборот. Обычно, в зависимости от условий, ставят одно гораздо больше другого, к примеру если важна целостность подаваемых данных, то push 1000, а если нужен быстрый поток (который параллельно делает что то еще), то pop 10. Или если поток только обрабатывает входящие данные, то pop 3600 * 24, чтоб он зря не крутился без данных ))) 

    Сейчас у меня приложение на Delphi 10.3.3 крутится месяц без остановки, архитектура - Основной поток -> Поток получения данных -> Поток обработки данных -> 100-200 потоков исполнителей. Весь обмен на очередях. Плюс поток логов и поток мониторинга (они получают данные, каждый по своей очереди, со всех потоков. 

    И никаких аномалий я не заметил, все работает как часы.

  6. 9 часов назад, Lenar Gubaidullin сказал:

    Попробовал скомпилировать по Android64 проект advancedTestApp

    сообщает ошибку компилирования libfastutils-android-thumb.a

    Вы создайте запрос прямо на первоисточнике https://github.com/zxing/zxing/issues - автор вам быстрее поможет.

    Прошу прощения, не туда ссылку дал ) Вот правильная https://github.com/Spelt/ZXing.Delphi/issues

  7. Только что, Евгений Корепов сказал:

    Друзья, вы будете смеяться - Эмбаркадера наконец то обратила внимание на заявку по этой проблеме. Правда в стиле моя-твоя непонимай. )))  ТРИ года (без одного месяца) заявка висела без движения. 

    https://quality.embarcadero.com/browse/RSP-16910

     

  8. В телефоне нет никаких гарантированных аппаратных данных - или по причине китайщины, или по тому что их можно изменить. Если уже вам так хочется "привязаться" к чему то неизменному, то привязывайтесь к телефонному номеру. Хотя и его может не быть. 

    Палец не панацея - у вас нет никаких гарантий что палец принадлежит владельцу персональных данных. 100% дактилоскопических данных пользователя у вас нет, а на этапе "привязки" пальца, телефон уже может быть в руках злоумышленника.

    У вас не получится сделать идеальную систему с абсолютной системой от дурака. Поэтому я и предложил исходить из того что приложение на телефоне запускает легальных пользователь. Все иное должно описываться в политике конфиденциальности, типа мы чтим закон о ПД, но если вы долбоклюй и отдали телефон и пинкод постороннему, то вы сами пролюбили свою медкарту.

    И пинкод никак не позволит войти на другом устройстве - пин код сохраняется локально на устройстве, в папке приложения. И если пользователь ввел его верно, то запросы на сервер авторизуются с заранее сохраненного на устройстве токена (guid, куки или что вам больше нравится). 

    Ситуации "А если кто взломает телефон и перенесет какой то файл на другое устройство" вас не должны волновать абсолютно. Вы предоставили пользователю приложение, а задача пользователя  - не пролюбить телефон и свои персональные данные. Дополнительно вы прикрываете свою задницу политикой конфиденциальности, где описываете что не обязаны охранять пользователя и его телефон круглые сутки.

  9. Почитал ваши сообщения по этой теме, вот ключевое (с отзывом пользователя) 

    Повторюсь - отпечаток пальца, не то что вам нужно. Он есть у небольшой части устройств. Возьмите на вооружение банковские клиенты - один раз ввел логин/пароль, если успешно, то придумал ПИН-код, и в дальнейшем входишь по нему. 

  10. Никакой логики по пальцу не нужно. По пальцу идет разблокировка телефона. Т.е. если пользователь смог запустить приложение - значит это легальный пользователь, потому как он смог разблокировать телефон (пальцем или пин-кодом). 

    Если у вас серьезные требования  к безопасности, то возьмите любое банковское приложение и скопируйте с него логику работы. Если требование к безопасности не строгие - то не нужно ничего городить, если пользователь запустил приложение, значит это легитимный пользователь. А если пользователь отдал телефон и свой палец соседу  - то он сам дурак ))))

  11. 3 часа назад, Сергей Сергеев сказал:

    Но ведь если скопировать этот файл на другое устройство - вся логика привязки сломается.. и возможен несанкционированный вход.. 

     

    Ну речь не шла о безопасности/авторизации/аутентификация. Речь была о получении уникального идентификатора на устройство.

    Если нужна авторизация, то ее разумно делать не локально в приложении, а на некоем сервере (а приложение в этом случае выступает тонким клиентом).

    И как правильно выше отметил Slym - для доступа к файлам приложения вам нужно взломать устройство (получить доступ пользователя root). ССЗБ - аббревиатура в данном контексте означает некие изначально ошибочные решения принятые разработчиком приложения ))) Погуглите ))))

  12. 1 час назад, Maka сказал:

    А как сделать, чтобы Interstitial video появлялось без звука?

    Подозреваю что такая попытка приведет к блокировке учетной записи. Нельзя вмешиваться в показ рекламы или изменять рекламный контент.

  13. В 23.11.2019 в 19:43, WebPuper сказал:

    М даааааааа... полностью лишились компилятора под x64 на год...  мои проекты подвисли в воздухе.

    У кого есть опыт публикации 32 разрядных приложений для Android на каких-нибудь площадках кроме Google Play ?  

    В Яндекс-маркете и Амазоне достаточно просто опубликовать приложение.

  14. 2 часа назад, Yarpda сказал:

    Да. нужно получение данных по HTTPS (иначе не пришлось бы возиться с SLL и проблемы бы не было как таковой). У меня в стандартном наборе нет компонента "THTTPClient" . Есть "TNETHTTPClient". Но судя по первому взгляду методы и свойства там схожие, попробую и этот вариант. Спасибо за наводку!

    Вам не нужен TNETHTTPClient, это всего лишь обертка для THTTPClient. Просто сделайте поиск по данному форуму по "THTTPClient" и вам откроется многое.

  15. 11 часов назад, Yarpda сказал:

    Выкладываю проект где можно наглядно все это проверить. В случае компиляции под Android x32 все работает. В случае x64 - перестает. На 32 и 64 деплоятся разные библиотеки ssl из разных папок. Установка в режиме Debug.

    Прошу помочь разобраться в проблеме. (Сам я предполагаю, что нужны какие-то специальные библиотеки ssl от INDY под х64, но их пока нет, и появятся ли неизвестно).

    SSL x64 Android issue.rar 1 \u041c\u0411 · 3 downloads

    В примере у вас получение данных по HTTPS. В рабочем проекте тоже самое? Может тогда не мучатся с Indy и его сторонними библиотеками, а использовать родной механизм андроида - THTTPClient?  

  16. 32 минуты назад, Олег Киреев сказал:

    Здравствуйте Евгений.

    Пожалуйста ответьте мне на такой вопрос по этой теме.

    Я пытаюсь отправить файл базы вот так:

    //Поделится БД
    procedure TForm_glavn.ButtonПоделитсяБДClick(Sender: TObject);
    begin
    if FileExists(TPath.GetSharedDocumentsPath+'/DB_BOKA.db3') then
    begin
       Try
       ShareFile(TPath.GetSharedDocumentsPath+'/DB_BOKA.db3', 'Это файл DB_BOKA.db3 из приложения БОКА.');
       ShowMessage('Отправлено.');
       Except
       ShowMessage('Не отправлено.');
       End;
    end else ShowMessage('Файл '+TPath.GetSharedDocumentsPath+'/DB_BOKA.db3'+' не найден.');
    end;

    себе на почту.

     Появляется сообщение что файл не найден.   Наверное дело в пути? Подскажите пожалуйста как узнать где лежит файл базы на телефоне? Поделитесь пожалуйста своим опытом.

    С Уважением. Олег.

    Файл будет лежать там, куда вы его положили. Откуда нам знать где на вашем телефоне может лежать какой то файл? 

  17. 4 часа назад, Partisan сказал:

    Если не менять формат файлов, то да.

    Если менять, что посоветуете из того что совместимо c multi-device FMX и Delphi 7?

    Посоветую не сжимать данные. За последние 10-15 лет объемы хранилищ несколько увеличились, скорости передачи тоже, так что скорее всего сжатие уже неактуально.

  18. 2 часа назад, krapotkin сказал:

    Безусловно)

    Смотрю в секции Variables можно на лету вычисления делать. Через как арифметика считается (чтоб по исходникам не искать)? просто интересно.

    И можно ли там использовать динамические параметры? Типа ширины ListView (или итема с учетом отступов)? Было бы вообще прикольно. Я обычно размер картинки как раз вычисляю динамически, в зависимости от ширины (типа 30% от ширины итема).

     

    ЗЫ Присмотрелся, вижу itemwidth - видимо это как раз то что мне нужно.

  19. 5 часов назад, krapotkin сказал:

    P.S.

    по факту использования мне показалось, что удобнее использовать не отдельный JSON файл, а прямо в коде константой задавать JSON строкой.

    (Видимо сказались приключения с деплоем)))

    Или получать по http с сервера - тут вообще простор, можно дизайн списка менять на лету ))))

  20. К сожалению тема никакого отношения в Умному дому не имеет. В телеграмме я поднимал тему о реальных технологиях умного дома - датчиках (задымление, протечка, газ, открытие двери/окна, движение), протоколы и технологии соединения всего этого, к примеру ZigBee, ну и работа со всем этим хозяйством.

    Тема прикольная и интересная. Написал на delphi класс работы в ZigBee шлюзом, нормально опрашиваю все датчики, но запись реализовать не удалось из за отсутствия в delphi библиотек шифрования "из коробки". Наработок куча, но все они времен Delph 7 - абсолютно все используют короткие ANSI строки, и в современных версиях среды результат шифрования/дешифровки может быть какой угодно, но не правильный.

    Пока все что нужно по быстрому написал на php, там хоть с шифрованием порядок, не надо изобретать велосипед или адаптировать код двадцатилетней давности.

    Так что теперь могу включать/выключать свет с помощью умной розетки, включать светильник на основном хабе, выбирая яркость и палитру, но на php ))))

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