Obiettivi:
Ambiente di test utilizzato:
Prerequisiti:
Step necessari per associare le notifiche
Step 1 : Configurare la distribuzione della app sul portale developer.apple.com e su https://appstoreconnect.apple.com/apps/<appId>


Step 2 : Aggiungere il codice di gestione sull’applicazione Delphi e importare l’sdk firebase per iOS

$(Firebase_6_28)\FirebaseAnalytics\nanopb.xcframework\ios-armv7_arm64\nanopb.framework;$(Firebase_6_28)\FirebaseAnalytics\GoogleUtilities.xcframework\ios-armv7_arm64\GoogleUtilities.framework;$(Firebase_6_28)\FirebaseAnalytics\GoogleDataTransport.xcframework\ios-armv7_arm64\GoogleDataTransport.framework;$(Firebase_6_28)\FirebaseAnalytics\GoogleAppMeasurement.framework;$(Firebase_6_28)\FirebaseAnalytics\FirebaseInstallations.xcframework\ios-armv7_arm64\FirebaseInstallations.framework;$(Firebase_6_28)\FirebaseAnalytics\FirebaseCoreDiagnostics.xcframework\ios-armv7_arm64\FirebaseCoreDiagnostics.framework;$(Firebase_6_28)\FirebaseAnalytics\FirebaseCore.xcframework\ios-armv7_arm64\FirebaseCore.framework;$(Firebase_6_28)\FirebaseAnalytics\FirebaseAnalytics.framework;$(Firebase_6_28)\FirebaseMessaging\FirebaseMessaging.xcframework\ios-armv7_arm64\FirebaseMessaging.framework;$(Firebase_6_28)\FirebaseMessaging\FirebaseInstanceID.xcframework\ios-armv7_arm64\FirebaseInstanceID.framework;$(Firebase_6_28)\FirebaseAnalytics\PromisesObjC.framework\ios-armv7_arm64\PromisesObjC.framework;$(Firebase_6_28)\FirebaseMLModelInterpreter\Protobuf.xcframework\ios-armv7_arm64\Protobuf.framework



