0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

.NETCoreコンソールアプリからFCMでのPUSH通知

Last updated at Posted at 2020-05-03

AndroidスマホにPUSH通知を送るというだけのことに、てこずりました。
参考にできそうな記事はたくさんあり、それを真似ているのに、なぜかPUSH通知されないのです。
とりあえず(自分は)こうやってできた、というメモ書きとして残します。

環境(状況)

C# .NETCore3.1
AndroidにPUSH通知を受信するサンプルアプリを作成・インストール済み
FCM(Firebase)にPUSH通知のためのプロジェクトを作成済み

ゴール

FCMにPUSH通知のリクエストをするC#ソースコードを得る。Azure内で動くC# .NETCore3のソースがほしいが、まずはコンソールアプリでよい。

(追記)
Azureで実行する際に、key.p12というファイルの取得を行うコードを変更しました。

やってみて分かったこと

  • PUSH通知のリクエスト(WebAPI)を送るエンドポイント(URL)が変更されている。
  • Google Api HTTP v1というAPIを使う。
  • Googleサービスアカウントに対しPrivate keyを作成し、それをOAuth2.0のアクセストークン取得に使う

紹介記事のほとんどは旧のエンドポイントが使われています。FCMに移行された2019/5以降の記事さえ、旧のエンドポイントが使われています。
紛らわしいのは、いまだに旧のエンドポイントにFCM HTTP APIで送ることができ、そのリクエストのレスポンスは"success": 1を返すことです。でも、AndroidにはPUSH通知がきません。もしかすると、FCMに移行された2019/5/29以降に作られたFirebaseプロジェクトでは、このようにリクエストは成功するけどPUSH通知は発生しない、という挙動になるのかもしれません。 (編集) 誤解の可能性がありました。PUSHデータ内の通知ペイロード(notification)の有無でAndroid側の挙動が変わること、Androidアプリ側が正しくない可能性もあったこと、等々・・。以下、旧プロトコルが使えないという記載を削除しました。

 POST https://fcm.googleapis.com/fcm/send

POST https://fcm.googleapis.com/v1/projects/{projectID}/messages:send

v1では新のほうのエンドポイントとなります。

旧のエンドポイントを使っている記事(例えばQiitaにもある)によれば、PostmanでPOSTコマンド一発でPUSH通知ができるようです。それに倣ってやってみると、確かにPOSTは成功し、レスポンスも"success": 1 が返ってきます。

一方、新のエンドポイントでは、APIがv1に変わっているので、上記のような記事の内容そのままとはいきません。さらに、v1ではOAuth2.0が使われておりアクセストークンを使うためやりとりが増えるはずなので、PostmanでPOSTコマンド一発、というわけにはいかなそうです。なのでPostmanで試してみることはやめ、いきなりC#コードを書いてみることにしました。

Googleドキュメントを読むと、一応、v1 APIでOAuthを使うにはどうしたらいいのかが書かれています。・・・が、いろんなことが沢山書かれているので、迷子になってしまいました。

結局こうした、というのを書き出してみると、
作成済みのFirebaseプロジェクトで、サービスアカウントに対し、Private keyを作成。
image.png
image.png
image.png
Jsonファイルを作る手順もあるようですが、今回のコードではP12を選択します。
image.png
作成された(ダウンロードされた) P12ファイルを、key.p12にリネームします。

.NETCore3.1で、コンソールアプリを作成します。この手順の説明は割愛します。

NuGetでGoogle.Api.AuthおよびGoogle.Apis.FirebaseCloudMessaging.v1をインストールします。また、key.p12をプロジェクトに追加し、出力ディレクトリにコピーで「新しい場合はコピーする」とします。
image.png

(追記) Androidへの通知のときにchannelを追加できるよう修正。

Program.cs
using System;
using System.Security.Cryptography.X509Certificates;

using Google.Apis.Auth.OAuth2;
using Google.Apis.Services;
using Google.Apis.FirebaseCloudMessaging.v1;

namespace SendToFcm
{
    class Program
    {

