Перейти к содержанию

Лидеры


Популярный контент

Показан контент с высокой репутацией за 09.07.2019 во всех областях

  1. 14 баллов
    Всем добрый вечер, Вот и прошло лето, а вместе с этим подходит к концу закрытое бета тестирование библиотеки FGX Native. Проделана огромная работа, как в разработке самой библиотеки, так и в разработке нового портала. Плодотворная работа во время бета тестирования принесла свои плоды. В результате: Были разработаны несколько новых интересных мобильных проектов: Аналог сервиса распознавания музыки Shazam на Delphi и FGX Native! Температурный дневник. Фиксация температуры, приема лекарств, построение графиков и рекомендации о приеме лекарств. Электронный конспект лекций по теме "Слесарное дело" с функциями самопроверки. Домашняя аптечка. Большой проект с демонстрацией возможностей библиотеки. Добавлены новые возможности и компоненты. Повышена стабильность работы библиотеки. И многое другое. Я рад с вами поделиться отличной новостью, которую многие с нетерпением ждали. До нового года запланирован релиз библиотеки FGX Native под Андроид, который будет доступен для РФ и стран СНГ: Разработка кроссплатформенных приложений под Андроид . Русскоязычная документация. Набор демонстрационных проектов. Более 40 готовых компонентов. Свой дизайнер форм. В течении следующих двух недель будет опубликована ссылка на сайт, посвященный библиотеке FGX Native. На нем вы сможете найти: описание возможностей, документацию, тарифы и многое другое - всё это поможет вам предварительно оценить возможности библиотеки для реализации своих проектов. Позже, ближе к новому году, будет выложена Trial сборка библиотеки и открыта продажа. Если у вас есть какие-либо вопросы - задавайте. Всем отличной рабочей недели! P.S. - Релиз под iOS запланирован на весну/лето 2020 года. - Релиз для других стран будет позже, после локализации документации.
  2. 9 баллов
    У меня в работе два приложения, и оба они не предназначены для Play market, так как имеют ограниченный круг использования, по сути, чисто внутрикорпоративные. Так что нежелательно и выкладывание их и на альтернативные магазины приложений. Автоматически возникает вопрос обновления. Если в первый раз мы можем установить приложение сами при помощи админов, то обновлять их не так просто. А контингент пользователей не справится с "скачайте APK по ссылке, найдите, куда его скачал браузер, и запустите вручную именно последний скачанный, а не какой попало"... Простейший способ - дать приложению скачать свежую копию с сайта и натравить на полученный файл системный инсталлер. Вот только свежие Andoird делать это напрямик запрещают. Нужен filepropvider. Целый день шуровал по мануалам и YT, Вот то что получилось в результате. Если у вас 10.3.3 как у меня, уже можно не вносить <provider>...</provider> в манифест и свой файл file_paths.xml (или как вам его советуют назвать в интернетах) в деплой. Теперь все это делается хоть несколько странно и однобоко, но автоматически, путем установки галочки Secure File Sharing после этого в манифесте автоматически пропишется один из вариантов размещения файлов, которые вы можете найти в интернете. Используется алиас external-path файл, показанный на рисунке, создается автоматически самой делфи. теперь остается отгадать, какой путь реально подставится вместо "." Как показала практика, все пути выглядят не так, как кажется, если исходить из простого здравого смысла. Целый день использования GetHomeDir и других полезных методов TPath завел меня совсем в тупик. Оказалось все проще (?) st:TMemoryStream; OutputDir: JFile; ApkFile: JFile; ApkUri: Jnet_Uri; path, filename: string; ... OutputDir := TAndroidHelper.Context.getExternalCacheDir(); path := JStringToString(OutputDir.getAbsolutePath); filename := path+'/ASDroid2.apk'; ApkFile := TJfile.JavaClass.init( StringToJstring(filename)); FApkUri := TAndroidHelper.JFileToJURI(ApkFile); st.Position := 0; st.SaveToFile(filename); обратите внимание, в provider_paths мы задаем external-paths, а в коде ищем ExternalCacheDir.!!! (For.Unbelievably.Creative.Knowers!) Потом все просто. FApkUri передаем в интент и запускаем итоговый код примерно таков. (скачивание в потоке с использованием небольшого собственного API, но там ничего важного, можно не обращать внимания) procedure TasdSettingsFrame.bDownloadClick(Sender: TObject); begin {$IFDEF ANDROID} bDownload.Enabled := False; DownloadAndRun(); {$ENDIF} end; {$IFDEF ANDROID} procedure TasdSettingsFrame.DownloadAndRun(); begin ttask.Run(procedure var aapi:TasdAPI; st:TMemoryStream; OutputDir: JFile; ApkFile: JFile; ApkUri: Jnet_Uri; path, filename: string; begin st := TMemoryStream.Create; aapi := TasdAPI.Clone(_API); try aapi.OnReceiveData := OnReceiveData; aapi.getApk(st); if aapi.Err.Code=0 then begin OutputDir := TAndroidHelper.Context.getExternalCacheDir(); path := JStringToString(OutputDir.getAbsolutePath); filename := path+'/ASDroid2.apk'; ApkFile := TJfile.JavaClass.init( StringToJstring(filename)); FApkUri := TAndroidHelper.JFileToJURI(ApkFile); st.Position := 0; st.SaveToFile(filename); TThread.Synchronize(nil,procedure begin bDownload.Enabled := true; StartActivity(FApkUri); end); end; finally st.Free; aapi.Free; end; end); end; procedure StartActivity(ApkUri: Jnet_Uri); var Intent: JIntent; begin Intent := TJIntent.Create(); Intent.setAction(TJIntent.JavaClass.ACTION_VIEW); Intent.addFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK or TJIntent.JavaClass.FLAG_ACTIVITY_CLEAR_TOP or TJIntent.JavaClass.FLAG_GRANT_WRITE_URI_PERMISSION or TJIntent.JavaClass.FLAG_GRANT_READ_URI_PERMISSION); Intent.setDataAndType(apkuri, StringToJString('application/vnd.android.package-archive')); TAndroidHelper.Activity.startActivity(Intent); end; procedure TasdSettingsFrame.OnReceiveData(const Sender: TObject; AContentLength: Int64; AReadCount: Int64; var Abort: Boolean); begin tthread.Synchronize(nil, procedure begin pb1.Max := AContentLength; pb1.Value := AReadCount; end); end; {$ENDIF} Вопросы остались конечно, почему так странно с каталогами, но выяснять пока нет желания. Работает - не трожь. Всем удачи. UPD. Для того, чтобы системный инсталлер запускался, нужно не забыть отметить еще одну галочку
  3. 8 баллов
    В общем удалось решить проблему с кнопками пульта. Теперь приложение распознает все кнопки с пульта. Если кому-то нужно, прикрепил архив. (Delphi 10.3.1 Rio) fmx_androidkey_fix.zip
  4. 6 баллов
    Brovin Yaroslav

    [FGX Native] Релиз!!!

    Поздравляю всех с наступающим новым годом и рад сообщить вам о релизе FGX Native. Это были 3 года плодотворной работы над этим проектом. За это время была проделана колоссальная работа. И еще многое предстоит преодолеть и реализовать. Рад, что успел зарелизить проект до 2020 года. Спасибо всем участника альфа и бета тестирования за оказанную помощь, обратную связь и поддержку. Надеюсь, что вам понравится полученный продукт и с каждым днем он будет лучше и интереснее. Так же рад поделиться, что в моей команде прибыл один разработчик Виктор. Который помог мне подготовить релиз и продолжить трудится со мной над развитием проекта FGX Native. Это позволит делать больше крутых фич и естественно заниматься поддержанием качества продукта. Триал можно скачать здесь: https://forum.fgx-native.com/. Продажа начнется 1 января 2020 года. Всех с новым "безбажным" годом.
  5. 6 баллов
    сделано на Datasnap - 3х звенка MsSql- Сервис Https - Клиент ( Андроид, Ios, Win, Mac) Личный кабинет пациента клиники (www.familydoctor.ru) открывает зарегистрированным пользователям доступ к медицинской карте (результаты лабораторных исследований и функциональной диагностики, описание приемов врачей, направления и рекомендации, истории посещений клиники (дата, время, специалист), программам медицинского наблюдения (перечень, период прикрепления), информации о движении средств по депозитам. Для пересылки выписок (файлов) из медицинской карты используется электронная почта (в системе должен быть настроенный Майл Агент на отправку почты).Полной версией приложения могут воспользоваться только пациенты, подключившие услугу "Личный кабинет" в регистратуре любого корпуса клиники "Семейный доктор".В новой версии изменен дизайн, появились новые функции и разделы:вход по номеру медкарты или ФИО;запрос нового пароля;заявка на онлайн запись;отмена приема;прейскурант услуг клиники;справочник адресов клиники. сервис оплаты услуг клиники через приложение.В ближайшем будущем функционал личного кабинета будет дополнен онлайн расписанием специалистов, возможностью электронной записи на приём. в гугл плее https://play.google.com/store/apps/details?id=com.familydoctor.FD Есть тестовый вход, обращайтесь.
  6. 6 баллов
    Это приложение для OS Windows выполняет: 1.Расчёт сцепления: -расчёт и подбор геометрических параметров нажимного и ведомого дисков, муфты выключения; -проверка параметров по теплонагруженности пар трения; -расчёт всех наиболее нагруженных деталей сцепления (пружины, пластины, подшипник). 2.Расчёт пневмогидравлического привода сцелпения: -подбор и проверка управляющего и исполнительного органов; -объём жидкости. 3.Возможность вноса и редактирования исходных данных и результатов в БД. 4.Распечатку всего расчёта с исходными данными, формулами, графиками, используемой литературой и результатами в MS Word. 5.Просмотр и изучение нажимного, ведомого дисков и муфты выключения в 3D. Изначально для работы в приложении необходимы некоторые знания конструкции сцепления и теории расчёта. Автор: Олег Киреев-ведущий инженер-конструктор, kireevoleg1966@gmail.com, +375 29 676 13 84 БЕЛАРУСЬ, г.Минск. Приму Ваши замечания и предложения. По совету Равиля Зарипова РАЗМЕСТИЛ на файлообменнике 12.08.2019г по этой: https://mega.dp.ua/a27WmeXKwY ссылке. На этом ресурсе обещают хранить 90 дней. Интересно услышать Ваши отзывы.
  7. 6 баллов
  8. 5 баллов
    Обновлена серия статей на тему использования Uses Permissions. Uses Permissions: Теория Uses Permissions: Добавляем метод onRequestPermissionsResult в приложение (для Delphi 10.1/10.2) Uses Permissions: Практика (для Delphi 10.3) Автор: Андрей Ефимов
  9. 5 баллов
    krapotkin

    Фреймворк для стандартного ListView

    еще один пример раскладки из реального проекта { "Columns":[], "Variables": [ {"Y_UNIT":"12"}, {"GAP":"8"}, {"ITEM_H":"2*GAP+5*Y_UNIT"}, {"IMG_H":"76"}, {"IMG_W":"76"}, {"STOCK_SIZE":"48"}, {"PRICE_COLW":"53"} ], "Objects": [ {"Name":"ID","Kind":"data"}, , {"Name":"img","Kind":"image", "Place":{"X":"0","Y":"0","W":"IMG_W","H":"IMG_H"}, } , {"Name":"Text","Kind":"text","TextHAlign":"leading","TextVAlign":"leading", "Place":{"X":"img.right","Y":"GAP","W":"itemwidth - IMG_W - GAP - 2*PRICE_COLW - GAP","H":"52"}, "WordWrap":true, "Color":"black", "Font":{"Size":12} } , {"Name":"earlier","Kind":"text","TextHAlign":"leading","TextVAlign":"leading", "Place":{"X":"text.left","Y":"ITEM_H-2*GAP+2","W":"itemwidth - 2*PRICE_COLW","H":"Y_UNIT"}, "WordWrap":false, "Color":"green", "Font":{"Size":10} } , {"Name":"price1","Kind":"text","TextHAlign":"trailing","TextVAlign":"trailing", "Place":{"X":"itemwidth-GAP-PRICE_COLW-W","Y":"GAP+2*Y_UNIT","W":"auto","H":"Y_UNIT*1.5", "priority":"WXYH"}, "WordWrap":false, "Color":"black", "Font":{"Size":15} } , {"Name":"imgstrike","Kind":"image", "Place":{"X":"price1.x-5","Y":"price1.y","W":"price1.w+8","H":"price1.h"}, } , {"Name":"price2","Kind":"text","TextHAlign":"trailing","TextVAlign":"trailing", "Place":{"X":"price1.right-W","Y":"ITEM_H-GAP-Y_UNIT*1.5","W":"auto","H":"Y_UNIT*1.5", "priority":"WXYH"}, "WordWrap":false, "Color":"black", "Font":{"Size":15, "style":"bold"} } , {"Name":"qty","Kind":"text","TextHAlign":"trailing","TextVAlign":"center", "Place":{"X":"itemwidth-PRICE_COLW-GAP","Y":"GAP","W":"PRICE_COLW","H":"2*Y_UNIT"}, "WordWrap":false, "Color":"black", "Font":{"Size":27, "style":"bold"} } , {"Name":"imgstock","Kind":"image", "Place":{"X":"itemwidth-STOCK_SIZE-3","Y":"ITEM_H-STOCK_SIZE-4","W":"STOCK_SIZE","H":"STOCK_SIZE"}, } ], "ItemHeight":"ITEM_H", "ItemSpaces": {"X":"0","Y":"0","W":"0","H":""}, "SideSpace":"0" }
  10. 5 баллов
    Владимир Б.

    TInstructor - Step-By-Step инструкция

    Собственно понадобился подобный компонент для FMX, но готового решения найти не смог - пришлось ваять свой. Использовать проще простого: var scenaries: TDictionary<TFmxObject, string>; begin scenaries := TDictionary<TFmxObject, string>.Create; scenaries.Add(btn_1, '1 Button'); scenaries.Add(btn_2, '2 Button'); scenaries.Add(btn_3, '3 Button'); scenaries.Add(rctngl, 'Rectangle'#13#10'Rectangle'#13#10'Rectangle'#13#10'Rectangle'#13#10'Rectangle'#13#10'Rectangle'#13#10'Rectangle'); scenaries.Add(pnl_1, 'Panel Panel Panel Panel Panel Panel Panel Panel Panel Panel'#13#10'Panel'); scenaries.Add(nil, 'Msg without target control!'); try instructor.LoadSteps(scenaries); finally FreeAndNil(scenaries); end; Репозиторий GitHub: https://github.com/ange007/TInstructor/
  11. 5 баллов
    Пока тестировал хелпер в боевом проекте он потихоньку оброс исрпавлениями/улучшениями: Загрузка из потока сделана через TBitmapSurface - это позволяет избежать множества глюков. LoadFromStream вынесен из Synchronize (основного потока) в поток HTTPClient - по результатам бенчмарка операция оказалась самая жручая. После исправления интерфейс перестал залипать совсем. Добавлен overload вариант с передачей в процедуру TListItemImage - для использования в TListView и корректной перерисовки подгруженных картинок через AListItemImage.Invalidate. unit BitmapAsyncLoader; interface uses FMX.Graphics, FMX.Surfaces, System.Net.HttpClient, System.Types, System.Classes, FMX.ListView.Types, FMX.ListView.Appearances; type TBitmapAsyncLoader = class helper for TBitmap procedure LoadFromURLAsync(const AUrl : String); overload; procedure LoadFromURLAsync(const AUrl : String; const AListItemImage : TListItemImage); overload; end; implementation var AHTTPClient : THTTPClient; procedure TBitmapAsyncLoader.LoadFromURLAsync(const AURL : String); begin try AHTTPClient.BeginGet( procedure (const ASyncResult: IAsyncResult) var AHTTPResponse : IHTTPResponse; ABitmapSurface : TBitmapSurface; begin if Not ASyncResult.IsCompleted then exit; try AHTTPResponse:=THTTPClient.EndAsyncHTTP(ASyncResult); except end; if Assigned(AHTTPResponse) and (AHTTPResponse.StatusCode = 200) then begin ABitmapSurface:=TBitmapSurface.Create; if TBitmapCodecManager.LoadFromStream(AHTTPResponse.ContentStream, ABitmapSurface, CanvasClass.GetAttribute(TCanvasAttribute.MaxBitmapSize)) then TThread.Synchronize(Nil, procedure begin if Assigned(Self)then Assign(ABitmapSurface); ABitmapSurface.Free; end ) else ABitmapSurface.Free; end; end, AURL ); except end; end; procedure TBitmapAsyncLoader.LoadFromURLAsync(const AURL : String; const AListItemImage : TListItemImage); begin try AHTTPClient.BeginGet( procedure (const ASyncResult: IAsyncResult) var AHTTPResponse : IHTTPResponse; ABitmapSurface : TBitmapSurface; begin if Not ASyncResult.IsCompleted then exit; try AHTTPResponse:=THTTPClient.EndAsyncHTTP(ASyncResult); except end; if Assigned(AHTTPResponse) and (AHTTPResponse.StatusCode = 200) then begin ABitmapSurface:=TBitmapSurface.Create; if TBitmapCodecManager.LoadFromStream(AHTTPResponse.ContentStream, ABitmapSurface, CanvasClass.GetAttribute(TCanvasAttribute.MaxBitmapSize)) then TThread.Synchronize(Nil, procedure begin if Assigned(Self) and Assigned(AListItemImage) then begin AListItemImage.BeginUpdate; Assign(ABitmapSurface); AListItemImage.Invalidate; AListItemImage.EndUpdate; end; ABitmapSurface.Free; end ) else ABitmapSurface.Free; end; end, AURL ); except end; end; initialization AHTTPClient:=THTTPClient.Create; finalization if Assigned(AHTTPClient) then AHTTPClient.DisposeOf; end. Тестовый проект, на этот раз с ListView (по кнопке добавляется 100 итемов) прилагаю. BitmapAsyncLoaderListView.7z
  12. 5 баллов
    Веб.бинар показал, что проделано огромная работа. Очень понравилось.
  13. 4 балла
    Дмитрий Потапов

    BlurBehind Control

    BlurBehind Control. Компонент позволяет использовать размытие, по типу, которое реализовано в WIndows 10, т.е компонент позволяет "размыть" то, что находится под ним. Пусть и увидел это непосредственно в самой студии на стартовой странице (Welcome Page), но все-таки подумал скинуть ссылку сюда. Исходники: https://github.com/grijjy/CodeRage2019/tree/master/BlurBehind Видео:
  14. 4 балла
    Eric Myval

    Unable to create process

    Результат следующий Мой проект корректно работает под 1) Windows 32/64 2) Android 32/64 3) iOS 32/64 (обязательно настроить сертификаты, которые можно создать и прикрепить в Xcode + настроить их в Rad Studio в разделе Project-Deployment-Provisioning, выбрать там ключи как вы их настроили на вашем маке + ОБЯЗАТЕЛЬНО в version info удалить текст в CFBundleIdentifier, должно быть пусто) 4) MacOS 32/64 5) iOS 32/64 simulator - не работает!!!
  15. 4 балла
    Одной из распространенных проблем, с которыми сталкивается разработчик в ходе разработки мобильных приложений, является построение UI. На вебинаре мы рассмотрим реализацию некоторых типовых шаблонов мобильных приложений в контексте библиотеки FGX Native, сравним подходы, используемые для реализации одинакового функционала в FMX и FGX, а также познакомимся с уникальными ключевыми особенностями FGX Native, которые раскрывают все достоинства нативной разработки. В вебинаре принимает участие создатель FGX – Ярослав Бровин. Дата: 11 июля 2019 12:00 МСК. Ссылка на регистрацию: http://forms.embarcadero.com/FGXNative
  16. 4 балла
    Maka

    переход к x64?

    Отвечают долго, 10-14 дней, а потом еще около 7 дней переписка, проверки и ожидание решения. Наберитесь терпения
  17. 4 балла
    krapotkin

    Загрузка настроек приложения из БД

    правильный ответ - не делать так )) нужно хранить настройки приложения в отдельном классе тогда кроме самого класса нужны методы, которые 1) читают пишут его из ... файла, БД, интернета и т.д. 2) в нужный момент (обычно чтобы изобразить форму и заполнить св-ва компонентов или еще для чего угодно) использовать эти настройки 3) вытекает из 2) сохранять в нужный момент новые значения в переменную, где лежат настройки для хранения настроек отлично подходит JSON. Т.к. он может иметь иерархическую структуру, что очень удобно. Его и хранить в БД. Можно и прямо поля, строки и все такое, но все равно, собирать их нужно в некое хранилище в программе. Пример разбирал тут http://www.cyberforum.ru/blogs/469693/blog4883.html
  18. 4 балла
    Отвечу сам себе. Проблема решена. Всего два дня поисков и вот он, случай - краеугольный камень поиска ошибок! Меня аж забомбило, когда я это откопал. Оказалось, что мой грид лежит на лайоуте, у которого hittest = false. Так вот до тех пор, пока я не перевел его в true грид отказывался принимать ondragover. Но как только layout.hittest:=true все заработало. Дальше дело техники.
  19. 4 балла
    Да, у меня. Я только не знаю, с чем это связано. Запрос именно на это приложение я отправлял вчера и ответа еще не получил. Но неделю назад отправлял на другие приложения (ответ я в какой-то теме публиковал). Но вчера на старые мои запросы пришли письма о том, решилась ли моя проблема. И вот я там еще раз написал о том, что хотелось бы получить продление, что у делфи нет компилятора андройд-64, что будет он только осенью или зимой и что выпущу обновление в течение 2-х недель после появления компилятора. Утром пришел формальный ответ, что мол передадим в техническую группу и чуть что - сообщим
  20. 4 балла
    Окончательный вариант. Долго бился с изменением размера картинки внутри потока (к примеру что бы в ListView не грузить картинки больше чем нужно). Средствами TBitmap это оказалось сделать невозможно (именно в потоке), чтение форумов, issue Эмбаркадеро, привело к туманному выводу что проблема в архитектуре FMX. В Токио, TBitmap стал потокобезопасным - это означает что никогда не пытайтесь использовать Bitmap в потоке, рано или поздно получите артефакты и глюки. Я решил проблему отказавшись от работы с TBitmap в потоке, и использовав для этого TBitmapSurface (загрузка из stream, изменение размеров). Что умеет хелпер: 1. Загрузка картинки в Bitmap и подгонкой размера (размер можно и не менять - не передавайте параметр ASize) procedure LoadFromURLAsync(const AURL : String; const ASize : TControlSize = nil); overload; 2. Загрузка картинки в TListItemImage ListView. После Окончания загрузки хелпер выполнит AListItemImage.Invalidate в основном потоке приложения для отрисовки картинки. procedure LoadFromURLAsync(const AURL : String; const AListItemImage : TListItemImage); overload; 3. Создание картинки. Тоже самое что и предыдущие, но можно сэкономить строчку кода ABitmap:=TBitmap.Create constructor CreateFromUrlAsync(const AURL : String; const AListItemImage : TListItemImage = nil); По картинкам в ListView - можете на свой страх и риск грузить 100500 картинок, но лучше использовать загрузку только для видимой части (+- еще сколько то итемов). Хелпер тупо грузит картинки и не обеспечивает механизм оптимальной загрузки. Протестировано на Windows и Android. Ответы на вопросы которые мне задавали: Почему не создавать отдельный поток для каждой картинки, в нем создавать THTTPClient и делать запрос - пробовал этот вариант, он медленнее на порядок, даже под виндой это чертовски медленно. AHTTPClient.BeginGet и так создает отдельный поток на каждый запрос. Почему AHTTPClient глобальный для юнита - в хелпере нельзя вводить свои переменные, а создавать AHTTPClient внутри функции не выйдет - он убьется до завершения потока. И текущий вариант быстрее. Код хелпера и архив с тестовым проектом: unit BitmapAsyncLoader; interface uses System.Net.HttpClient, System.Net.URLClient, System.SysUtils, System.Types, System.Classes, FMX.Graphics, FMX.Surfaces, FMX.Types, FMX.ListView.Types; type TBitmapAsyncLoader = class helper for TBitmap private function ResizeBitmapSurface(const ABitmapSurface : TBitmapSurface; const AWidth, AHeight : Integer) : TBitmapSurface; procedure SynchronizeAssignFromBitmapSurface(const ABitmapSurface : TBitmapSurface; const AListItemImage : TListItemImage = nil); procedure StartHTTPThread(const AURL : String; const AWidth, AHeight : Integer; const AListItemImage : TListItemImage = nil); public procedure LoadFromURLAsync(const AURL : String; const ASize : TControlSize = nil); overload; procedure LoadFromURLAsync(const AURL : String; const AListItemImage : TListItemImage); overload; constructor CreateFromUrlAsync(const AURL : String; const AListItemImage : TListItemImage = nil); end; implementation type THTTPClientListener = class class procedure HTTPClientValidateServerCertificate(const Sender: TObject; const ARequest: TURLRequest; const Certificate: TCertificate; var Accepted: Boolean); end; var AHTTPClient : THTTPClient; constructor TBitmapAsyncLoader.CreateFromUrlAsync(const AURL : String; const AListItemImage : TListItemImage = nil); begin Create; LoadFromURLAsync(AURL, AListItemImage); end; procedure TBitmapAsyncLoader.LoadFromURLAsync(const AURL : String; const AListItemImage : TListItemImage); var AWidth, AHeight : Integer; begin if Assigned(AListItemImage) then begin AWidth:=Round(AListItemImage.Width); AHeight:=Round(AListItemImage.Height); end else begin AWidth:=-1; AHeight:=-1; end; StartHTTPThread(AURL, AWidth, AHeight, AListItemImage); end; procedure TBitmapAsyncLoader.LoadFromURLAsync(const AURL : String; const ASize : TControlSize = nil); var AWidth, AHeight : Integer; begin if Assigned(ASize) then begin AWidth:=Round(ASize.Width); AHeight:=Round(ASize.Height); end else begin AWidth:=-1; AHeight:=-1; end; StartHTTPThread(AURL, AWidth, AHeight); end; function TBitmapAsyncLoader.ResizeBitmapSurface(const ABitmapSurface : TBitmapSurface; const AWidth, AHeight : Integer) : TBitmapSurface; begin if (AWidth <> -1) and (AHeight <> -1) then begin try Result:=TBitmapSurface.Create; Result.StretchFrom(ABitmapSurface, AWidth, AHeight, ABitmapSurface.PixelFormat); finally ABitmapSurface.Free; end; end else Result:=ABitmapSurface; end; procedure TBitmapAsyncLoader.SynchronizeAssignFromBitmapSurface(const ABitmapSurface : TBitmapSurface; const AListItemImage : TListItemImage = nil); begin TThread.Synchronize(Nil, procedure begin Assign(ABitmapSurface); ABitmapSurface.Free; if Assigned(AListItemImage) then AListItemImage.Invalidate; end ); end; procedure TBitmapAsyncLoader.StartHTTPThread(const AURL : String; const AWidth, AHeight : Integer; const AListItemImage : TListItemImage = nil); begin AHTTPClient.BeginGet( procedure (const ASyncResult: IAsyncResult) var AHTTPResponse : IHTTPResponse; ABitmapSurface : TBitmapSurface; begin if Not ASyncResult.IsCompleted then exit; try AHTTPResponse:=THTTPClient.EndAsyncHTTP(ASyncResult); except exit; end; if Assigned(AHTTPResponse) and (AHTTPResponse.StatusCode = 200) then begin ABitmapSurface:=TBitmapSurface.Create; if TBitmapCodecManager.LoadFromStream(AHTTPResponse.ContentStream, ABitmapSurface, Self.CanvasClass.GetAttribute(TCanvasAttribute.MaxBitmapSize)) then begin ABitmapSurface:=ResizeBitmapSurface(ABitmapSurface, AWidth, AHeight); SynchronizeAssignFromBitmapSurface(ABitmapSurface, AListItemImage); end; end; end, AURL ); end; class procedure THTTPClientListener.HTTPClientValidateServerCertificate(const Sender: TObject; const ARequest: TURLRequest; const Certificate: TCertificate; var Accepted: Boolean); begin Accepted:=True; end; initialization AHTTPClient:=THTTPClient.Create; AHTTPClient.OnValidateServerCertificate:=THTTPClientListener.HTTPClientValidateServerCertificate; finalization if Assigned(AHTTPClient) then AHTTPClient.DisposeOf; end. BitmapAsyncLoader.7z
  21. 4 балла
    Ingalime

    переход к x64?

    https://community.idera.com/developer-tools/b/blog/posts/google-play-store-android-32-bit-extension-for-delphi-and-c-builder-customers
  22. 4 балла
    qz5

    Версия андроид

    Я разбавлю своим вариантом: Leagoo Power 2. У него цена около 3000 рублей, из коробки идет Андроид 8.1, но можно поставить Андроид 9 и даже... Android 10!!! С одной стороны у меня среди родственников есть смарты от 4ой до 9-ой версии Андроид, да и моя прога сейчас на всех работает (пока она простая). Но с другой стороны решил поискать дешевый смарт, на который можно несколько разных версий Андроид поставить, но: 1. чтобы это было легко, без всяких разблокировок и т.п. (у новых Xiaomi, Huawei как раз проблемы с заблокированным загрузчиком) 2. чтобы был максимально дешевый 3. чтобы можно было поставить Андроид 8.1 и Андроид 9, причем разные сборки 4. чтобы не надо было ставить всякие Flash Tools и т.п. - искал, чтобы прошивка была простой и максимально без лишних программ Оказалось, что Leagoo Power 2 Pro: 1. Поддерживает GSI-прошивки от Project Treble (Андроид 8.1, Андроид 9 и Android 10) 2. стоит около 3000 рублей 3. Для прошивки не нужно никаких лишних программ! Достаточно ADB, а он и так уже идет вместе с Delphi (можно и самому ADB ставить на комп, если Delphi нет например) Взял на будущее, чтобы было дешевое устройство, на котором можно экспериментировать с прошивками Правда сам пока не пробовал - телефон получил, всё работает, но пока закинул его в коробочку, тестирую на смартфоне с Андроид 7 (он всё равно постоянно на столе и там нужные мне программы). Как прошить ТВРП: https://4pda.ru/forum/index.php?showtopic=928803&st=120#entry81458052 Другие версии Андроид брать здесь: https://4pda.ru/forum/index.php?showtopic=892755 Где купить: решайте сами, многие покупают на Пандао, но я почитал отзывы - Пандао какой-то странный магазин, ничего там не покупал и не стал из-за 200 рублей рисковать. Я взял там, где советует официальный производитель: https://vk.com/wall-148943419_19677 Доставила почта Сингапура за 20 дней. p.s. я кучу разных вариантов пересмотрел и остановился именно на нем. Самая легкая перепрошивка из всех, недорогой смарт, есть запчасти, возможность ставить разные кастомы. может кому пригодится
  23. 4 балла
    mazayhin

    Как узнать Device Name на Андроиде?

    Это будет имя Bluetooth-адаптера. //uses System.Bluetooth; TBluetoothManager.Current.CurrentAdapter.AdapterName
  24. 3 балла
    krapotkin

    Фреймворк для стандартного ListView

    Всем привет! После долгого творческого запоя я запилил альфу либы, которая позволяет юзать обычный, не-генномодифицированный ListView. Данные подаются в виде модели данных, описание раскладки итема лежит в JSON. Для работы пишется примитивный наследник класса-адаптера, который биндит данные модели на элементы из JSON. Я решил, что руками делать это дешевле чем через RTTI { TMyAdapter } procedure TMyAdapter.SetupDrawableContent(const ADrawable: TListItemDrawable; const AData: TMyData); begin if SameText( ADrawable.Name, 'text') then begin (ADrawable as TListItemText).Text := AData.Text; end else if SameText( ADrawable.Name, 'detail') then begin (ADrawable as TListItemText).Text := AData.Detail; end else if SameText( ADrawable.Name, 'balance') then begin (ADrawable as TListItemText).Text := FormatFloat('0.00', AData.Balance); end else if SameText( ADrawable.Name, 'reserved') then begin (ADrawable as TListItemText).Text := FormatFloat('0.00', AData.Reserved); end end; Главная хитрость и отличие от стандартного DynamicAppearance+LiveBinding - переменная высота итемов ListView и использование арифметики в описании раскладки. Можно указать Detail.Y = Text.Bottom + 5, ItemHeight = Detail.Bottom + 10, Detail.W = ItemWidth/2 - X {"Kind":"rect","Name":"BonusRect","Value":"", "Place":{"X":"itemwidth*3/4","Y":"Text.Y","W":"ItemWidth/4-5","H":"50"}, "BorderColor":"#FF005500", "Color":"lime", "LineWidth":3}, {"TextHAlign":2,"TextVAlign":1,"Kind":"text","Name":"Balance","Value":"", "Place":{"X":"BonusRect.x+5","Y":"Text.Y","W":"BonusRect.w-10","H":"50"}, "WordWrap":true, "Color" :"Black", "Font":{"Size":18,"Style":""}} ], "ItemHeight":"detail.bottom+10", Это дает довольно гибкую систему. Не на все случаи жизни, но все, что нужно, можно после автоматической раскладки дополнительно приписать в OnUpdateObjects Код для работы примерно такой procedure TForm1.FormCreate(Sender: TObject); begin data:= TMyDataList.CreateFromFile(ExePath()+'data.json'); // загрузка в модель данных Adapter := TMyAdapter.Create(lvWallets, data.Items, ExePath()+'pattern.json'); // создание адаптера и загрузка шаблона Adapter.Pattern.SetupListView(lvWallets); // задать отступы и разную мелочь Adapter.ResetView(); // здесь в цикле из модели данных создается нужное количество итемов ListView end; procedure TForm1.lvWalletsUpdatingObjects(const Sender: TObject; const AItem: TListViewItem; var AHandled: Boolean); begin Adapter.SetupContent(AItem); // загрузить текст, картинки и другое содержимое в элементы итема Adapter.Pattern.DoLayout(AItem); // поправить раскладку в соответствии с содержимым элементов итема end; Для использования кроме стандартных - текст, картинка, кнопка - создано несколько дополнительных элементов итема - прямоугольник, круг, уголок, линия. Отличие от ModernLV - , 1) все происходит без правки системных файлов 2) пока нет колонок и других особых изысков. На результат работы смотреть тут. Исходники пока не причесаны, будут чуть позже ListViewFramework.7z
  25. 3 балла
    Slym

    multicast udp

    А в инде все готово... procedure TForm1.FormCreate(Sender: TObject); begin IdUDPServer1.ReuseSocket:=TIdReuseSocket.rsTrue; IdUDPServer1.DefaultPort:=9898; IdUDPServer1.Active:=true; end; procedure TForm1.IdUDPServer1AfterBind(Sender: TObject); begin IdUDPServer1.Bindings[0].AddMulticastMembership('224.0.0.50'); end;
  26. 3 балла
    Может кому пригодится. вот решение. procedure TfrmSendEmail.SendEmail(); {$IF DEFINED(ANDROID)} var lIntent: JIntent; lJRecipient: TJavaObjectArray<JString>; lURI: Jnet_Uri; lJFile: JFile; lFileName: string; lFilePath: string; {$ENDIF} begin {$IF DEFINED(ANDROID)} lJRecipient:= TJavaObjectArray<JString>.Create(1); lJRecipient.Items[0]:= StringToJString(eEmail.Text); lFileName:= AttachFileName; lFilePath:= System.IOUtils.TPath.Combine(System.IOUtils.TPath.GetSharedDownloadsPath, lFileName); lIntent:= TJIntent.Create; lIntent.setType(StringToJString('application/excel')); lIntent.setAction(TJIntent.JavaClass.ACTION_SEND); lIntent.setFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK); lIntent.putExtra(TJIntent.JavaClass.EXTRA_EMAIL, lJRecipient); lIntent.putExtra(TJIntent.JavaClass.EXTRA_SUBJECT, StringToJString(eSubject.Text)); lIntent.putExtra(TJIntent.JavaClass.EXTRA_TEXT, StringToJString(mEmailMessage.Text)); lJFile:= TJFile.JavaClass.init(StringToJString(lFilePath)); lURI:= TAndroidHelper.JFileToJURI(lJFile); lIntent.setData(lURI); lIntent.putExtra(TJIntent.JavaClass.EXTRA_STREAM, TJParcelable.Wrap((lURI as ILocalObject).GetObjectID)); TAndroidHelper.Activity.startActivity(lIntent); {$ENDIF}
  27. 3 балла
    slav_z

    Срабатывает OnClick на ListBox при скроллинге

    в OnClick элемента списка сделайте проверку: procedure TForm1.ListBoxItemClick(Sender: TObject); begin if not ListBox.AniCalculations.Moved then DoItemClick; end;
  28. 3 балла
    krapotkin

    Не подключается Huawei

    Короче, действуем примерно так. Я надеюсь, что базовые действия - скачать google latest adb driver - мы уже провели, но наш No- или Brand- name телефон недоступен Тогда 1) идем в диспетчер устройств, находим там наше невстающее устройство, кликаем дважды, и на закладке Сведения выбираем свойство ИД оборудования. Копируем себе что-то типа 2) идем к файлам того самого драйвера, открываем android_winusb.inf находим разделы [Google.NTx86] и [Google.NTamd64] и вписываем туда, прямо в оба ;galaxy tab a 2019 %SingleAdbInterface% = USB_Install, USB\VID_04E8&PID_6866 %CompositeAdbInterface% = USB_Install, USB\VID_04E8&PID_6866&MI_01 3) делаем обновить драйвер, выбираем вариант Вручную, и указываем тот модифицированный файл если не берет автоматом, то "Выбрать из списка уже установленных..." --> "Есть диск" --> "Да, мне пофиг что он не подписан" 4) The End
  29. 3 балла
    Приложение для получения информации расчётным путём об углах: - вертикальной плоскости; - в горизонтальной плоскости; - объёмный; - эквивалентный в шарнирах карданных валов на основе сделанных замеров на собранном автобусе, троллейбусе, грузовике. Может пригодиться работникам сервисных служб, лицам эксплуатирующим грузовую или пассажирскую автомобильные техники, лицам не конструкторских служб. Особенно в случае нахождения в месте недоступном к интернету и компьютеру. Работает на устройствах под OS Android. Существует и более расширенная версия для OS Windows. Пожалуйста, с предложениями и пожеланиями обращайтесь к разработчику: Кирееву Олегу по тел. +375 29 676 13 84 или пишите на kireevoleg1966@gmail.com. Буду рад Вашему любому отзыву. С Уважением. UgolKardZamer_v5.rar
  30. 3 балла
    Коллеги, я опубликовал на сайте FGX свое приложение. Можете «щупать». https://forum.fgx-native.com/topic/76-медицинская-программа-для-оценки-взаимодействия-препаратов/
  31. 3 балла
    В процессе разработки столкнулся с очень странной ситуацией, корни которой до сих пор неясны, но решение нашлось. Итак. Делфи 10.3.3. Чистое приложение - пустая форма и кнопка. Отлично работает на разных устройствах кроме Samsung Galaxy Tab A (2016). Android 5.1.1 Программа падает, не успев даже загрузиться. Любая. При этом она же, скомпилированная на другом компе, запускается нормально. И даже после изменения SDK/NDK на нем, ничего не падает. LogCat дает крайне странную картину java.lang.IllegalArgumentException: Unable to load native library: /data/app-lib/com.embarcadero.Project1-1/libProject1.so Начинаем экспериментировать с SDK, NDK и т.д. Поставил также хотфиксы для 10.3.3. Сразу скажу, SDK/NDK ставились отдельно через Android studio, не скачивались вместе с Delphi. Не торопитесь бросать чтение на этом месте!)) На другом компе, где все работает, все ставилось точно так же. Короче, очень много комбинаций версий SDK/NDK проверено. Результат такой. При постепенном понижении версии NDK все взлетело при NDK v22. При этом версия SDK видимо такого большого влияния не имеет, потому что этот вариант нормально работает Повторюсь. На других устройствах все работало и на более новых Ndk. Xiaomi Mi Pad4 , Samsung Galaxy Tab A (2019), Xiaomi Redmi 5 и 5Plus Спасибо за участие и помощь в разборе завалов @Andrey Efimov
  32. 3 балла
    В телефоне нет никаких гарантированных аппаратных данных - или по причине китайщины, или по тому что их можно изменить. Если уже вам так хочется "привязаться" к чему то неизменному, то привязывайтесь к телефонному номеру. Хотя и его может не быть. Палец не панацея - у вас нет никаких гарантий что палец принадлежит владельцу персональных данных. 100% дактилоскопических данных пользователя у вас нет, а на этапе "привязки" пальца, телефон уже может быть в руках злоумышленника. У вас не получится сделать идеальную систему с абсолютной системой от дурака. Поэтому я и предложил исходить из того что приложение на телефоне запускает легальных пользователь. Все иное должно описываться в политике конфиденциальности, типа мы чтим закон о ПД, но если вы долбоклюй и отдали телефон и пинкод постороннему, то вы сами пролюбили свою медкарту. И пинкод никак не позволит войти на другом устройстве - пин код сохраняется локально на устройстве, в папке приложения. И если пользователь ввел его верно, то запросы на сервер авторизуются с заранее сохраненного на устройстве токена (guid, куки или что вам больше нравится). Ситуации "А если кто взломает телефон и перенесет какой то файл на другое устройство" вас не должны волновать абсолютно. Вы предоставили пользователю приложение, а задача пользователя - не пролюбить телефон и свои персональные данные. Дополнительно вы прикрываете свою задницу политикой конфиденциальности, где описываете что не обязаны охранять пользователя и его телефон круглые сутки.
  33. 3 балла
    Проблема была в правах доступа на МАКе. Выяснилось случайно, когда попробовал делоить тот же проект под МАК и IDE выдала явную ошибку о невозможности создать файл во вложенной в /Users/macuser/PAServer директории. Вылечилось раздачей прав Read & Wtite для ролей staff/everyone для папки PAServer и вложенных директорий (Apply to enclosed items). На quality.embarcadero.com есть по крайней мере две заявки на эту тему, почему-то закрытые: RSP-25526 и RSP-26093 В первой автор откатился на Mojave, во второй стоит «Resolution: Cannot Reproduce». Так что описанная проблема спорадический возникает. Всем успехов и поменьше граблей на пустом месте :)
  34. 3 балла
    Пока не изменились. Сейчас активно ведется работа над подготовкой релиза. Сюда входит ряд работ: Подготовка триал версии библиотеки. Библиотека уже собирается для триала, но остается еще работа по подготовке установщика. Создание EULA Налаживание процесса продажи по подписке. Решение лицензионных вопросов. и другие момент. Но перед тем, как выбирать на чем делать проект я все-таки рекомендую вначале ознакомиться с будущем триалом, чтобы понять о возможностях продукта. Чтобы Ваши ожидания оправдались или не оправдались заранее. Из доп. бонусов в этом месяце еще добавлен новый компонент камера, которая позволяет использовать камеру прямо в вашем приложении с превью и без тормозов. Так же параллельно ведется работа над сканером штрихкодов.
  35. 3 балла
    Barbanel

    Динамическое изменение массива записей

    Большое количество - это сколько? 100, 100 000, 100 000 000? Каждый раз увеличивая размер на один элемент, менеджер памяти ищет непрерывный незанятый кусок памяти такой длины, чтобы уместить все элементы. Хорошо если место под уже выделенный массив позволяет увеличить размер, не упираясь в участики памяти занятые другими данными. Иногда после очередного увеличения массива, уже выделенного участка памяти более не хватает. В таком случае менеджеру приходится искать новый, и копировать старые данные в новый участок памяти, а старый участок помечать как свободный. Разумеется это занимает время. Именно это и приводит к "не так быстро, как хотелось бы". Чтобы избежать этого: 1 Способ курильщика, простой: Увеличиваем размер массива не на 1 элемент, а сразу на 16/32/128/1024 элемента (вам виднее, в зависимости от того сколько у вас может быть элементов в массиве). Также заводим счетчик - номер последнего занятого элемента в массиве, и после каждого добавления - увеличиваем этот счетчик на единицу. Этот способ не избавит от проблемы, но будет приводить к менее частому перераспределению памяти. 2 Способ здорового человека, чуть сложнее: используйте указатели. Заведите массив указателей (либо TList), выделяйте место под каждую новую запись (ваш record) вручную, и помещайте указатель на него в ваш массив указателей (или в TList). Не забывайте освобождать выделенную память, когда ваши обьекты больше не нужны. Этот спобоб более правильный, так как в этом случае перераспределение происходит очень редко. Кстати, реализация TList использует внутри себя первый способ.
  36. 3 балла
    CyberStorm

    Ошибка "Java class JAdSize could not be found"

    Нужно библиотеки почистить: Вот тут еще много написано:
  37. 3 балла
    CyberStorm

    Android 64

    Спасибо! Благодаря вашим наводкам наткнулся на инструкцию как собрать бандлы: http://docwiki.embarcadero.com/RADStudio/Rio/en/Submitting_Your_Android_App_to_Google_Play Пришлось грузить гуглу зашифрованный ключ, пришлось помучаться (https://stackoverflow.com/questions/44103024/how-to-enable-google-play-app-signing) И теперь собираются полноценные рабочие приложения!
  38. 3 балла
    Brovin Yaroslav

    [FGX Native] Сайт библиотеки

    Рад представить вашему вниманию сайт библиотеки FGX Native https://fgx-native.com Здесь Вы сможете найти: описание возможностей, документацию, тарифы и многое другое. Всё это поможет вам предварительно оценить возможности библиотеки для реализации своих проектов. P.S. Trial версия и открытие продаж запланированы на конец декабря.
  39. 3 балла
    krapotkin

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

    ну, есть идеи, как бы модифицировать код, но и так сойдет я бы перефразировал if frmScanWindow = nil then frmScanWindow := TFrmScanWindow.Create(NIL); frmScanwindow.showModal( procedure (const AResult:TModalResult) begin if AResult = mrOK then begin ....... и может быть даже FreeAndNil(frmScanwindow); end; end);
  40. 3 балла
    gonzales

    переход к x64?

    Вот моя переписка. Прислали вот такое письмо с вопросами Hello Alexey, Thanks for contacting Google Play Developer Support. Apologies for the delayed response. I understand you would like an extension to become 64-bit compliant. In order to submit your request, can you please provide the following: Reason for not being able to be compliant in time (if there’s a dependency on third party tools, please specify it) Reason for your request and your plan for migration Specific plan on how you will become compliant, with an estimation date for building 64-bit support that you can commit (For example: The app will be compliant 2 weeks after Embarcadero is compliant.) I look forward to your reply and assisting you further. Regards, Liz Google Play Developer Support я ответил так Hello Liz! Thank you for your letter. In answer to your questions, i provide that as soon as Embarcadero will make a 64x-compiler for Android, i will use it and make a compatible application. I hope, that it won't take long, i dont use any third party tools, only Embarcadero RAD Studio. I'm disappointed, that Embarcadero do not release a new version in time, like they still don't announce it. Also to this I want to ask, if i need to update my application in Google Play Market, i need to reques this extension every time, or only onсe? My application is made for users of our smart home system, and I'm very worried, that our new customers can't download it from Play Market, so I hope for a positive decision of my request!
  41. 3 балла
    krapotkin

    StatusBar Color

    Запустил код по ссылке на delphi 10.3.2, android 8.1 Xiaomi redmi 5 plus В моем случае выяснилось, что поведение зависит от состояния Mainform.Borderstyle Если none - ведет себя как Fullscreen, статусбар прячется Дополнено! Чистый проект на 10.3.2 сам добавляет в Deployment файл styles-v21.xml Его нужно отключить! иначе будет только вариант Fullscreen (он же Borderstyle=none) когда статусбар скрыт и выезжает полупрозрачный, либо обычный неокрашенный статаусбар. Если без него впоследствии что-то не взлетит, можно так же как с основным styles.xml добавить в deployment свой, модифицированный, со строками <item name="android:windowTranslucentStatus">true</item> <item name="android:windowTranslucentNavigation">false</item> У меня после отключения окрашивание статусбара работает корректно.
  42. 3 балла
    Короче уточнил: бета-версия 10.3.3 будет называться Sugarloaf, она выйдет до конца этого месяца, там будет 64-битный компилятор под Андроид, но так и не понял по поводу - дадут ли "коммунякам" или нет так в ближайшие 7 дней ждем Sugarloaf
  43. 3 балла
    Евгений Корепов

    Затирание bitmap canvas при map-unmap

    Я разобрался в чем дело: Вместо TMapAccess.Write используйте TMapAccess.ReadWrite. TMapAccess.Write по какой то причине затирает если не все, то некоторые последние изменения канваса. В доке http://docwiki.embarcadero.com/Libraries/Rio/en/FMX.Graphics.TBitmap.Map не нашел упоминания о таком поведении.
  44. 3 балла
    Хорошая новость: вместо ожидания 10.4 - выйдет версия 10.3.3 в 2019 году, в котором появится компилятор для Андроид 64-бит Новый роадмап найдете здесь: https://community.idera.com/developer-tools/b/blog/posts/august-2019-delphi-android-beta-plans-august-roadmap-update
  45. 3 балла
    добавьте дополнительный layout (align = contest) и на него поместите все компоненты и у MultiView parent укажите layout
  46. 3 балла
    Получил продление для приложений
  47. 3 балла
    Расскажу о том как я добился нормальной фоновой работы приложения. В моем понимании нормальная фоновая работа приложения - это сохранять геокоординаты и систематически (по мере их накопления передавать на сервер). По сути у нас получился трекер. Те кто считают что iOS такое не умеет делать, и все что будет написано ниже это фейк лучше закройти эту тему. Итак начнем, по пунктам: 1) Добавляем к проекту ключ NSLocationAlwaysAndWhenInUseUsageDescription - для новых иОС это обязательно, начиная с 11 или 12 версии уже не помню 2) Сообщаем приложению о намерении что мы будем использовать геокоординаты в фоне (редактируем ключ UIBackgroundModes выставляя галочку напротив location) 3) Далее для того чтобы не поломать другие приложения которые используют геолокацию создаем специальную дерективу, которая будет сообщать о том что наше приложение будет использовать геолокацию в фоне, я ее назвал iOS_RequestAlwaysAuthorization 4) Дальше намного сложнее, нам нужно исправить исходники самой Delphi, а именно System.iOS.Sensors. Изменять будем процедуру TiOSLocationSensor.DoStart, все что отличается от стандартного у меня в рамках описания моей директивы: function TiOSLocationSensor.DoStart: Boolean; var I: Integer; begin {$ifdef iOS_RequestAlwaysAuthorization} if TOSVersion.Check(8) and (FLocater <> nil) then FLocater.requestAlwaysAuthorization; {$else iOS_RequestAlwaysAuthorization} if TOSVersion.Check(8) and (FLocater <> nil) then FLocater.requestWhenInUseAuthorization; {$endif iOS_RequestAlwaysAuthorization} // check authorization if Authorized = TAuthorizationType.atUnauthorized then SensorError(SLocationServiceUnauthorized); // check if location sensor is enabled if not FLocater.locationServicesEnabled then SensorError(SLocationServiceDisabled); // start location updates if (LocationChange = TLocationChangeType.lctLarge) and CanUseSignifChangeNotifs then FLocater.startMonitoringSignificantLocationChanges else FLocater.startUpdatingLocation; // start heading updates if CanUseHeading then begin FLocater.startUpdatingHeading; end; // start monitoring regions if CanMonitorRegions then for I := 0 to Regions.Count - 1 do FLocater.startMonitoringForRegion(ConvLocationRegion(Regions[I])); Result := FLocater.locationServicesEnabled; if Result then Result := Authorized = TAuthorizationType.atAuthorized; {$ifdef iOS_RequestAlwaysAuthorization} FLocater.setAllowsBackgroundLocationUpdates(True); FLocater.setPausesLocationUpdatesAutomatically(False); {$endif iOS_RequestAlwaysAuthorization} end; Собственно усе, можно наслаждаться фоновой работой. Все это работает под Delphi 10.2.3. На телефоне iPhone 6s под управлением iOS 11. Как было сказано выше, работает как геолокация так и инет и вообще все остальные процессы внтури приложения, такие как TTimer Собственно вот результат данного трекера: Если приблизить то можно увидеть насколько точно и часто он обновляет координаты: И да, огромное спасибо человеку с ником Artyom Karapetyan, именно он натолкнул на мысль того как надо правильно все сделать
  48. 3 балла
    У меня тоже обновления без проблем проходят! Просто как всегда загружаю .apk и заливаю новые версии, никто не жалуется и ничего не просит. <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="28" />
  49. 3 балла
    Евгений Корепов

    Работа с камерой - Rad 10.3

    Вот кусок кода из боевого приложения, достаточно разрешения на доступ к камере, больше никаких разрешений не надо. Надеюсь вам поможет. FScanCamera : TCameraComponent; FScanManager - не обращайте внимания, это распознавание QR кодов. ImageCamera : TImage; - картинка на форме где отображаются кадры с камеры Работа начинается с ScanStart() {$IFDEF MOBILE} // *************************************************************** // ****** Сканирование QR кода ****** // *************************************************************** procedure TFormMain.ScanStart(); var AppEventSvc: IFMXApplicationEventService; APermissionCamera : String; begin if TPlatformServices.Current.SupportsPlatformService(IFMXApplicationEventService, IInterface(AppEventSvc)) then AppEventSvc.SetApplicationEventHandler(AppEvent); FScanFrameTake := 0; CButtonScan.Text:='Отменить сканирование'; {$IFDEF IOS} ScanStarting(); {$ENDIF IOS} {$IFDEF ANDROID} APermissionCamera := JStringToString(TJManifest_permission.JavaClass.CAMERA); PermissionsService.RequestPermissions([APermissionCamera], CameraPermissionRequestResult, ExplainReason); {$ENDIF ANDROID} end; procedure TFormMain.ScanStop(); begin if Assigned(FScanCamera) then begin if FScanCamera.Active then FScanCamera.Active:=False; FScanCamera.Free; end; { if Assigned(FScanManager) then begin FScanManager.Free; end; } FScanInProgress := false; LayoutCamera.Height:=0; CButtonScan.Text:='Сканировать QR-код'; end; {$IFDEF ANDROID} procedure TFormMain.CameraPermissionRequestResult(Sender: TObject; const APermissions: TArray<string>; const AGrantResults: TArray<TPermissionStatus>); begin if (Length(AGrantResults) = 1) and (AGrantResults[0] = TPermissionStatus.Granted) then begin ScanStarting(); end else TDialogService.ShowMessage('Сканирование QR-кода не возможно, требуемое разрешение не было дано') end; procedure TFormMain.ExplainReason(Sender: TObject; const APermissions: TArray<string>; const APostRationaleProc: TProc); begin TDialogService.ShowMessage('Приложению нужен доступ к камере для сканирования QR-кода ...', procedure(const AResult: TModalResult) begin APostRationaleProc; end) end; {$ENDIF ANDROID} procedure TFormMain.ScanStarting(); begin FScanInProgress := false; if Not Assigned(FScanManager) then FScanManager:= TScanManager.Create(TBarcodeFormat.QR_CODE, nil); if Not Assigned(FScanCamera) then FScanCamera:=TCameraComponent.Create(Self); FScanCamera.OnSampleBufferReady:=ScanCameraSampleBufferReady; FScanCamera.Quality := FMX.Media.TVideoCaptureQuality.MediumQuality; FScanCamera.Active := false; FScanCamera.Kind := FMX.Media.TCameraKind.BackCamera; FScanCamera.FocusMode := FMX.Media.TFocusMode.ContinuousAutoFocus; FScanCamera.Active := True; LayoutCamera.Height:=LayoutCamera.Width; end; { procedure TFormMain.btnStopCameraClick(Sender: TObject); begin end; } procedure TFormMain.ScanCameraSampleBufferReady(Sender: TObject; const ATime: TMediaTime); begin TThread.Synchronize(TThread.CurrentThread, GetImageCamera); end; procedure TFormMain.GetImageCamera; var scanBitmap: TBitmap; ReadResult: TReadResult; begin FScanCamera.SampleBufferToBitmap(ImageCamera.Bitmap, True); if (FScanInProgress) then exit; { This code will take every 4 frame. } Inc(FScanFrameTake); if (FScanFrameTake mod 4 <> 0) then exit; scanBitmap := TBitmap.Create(); scanBitmap.Assign(ImageCamera.Bitmap); ReadResult := nil; // There is bug in Delphi Berlin 10.1 update 2 which causes the TTask and // the TThread.Synchronize to cause exceptions. // See: https://quality.embarcadero.com/browse/RSP-16377?jql=project%20%3D%20RSP%20AND%20issuetype%20%3D%20Bug%20AND%20affectedVersion%20%3D%20%2210.1%20Berlin%20Update%202%22%20AND%20status%20%3D%20Open%20ORDER%20BY%20priority%20DESC TTask.Run( procedure begin try FScanInProgress := True; try ReadResult := FScanManager.Scan(scanBitmap); except on E: Exception do begin TThread.Synchronize(nil, procedure begin LabelAPIKey.Text := 'Ключ доступа : ' + E.Message; end); exit; end; end; TThread.Synchronize(nil, procedure begin if (ReadResult <> nil) then begin if ProcessingAPIKeyHex(ReadResult.Text) then begin ScanStop(); end; end; end); finally ReadResult.Free; scanBitmap.Free; FScanInProgress := false; end; end); end; { Make sure the camera is released if you're going away. } function TFormMain.AppEvent(AAppEvent: TApplicationEvent; AContext: TObject): Boolean; begin case AAppEvent of TApplicationEvent.WillBecomeInactive, TApplicationEvent.EnteredBackground, TApplicationEvent.WillTerminate: if Assigned(FScanCamera) then FScanCamera.Active := false; end; Result:=True; end;
  50. 3 балла
    Alex7wrt

    android:minSdkVersion после 1 августа

    В справке Google говорится исключительно о targetSdkVersion, а не о minSdkVersion. И targetSdkVersion="26" - это условие для прошлого года. В этом году нужно писать targetSdkVersion="28"
Эта таблица лидеров рассчитана в Москва/GMT+03:00
×
×
  • Создать...