unit iOSapi.FirebaseCommon;
{*******************************************************}
{ }
{ CodeGear Delphi Runtime Library }
{ }
{ Copyright(c) 2010-2021 Embarcadero Technologies, Inc. }
{ All rights reserved }
{ }
{*******************************************************}
interface
uses
Macapi.ObjectiveC,
iOSapi.CocoaTypes, iOSapi.Foundation;
const
FIRInstanceIDErrorUnknown = 0;
FIRInstanceIDErrorAuthentication = 1;
FIRInstanceIDErrorNoAccess = 2;
FIRInstanceIDErrorTimeout = 3;
FIRInstanceIDErrorNetwork = 4;
FIRInstanceIDErrorOperationInProgress = 5;
FIRInstanceIDErrorInvalidRequest = 7;
FIRInstanceIDAPNSTokenTypeUnknown = 0;
FIRInstanceIDAPNSTokenTypeSandbox = 1;
FIRInstanceIDAPNSTokenTypeProd = 2;
type
FIRInstanceIDError = NSUInteger;
FIRAppClass = interface(NSObjectClass)
['{B8962096-555F-498E-B102-8EC66E871EF2}']
{class} procedure configure; cdecl;
end;
FIRApp = interface(NSObject)
['{FFF4B247-25C6-47B8-BBC5-893D2170EFA5}']
end;
TFIRApp = class(TOCGenericImport<FIRAppClass, FIRApp>) end;
FIRInstanceIDClass = interface(NSObjectClass)
['{4A9F1C85-AEDE-4284-A7DC-0EF9111504B1}']
{class} function instanceID: pointer; cdecl;
end;
FIRInstanceID = interface(NSObject)
['{2967A1F9-98F5-40E6-8BDA-A25D3C699ED3}']
function token: NSString; cdecl;
end;
TFIRInstanceID = class(TOCGenericImport<FIRInstanceIDClass, FIRInstanceID>) end;
implementation
uses
System.Sqlite, System.ZLib,
iOSapi.StoreKit;
const
libSystemConfiguration = '/System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration';
procedure ClangRTLoader; cdecl; external '/usr/lib/clang/lib/darwin/libclang_rt.ios.a';
procedure FirebaseAnalyticsLoader; cdecl; external 'FirebaseAnalytics';
procedure FirebaseCoreLoader; cdecl; external 'FirebaseCore';
procedure FirebaseCoreDiagnosticsLoader; cdecl; external 'FirebaseCoreDiagnostics';
procedure FirebaseInstallationsLoader; cdecl; external 'FirebaseInstallations';
procedure FoundationLoader; cdecl; external {$IFDEF IOS32}libFoundation{$ELSE}framework 'Foundation'{$ENDIF};
procedure GoogleAppMeasurementLoader; cdecl; external 'GoogleAppMeasurement';
procedure GoogleDataTransportLoader; cdecl; external 'GoogleDataTransport';
procedure GoogleUtilitiesLoader; cdecl; external 'GoogleUtilities';
procedure nanopbLoader; cdecl; external 'nanopb';
procedure PromisesObjCLoader; cdecl; external 'PromisesObjC';
//procedure PromisesObjCLoader; cdecl; external 'PromisesObjC';
procedure SystemConfigurationLoader; cdecl; external {$IFDEF IOS32}libSystemConfiguration{$ELSE}framework 'SystemConfiguration'{$ENDIF};
procedure StoreKitLoader; cdecl; external {$IFDEF IOS32}libStoreKit{$ELSE}framework 'StoreKit'{$ENDIF};
end.
unit iOSapi.FirebaseMessaging;
{*******************************************************}
{ }
{ CodeGear Delphi Runtime Library }
{ }
{ Copyright(c) 2010-2021 Embarcadero Technologies, Inc. }
{ All rights reserved }
{ }
{*******************************************************}
interface
uses
Macapi.ObjectiveC,
iOSapi.CocoaTypes, iOSapi.Foundation;
const
FIRMessagingErrorUnknown = 0;
FIRMessagingErrorAuthentication = 1;
FIRMessagingErrorNoAccess = 2;
FIRMessagingErrorTimeout = 3;
FIRMessagingErrorNetwork = 4;
FIRMessagingErrorOperationInProgress = 5;
FIRMessagingErrorInvalidRequest = 7;
FIRMessagingMessageStatusUnknown = 0;
FIRMessagingMessageStatusNew = 1;
FIRMessasingAPNSTokenTypeUnknown = 0;
FIRMessasingAPNSTokenTypeSandbox = 1;
FIRMessasingAPNSTokenTypeProd = 2;
type
FIRInstanceIDAPNSTokenType = NSInteger;
FIRMessagingAPNSTokenType = NSInteger;
FIRMessagingError = NSUInteger;
FIRMessagingMessageStatus = NSInteger;
TFIRMessagingConnectCompletion = procedure(error: NSError) of object;
FIRMessagingMessageInfoClass = interface(NSObjectClass)
['{FDAC534F-3D79-4FF6-824E-50DC7423662A}']
end;
FIRMessagingMessageInfo = interface(NSObject)
['{4D70F5C5-3635-405F-895C-F41C8D1FD76B}']
function status: FIRMessagingMessageStatus; cdecl;
end;
TFIRMessagingMessageInfo = class(TOCGenericImport<FIRMessagingMessageInfoClass, FIRMessagingMessageInfo>) end;
FIRMessagingRemoteMessageClass = interface(NSObjectClass)
['{EF45D074-C7A5-4DB2-BCD1-53B8650419F4}']
end;
FIRMessagingRemoteMessage = interface(NSObject)
['{6E2F8E14-FD8D-4B5D-8026-A607BE0B8F9C}']
function appData: NSDictionary; cdecl;
end;
TFIRMessagingRemoteMessage = class(TOCGenericImport<FIRMessagingRemoteMessageClass, FIRMessagingRemoteMessage>) end;
FIRMessaging = interface;
FIRMessagingDelegate = interface(IObjectiveC)
['{264C1F0E-3EA9-42AC-9802-EF1BC9A7E321}']
procedure applicationReceivedRemoteMessage(remoteMessage: FIRMessagingRemoteMessage); cdecl;
[MethodName('messaging:didReceiveMessage:')]
procedure didReceiveMessage(messaging: FIRMessaging; remoteMessage: FIRMessagingRemoteMessage); cdecl;
[MethodName('messaging:didRefreshRegistrationToken:')]
procedure didRefreshRegistrationToken(messaging: FIRMessaging; fcmToken: NSString); cdecl;
[MethodName('messaging:didReceiveRegistrationToken:')]
procedure didReceiveRegistrationToken(messaging: FIRMessaging; fcmToken: NSString); cdecl;
end;
FIRMessagingClass = interface(NSObjectClass)
['{62AF9A4C-681E-4BCD-9063-6209CAE08296}']
{class} function messaging: pointer; cdecl;
end;
FIRMessaging = interface(NSObject)
['{A721C3D4-82EB-4A7B-A5E5-42EF9E8F618E}']
function APNSToken: NSData; cdecl;
procedure connectWithCompletion(handler: TFIRMessagingConnectCompletion); cdecl;
function delegate: Pointer; cdecl;
procedure disconnect; cdecl;
procedure sendMessage(msg: NSDictionary; receiver: NSString; messageID: NSString; ttl: Int64); cdecl;
procedure setAPNSToken(apnsToken: NSData; tokenType: FIRMessagingAPNSTokenType); cdecl;
procedure setDelegate(delegate: Pointer); cdecl;
function shouldEstablishDirectChannel: Boolean; cdecl;
procedure setShouldEstablishDirectChannel(value: Boolean); cdecl;
procedure subscribeToTopic(topic: NSString); cdecl;
procedure unsubscribeFromTopic(topic: NSString); cdecl;
end;
TFIRMessaging = class(TOCGenericImport<FIRMessagingClass, FIRMessaging>) end;
function kFIRInstanceIDTokenRefreshNotification: NSString; cdecl;
implementation
uses
iOSapi.FirebaseCommon,
Macapi.Helpers;
function kFIRInstanceIDTokenRefreshNotification: NSString;
begin
Result := StrToNSStr('com.firebase.iid.notif.refresh-token');
end;
procedure FirebaseInstanceIDLoader; cdecl; external 'FirebaseInstanceID';
procedure FirebaseMessagingLoader; cdecl; external 'FirebaseMessaging';
procedure ProtobufLoader; cdecl; external 'Protobuf';
end.
interface
uses xxxx
,System.PushNotification
{$IFDEF ANDROID},FMX.PushNotification.Android {$ENDIF}
{$IFDEF IOS}
, FMX.PushNotification.iOS
, FMX.PushNotification.FCM.iOS
{$ENDIF}
..
..
..
uses System.NetEncoding,
{$IFDEF IOS}
,iOSapi.Foundation
,iOSapi.CoreTelephony
{$ENDIF}
{$IFDEF ANDROID}
,Androidapi.Helpers,
Androidapi.JNIBridge,
Androidapi.Jni,
Androidapi.JNI.JavaTypes,
FMX.Platform.Android,
Androidapi.JNI.Os,
FMX.Helpers.Android
{$ENDIF}
;
TfmxMain = class(TForm)
....
private
{ Private declarations }
o : TMyBridgeObject;
// PUSH NOTIFICATION ID
FDeviceId: string;
FDeviceToken: string;
function HandleAppEvent(AAppEvent: TApplicationEvent; AContext: TObject): Boolean;
procedure btnInitializePushClick(Sender: TObject);
{$IF (defined(ANDROID)) OR (defined(IOS))}
procedure OnServiceConnectionChange(Sender: TObject; PushChanges: TPushService.TChanges);
procedure OnReceiveNotificationEvent(Sender: TObject; const ServiceNotification: TPushServiceNotification);
{$ENDIF}
public
{ Public declarations }
....
end;
{$IF defined(ANDROID) OR defined(IOS)}
procedure TfmxMain.OnReceiveNotificationEvent(Sender: TObject;
const ServiceNotification: TPushServiceNotification);
var
MessageText: string;
begin
MemoLog.Lines.Add('-----------------------------------------');
MemoLog.Lines.Add('DataKey = ' + ServiceNotification.DataKey);
MemoLog.Lines.Add('Json = ' + ServiceNotification.Json.ToString);
MemoLog.Lines.Add('DataObject = ' + ServiceNotification.DataObject.ToString);
MemoLog.Lines.Add('---------------------------------------');
end;
procedure TfmxMain.OnServiceConnectionChange(Sender: TObject;
PushChanges: TPushService.TChanges);
var
PushService: TPushService;
begin
PushService := TPushServiceManager.Instance.GetServiceByName
(TPushService.TServiceNames.FCM);
if TPushService.TChange.DeviceToken in PushChanges then
begin
FDeviceToken := PushService.DeviceTokenValue
[TPushService.TDeviceTokenNames.DeviceToken];
MemoLog.Lines.Add('Firebase Token: ' + FDeviceToken);
// Log.d('Firebase device token: token=' + FDeviceToken);
end;
if (TPushService.TChange.Status in PushChanges) and
(PushService.Status = TPushService.TStatus.StartupError) then
MemoLog.Lines.Add('Error: ' + PushService.StartupError);
end;
{$ENDIF}
procedure TfmxMain.btnIniutializePushClick(Sender: TObject);
{$IF (defined(ANDROID) OR defined(IOS))}
var
PushService: TPushService;
ServiceConnection: TPushServiceConnection;
Notifications: TArray<TPushServiceNotification>;
begin
PushService :=
TPushServiceManager.Instance.GetServiceByName(TPushService.TServiceNames.FCM);
ServiceConnection := TPushServiceConnection.Create(PushService);
ServiceConnection.Active := True;
ServiceConnection.OnChange := OnServiceConnectionChange;
ServiceConnection.OnReceiveNotification := OnReceiveNotificationEvent;
FDeviceId :=
PushService.DeviceIDValue[TPushService.TDeviceIDNames.DeviceId];
MemoLog.Lines.Add('DeviceID: ' + FDeviceId);
MemoLog.Lines.Add('Ready to receive!');
// Checks notification on startup, if application was launched fromcold start
// by tapping on Notification in Notification Center
Notifications := PushService.StartupNotifications;
if Length(Notifications) > 0 then
begin
MemoLog.Lines.Add('-----------------------------------------');
MemoLog.Lines.Add('DataKey = ' + Notifications[0].DataKey);
MemoLog.Lines.Add('Json = ' + Notifications[0].Json.ToString);
MemoLog.Lines.Add('DataObject = ' +
Notifications[0].DataObject.ToString);
MemoLog.Lines.Add('-----------------------------------------');
end;
end;
{$ELSE}
begin
end;
{$ENDIF}
Step 3: Configurare il progetto su firebase:



A questo punto, compilate l’applicazione e fatela girare sul vostro dispositivo.
All’interno di memoLog troverete un JSON contente il deviceID, dovete copiarlo per fare un test di invio del primo messaggio da firebase.
Step 5) Invio di un messaggio di push di prova da firebase console o dal tuo server

Copiare la chiave server ed eseguire una chiamata rest come segue:

Il JSON deve contenere anche l’oggetto “notification” se volete che la notifica arrivi anche quando la vostra app non è attiva:
{
"to": "d-fmNb_zQ6u39hIOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"priority" : "high",
"message_id":"2205",
"time_to_live": 200,
"notification":{
"title":"Portugal vs. Denmark",
"body":"great match!"
},
"data":{
"body":"Ciao",
"title":"Cisco"
}
}
that’s all