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

Пользователи
  • Публикаций

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

  • Посещение

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

    54

Весь контент Евгений Корепов

  1. Прошу прощения, я ввел вас в заблуждение (тестировал на одном своем проекте). Открытие подобных ссылок вы должны делать самостоятельно, обрабатывая событие браузера ShouldStartLoadWithRequest. Вот код: uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, {$IFDEF ANDROID} Androidapi.JNI.Net, Androidapi.JNI.GraphicsContentViewText, Androidapi.Helpers, {$ENDIF ANDROID} FMX.Types, FMX.Graphics, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.StdCtrls, FMX.WebBrowser, FMX.Controls.Presentation; ..... const ConstMainURL = 'http://www.docme.ru/contacts'; .... procedure THeaderFooterForm.WebBrowser1ShouldStartLoadWithRequest( ASender: TObject; const URL: string); begin if Not URL.StartsWith(ConstMainURL) then // Если ссылка перехода отличается от базовой, то открываем ее через активити begin WebBrowser1.Stop; OpenURL(URL); end; end; procedure THeaderFooterForm.OpenURL(const AUrl: string); {$IFDEF ANDROID} var Uri: Jnet_Uri; OpenLinkIntent: JIntent; {$ENDIF ANDROID} begin {$IFDEF MSWINDOWS} ShellExecute(0, 'open', PChar(AUrl), nil, nil, SW_SHOWNORMAL); {$ENDIF MSWINDOWS} {$IFDEF ANDROID} Uri := StrToJURI(AUrl); OpenLinkIntent := TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_VIEW, Uri); TAndroidHelper.Activity.startActivity(OpenLinkIntent); {$ENDIF ANDROID} end; И прикрепляю ваш проект с моими изменениями WebPrj.zip
  2. На 10.3 отлично работает. Скиньте тестовый проект, проверю, может ошибка в чем то другом?
  3. Евгений Корепов

    Работа с атрибутами текста

    Век живи, век учись. Спасибо, не знал о такой возможности. Поигрался в тестовом проекте - все действительно работает.
  4. Все отлично обрабатывается и открывается. Любой браузер по определению должен это делать. У вас должна быть правильная ссылка на электронную почту, в примеру <a href="mailto:putin@russia.gov">Напишите письмо президенту</a> P.S. Или так, если хотите видеть адрес <a href="mailto:putin@russia.gov">putin@russia.gov</a>
  5. Евгений Корепов

    TMemo для вывода лога тормозит

    С GlobalUseDirect2D := false; приложение и должно грузить процессор, вы же явно указываете что рисуем только процессором. Возможно стоит подумать о реализации приложения в VCL? Или пересмотреть архитектуру приложения? Я бы на вашем месте пошел одним из трех путей: 1. Лить логи в отдельный TStringList, и использовать Memo в качестве "окна" для просмотра содержимого TStringList. Ограничить количество строк в Мемо к примеру сотней и с помощью контролов и кода дать возможность гонять это "окно" по содержимому TStringList. Этот метод я использовал в одном приложении, которое должно было работать месяцами, с большим количеством логов. Метод вполне себя оправдал. Вот уважаемый krapotkin тоже намекал на примерно этот способ. 2. Отказался от Memo, все таки этот компонент предназначен для редактирования небольших текстов, а не скоростного вывода десятков тысяч строк логов. Посмотрите в строну ListView. Конечно для копирования части строки лога придется придумывать некий велосипед (к примеру по клику кидать строку в Edit/Memo и оттуда уже копировать). 3. Сделал бы отдельное приложение/систему для логов. К примеру основное приложение льет логи по TCP или UDP куда то в другое приложение (желательно на другом компьютере/хостинге, которое в свою очередь заточено по визуализацию исключительно логов. А лучше лить в sql базу как предложил уважаемый POV
  6. Евгений Корепов

    TMemo для вывода лога тормозит

    Все ваши проблемы решаются добавлением трех строчек в код: Перед началом работы, сразу задаем количество строк Memo.Lines.Capacity:=1000000; Мемо сразу зарезервирует в своем TStringList нужный объем. Это позволит сократить накладные расходы на добавление в несколько раз. Перед добавлением строк в Memo обязательно делаем Memo.BeginUpdate; Это отключит перерисовку и другие операции. После добавления строк в Memo обязательно делаем Memo.EndUpdate; Это отрисует все изменения которые мы произвели. Вот итоговый код (в форме еще глобальный счетчик FLinesCounter : Integer;): procedure TForm1.FormCreate(Sender: TObject); Var I : Integer; begin Memo.Lines.Capacity:=1000000; Timer.Interval:=10; FLinesCounter:=1; Memo.BeginUpdate; for I := 1 to 10000 do begin Memo.Lines.Add('Это тест ' + FLinesCounter.ToString); Inc(FLinesCounter); end; Memo.EndUpdate; end; procedure TForm1.Button1Click(Sender: TObject); begin Timer.Enabled:=True; end; procedure TForm1.Log(const AMessage : String); const ConsMaxLogSize = 50000; begin Memo.BeginUpdate; // while Memo.Lines.Count > ConsMaxLogSize do // Memo.Lines.Delete(0); Memo.Lines.Add(AMessage); Memo.GoToTextEnd; Memo.EndUpdate; end; procedure TForm1.TimerTimer(Sender: TObject); begin Log('Это тест ' + FLinesCounter.ToString); Inc(FLinesCounter); end; Код добавляет в Мемо 10 тысяч строк за примерно пол секунды. И добавление по таймеру 100 строк в секунду отнимает примерно 0% процессорного времени. Все будет работать без тормозов до разумного предела, при очень больший количествах строк вы столкнетесь с тормозами выделения памяти приложению, тут нужно будет использовать иные механизмы.
  7. Я бы на вашем месте создавал не картинку, а к примеру PDF, там не будет проблем с несколькими страницами
  8. Евгений Корепов

    Проигрывание стандартных звуковых эффектов Android

    Задался вопросом, нашел ответ, может кому пригодится. uses Androidapi.JNI.Media, Androidapi.Helpers, Androidapi.JNIBridge, AndroidApi.Jni.JavaTypes, Androidapi.JNI.GraphicsContentViewText; .... procedure TFormMain.PlaySoundEffects(const ASoundID : Integer; AVolume : Single = 1.0); var AudioObj: JObject; Audio: JAudioManager; begin AudioObj:= TAndroidHelper.Context.getSystemService(TJContext.JavaClass.AUDIO_SERVICE); Audio:= TJAudioManager.Wrap((AudioObj as ILocalObject).GetObjectID); Audio.loadSoundEffects; Audio.playSoundEffect(ASoundID, AVolume); end; Константы звуковых эффектов тут https://developer.android.com/reference/android/view/SoundEffectConstants Правда у меня только звук "чпок" на всех константах. Но мне он и был нужен )
  9. Евгений Корепов

    Запуск приложения от PUSH-уведомления

    Подниму тему наверх. Кто нибудь пробовал это делать в 10.3 ? Что то перестала логика работать. Причем пуши висящие в шторке, теперь исчезают сами, при старте приложения. Толи поменялась логика работы то ли просто глюк. function TGCMPushService.GetStartupNotifications: TArray<TPushServiceNotification>; var LBundle: JBundle; begin LBundle := MainActivity.getStartupGCM; if LBundle <> nil then Result := TArray<TPushServiceNotification>.Create(TGCMPushServiceNotification.Create(LBundle)) else Result := nil; end; Вот тут MainActivity.getStartupGCM ВСЕГДА отдает NIL
  10. Евгений Корепов

    GCM исчез, теперь Firebase Cloud Messaging, но как?

    При публикации нового приложения я обнаружил исчезновение Google Cloud Messaging из консоли разработчика, теперь вместо него Firebase Cloud Messaging. Как я понимаю возможность push сообщений для Delphi закончилась? Или как то можно прикрутить FCM к проекту на Delphi?
  11. Евгений Корепов

    GCM исчез, теперь Firebase Cloud Messaging, но как?

    Спасибо огромное! Опять начал это делать, все забыл, каждый раз как заново ) Начал гуглить и тут раз - и моя же тебя с вашим ответом! Все помогло!
  12. Евгений Корепов

    [Android] TWebBrowser не обновляется прокрутка

    Добавьте простенький JS скрипт на вашу страницу (вот для примера две функции - скролл в самый низ и скролл наверх): <script> function ScrollToBottom() { window.scrollTo(0, document.body.scrollHeight); } function ScrollToTop() { window.scrollTo(0, 0); } </script> И в событии браузера запускайте procedure TFormMain.OnWebBrowserDidFinishLoad(ASender: TObject); begin try FWB.EvaluateJavaScript('ScrollToTop()'); except end; end;
  13. Евгений Корепов

    Firedac+База ms access + android можно?

    Как то это сделать можно, потому как существуют готовые приложения типа https://play.google.com/store/apps/details?id=com.kmsoft.access_db_viewer , но подозреваю что нужно полностью с нуля писать ручками свой DB провайдер для access
  14. Евгений Корепов

    Доступ к SharedDocumentsPath

    http://docwiki.embarcadero.com/RADStudio/Rio/en/Android_Permission_Model
  15. Евгений Корепов

    THTTPClient - Ошибка запроса

    А лучше перейдите на Токио - она же теперь вроде бесплатная?
  16. Евгений Корепов

    THTTPClient - Ошибка запроса

    Действительно, проверил на XE8 - есть ошибка. И в Berlin тоже она есть. Исправлена только в Tokyo 10.2.3. Но просто надо поправить исходник, сегодня посмотрю в чем там дело....
  17. Евгений Корепов

    THTTPClient - Ошибка запроса

    Все работает без проблем, вот код: unit Unit1; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, System.Net.HTTPClient, FMX.Controls.Presentation, FMX.ScrollBox, FMX.Memo; type TForm1 = class(TForm) procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private { Private declarations } public { Public declarations } FHTTPClient : THTTPClient; function GetHTTP(const AURL : String; out AContent : String) : boolean; end; var Form1: TForm1; implementation {$R *.fmx} procedure TForm1.FormCreate(Sender: TObject); Var AContent, AURL : String; begin FHTTPClient:=THTTPClient.Create; if GetHTTP('https://imgvip.net/', AContent) then //Тут работаем с полученным AContent end; procedure TForm1.FormDestroy(Sender: TObject); begin if Assigned(FHTTPClient) then FHTTPClient.Free; end; function TForm1.GetHTTP(const AURL : String; out AContent : String) : boolean; Var AHTTPResponse : IHTTPResponse; begin Result:=False; AHTTPResponse:=FHTTPClient.Get(AURL); if Assigned(AHTTPResponse) then begin if AHTTPResponse.StatusCode=200 then AContent:=AHTTPResponse.ContentAsString else raise Exception.Create(AHTTPResponse.StatusText); end else raise Exception.Create('Unknow error'); end; end.
  18. Евгений Корепов

    THTTPClient - Ошибка запроса

    Вот так попробуйте, без stream (это лишняя прокладка). И узнайте точно - в какой кодировке отдает контент ваш сайт. Если это utf-8 то ничего предпринимать не нужно. Var HTTPResponse : IHTTPResponse; begin HTTPResponse:=FHTTPClient.Get(URL); if Assigned(HTTPResponse) then if HTTPResponse.StatusCode=200 then Result:= HTTPResponse.ContentAsString; //наш результат else ErrorMsg:=HTTPResponse.StatusText;
  19. Евгений Корепов

    Генерация CRC32 hash строки

    Вот отличный набор всего-всего - Fundamentals 4 Library и Fundamentals 5 Library https://github.com/fundamentalslib/fundamentals4 https://github.com/fundamentalslib/fundamentals5 Я использую https://github.com/fundamentalslib/fundamentals4/blob/master/Source/Utils/cHash.pas
  20. Евгений Корепов

    [TWebBrowser] Как отловить событие выполнения JavaScript?

    Вот тут https://github.com/freeonterminate/delphi/tree/master/TWebBrowser TWebBrowserEx Имеет интересный метод // ↓ can taking id of bar's attribute value. Value := FWebBrowser.GetTagValue('bar', 'value'); Можно в JS функции результат записать в невидимый <div id="lalala" value="результат"> и прочесть его с помощью функции.
  21. По пункту 1 : Из за того что код парсинга JSON сотрудники Эмабаркадеро делали "по быстрому" (просто переделали ранее написаный код парсинга XML), то там присутствуют ошибки и конструкция ABase64:=JSON.GetValue<string>('body.nextStep.pdf'); будет работать, но только при убывающей луне и на южном склоне холма 😉 Исправили проблему только в Carnival. По пункту 2 : Согласен полностью. По пункту 3: Согласен полностью. По пункту 4 : Согласен, но я показывал как топикстартеру как выполнить его задачу, а не писал учебник по идеальному программированию 😉 Да и компилятор все равно вставляет код очистки локальных переменных при выходе из функции, так что будем считать что я просто снизил нагрузку на процессор 😉
  22. Накидал вам функцию (проверил - работает): unit Unit1; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, System.JSON, System.NetEncoding, System.IOUtils; type TForm1 = class(TForm) procedure FormCreate(Sender: TObject); private { Private declarations } public { Public declarations } function ExtractPDFContentBase64(const AJSONString : String; out AFileName : String) : boolean; end; var Form1: TForm1; implementation {$R *.fmx} function TForm1.ExtractPDFContentBase64(const AJSONString : String; out AFileName : String) : boolean; Var AJSONObject, AJSONObjectBody, AJSONObjectNextStep : TJSONObject; ACode : Integer; AStreamSource, AStreamDest : TMemoryStream; ADecodeByteCount : Integer; ABase64 : String; begin // Выставляем результат функции в False Result:=False; // Парсим JSON строку в JSON объект AJSONObject:=TJSONObject(TJSONObject.ParseJSONValue(AJSONString)); if Not Assigned(AJSONObject) then exit; // Проверям поле code на предмет содержания http code 200 (это я домыслил, можно удалить) if Not AJSONObject.TryGetValue('code', ACode) then exit; if ACode <> 200 then exit; // Извлекаем body if Not AJSONObject.TryGetValue('body', AJSONObjectBody) then exit; if Not Assigned(AJSONObjectBody) then exit; // Из body извлекаем instanceId - будем использовать как имя файла if Not AJSONObjectBody.TryGetValue('instanceId', AFileName) then exit; // Склеиваем полное имя файла // AFileName:=TPath.Combine(TPath.GetSharedDownloadsPath, AFileName + '.pdf'); AFileName:=TPath.Combine(TPath.GetSharedDownloadsPath, AFileName + '.jpeg'); // Я тестил на картинке // Извлекаем nextStep if Not AJSONObjectBody.TryGetValue('nextStep', AJSONObjectNextStep) then exit; if Not Assigned(AJSONObjectNextStep) then exit; // Содаем поток-источник и помещаем в него base64 AStreamSource:=TMemoryStream.Create; if Not AJSONObjectNextStep.TryGetValue('pdf', ABase64) then exit; AStreamSource.WriteBuffer(Pointer(ABase64)^, Length(ABase64) * 2); // Длину строки умножаем на 2, так как строка юникод AStreamSource.Position:=0; // Создаем поток-назначение AStreamDest:=TMemoryStream.Create; // Декодируем base64 из текста в потоке AStreamSource в бинарные данные в поток AStreamDest ADecodeByteCount:=TNetEncoding.Base64.Decode(AStreamSource, AStreamDest); // Проверяем сколько байт было декодировано if (ADecodeByteCount > 0) then begin AStreamDest.Position:=0; try // Сохраняем поток с бинарными данными в файл с ранее собранным именем AStreamDest.SaveToFile(AFileName); except exit; end; end; // Выставляем результат функции в True Result:=True; end; procedure TForm1.FormCreate(Sender: TObject); Var AJSONString : String; AFileName : String; begin AJSONString:=TFile.ReadAllText('d:\JSON_example.txt'); if ExtractPDFContentBase64(AJSONString, AFileName) then begin // Что то делаем с PDF файлом AFileName end; end; end.
  23. Евгений Корепов

    [DELPHI FMX Android] [6.0] Не удается загрузить SSL библиотеку

    Поддерживаю мнение Равиля - в вашем случае удобнее использовать отправку через мессенждеры (телеграм в частности) или соцсети (везде есть апи для этого дела). Отослать емайл вы можете средствами самого андроида, не прибегая к низкоуровневой работе с smtp протоколом. К примеру вот так (код скопипастил, возможно требуется корректировка) : procedure TForm1.CreateEmail(const Recipient, Subject, Content, Attachment: string); var JRecipient: TJavaObjectArray<JString>; Intent: JIntent; Uri: Jnet_Uri; AttachmentFile: JFile; begin JRecipient := TJavaObjectArray<JString>.Create(1); JRecipient.Items[0] := StringToJString(Recipient); Intent := TJIntent.Create; Intent.setAction(TJIntent.JavaClass.ACTION_SEND); Intent.setFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK); Intent.putExtra(TJIntent.JavaClass.EXTRA_EMAIL, JRecipient); Intent.putExtra(TJIntent.JavaClass.EXTRA_SUBJECT, StringToJString(Subject)); Intent.putExtra(TJIntent.JavaClass.EXTRA_TEXT, StringToJString(Content)); if Attachment <> '' then begin AttachmentFile := TJFile.JavaClass.init(StringToJString(Attachment)); Uri := TJnet_Uri.JavaClass.fromFile(AttachmentFile); Intent.putExtra(TJIntent.JavaClass.EXTRA_STREAM, TJParcelable.Wrap((Uri as ILocalObject).GetObjectID)); end; Intent.setType(StringToJString('vnd.android.cursor.dir/email')); SharedActivity.startActivity(Intent); end; Так же вы можете использовать различные сетевые хранилища для сбора данных (ЯндексДиск и другие), их апи позволяет довольно просто это делать по http протоколу. Можно использовать Google Docs, и подобное. Или бесплатный хостинг и на нем на php сделать систему сбора/хранения. Возможностей куча. Нынче проблема не как реализовать, а какой вариант реализации выбрать (сам постоянно мучаюсь этим вопросом в своих проектах)
  24. Евгений Корепов

    Воспроизведение без задержки

    Ну вряд ли найдется метод "более простой", я имел ввиду методы конкретной платформы, к примеру для андроида JAudioTrack или JAudioManager. Посмотрите вот тут http://www.fmxexpress.com/free-game-audio-manager-wrapper-class-in-delphi-xe6-firemonkey-for-android-ios-windows-and-osx/ может вам подойдет, или поищите (даже на этом форуме) JAudioTrack
  25. Евгений Корепов

    Воспроизведение без задержки

    Для начала избавьтесь от создания TMediaPlayer. Правда по приведенному коду неясно создается он каждый раз или используется первый созданный экземпляр. MediaPlayerOK и procedure Play_SoundOK потомки какой то одной формы? Ну и проигрывать звук лучше более простыми методами, хотя в большинстве они платформо-зависимы (к примеру sndPlaySound из Winapi.MMSystem.pas).