Firebase Cloud Messaging を使ってAndroid端末にメッセージ送信する【Delphi 10.1 Berlin update 2】

#Firebase Cloud Messaging を使ってAndroid端末にメッセージ送信する【Delphi 10.1 Berlin update 2】
元ネタは下記URLです
http://thundaxsoftware.blogspot.jp/2017/01/firebase-cloud-messaging-with-delphi.html

GoogleのFireBaseを使用して
メッセージをAndroid端末にプッシュできることを確認しました。

私的備忘録を兼ねて

#環境
Delphi 10.1 Berlin update 2
Android 4.1.1
Firebase

#Todo
1.FireBaseでプロジェクトを作成します
2.Android端末側でFCM Tokenをリクエストします
3.Android端末側でFCM Push Notificationを受け取ります

#FireBaseでプロジェクトの作成
![image](https://qiita-image-store.s3.amazonaws.com/0/143249/096ff1e2-db64-1261-e37a-7bc8955f96ae.png)
新規プロジェクトをFireBase側で作成します。

![image](https://qiita-image-store.s3.amazonaws.com/0/143249/66cf68d2-8d38-0723-13ac-24a135c952aa.png)
プロジェクト名は任意で登録します。
後からでも修正が可能です。

![image](https://qiita-image-store.s3.amazonaws.com/0/143249/cd97e6dd-dc52-878a-f4fd-4daa38eda2f3.png)
プロジェクトにアプリケーションを追加します。
今回はAndroidです。

![image](https://qiita-image-store.s3.amazonaws.com/0/143249/d14b29a9-b619-ba13-bcf2-b1b751988944.png)
パッケージ名を入力して、
アプリを追加します。
アプリを追加ボタンを押すとgoogle-services.jsonが取得できます。
jsonにはアプリの情報が記載されています。

![image](https://qiita-image-store.s3.amazonaws.com/0/143249/a247977d-3067-f5ae-92c2-a3101db9378b.png)
続行ボタン

![image](https://qiita-image-store.s3.amazonaws.com/0/143249/dab7a147-ccfc-bfea-3ae0-c6684006f7fd.png)
終了ボタン
FireBaseのプロジェクトにアプリが追加できました。

パッケージ名をDelphi側で登録しておく必要があります。
FireBaseのパッケージ名とDelphiのパッケージを一緒にすればよいので

![image](https://qiita-image-store.s3.amazonaws.com/0/143249/4759151e-ebef-f9e7-7376-80be5f687e1a.png)
Delphi側でもpackage名を定義しておきます。

#Android端末側でFCM Tokenのリクエスト
FormにButtonとMemoをおきます。
![image](https://qiita-image-store.s3.amazonaws.com/0/143249/c6b92ace-0c1f-a538-9483-34ac182a355e.png)
Buttonをクリックすると、
FCM Tokenをリクエストして、
その結果をMemoに出力します。

```
unit Mainform;

interface

uses
  System.SysUtils
  , System.Types
  , System.UITypes
  , System.Classes
  , System.Variants
  , FMX.Types
  , FMX.Controls
  , FMX.Forms
  , FMX.Graphics
  , FMX.Dialogs
  , System.PushNotification
  , FMX.Controls.Presentation
  , FMX.ScrollBox, FMX.Memo,
  , FMX.StdCtrls
  , System.Notification
  {$IFDEF ANDROID}
    , FMX.PushNotification.Android
  {$ENDIF}
  ;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { private 宣言 }
    PushService : TPushService;
    ServiceConnection : TPushServiceConnection;
    procedure ShowTokenExecute(Sender:TObject);
    procedure OnServiceConnectionChange(Sender : TObject; PushChange: TPushService.TChanges);
    procedure OnReceiveNotificationEvent(Sender : TObject; const ServiceNotification: TPushServiceNotification);
  public
    { public 宣言 }
  end;
procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowTokenExecute(Self);
end;

procedure TForm1.ShowTokenExecute(Sender: TObject);
var
  DeviceId, DeviceToken : String;
begin
  {$IFDEF ANDROID}
    PushService := TPushServiceManager.Instance.GetServiceByName(TPushService.TServiceNames.GCM);
    PushService.AppProps[TPushService.TAppPropNames.GCMAppID] := 'SENDER ID';
  {$ENDIF}
  ServiceConnection := TPushServiceConnection.Create(PushService);
  ServiceConnection.Active := True;
  ServiceConnection.OnChange := OnServiceConnectionChange;
  ServiceConnection.OnReceiveNotification := OnReceiveNotificationEvent;

  DeviceId := PushService.DeviceIDValue[TPushService.TDeviceIDNames.DeviceID];
  DeviceToken := PushService.DeviceTokenValue[TPushService.TDeviceTokenNames.DeviceToken];


  Memo1.Lines.Add('DeviceID:' + DeviceId);
  Memo1.Lines.Add('FCM Token:' + DeviceToken);
  Memo1.Lines.Add('Ready to Receive!');
end;
procedure TForm1.OnReceiveNotificationEvent(Sender: TObject;
  const ServiceNotification: TPushServiceNotification);
var
  MessageText : String;
begin
  // Do something with the notification received from FCM
end;

procedure TForm1.OnServiceConnectionChange(Sender: TObject;
  PushChange: TPushService.TChanges);
begin
  // Do something if the service connection change;
end;
```
Buttonをクリックすると、
Memoに出力されます。


![image](https://qiita-image-store.s3.amazonaws.com/0/143249/73b9bb9a-6e20-5def-6784-38f41ae3c26a.png)
SenderID部分にFireBaseの送信者IDを入力する必要があります。
ShowTokenExecute部の
```PushService.AppProps[TPushService.TAppPropNames.GCMAppID] := 'SENDER ID';
```をSENDER IDを修正してください


また、Delphi側でAndroid用のManifestへの記述が必要となります。
##Delphi側でのManifestへの設定 その1
![image](https://qiita-image-store.s3.amazonaws.com/0/143249/887ec61b-ddcc-a500-e100-f28e8a3149a8.png)
資格リストからプッシュ通知の受信をTrueにします。

##Delphi側でのManifestへの設定 その2
```
<%uses-permission%>
<!-- This needs to be added to receive FCM pushes. 
  It is used when receiving a broadcast from GCM server that contains a GCM message. -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
  
<!-- Add this intent under %services%. -->
<intent-filter>  
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> 

<!-- Add this service under %receivers%. -->
<service android:name="com.embarcadero.gcm.notifications.GCMIntentService" />
```
各項目がManifestに記載されていることを確認する。
なければ、追加する。

実際にTokenをRequestしてみます。
![image](https://qiita-image-store.s3.amazonaws.com/0/143249/3c6814f3-2186-031c-68c4-8f5a48654dc3.png)
Buttonをタップして、
実際に取得した状態です。
DeviceIDとFCM Tokenが取得できています。

#AndroidでPushを受信
Android側のReceiveNotificationEventを追加します。
また、NotificationEventから、Android側のNotificationCenterも記述します。

```
procedure TForm1.OnReceiveNotificationEvent(Sender: TObject;
  const ServiceNotification: TPushServiceNotification);
var
  MessageText : String;
begin
  Memo1.Lines.Add('Datakey = ' + ServiceNotification.DataKey);
  Memo1.Lines.Add('Json = ' + ServiceNotification.Json.ToString);
  Memo1.Lines.Add('DataObject = ' + ServiceNotification.DataObject.ToString);


  {$IFDEF ANDROID}
    MessageText := ServiceNotification.DataObject.GetValue('gcm.notification.body').Value;
  {$ENDIF}
  Memo1.Lines.Add(DateTimetoStr(Now) + 'Message = ' + MessageText);
  ShowAndroidNotification(MessageText, 0);

  // Do something with the notification received from FCM
end;

procedure TForm1.ShowAndroidNotification(MessageText: string;
  NotificationNumber: integer);
var
  NotificationCenter : TNotificationCenter;
  Notification : TNotification;
begin
  NotificationCenter := TNotificationCenter.Create(nil);
  try
    Notification := NotificationCenter.CreateNotification;
    try
      Notification.Name := MessageText;
      Notification.AlertBody := MessageText;
      Notification.Title := MessageText;
      Notification.EnableSound := false;
      Notification.Number := NotificationNumber;
      NotificationCenter.ApplicationIconBadgeNumber := NotificationNumber;
      NotificationCenter.PresentNotification(Notification);
    finally
      Notification.DisposeOf;
    end;
  finally
    NotificationCenter.Free;
    NotificationCenter.DisposeOf;
  end;
end;

```
これで受信後、Android側でNotificationを表示させることができます。

早速FireBaseからメッセージを送ってみましょう。
![image](https://qiita-image-store.s3.amazonaws.com/0/143249/36f4a131-90cd-831e-072d-067c8d8731aa.png)
しばらくすると、
Android側でメッセージが表示できます。

![image](https://qiita-image-store.s3.amazonaws.com/0/143249/dc3b998b-9605-555b-609d-b1844a9b27bc.png)

無事に受信できました。



次はiOSでメッセージを受信できるようにしたいと思います。