質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
87.20%
Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

解決済

FCM Push通知が届かない場合がある

ludolf
ludolf

総合スコア39

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

1回答

0評価

0クリップ

8365閲覧

投稿2020/09/09 11:35

いつもお世話になっております。

早速ですが表題の件でご教授頂きたく本件を投稿しました。

基本情報

先ずは基本情報から説明させていただくと、
Push通知を送信するのに使用しているツールは、FirebseCloudMessenging(以降FCMとする)を使用して送信しております。
FirebaseAdminSDKで送信していてNode.jsを通して送信しております。
その他諸々の設定はすべて出来ており、通知もIOS・Android届いている状況です。

ただ表題に書いてある通り、届かない場合があります。
といってもこういうパターンで送ると届かないとかではなく、急に届かなくなったりと不規則な動きをしています。
送れなかったパターンを再度1~2時間後に送信してみると、治ってたりしているので具体的にどういった送信が届いていないのか説明ができません。

やったこと

Push通知が送れない場合こういったケースがあると紹介しているサイトをたくさん見てみましたが、該当するケースがありませんでした。

自分が調べて届かないケースをまとめてみました。(文字数が越えてしまったので代表的なやつを記入しています)
「Dozeモードだと届かない」
「メッセージには有効期限がある」
「省エネモードだと届かない」
「重要度設定を低めにすると届かない」
「チャンネルが登録されていない」
「トピックが正しく設定されていない」
「最大文字数(4KB)を超えている」
「バックグランド・フォアグランドでは設定が必要」
「指定バックオフで送れなかった場合は再度送信するロジックを導入する」

チャンネルやトピックスに関しては普通に通知を受け取れているので、関係ないかと思っています。

以前フォアグランドは届くがバックグランドでは通知が届かない問題があり、質問している記事があるので載せておきます。
URL:https://teratail.com/questions/261240

上のURLで書いてあるようにデータペイロードのみで送信しています。

以上が基本情報です。

プログラム

Nodeでやっている処理は以下になります。

Node.js

