Category: Firemonkey

How to stop duplicating child components (Delphi 10.1 Berlin Firemonkey)

I am creating a component with a published "VisibleItems" property. When the property of an item is checked/un-checked an item is either added or removed from the component and stored in the dfm (Which works), however; when the the component is streamed from the dfm into the IDE duplicate items are created. I've overridden the protected "Loaded" procedure of the item (TMyTreeViewItem) and added a "CreateDefaultItem" procedure to the parent component (TDesignTimeTreeView) which appears to work for Windows but not for Android. I tried marking properties in the parent and child components with the "stored False" directive. I've also tried overriding the "Loaded" procedure in the main component. Below is a minimal version of the component. If the TMyTreeViewItem.Loaded and TDesignTimeTreeView.CreateDefaultItem are bypassed the component duplication starts to happen in the IDE when toggling between "View as Text" and "View as Form" (Alt + F12). unit DesignTimeTreeView; interface uses System.SysUtils, System.Classes, System.Types, System.UITypes, FMX.Types, FMX.Controls, FMX.Layouts, FMX.TreeView; type {$SCOPEDENUMS ON} TItemId = (NONE, Default, Custom, One, Two); {$SCOPEDENUMS OFF} TMyTreeViewItem = class(TTreeViewItem) private FId : TItemId; procedure SetFId(const Value: TItemId); protected procedure Loaded; override; published property Id: TItemId read FId write SetFid; end; TVisibleItemsChange = procedure(Id: TItemId; Visible: Boolean) of object; TVisibleItems = class(TPersistent) private FItem1 : Boolean; FItem2 : Boolean; FOnChange : TVisibleItemsChange; procedure SetVisibility(Id: TItemId; Visible: Boolean); procedure SetFItem1(const Visible: Boolean); procedure SetFItem2(const Visible: Boolean); property OnChange: TVisibleItemsChange read FOnChange write FOnChange; published property Item1: Boolean read FItem1 write SetFItem1; property Item2: Boolean read FItem2 write SetFItem2; end; TDesignTimeTreeView = class(TTreeView) private { Private declarations } FVisibleItems : TVisibleItems; FDefaultMyTreeViewItem : TMyTreeViewItem; function GetItemById(Id: TItemId): TMyTreeViewItem; function GetItemName(Id: TItemId): string; procedure AddItem(Id: TItemId); procedure OnVisibilityChange(Id: TItemId; Visible: Boolean); procedure OnItemClick(Sender: TObject); procedure OnItemTap(Sender: TObject; const Point: TPointF); procedure CreateDefaultItem; const PREFIX = 'StandardItem_'; protected { Protected declarations } public { Public declarations } constructor Create(AOwner: TComponent); override; published { Published declarations } property VisibleItems: TVisibleItems read FVisibleItems write FVisibleItems; end; procedure Register; implementation procedure Register; begin RegisterComponents('Samples', [TMyTreeViewItem, TDesignTimeTreeView]); end; { TDesignTimeTreeView } procedure TDesignTimeTreeView.AddItem(Id: TItemId); var Item : TMyTreeViewItem; ItemName : string; i : Integer; Sub : TTreeViewItem; begin ItemName := GetItemName(Id); Item := GetItemById(Id); if Item <> nil then RemoveObject(Item); Item := TMyTreeViewItem.Create(nil); Item.FId := Id; Item.Text := ItemName; Item.Name := ItemName; Item.HitTest := True; Item.OnClick := OnItemClick; Item.OnTap := OnItemTap; Item.Parent := Self; for i := 1 to 10 do begin Sub := TTreeViewItem.Create(nil); Sub.Text := 'Sub Item (' + i.ToString + ')'; Sub.Parent := Item; end; end; constructor TDesignTimeTreeView.Create(AOwner: TComponent); begin inherited Create(AOwner); ItemHeight := 46; CreateDefaultItem; FVisibleItems := TVisibleItems.Create; FVisibleItems.OnChange := OnVisibilityChange; { Set the default values } FVisibleItems.FItem1 := False; FVisibleItems.FItem2 := False; end; procedure TDesignTimeTreeView.CreateDefaultItem; var Item : TMyTreeViewItem; const DEFAULT_ITEM_NAME = 'DEFAULT_MYTREEVIEWITEM'; begin if Owner <> nil then if Owner.FindComponent(DEFAULT_ITEM_NAME) <> nil then begin Item := TMyTreeViewItem(Owner.FindComponent(DEFAULT_ITEM_NAME)); if Item.Id <> TItemId.Default then Item.Free else Exit; end; if Assigned(FDefaultMyTreeViewItem) then FreeAndNil(FDefaultMyTreeViewItem); FDefaultMyTreeViewItem := TMyTreeViewItem.Create(Owner); FDefaultMyTreeViewItem.FId := TItemId.Default; FDefaultMyTreeViewItem.Name := DEFAULT_ITEM_NAME; FDefaultMyTreeViewItem.Text := 'Created by TDesignTimeTreeView. This makes it so you do not have ' + 'to add a TMyTreeViewItem on the form just so this component will ' + 'work.'; FDefaultMyTreeViewItem.Parent := TFmxObject(Owner); FDefaultMyTreeViewItem.Visible := False; end; function TDesignTimeTreeView.GetItemById(Id: TItemId): TMyTreeViewItem; var i : Integer; ItemName : string; begin Result := nil; ItemName := GetItemName(Id); for i := 0 to Count - 1 do if Items[i].Name = ItemName then Result := TMyTreeViewItem(Items[i]); end; function TDesignTimeTreeView.GetItemName(Id: TItemId): string; begin Result := PREFIX + Ord(Id).ToString; end; procedure TDesignTimeTreeView.OnItemClick(Sender: TObject); var Item : TMyTreeViewItem; begin Item := TMyTreeViewItem(Sender); Item.Text := Ord(Item.Id).ToString + ' Clicked (' + FormatDateTime('h:nn:ss.zzzAM/PM', Now) + ')'; end; procedure TDesignTimeTreeView.OnItemTap(Sender: TObject; const Point: TPointF); begin OnItemClick(Sender); end; procedure TDesignTimeTreeView.OnVisibilityChange(Id: TItemId; Visible: Boolean); var Item : TMyTreeViewItem; begin Item := GetItemById(Id); if Item <> nil then RemoveObject(Item); if Visible then AddItem(Id); end; { TVisibleItems } procedure TVisibleItems.SetFItem1(const Visible: Boolean); begin SetVisibility(TItemId.One, Visible); end; procedure TVisibleItems.SetFItem2(const Visible: Boolean); begin SetVisibility(TItemId.Two, Visible); end; procedure TVisibleItems.SetVisibility(Id: TItemId; Visible: Boolean); begin case Id of TItemId.Custom: { Do Nothing }; TItemId.One: FItem1 := Visible; TItemId.Two: FItem2 := Visible; end; if Assigned(FOnChange) then FOnChange(Id, Visible); end; { TMyTreeViewItem } procedure TMyTreeViewItem.Loaded; begin if Id = TItemId.NONE then begin Self.Destroy; Exit; end; if Id = TItemId.Default then Exit; if not (Parent is TDesignTimeTreeView) then Self.Destroy; inherited; end; procedure TMyTreeViewItem.SetFId(const Value: TItemId); begin { Read Only: But we want to see it in the .fmx file of the form } end; end. I expect that when VisibleItems.Item1 is checked a TMyTreeViewItem will be added to the component and stored in the dfm (Which is working). The component also appears to be streaming from the dfm to the IDE correctly. I also expect to see Item1 and Item2 on the form (If they are checked) when the program runs (Which is working for Windows). When I drop this component onto a multi-device-applicaiton form, set VisibleItems.Item1 and Item2 to true, and finally deploy it to an Android device I get the following errors: *.apk raised ececption class EComponentError with message 'A component named DEFAULT_MYTREEVIEWITEM already exists'. *.apk raised exception class Segmentation fault (11). *.apk raised exception class Illegal instruction (4).
Read More

