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

gonzales

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

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

  • Посещение

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

    27

Весь контент gonzales

  1. Нашел причину зависания, не отрабатывает регистрация Пушей. {$IFNDEF MSWINDOWS} Push.PushServiceRegister; for vCurNotification in Push.FPushService.StartupNotifications do begin Push.OnReceiveNotificationEvent(self, vCurNotification); end; Push.ClearAllNotification; {$ENDIF} закомментировал, программа стала подниматься, буду с ними отдельно разбираться. А пока не понятно, почему не показывается первая форма-заставка??? Если кто знает, подскажите пожалуйста.
  2. gonzales

    Переход на 10.2.3

    Доброго времени суток! Установил 10.2.3, пытаюсь перевести на него проект. Нормально запускается только под win. Андроид и iOS умирают на заставке. Дебаг работает почему-то только на андроид, но даже на нем не могу понять, что не так. Пробовал сделать следующие: удалил все из папки Android, делал revert system files to default в target platform - libraries, гонял туда сюда sdk. Ничего не помогает. Кусок кода следующий файл проекта uses System.StartUpCopy, FMX.Forms, main_unit in 'main_unit.pas' {Form1}, settings_unit in 'settings_unit.pas' {Form2}; {$R *.res} begin Application.Initialize; Application.FormFactor.Orientations := [TFormOrientation.Portrait]; Application.CreateForm(TSplashForm, SplashForm); Application.Run; end. procedure TSplashForm.FormShow(Sender: TObject); begin SplashForm.LoadProgramm; end; procedure TSplashForm.LoadProgramm; begin StartUpLabel.Text := 'Инициализация'; application.ProcessMessages; Application.CreateForm(TForm1, Form1); application.ProcessMessages; label1.Text:=VERSION; Application.CreateForm(TForm2, Form2); application.ProcessMessages; Form1.documentsfolder := System.IOUtils.TPath.GetDocumentsPath + PathDelim + DIR_NAME + PathDelim; {$IFDEF ANDROID} Form1.downloadfolder := System.IOUtils.TPath.GetSharedMoviesPath + PathDelim; {$ENDIF} {$IFDEF IOS} Form1.downloadfolder := System.IOUtils.TPath.GetDocumentsPath + PathDelim + DIR_NAME + PathDelim; {$ENDIF} {$IFDEF MSWINDOWS} Form1.downloadfolder := System.IOUtils.TPath.GetSharedMoviesPath + PathDelim; {$ENDIF} {$IFDEF MACOS} Form1.downloadfolder := System.IOUtils.TPath.GetSharedMoviesPath + PathDelim; {$ENDIF} try Form1.SettingsXML.LoadFromFile(Form1.settingsfilename); Form1.SettingsXML.Active := true; except showmessage('Не найден файл '+Form1.settingsfilename); end; if Form1.SettingsXML.Active = true then begin form1.Settings := Form1.SettingsXML.ChildNodes.Nodes['content'].ChildNodes.Nodes['Settings']; Form1.ExecuteSettings; form2.ConnectToHost; end; PreloadConfiguration; application.ProcessMessages; StartUpLabel.Text := 'Старт программы'; application.ProcessMessages; application.MainForm := Form1; form1.Show; form2.CheckUserPriv; На 10.1 при вызове processmessages отрисовывалась форма SplashScreen ну и далее. А тут нет отрисовки, висит картинка заставки и все(((
  3. В связи с требованием Apple выкладывать в AppStore программы с SDK не ниже 11.0 опять возникла необходимость использовать XCode выше 8.2. По итогу все срослось, конфигурация такая Delphi 10.1 Up2 Xcode 9.2 SDK 11.2 Для того, чтобы все компилилось необходимо сделать две вещи. 1. В SDK добавить FileProvider 2. В XCode добавить PackageApplication (https://stackoverflow.com/questions/43068608/xcrun-error-unable-to-find-utility-packageapplication-not-a-developer-tool)
  4. Решил вот так, если вдруг кому надо procedure TForm1.SortGroup; var i, j: integer; elementscount: byte; begin elementscount := Form1.RoomsScrollBox.Content.Children.Count; for i := 1 to elementscount do for j := 0 to elementscount - 1 do begin if (Form1.RoomsScrollBox.Content.Children.Items[j] as TEssence).SortIndex = i then begin (Form1.RoomsScrollBox.Content.Children.Items[j] as TEssence).Position.Y := 10000; break; end; end; end; соответственно элементы с самым низким индексом будут наверху. Единственное ограничение, что индексы элементов должны быть подряд, без пропусков. Это не очень удобно, надо будет переделать
  5. Доброго времени суток! Ищу изящное решение быстрой сортировки элементов, помещенных в Контент скролбокса. Все элементы имеют свойство SortIndex, чем он выше, тем выше должен быть элемент. Есть куча алгоритмов сортировки, но пока не пойму как их применить при условии того, что все элементы имеют align = top. Заранее всем спасибо за ответы. PS. Создать элементы сразу в нужной последовательности невозможно, поэтому нужна именно сортировка уже созданных
  6. gonzales

    SIP клиент

    Доброго всем дня! Ищу компонент для SIP телефонии для Андроид и iOS под Firemonkey. Или ищу разработчика, способного написать такой))) Всем заранее спасибо за ответы!!!
  7. Я же писал, флаг FreeOnTerminate стоит, но не отрабатывает в Андроид. Поэтому пришлось убивать
  8. Помогло Thread.IdHTTP.Disconnect; Thread.Terminate; Thread:=nil; Thread.Free;
  9. Ну так я это и хочу сделать. Прикольно, ща попробую.
  10. С potok.terminated не понял, почему так, ведь при создании выставил флаг freeonterminate. По идее все должно быть, может конечно он не отрабатывает.
  11. DisposeOf к сожалению я не могу использовать, так как надо уничтожить объект при нажатии на него самого. Поэтому использую Release, как отложенный деструктор, как только объект освободится, он будет уничтожен.
  12. Доброго времени суток! Не знаю, в какой раздел правильнее написать, потому как проблема из разных областей. Собственно проблема в следующем Есть базовый класс, TEssence type TEssence = class(TRectangle) private procedure EssenceMouseEnter(Sender: TObject); procedure EssenceMouseLeave(Sender: TObject); public EssenceName: TLabel; EssenceImage: TImage; ImageSize: integer; constructor Create(AOwner: TComponent); Overload; constructor CreateCustom(AOwner: TComponent; X: Single; Y: Single; W: Single; H: Single; R: Single; Str_T: Single; Str_C: cardinal; Fill_C: cardinal; FontColor: cardinal; FontSize: Single; Im_size: Single; text: string); Overload; destructor Destroy; Overload; procedure SetName(Name: string); procedure SetIcon(iconnumber: integer); end; Есть наследники от базового класса. Среди них есть есть класс TCamera type TCamera = class(TEssence) public Thread: TCameraThread; Camera_id: byte; Snapshot_url: string; GetRecords_url: string; Record_url: string; DelFile_url: string; Camera_Image: TImage; CameraActive: boolean; CameraValue: TCircle; buttonLayout: TLayout; DetailsButton: TButton; RecordsCount: integer; RecordsArray: array of String; constructor Create(AOwner: TComponent); Overload; constructor CreateCustom(AOwner: TComponent; X: Single; Y: Single; W: Single; H: Single; R: Single; Str_T: Single; Str_C: cardinal; Fill_C: cardinal; FontColor: cardinal; FontSize: Single; Im_size: Single; text: string); Overload; destructor Destroy; Overload; procedure CameraSetURL; procedure StartCamera; procedure StopCamera; procedure CameraClick(Sender: TObject); procedure CameraRestart(Sender: TObject); procedure DownloadClick(Sender: TObject); procedure DeleteClick(Sender: TObject); procedure DetailClick(Sender: TObject); end; destructor TCamera.Destroy; begin StopCamera; buttonLayout.Release; CameraValue.Release; inherited; end; procedure TCamera.StopCamera; begin if Thread<>nil then begin Thread.IdHTTP.Disconnect; Thread.Terminate; end; if Camera_Image<>nil then begin Camera_Image.Release; Camera_Image := nil; CameraActive := false; SetLength(RecordsArray, 0); end; end; Он отличается от других подобных, что в при создании экземпляра в нем создается поток TCameraThread, в котором я получаю изображение с камеры. type TCameraThread = class(TThread) private aStream: TMemoryStream; newStream: TMemoryStream; public IdConnection: TIdConnectionIntercept; IdHTTP: TIdHTTP; url: string; bmp: tbitmap; constructor Create(abmp: tbitmap); Overload; destructor Destroy; Overload; procedure Execute; override; procedure Receive(ASender: TIdConnectionIntercept; var ABuffer: TIdBytes); end; constructor TCameraThread.Create(abmp: tbitmap); // (abmp: tbitmap; aurl: string); begin inherited Create(true); bmp := abmp; FreeOnTerminate := true; aStream := TMemoryStream.Create; newStream := TMemoryStream.Create; IdHTTP := TIdHTTP.Create; IdConnection := TIdConnectionIntercept.Create; IdHTTP.Intercept := IdConnection; IdConnection.OnReceive := Receive; end; destructor TCameraThread.Destroy; begin bmp.Free; bmp:=nil; aStream.Free; aStream:=nil; newStream.Free; newStream:=nil; IdHTTP.Free; IdHTTP:=nil; IdConnection.Free; IdConnection:=nil; inherited; end; И есть процедура FreeRoom, которой я пользуюсь для того, чтобы убивать все элементы procedure TForm1.FreeRoom; var i: integer; begin Form1.MasterTimer.Enabled := false; for i := Form1.RoomsScrollBox.ComponentCount - 1 downto 0 do begin if Form1.RoomsScrollBox.Components[i] is TEssence then begin (Form1.RoomsScrollBox.Components[i] as TEssence).Release; end; end; SetLength(Form1.RoomElements, 0); CurrentRoomElement := 0; end; Я всегда думал, что при такой конструкции будет следующий порядок, вызовется деструктор TCamera, в котором сработает функция StopCamera, которая остановит и уничтожит поток и уничтожится экземпляр класса TCamera. И все это нормально (наверное) работало до тех пор, пока я не прикрутил сервис IFMXApplicationEventService. Задача была крайне простой, при сворачивании приложения уничтожить все объекты и потоки, а при разворачивании опять все запустить. Соответственно была сделана вот такая простая контрукция procedure TForm1.FormCreate(Sender: TObject); var aFMXApplicationEventService: IFMXApplicationEventService; begin if TPlatformServices.Current.SupportsPlatformService(IFMXApplicationEventService, IInterface(aFMXApplicationEventService)) then aFMXApplicationEventService.SetApplicationEventHandler(HandleAppEvent); end; function TForm1.HandleAppEvent(AAppEvent: TApplicationEvent; AContext: TObject): boolean; begin case AAppEvent of TApplicationEvent.BecameActive: begin Form1.CheckDefaultRoom; end; TApplicationEvent.WillBecomeInactive: begin MasterTimer.Enabled := false; Form1.FreeRoom; end; end; Result := true; end; Но происходит странное. Если у меня есть экземпляр TCamera с потоком внутри, то сворачивается приложение нормально, но уже не разворачивается, просто висит в памяти, или показывает черный экран. Если среди объектов нет TCamera, то все отрабатывает правильно. Судя по всему дело именно в потоке, который каким-то образом валит приложение. Еще одна странность, что я не могу отдебажить приложение, я поставил точку остановки на деструкторе, но программа не останавливается в нем, причем не только в Андроид, но и в винде. Третий день уже бьюсь, подскажите, кто чем может, буду признателен за любую информацию. Заранее спасибо!
  13. gonzales

    Пуши в IOS

    Так а в чем конкретно проблема? В коде есть OnReceiveNotificationEvent - вызывается когда придет пуш. Соответственно вместо ShowMessage(aText); пишите вызов новой формы. Если она уже создана, то просто FormB.visible:=true;, если не создана, то вызов конструктора, (примерно так FormB:=TForm.Create;, соответственно конструктор должен быть описан)
  14. gonzales

    Пуши в IOS

    Все правильно, так и работает. При публикации в аппсторе sandbox (песочница) надо снять
  15. Забыл уточнить, что во втором варианте программа вообще завешивается))))
  16. Доброго времени суток! Столкнулся с задачей организовать прием MJPEG c ip-камеры. Само по себе все работает. На кнопке висит GET запрос в камеру procedure TForm1.FormCreate(Sender: TObject); begin FReceivedData := TMemoryStream.Create; FParsedData := TMemoryStream.Create; end; procedure TForm1.DeleteStream(Stream: TMemoryStream; Amount: Integer); var bufStream: TMemoryStream; newSize: int64; begin bufStream := TMemoryStream.Create; // Check size if (Amount < 0) then Amount := 0 else if Amount > Stream.Size then Amount := Stream.Size; Stream.Position := Amount; newSize := Stream.Size - Amount; bufStream.SetSize(newSize); bufStream.Position := 0; bufStream.CopyFrom(Stream, newSize); Stream.Clear; Stream.SetSize(newSize); Stream.Position := 0; bufStream.Position := 0; Stream.CopyFrom(bufStream, newSize); bufStream.Free; bufStream := nil; end; procedure TForm1.Button6Click(Sender: TObject); begin IdHTTP1.Get('http://192.168.0.9/videostream.cgi?user=admin&pwd=888888', FReceivedData); end; На форме idHTTP, idIOHandler и IdConnectionIntercept У IdConnectionIntercept есть метод OnReceive. procedure TForm1.IdConnectionInterceptReceive(ASender: TIdConnectionIntercept; var ABuffer: TIdBytes); begin Form1.ParseJPEGData; end; procedure TForm1.ParseJPEGData; var i: Integer; StartPos, EndPos: Integer; StartPt: Pointer; Data, DataNext: PByte; Amount: Integer; buffer: TBytes; begin // Check size if (FReceivedData.Size < 2) then Exit; // Initialize Amount := 0; StartPos := -1; StartPt := nil; // Data pointers Data := FReceivedData.Memory; DataNext := Data; Inc(DataNext); try // Parsing loop for i := 0 to FReceivedData.Size - 2 do begin // Check if we have found the start code if (StartPos = -1) and (Data^ = $FF) and (DataNext^ = $D8) then begin StartPos := i; StartPt := Data; end // Check if we have found the JPEG end code else if (StartPos >= 0) and (Data^ = $FF) and (DataNext^ = $D9) then begin // End position EndPos := i; // Copy data (Higher performance than passing whole stream to load, // because FBitmap.LoadFromStream will create a memory stream and copy // everything if Position <> 0 FReceivedData.Position := StartPos; FParsedData.SetSize((EndPos + 2) - StartPos); FParsedData.Position := 0; FParsedData.CopyFrom(FReceivedData, (EndPos + 2) - StartPos); // CopyMemory(FParsedData.Memory, StartPt, (EndPos + 2) - StartPos); // Load bitmap on screen Image1.Bitmap.LoadFromStream(FParsedData); FParsedData.Clear; Application.ProcessMessages; // Amount of data to delete Amount := EndPos + 2; // Reset StartPos := -1; StartPt := nil; end; // Next pointer Inc(Data); Inc(DataNext); end; // Delete the amount of parsed data // FReceivedData.Delete(Amount); DeleteStream(FReceivedData, Amount); FReceivedData.Position := FReceivedData.Size; Application.ProcessMessages; except FReceivedData.Clear; end; end; Так все работает, но сильно грузит основной поток, так что даже программу нельзя закрыть. Подумал, что может вынести процедуру ParseJPEGData в поток. Но что-то не срабатывает. Вот код, прокомментируйте пожалуйста procedure TForm1.ParseJPEGDataThread; begin TTask.Run( procedure var aStream, newStream: TMemoryStream; i: Integer; StartPos, EndPos: Integer; StartPt: Pointer; Data, DataNext: PByte; Amount: Integer; begin aStream := TMemoryStream.Create; newStream := TMemoryStream.Create; TThread.Synchronize(TThread.CurrentThread, procedure begin aStream.CopyFrom(FReceivedData, FReceivedData.Size); end); try if (aStream.Size < 2) then Exit; // Initialize Amount := 0; StartPos := -1; StartPt := nil; // Data pointers Data := aStream.Memory; DataNext := Data; Inc(DataNext); try // Parsing loop for i := 0 to aStream.Size - 2 do begin // Check if we have found the start code if (StartPos = -1) and (Data^ = $FF) and (DataNext^ = $D8) then begin StartPos := i; StartPt := Data; end // Check if we have found the JPEG end code else if (StartPos >= 0) and (Data^ = $FF) and (DataNext^ = $D9) then begin // End position EndPos := i; // Copy data (Higher performance than passing whole stream to load, // because FBitmap.LoadFromStream will create a memory stream and copy // everything if Position <> 0 aStream.Position := StartPos; newStream.SetSize((EndPos + 2) - StartPos); newStream.Position := 0; newStream.CopyFrom(aStream, (EndPos + 2) - StartPos); TThread.Synchronize(TThread.CurrentThread, procedure begin Image1.Bitmap.LoadFromStream(newStream); end); // Load bitmap on screen newStream.Clear; Application.ProcessMessages; // Amount of data to delete Amount := EndPos + 2; // Reset StartPos := -1; StartPt := nil; end; // Next pointer Inc(Data); Inc(DataNext); end; // Delete the amount of parsed data // FReceivedData.Delete(Amount); TThread.Synchronize(TThread.CurrentThread, procedure begin DeleteStream(FReceivedData, Amount); FReceivedData.Position := FReceivedData.Size; end); except TThread.Synchronize(TThread.CurrentThread, procedure begin FReceivedData.Clear; end); end; finally FreeAndNil(aStream); FreeAndNil(newStream); end; end) end;
  17. gonzales

    Пуши в IOS

    Еще доп. накину на вентилятор, вдруг кому пригодится. Чтобы в iOS появилась наклейка с цифрой на иконке программы нужно добавить в JSON запроса пуша в объект notification пару badge=цифра
  18. На всякий случай кидаю ответ. Все остальное в iOS не работает вот статейка вообще конечно костыль, но по другому добиться нормального splashScreen в iOS у меня не получилось
  19. gonzales

    Пуши в IOS

    Вопрос решился. Есть одно дополнение в код ZyBy Если необходимо обработать сообщение внутри программы правильный код будет такой // это событие срабатывает при открытом приложении {$IFDEF ANDROID} // устраняем ошибку с чтением текста уведомления, // если уведомление отправлено из консоли firebase // и не заполнены дополнительные поля (message, title) aObj := ANotification.DataObject.GetValue(GCMSignature); if aObj <> nil then aText := aObj.value else aText := ANotification.DataObject.GetValue(FCMSignature).value; {$ENDIF} {$IFDEF IOS } aObj := ANotification.DataObject.GetValue(APNsSignature); if aObj <> nil then aText := (aObj as TJSONObject).GetValue('body').Value; {$ENDIF}
  20. gonzales

    Пуши в IOS

    Вот процедура конвертации токена APN в FCM uses // RTL System.Net.HttpClient, System.Net.URLClient, System.NetConsts, System.Threading, // REST REST.Types; const cSandboxValues: array[Boolean] of string = ('false', 'true'); cHTTPResultOK = 200; cFCMIIDBatchImportURL = 'https://iid.googleapis.com/iid/v1:batchImport'; cFCMAuthorizationHeader = 'Authorization'; cFCMAuthorizationHeaderValuePair = 'key=%s'; cResultsValueName = 'results'; cStatusValueName = 'status'; cRegistrationTokenValueName = 'registration_token'; cStatusValueOK = 'OK'; cFCMResultError = 'FCM Result Error: %s'; cFCMJSONError = 'FCM Unexpected JSON: %s'; cHTTPError = 'HTTP Error: %s. Response: %s'; cFCMRequestJSONTemplate = '{ "application": "%s", "sandbox": %s, "apns_tokens": [ "%s" ] }'; AAppBundleID = 'xxxxxxxxx'; AServerKey = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'; procedure TForm1.Button2Click(Sender: TObject); var ARequest: string; LStream: TStream; LHTTP: THTTPClient; LResponse: IHTTPResponse; begin ARequest:=Format(cFCMRequestJSONTemplate, [AAppBundleID, cSandboxValues[true], Edit1.Text]); LStream := TStringStream.Create(ARequest); LHTTP := THTTPClient.Create; try LHTTP.CustomHeaders[cFCMAuthorizationHeader] := Format(cFCMAuthorizationHeaderValuePair, [AServerKey]); LHTTP.ContentType := CONTENTTYPE_APPLICATION_JSON; LResponse := LHTTP.Post(cFCMIIDBatchImportURL, LStream); if LResponse.StatusCode = cHTTPResultOK then Memo2.Lines.Add(LResponse.ContentAsString); finally LHTTP.Free; end; LStream.Free; end;
  21. gonzales

    Пуши в IOS

    Прошу помощи!!!!! Проблема схожая, поэтому напишу в эту ветку. Не приходят пуши на iOS. С Андроид все в порядке. Пересмотрел все статьи и форум тысячу раз, не могу понять, в чем проблема. Чтобы сразу многие вопросы отсечь, отвечу 1. Приложение в стадии development (release), Delphi 10.1 up2 + xCode 8.2 2. Все сертификаты есть, все установлено и экспортировано в FireBase. Даже заново сделан provising profile с учетом внедрения push notification. 3. Регистрация PushServiceRegister проходит успешно, система отдает FDeviceToken 4. при старте приложения выскакивает окно с разрешением на уведомления, конечно соглашаемся. 5. Для конвертации токена была написана процедура, вот ее возврат {"results":[{"registration_token":"fB5GK_gykQ8:APA91bFtfKYsNbHIlsLEdx0P8BCCddVj2EC0yqFDNPS9sDvo1AHJC4Kc_ydWNZlNeuRUPSDKCjDRlYAAbUEJ3gvOiuBnsv28IgIbHRmfSFjQYq0Cg6wyma4WZrDs6pEMCRIrFuLYWJly","apns_token":"c20590d04800eb051dca60275861ec74a4a93674b4b8e348135a4ad3a04a7bb0","status":"OK"}]} как видно токен валиден, правда я проверял, что если изменить цифры в apns_token то результат все равно положительный 6. Из консоли FireBase пытаюсь отослать пуш по известному токену, система ошибок не выдает, но пуш не приходит(((( 7. Использованный SDK 10.2, на устройстве версия ios - 9.3.5 Если можно, прошу кого-нибудь сконвертировать на php-сервере вот такой apn токен (c20590d04800eb051dca60275861ec74a4a93674b4b8e348135a4ad3a04a7bb0) и сравнить с тем, что я получаю из процедуры (fB5GK_gykQ8:APA91bFtfKYsNbHIlsLEdx0P8BCCddVj2EC0yqFDNPS9sDvo1AHJC4Kc_ydWNZlNeuRUPSDKCjDRlYAAbUEJ3gvOiuBnsv28IgIbHRmfSFjQYq0Cg6wyma4WZrDs6pEMCRIrFuLYWJly) В параметрах конвертации Sandbox = true (приложение не выложено в AppStore). Ноя пробывал и так и так, результат один. Прошу помощи, уже 3 дня бьюсь!!!
  22. Приведенный здесь код тоже оказался рабочий при посылке пуша по токену. Пуш приходит. Но встает вопрос, как обработать его при открытии приложения?
  23. Что все завершено, см скрин Нет, пока только тест. Сейчас сделал все по примеру Равиля http://blog.rzaripov.kz/2017/02/firebase-android-ios-2.html В нем работает ПУШ при таргетировании на устройство, обычный так и не приходит
  24. У меня закрадываются сомнения, что я чего-то не понимаю в отправке пушей. Нужен ли еще дополнительно сервер для отправки пушей, как написано в этой статье Хотя судя по этой статье для тестирования пушей ничего кроме FireBase не надо Евгений, поясните пожалуйста строку GetHTTP(CommandRegisterFCM); В демо примере такого нет.
  25. Еще раз хочу уточнить технику секса 1. Регистрирую приложение для Андроид в FireBase 2. В настройках проекта на вкладке Cloud Messaging копирую Идентификатор отправителя 3. Открываю Demo проект, кстати вопрос, DW.PushClient.pas и DW.RegisterFCM.pas лежат не в папке с Демо, тем не менее все компилится, как-то странно. Эти файлы никуда не нужно положить? 4. Вношу изменения constructor TForm1.Create(AOwner: TComponent); begin inherited; FPushClient := TPushClient.Create; FPushClient.GCMAppID :='280557678639'; //cFCMSenderID; FPushClient.ServerKey :=''; //cFCMServerKey; FPushClient.BundleID :=''; //cFCMBundleID; FPushClient.UseSandbox := True; // Change this to False for production use! FPushClient.OnChange := PushClientChangeHandler; FPushClient.OnReceiveNotification := PushClientReceiveNotificationHandler; FPushClient.Active := True; end; 5. Запускаю на телефоне. Компилится без ошибок. После старта наблюдаю значения DeviceID и DeviceToken 6. В FireBase на вкладке Notifications создаю новое сообщение, в котором указываю Цель - сегмент пользователей, выбираю свое приложение, жму "Отправить сообщение" По идее все. Может чего упустил? Может ли кто-нибудь повторить такой подход, был бы крайне благодарен?
×
×
  • Создать...