…省略 /*************************************** * 個別トークン配信 **************************************/ async function send_push_notice_single(parameter_data, set_fcm, DB_obj,) { return new Promise((resolve,reject) => { var topic = parameter_data['topic']; var condition = "'Android' in topics || 'info_topic' in topics"; //デフォルト値 user_id = "0"; } //送られてきたURLをデコードする let decodeURI = decodeURIComponent(parameter_data['url']); decodeURI = decodeURIComponent(decodeURI); decodeURI = decodeURIComponent(decodeURI); let decodeImage = decodeURIComponent(parameter_data['image']); decodeImage = decodeURIComponent(decodeImage); decodeImage = decodeURIComponent(decodeImage); //トークン送信 var message = { data : { title : parameter_data['title'], message : parameter_data['message'], url : decodeURI, uid : user_id, type : parameter_data['type'], image : decodeImage, android_channel_id: parameter_data['channel'] }, token: parameter_data['token'] }; console.log(message); var response_data = ''; // Send a message to devices subscribed to the provided topic. set_fcm.messaging().send(message) .then((response) => { // Response is a message ID string. console.log('Successfully sent message:', response); response_data = { code : 'Successfully sent message', log : { send_type : 'single', error_info : response, push_data : message } }; resolve(response_data); }) .catch((error) => { console.log('Error sending message:', error); response_data = { code : error['errorInfo']['code'], log : { send_type : 'single', error_info : error['errorInfo'], push_data : message } }; resolve(response_data); // resolve(true); }); });

Android側

java

public class MyFirebaseMessagingService extends FirebaseMessagingService { private static final String TAG = "MyFirebaseMsgService"; @Override public void onNewToken(String token) { …省略 } @Override public void onMessageReceived(RemoteMessage remoteMessage) { if (remoteMessage != null) { long id = 0; String type = remoteMessage.getData().get("type"); String title = remoteMessage.getData().get("title"); String message = remoteMessage.getData().get("message"); String url; String uid; String image; if(remoteMessage.getData().get("type") != null){ type = remoteMessage.getData().get("type"); }else{ Log.d(TAG,"type何も入っていません"); type = ""; } //会員機能なのか非会員機能なのかを分ける処理 if(remoteMessage.getData().get("uid") != null && remoteMessage.getData().get("uid") != ""){ uid = remoteMessage.getData().get("uid"); }else{ Log.d(TAG,"uid何も入っていません"); uid = "0"; } //飛ばしたいリンクがあれば登録する処理 if(remoteMessage.getData().get("url") != null){ url = remoteMessage.getData().get("url"); }else{ Log.d(TAG,"url何も入っていません"); url = ""; } //画像があれば登録する処理 if(remoteMessage.getData().get("image") != null){ image = remoteMessage.getData().get("image"); }else{ Log.d(TAG,"image何も入っていません"); image = ""; } //チャンネル String channel = remoteMessage.getData().get("android_channel_id"); //タイトルのないPush通知など存在しないはずだに if (title != null || message != null) { Log.d(TAG,"プッシュ通知が届きました。"); // 通知メッセージを処理 Log.d(TAG, "これですね →" + remoteMessage.getData().toString()); if(!type.equals("oubo") && !type.equals("scout")) { //プッシュ通知をデータベースに入れ込み PushList pushList = new PushList(); pushList.type = type; pushList.title = title; pushList.message = message; pushList.receive_time = dateTime; pushList.url = url; pushList.batch = 1; pushList.uid = Integer.parseInt(uid); pushList.image = image; //ユーザーデータベースを宣言 UserDatabase db = Room.databaseBuilder(getApplication().getApplicationContext(), UserDatabase.class, myClass.TABLE_NAME).addMigrations(MIGRATION_1_2).addMigrations(MIGRATION_2_3).addMigrations(MIGRATION_3_4).addMigrations(MIGRATION_4_5).build(); //追加したレコードIDを戻り値として設定 id = db.pushListDao().insert(pushList); } } //Push通知表示用メソッド呼び出し //補足:URLクラスを呼び出すとtry/chatchしないといかんのだ try { sendNotification(id,title,message,channel,url,image); } catch (IOException e) { e.printStackTrace(); } }    /** * フォアグランドでもPush通知を受け取る */ private void sendNotification(Long id,String title, String body, String channel, String url, String image) throws IOException { //タップされたときの遷移画面設定 Intent intent = new Intent(this, MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY); intent.putExtra("PushReceive",url); intent.putExtra("PushRecodeId",id.intValue()); //senderIDを指定するために乱数を使用 randamId = UUID.randomUUID().hashCode(); //一度のみ PendingIntent pendingIntent = PendingIntent.getActivity(this, randamId, intent,PendingIntent.FLAG_UPDATE_CURRENT); Bitmap bitmap = null; Log.d(TAG,"画像生成失敗"); //デフォルトスタイル適用 BigTextPushStyle(title,body,channel,bitmap,pendingIntent); } //大きい画像を表示させるときのスタイル private void LaurgePicturePushStyle(String title, String body, String channel, Bitmap bitmap, PendingIntent pendingIntent){ Notification bigPictureStyle = new NotificationCompat.Builder(this,channel) .setSmallIcon(R.drawable.pushicon) .setContentTitle(title) .setContentText(body) .setLargeIcon(bitmap) .setAutoCancel(true) .setContentIntent(pendingIntent) .setPriority(NotificationCompat.PRIORITY_HIGH) .setStyle(new NotificationCompat.BigPictureStyle().bigPicture(bitmap) ).build(); //マネージャーさん呼び出し NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); //Push通知を表示 notificationManager.notify(randamId, bigPictureStyle); } //長文用 private void BigTextPushStyle(String title, String body, String channel, Bitmap bitmap, PendingIntent pendingIntent){ Notification bigTextStyle = new NotificationCompat.Builder(this,channel) .setSmallIcon(R.drawable.pushicon) .setContentTitle(title) .setContentText(body) .setLargeIcon(bitmap) .setAutoCancel(true) .setContentIntent(pendingIntent) .setPriority(NotificationCompat.PRIORITY_HIGH) .setStyle(new NotificationCompat.BigTextStyle() ).build(); //マネージャーさん呼び出し NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); //Push通知を表示 notificationManager.notify(randamId, bigTextStyle); }

(とりあえずAndroidで表示する文を投稿しましたが、IOSも必要であれば載せます。)

以上のプログラムで送信しています。

PHP側でPush通知を送信できる管理画面を作成していて実際に送信した内容をconsole.logで表示してみていますが、エラーはめったに表示されません。
エラーがあったとしてもトークンがありませんというエラー以外でていません。

受け取れないパターンについて

受け取れないパターンですが、特に多かったパターンがAndroidアプリを再起動?(タスク切り)してPush通知を送信すると届かないことが多いです。(IOSは特になし)
5通Push通知を30秒ほど間隔をあけて送信し、2通目までは連続で送信して3通目からはアプリを再起動して送信したのですが、3~5通目が届かないことが多いです。
たまにまとめて3通同じ時間に来たり、3通目からまったく通知が届かない場合もあります。
(1~2時間後に同じことをしたら届くこともありました)

長文で理解しずらいかと思いますが、お力添え頂ければ幸いです。
どんな些細な回答でも嬉しいのでぜひ回答ください泣

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

まだ回答がついていません

会員登録して回答してみよう

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。