Delphi Berlin: Why Icon Application and Launch Image do not work on iOS Simulator?

I'm defining the images for the app icon and the splash screen (iOS Simulator platform - iOS 10.1) as indicated in Project || Options -> Application. All images are correctly indicated in deployament and are being updated, but when running the application in iOS Simulator, the icon image and launch image are not updated and the default firemonkey icon is shown. Anyone have any idea what might be happening? Thanks.
Read More

GrijjyCloudLogger, remote logging for Windows, iOS, Android, macOS and Linux – grijjy blog

Interesting use-case based on ZeroMQ and Google Protocol Buffers: [WayBack] GrijjyCloudLogger, remote logging for Windows, iOS, Android, macOS and Linux – grijjy blog. Everything is Open Source at GitHub: grijjy/GrijjyCloudLogger: GrijjyCloudLogger, remote logging for Windows, iOS, Android, macOS and Linux grijjy/DelphiZeroMQ: Delphi implementation of ZeroMQ Majordomo protocol and CZMQ high level binding grijjy/GrijjyFoundation: Foundation classes used by other Grijjy repositories Via: [WayBack] The Grijjy team is proud to introduce our GrijjyCloudLogger, https://blog.grijjy.com/2017/08/22/grijjycloudlogger-remote-logging-for-windows-ios-android… – Allen Drennan – Google+ –jeroen Related: For my research list: Delphi and ZeroMQ
Read More