        static void Main(string[] args)
        {
            String serviceAccountEmail = "hoge_webservices@appspot.gserviceaccount.com";


            // fine on local. but it doesn't work on Azure. not sure why.
            // var certificate = new X509Certificate2(@"key.p12", "notasecret", X509KeyStorageFlags.Exportable);
            // this works on Azure.
            var certificate = new X509Certificate2(file, "notasecret", X509KeyStorageFlags.MachineKeySet |
                                                                        X509KeyStorageFlags.PersistKeySet |
                                                                        X509KeyStorageFlags.Exportable);


            ServiceAccountCredential credential = new ServiceAccountCredential(
               new ServiceAccountCredential.Initializer(serviceAccountEmail)
               {
                   Scopes = new[] { Google.Apis.FirebaseCloudMessaging.v1.FirebaseCloudMessagingService.Scope.CloudPlatform }
               }.FromCertificate(certificate));

            // Create the service.
            var service = new FirebaseCloudMessagingService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = "PUSH API Sample",
            });

            
            
            var requestBody = new Google.Apis.FirebaseCloudMessaging.v1.Data.SendMessageRequest();
            requestBody.Message = new Google.Apis.FirebaseCloudMessaging.v1.Data.Message();

            // token is a target which you want to send a PUSH to, and was made by an android-terminal with an android-app.
            requestBody.Message.Token = "eGxxxxx0VxI:APA91xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxNG-f";
            // Notification is to be seen on the android display.
            requestBody.Message.Android = new Google.Apis.FirebaseCloudMessaging.v1.Data.AndroidConfig();
            requestBody.Message.Android.Priority = "high";
            requestBody.Message.Android.Notification = new Google.Apis.FirebaseCloudMessaging.v1.Data.AndroidNotification();
            requestBody.Message.Android.Notification.Body = "body of your notif";
            requestBody.Message.Android.Notification.Title = "title of your notif";
            requestBody.Message.Android.Notification.ChannelId = "channelId";
            // Data is data used by android app.
            requestBody.Message.Data = new System.Collections.Generic.Dictionary<string, string>();
            requestBody.Message.Data.Add("key1", "123");
            requestBody.Message.Data.Add("key2", "456");

            // projectId is from Firebase projcect
            var projectId = "hoge_webservices";
            // "Projects" is an instance of ProjectsResource. Projects.Messages is a REST resource.
            var send = service.Projects.Messages.Send(requestBody, $"projects/{projectId}");

            try
            {
                // Send HttpRequest
                // Execute() returns a supposed-to-be "response" but no information in it, either success or error.
                // Errors will be thrown as exceptions.
                var response = send.Execute();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }


            Console.WriteLine("Press any key to continue...");
            Console.ReadKey();
        }
    }
}

参考

結局、Google公式ドキュメントを拾い読みしました。

エンドポイントが変わっていますよ、というドキュメント
以前の HTTP から HTTP v1 に移行する
HTTP v1のPUSH通知に載せるデータが比較的簡単に説明されているドキュメント。
FCM メッセージについて
C#(.NET)コード実装例は、Google API クライアントライブラリのドキュメントにあります。残念ながらずばり自分の欲しいものがある可能性は低そう。
API Client Libraries .NET ガイド Get Started
そこからさらにOAuth周りの実装は下記のページ。ここから、"サービスアカウント"を使えばよさそうだとわかり、"Service Account"のところのサンプルコードにより、ServiceAccountCredentialやxxxService(⇒FirebaseCloudMessagingService)というクラスを使えばよいことが分かります。
API Client Libraries .NET ガイド OAuth 2.0
ここら辺までわかったら、GitHubのソースを見ながら、FirebaseCloudMessagingServiceを使ったサンプルコードを作ってみます。
GitHub googleapis/google-api-dotnet-client
そこからAPIごとのクラス
そこからFCM

上記のGitHubのソースから、さらにProjectsResourceおよびProjectsResource.MessagesResourceへ進めばよいと見当がつきます。ここで下記のAPIドキュメントが参考になることがわかりました。
APIリファレンス REST Resource: projects.messages
このAPIリファレンスではメソッドを試す機能があるようです。ここでの例なら、Methodsのsendをクリックすると下記ページに移り、そこにTry this APIとあります。私は残念ながらOAuthをどうすればよいか分からず使えませんでした。
image.png

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?