How clear all forms and open a new one in Firemonkey?

Let's suppose the user is navigating throughout an Android/iOS app and open the following forms: Form A --> Form B --> Form C In Form C he press a button to logout from the app. This should clear all the previous forms (including Form C) and open a new Form (Signin Form D). So it would be something like that: Form A --> Form B --> Form C --> Press Logout Button Close Form A, B and C Open Form D Now if the user press the back button in Form D the app will be closed because there are no more forms in the task. I tried to open Form D and close previous ones but it didn't freed completely the previous forms. Anyway to achieve this for Android/iOS?
Read More

More service than ever for Delphi development with TMS certified consulting partners

Over the past couple of years, it has become clear to us that for many individual software developers and in many companies where Delphi is used as the main software development tool, the challenges have not become easier:

  • It is not easy to find software developers, let alone good Delphi developers
  • Where Windows knowledgde was fine 10 years ago, these days knowledge of macOS, iOS, Linux, Android, web technologies is mandatory to be relevant
  • Architectures are shifting towards microservices based backends, use of push notifications etc…
  • There are more highly complex libraries, SDKs, REST services, components than ever to choose from

It has always been the goal of TMS software from our first days to deliver easy to use software components that take out a lot of deep technical challenges out of software development and allowing our users to focus on the business logic. While we also always aim to deliver fast & professional support services for our components, the needs of our customers also often exceed what regular product based support can offer. We see more and more customers wanting:

  • Assistance in setting up new architectures
  • Outsourcing specific component integrations or entire project developments
  • On-site training & consulting
  • Migrations of existing projects to unicode, cross-platform or web
  • Temporarily extra resources for projects
  • Help in getting started entirely new web projects with TMS WEB Core and/or FNC components
  • – …


Therefore, we’ve started our network of TMS certified consulting partners. These are partner companies we know, have a long term relationship with and that we know have deep and expert level knowledge in Delphi and our TMS software component products. Important is the presence of these partners in the same time-zone, speaking the same language, directly reachable by phone or in the office.

We have created a special landing page for our partners where you can find a partner nearby. With this launch, we can already present 5 TMS certified consulting partners in 3 continents: FlixEngineering in the USA (English), our branch in Brazil for South America (Portuguese & English), C-Quel for the Benelux (Dutch, French, English), Kassebaum Engineering for Germany, Swiss, Austria (German, English) and Softacom for entire Europe (English, Russian). We have added the areas of expertise of our different consulting partners on the landing page. While our consulting partners have expert level knowledge in Delphi and our components, there is also a direct line and close collaboration with our development team. So, our partners are always backed by our component development team and have an insight in our internal developments, upcoming products, … so the partners can at all times make the best possible & well-informed decisions for helping Delphi users.

Visit the partners landing page for more information and details!

We also plan for extending our network of consulting partners in the coming months and years. Especially in the areas of Asia, Australia, South Europe, South Africa where there is also a lot of Delphi development with TMS components going on. If your organisation is interested in becoming such partner, feel free to reach out & discuss.

One thing is clear, as a Delphi developer working with TMS components, you are never alone. Your projects with Delphi and TMS components are guaranteed for success with our team that is always ready for excellent component specific support via email or our forums and our partners offering a wide range of services beyond this.

Read More

Read More

Delphi + iOS : How to translate this code to Delphi?

I try to translate header of FBAudienceNetwork.framework to Delphi typedef NS_ENUM(NSUInteger, FBNativeAdViewTag) { FBNativeAdViewTagIcon = 5, FBNativeAdViewTagTitle, FBNativeAdViewTagCoverImage, FBNativeAdViewTagSubtitle, FBNativeAdViewTagBody, FBNativeAdViewTagCallToAction, FBNativeAdViewTagSocialContext, FBNativeAdViewTagChoicesIcon, FBNativeAdViewTagMedia, }; /** Use this category to set tags for views you are using for native ad. This will enable better analytics. */ @interface UIView (FBNativeAdViewTag) @property (nonatomic, assign) FBNativeAdViewTag nativeAdViewTag; @end Delphi code const FBNativeAdViewTagIcon = 5; FBNativeAdViewTagTitle = 6; FBNativeAdViewTagCoverImage = 7; FBNativeAdViewTagSubtitle = 8; FBNativeAdViewTagBody = 9; FBNativeAdViewTagCallToAction = 10; FBNativeAdViewTagSocialContext = 11; FBNativeAdViewTagChoicesIcon = 12; FBNativeAdViewTagMedia = 13; type FBNativeAdViewTag = NSUInteger; FBNativeAdViewTag = interface(IObjectiveC) ['{F87149BD-3905-4566-B5B0-85F2C5ABB121}'] procedure setNativeAdViewTag(nativeAdViewTag: FBNativeAdViewTag); cdecl; function nativeAdViewTag: FBNativeAdViewTag; cdecl; end; I get error: Identifier redeclared 'FBNativeAdViewTag' How to translate this code to Delphi?
Read More

Deploying SQLite database with Delphi application on Android

I'm having some trouble with adding SQLite database into my Android application written in Delphi. First, I have added the database file into the project manager and in deployment manager changed its Remote Path to .\assets\internal\. Then I have added the following code into FDConnection BeforeConnect event. The code is: begin {$IFDEF ANDROID} MissiledbConnection.Params.Values['ColumnMetadataSupported'] := 'False'; MissiledbConnection.Params.Values['Database'] := TPath.Combine(TPath.GetDocumentsPath, 'MissileDB.db'); {$ENDIF} end; Despite that, I'm still getting this error while trying to compile Android version of my application: [FireDAC][Stan][Def]-254. Definition [MissileDB.db] is not found in [] When I compile my application under Windows, everything works perfectly fine. I honestly have no idea what I'm doing wrong, since every tutorial I've found only mentions the Deployment manager and the event code, which I implemented as I shown. Thank you in advance for your help.
Read More

TEdit with clear button [duplicate]

This question already has an answer here: Clear TEdit control rad studio delphi 1 answer I have a TEdit control where the "StyleLookup" property is set to "clearingeditstyle". The control is rendered perfect on Win64 an Android with an X on the right edge. But I could not find an "OnClear" event on the TEdit. What event is called, when th user klicks or presses the clear X? I have some 2yrs worked in Delphi / VCL. Now I'm writing my first Firemonkey commercial app. Very difficult.
Read More

Procrastination Books

"Books. I like 'em." -- bumper sticker Contrary to the title, these are not books on the art of procrastination. I've just been dragging my feet making a post about new Delphi books. Delphi Programming Projects by William Duarte Delphi is a cross-platform programming language and software development kit that supports rapid application development for Microsoft Windows, Apple Mac OS X
Read More

Run Multiple Commands in Parallel?

I need to crop two portions of one paged pdf and them join as simple image. This is Unit2 which executes the commands: unit Unit2; interface uses System.SysUtils,FMX.Forms,WinAPI.Windows,Unit1; procedure Run(const ACommand, AParameters: String); procedure BadInput; procedure ProceBits; implementation procedure ProceBits; begin Unit1.ProcessCards; end; procedure BadInput; begin raise Exception.Create('Wrong Password'); end; procedure Run(const ACommand, AParameters: String); const CReadBuffer = 2400; var saSecurity: TSecurityAttributes; hRead: THandle; hWrite: THandle; suiStartup: TStartupInfo; piProcess: TProcessInformation; pBuffer: array[0..CReadBuffer] of AnsiChar; dBuffer: array[0..CReadBuffer] of AnsiChar; dRead: DWord; dRunning: DWord; dPresent: DWord; begin saSecurity.nLength := SizeOf(TSecurityAttributes); saSecurity.bInheritHandle := True; saSecurity.lpSecurityDescriptor := nil; if CreatePipe(hRead, hWrite, @saSecurity, 0) then try FillChar(suiStartup, SizeOf(TStartupInfo), #0); suiStartup.cb := SizeOf(TStartupInfo); suiStartup.hStdInput := hRead; suiStartup.hStdOutput := hWrite; suiStartup.hStdError := hWrite; suiStartup.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW; suiStartup.wShowWindow := SW_HIDE; if CreateProcess(nil, PChar(ACommand + ' ' + AParameters), @saSecurity, @saSecurity, True, NORMAL_PRIORITY_CLASS, nil, nil, suiStartup, piProcess) then try repeat dRunning := WaitForSingleObject(piProcess.hProcess, 100); PeekNamedPipe(hRead, nil,0,nil,@dPresent,nil); if (dPresent > 0) then repeat dRead := 0; ReadFile(hRead, pBuffer[0], CReadBuffer, dRead, nil); pBuffer[dRead] := #0; OemToCharA(pBuffer, dBuffer); until (dRead < CReadBuffer); Application.ProcessMessages(); until (dRunning <> WAIT_TIMEOUT); Finally CloseHandle(piProcess.hProcess); CloseHandle(piProcess.hThread); end; Finally CloseHandle(hRead); CloseHandle(hWrite); if (CardType ='Students') or (CardType ='Workers') or (CardType ='Family') and (FileExists(Output)) then ProceBits else if (CardType = '')// for the first part of the card then {*do nothing*} else badinput; end; end; end. and below is how i call Run command: uses Unit2; function ValidateCardType(Const s: string) :string; begin if TRegex.IsMatch(s,'^[A-Z]{4}[0-9]{4}$') then begin Result:= 'Student'; end else if TRegex.IsMatch(s,'^[0-9{8}$]') then begin Result:= 'Workers'; end else if (s='BN') or (s='BS') then begin Result:= 'Family'; end else begin Result:= 'Error'; Exit end; end; procedure TForm1.Edit1Change(Sender: TObject); var Password,DimA,DimB: string; vINI: TMEMINIFile; begin if PDFFile.IsEmpty then begin ShowMessage('Can't Work On Empty Stomach !'); AniIndicator1.Visible:=False; end else AniIndicator1.Visible:=True; begin vINI := TMemINIFile.Create('values.ini'); Password:= Edit1.Text; CardType:= ValidateCardType(Password); ClearImage; if CardType ='Student' then begin DimA := vINI.ReadString('Card1','dimes',''); Output:= GetCurrentDir+'\tools/AC-1.png'; Run(Executable,'-opw '+ Password +' -cropbox -png ' + DimA + ' ' + PdfFile+' tools/AC'); end else if CardType ='Workers' then begin DimA := vINI.ReadString('Card2','dimesA',''); DimB := vINI.ReadString('Card2','dimesB',''); Output:= GetCurrentDir+'\tools/PCb-1.png'; CardType:=''; Run(Executable,'-upw '+ Password +' -cropbox -png ' + DimA + ' ' + PdfFile+' tools/PCa'); CardType:=Workers; Run(Executable,'-upw '+ Password +' -cropbox -png ' + DimB + ' ' + PdfFile+' tools/PCb'); end else if CardType ='Family' then begin DimA := vINI.ReadString('Card3','dimesA',''); DimB := vINI.ReadString('Card3','dimesB',''); Output:= GetCurrentDir+'\tools/Bb-1.png'; CardType:=''; Run(Executable,' -cropbox -png ' + DimA + ' ' + PdfFile+' tools/Ba'); CardType:='Family'; Run(Executable,' -cropbox -png ' + DimB + ' ' + PdfFile+' tools/Bb'); end else begin AniIndicator1.Visible:=False; BadInput; end; VINI.Free; end; end; For CardType Family or Worker i need to crop two parts of the pdf. The code works fine but the commands are running like in FIFO method, but i need to run both commands in parallel mode so i can save time that is being taken by second command till it finishes. How can i run both commands (for CardType Family or Worker) in parallel, and fetch errors from pdftocairo.exe (such as wrong password) ?
Read More

Delphi FMX Running Parallel commands?

I need to crop two portions of one paged pdf and them join as simple image. i am using below code to crop pdf using PDFToCairo.exe : var Output,Dim1,Dim2,PDFFile: String; Edit1:TEdittext; procedure Run(const ACommand, AParameters: String; CardType: String; Image:TImage); const CReadBuffer = 2400; var saSecurity: TSecurityAttributes; hRead: THandle; hWrite: THandle; suiStartup: TStartupInfo; piProcess: TProcessInformation; pBuffer: array[0..CReadBuffer] of AnsiChar; dBuffer: array[0..CReadBuffer] of AnsiChar; //<----- update dRead: DWord; dRunning: DWord; dPresent: DWord; begin saSecurity.nLength := SizeOf(TSecurityAttributes); saSecurity.bInheritHandle := True; saSecurity.lpSecurityDescriptor := nil; if CreatePipe(hRead, hWrite, @saSecurity, 0) then try FillChar(suiStartup, SizeOf(TStartupInfo), #0); suiStartup.cb := SizeOf(TStartupInfo); suiStartup.hStdInput := hRead; suiStartup.hStdOutput := hWrite; suiStartup.hStdError := hWrite; suiStartup.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW; suiStartup.wShowWindow := SW_HIDE; if CreateProcess(nil, PChar(ACommand + ' ' + AParameters), @saSecurity, @saSecurity, True, NORMAL_PRIORITY_CLASS, nil, nil, suiStartup, piProcess) then try repeat dRunning := WaitForSingleObject(piProcess.hProcess, 100); PeekNamedPipe(hRead, nil,0,nil,@dPresent,nil); if (dPresent > 0) then repeat dRead := 0; ReadFile(hRead, pBuffer[0], CReadBuffer, dRead, nil); pBuffer[dRead] := #0; OemToCharA(pBuffer, dBuffer); until (dRead < CReadBuffer); Application.ProcessMessages(); until (dRunning <> WAIT_TIMEOUT); Finally CloseHandle(piProcess.hProcess); CloseHandle(piProcess.hThread); if CardType='CardA' then begin if FileExists(output) then begin Output:=GetCurrentDir+'\tools/CB-1.png'; Run(GetCurrentDir+'\pdftocairo.exe','-upw '+ Form2.Edit1.Text +' -cropbox -png '+ dimP2 +' ' + PdfFile+' tools/PCb','CardB',Form2.Image1) end else ShowMessage('Password Error'); end; if CardType='CardB' then begin if FileExists(output) then begin ProcessCards(CardType); //Joining Images Here end else begin ShowMessage('Some Error Occured'); Form2.AniIndicator1.Visible:=False; end; end; end; Finally CloseHandle(hRead); CloseHandle(hWrite); end; end; //On OnTTargetDrop procedure TForm2.DropTarget1Dropped(Sender: TObject; const Data: TDragObject; const Point: TPointF); begin PdfFile:= Data.Files[0]; Caption:= 'PDFLoaded: '+ ExtractFileName(PdfFile); end; ///On Button Click Ini := TMemINIFile.Create('values.ini'); dimP1:= INI.ReadString('Card1','dimeP1',''); dimP2:= INI.ReadString('Card1','dimeP2',''); Output:= GetCurrentDir+'\tools/CA-1.png'; Run(executable,'-upw '+ Edit1.Text +' -cropbox -png '+ dimP1 +' ' + PdfFile+' tools/CA','CardA',Image1); Using this code i can run or give one command at time to pdftocairo.exe and then on completion of first one(took 5sec) it will start second command which will crop other portion of pdfpage and will take next 5 seconds. How can i run or give multiple commands to pdftocairo at same time so i can save the 5 seconds of second crop as it waits for the first one to complete. and this code can't read errors(ie: wrong password) from the command executaion i need to handle this in very dependent way as it looks for the first cropped image in the folder if it's found then it start next command. Is there any better approach to do this ?
Read More

Change small icon in push notification on Android with Delphi XE 10.3 Rio

I have a problem with the small icon in push notification on Android devices. The icon shows black. I have followed the steps indicated by pudnivec74 in this post How to change small icon image in notification on Android device with DELPHI , and it works, but only when application is running, when the application is closed the icon stills appears black. I have also added in the file AndroidManifest.template.xml these lines: <meta-data android: name = "com.google.firebase.messaging.default_notification_icon" android: resource = "@ drawable / ic_notification" /> and remains the same. Does anyone know the solution? Here is the code that I used: procedure TFrmMain.FormCreate(Sender: TObject); begin try {$IF DEFINED(ANDROID)} APushService := TPushServiceManager.Instance.GetServiceByName(TPushService.TServiceNames.GCM); APushService.AppProps[TPushService.TAppPropNames.GCMAppID] :=UResource.NUMEROPROYECTOANDROID; {$ELSE} APushService := TPushServiceManager.Instance.GetServiceByName(TPushService.TServiceNames.APS); {$ENDIF} AServiceConnection := TPushServiceConnection.Create(APushService); AServiceConnection.Active := True; {$IF DEFINED(ANDROID)} AServiceConnection.OnReceiveNotification := OnReceiveNotificationPushAndroid; {$ELSE} AServiceConnection.OnReceiveNotification := OnReceiveNotificationPushiOS; {$ENDIF} VKAutoShowMode := TVKAutoShowMode.Always; except on E: Exception do end; end; procedure TFrmMain.OnReceiveNotificationPushAndroid(Sender: TObject; const ANotification: TPushServiceNotification); var {$IFDEF ANDROID} Ntf: JNotification; ntfBuilder: JNotificationCompat_Builder; ntfManager: JNotificationManager; {$ENDIF} Mensaje, Titulo: String; begin {$IFDEF ANDROID} try //ShowMessage(ANotification.Json.ToString); Titulo := Copy(ANotification.Json.GetValue('title').ToString, 2, Length(ANotification.Json.GetValue('title').ToString)-2); Mensaje := Copy(ANotification.Json.GetValue('message').ToString, 2, Length(ANotification.Json.GetValue('message').ToString)-2); ntfBuilder:= TJNotificationCompat_Builder.JavaClass.init(TAndroidHelper.Context); ntfBuilder.setSmallIcon(TAndroidHelper.Context.getResources.getIdentifier(StringToJString('ic_notification'), StringToJString('drawable'), TAndroidHelper.Context.getPackageName)); ntfBuilder.setContentTitle(StrToJCharSequence(Titulo)); ntfBuilder.setContentText(StrToJCharSequence(Mensaje)); ntfBuilder.setAutoCancel(True); Ntf:= ntfBuilder.build; Ntf.defaults := TJNotification.JavaClass.DEFAULT_SOUND; if Ntf.defaults <> TJNotification.JavaClass.DEFAULT_VIBRATE then Ntf.defaults := Ntf.defaults + TJNotification.JavaClass.DEFAULT_VIBRATE; ntfManager:= TJNotificationManager.Wrap((TAndroidHelper.Context.getSystemService(TJContext.JavaClass.NOTIFICATION_SERVICE) as ILocalObject).GetObjectID); ntfManager.notify(1, Ntf); except on E: Exception do end; {$ENDIF} end;
Read More