【问题标题】:Unable to send notification to multiple devices using FCM无法使用 FCM 向多个设备发送通知
【发布时间】:2016-12-13 07:15:13
【问题描述】:

我仅在一个设备中收到通知,该设备设置为存储在 mySQL DB 中的表的第一个令牌,并且通知不会发送到其余的令牌编号。我尝试了一个WHILE 循环并将令牌编号存储在一个数组中,但它不起作用。

请提出解决方案。谢谢。

这是我的代码:

<?php
require "init.php";
$message=$_POST['message'];
$title=$_POST['title'];
$path_to_fcm='https://fcm.googleapis.com/fcm/send';
$server_key="A*************************Q";
$sql="select token from fcm_info";
$result =mysqli_query($con,$sql);
$row=mysqli_fetch_row($result);
$key=$row[0];
$headers = array(

    'Authorization:key=' .$server_key,
    'Content-Type:application/json'
);
$fields =array('to'=>$key,  
                'notification'=>array('title'=>$title,'body'=>$message));  

$payload =json_encode($fields);
$curl_session =curl_init();
curl_setopt($curl_session,CURLOPT_URL, $path_to_fcm);
curl_setopt($curl_session,CURLOPT_POST, true);
curl_setopt($curl_session,CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl_session,CURLOPT_RETURNTRANSFER,true);
curl_setopt($curl_session,CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl_session,CURLOPT_IPRESOLVE, CURLOPT_IPRESOLVE);
curl_setopt($curl_session,CURLOPT_POSTFIELDS, $payload);
$result=curl_exec($curl_session);
curl_close($curl_session);
mysqli_close($con);
?>

【问题讨论】:

  • 你应该添加代码而不是截图!
  • 获取sql结果为数组,并用它来调用请求
  • 我在上面编辑了我的代码。我使用了数组,但它不起作用,它只将通知发送到一个设备..如果你能帮助我准确地纠正代码,因为我是新手..谢谢

标签: php android firebase firebase-cloud-messaging


【解决方案1】:

使用“registration_ids”而不是“to”并传递逗号分隔的多个注册 ID 以在 FCM 中使用多播。最终的有效载荷应该是这样的:

{
"registration_ids":["id1","id2",...],
  "priority" : "normal",
  "data" : {
    "title" : "Title",
    "message" : "Message to be send",
    "icon": "icon_path"
  }
}

请参阅https://developers.google.com/cloud-messaging/http-server-ref 以获取更多帮助

【讨论】:

    【解决方案2】:
    //////////////////////    FCM  START      /////////////////////////
    
      $path_to_fcm = "https://fcm.googleapis.com/fcm/send";
    
      $server_key = "your_server_key";
    
      $headers = array(
        'Authorization:key=' . $server_key, 
        'Content-Type:application/json');
    
    
      $keys = ["key_1", "key_2"];
    
      $fields = array(
        "registration_ids" => $keys,
        "priority" => "normal",
        'notification' => array(
              'title' => "title of notification",
              'body' => "your notification goes here" 
             )
           );
    
       $payload = json_encode($fields);
    
    
      $curl_session = curl_init();
    
      curl_setopt($curl_session, CURLOPT_URL, $path_to_fcm);
      curl_setopt($curl_session, CURLOPT_POST, true);
      curl_setopt($curl_session, CURLOPT_HTTPHEADER, $headers);
      curl_setopt($curl_session, CURLOPT_RETURNTRANSFER, true);
      curl_setopt($curl_session, CURLOPT_SSL_VERIFYPEER, false);
      curl_setopt($curl_session, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
      curl_setopt($curl_session, CURLOPT_POSTFIELDS, $payload);
    
      $curl_result = curl_exec($curl_session);
    
    //////////////////////    FCM  END      /////////////////////////
    

    这对我有用。

    【讨论】:

      【解决方案3】:

      您需要在方法中覆盖通知发送逻辑,然后开始循环并在每次迭代中调用该方法,将令牌和消息传递给方法。

      【讨论】:

      • 您好,能否请您解释一下从哪里开始循环并在上面的代码中进行迭代,因为我之前做过循环但徒劳无功,我已经编辑了我的帖子,代码可用。
      【解决方案4】:

      请提出解决方案

      我想建议使用Services。最推荐您阅读 Android Studio here 的文档。

      关于服务有很多需要了解的地方,但目前我相信 sn-p 对您最有帮助,这里有一些代码,

      创建一个名为 HelloService 的类

      并将以下代码粘贴到正确的导入中*

      public class HelloService extends Service {
      private Looper mServiceLooper;
      private ServiceHandler mServiceHandler;
      
      // Handler that receives messages from the thread
       private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }
        @Override
        public void handleMessage(Message msg) {
            // Normally we would do some work here, like download a file.
            // For our sample, we just sleep for 5 seconds.
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                // Restore interrupt status.
                Thread.currentThread().interrupt();
            }
            // Stop the service using the startId, so that we don't stop
            // the service in the middle of handling another job
            stopSelf(msg.arg1);
        }
      }
      
      @Override
      public void onCreate() {
      // Start up the thread running the service.  Note that we create a
      // separate thread because the service normally runs in the process's
      // main thread, which we don't want to block.  We also make it
      // background priority so CPU-intensive work will not disrupt our UI.
      HandlerThread thread = new HandlerThread("ServiceStartArguments",
              Process.THREAD_PRIORITY_BACKGROUND);
      thread.start();
      
      // Get the HandlerThread's Looper and use it for our Handler
      mServiceLooper = thread.getLooper();
      mServiceHandler = new ServiceHandler(mServiceLooper);
        }
      
        @Override
         public int onStartCommand(Intent intent, int flags, int startId) {
         Toast.makeText(this, "servicestarting",Toast.LENGTH_SHORT).show();
      
      
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        mServiceHandler.sendMessage(msg);
      
        // If we get killed, after returning from here, restart
        return START_STICKY;
            }
      
      @Override
      public IBinder onBind(Intent intent) {
         // We don't provide binding, so return null
         return null;
                }
      
      
       @Override
       public void onDestroy() {
         Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
       }
      }
      

      “这太夸张了”你可能会这样想。然而事实恰恰相反。

      服务 + Firebase 示例

      假设您想在某个数据库中发生修改时通知用户,而不是从 Firebase 推送消息

      首先,在 Oncreate 上创建数据库引用

      mDatabaseLike=FirebaseDatabase.getInstance().getReference().child("Likes"); 
      

      转到“handleMessage 方法”并添加以下内容

            @Override
          public void handleMessage(Message msg) {
      
      
      
              mDatabaseLike.addValueEventListener(new ValueEventListener() {
                  @Override
                  public void onDataChange(DataSnapshot dataSnapshot) {
      
                   notifyUserOfDBupdate()
      
      
                  }
      
                  @Override
                  public void onCancelled(DatabaseError databaseError) {
      
                  }
              });
      
      
      
      
              //stopSelf(msg.arg1);
          }
      }
      

      这里是 notifyUserOfDBupdate 方法以及如何通知用户

         private void notifyUserOfDBupdate() {
          //Intents
          Intent Pdf_view = new Intent(this, //class to throw the user when they hit on notification\\.class);
          PendingIntent pdf_view = PendingIntent.getActivity(this, 0, Pdf_view, 0);
      
      
          //Notification Manager
          NotificationManager nm = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
      
      
          //The note
          Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
          Notification noti = new NotificationCompat.Builder(getApplicationContext())
                  .setTicker("TickerTitle")
                  .setContentTitle("content title")
                  .setSound(soundUri)
                  .setContentText("content text")
                  .setContentIntent(pdf_view).getNotification();
      
      
          //Execution
          noti.flags = Notification.FLAG_AUTO_CANCEL;
          nm.notify(0, noti);
      }
      

      现在在您的真实设备上运行您的应用程序一次,然后在模拟器上运行第二次。一旦两者中的任何一个修改了您的 firebase 数据库,另一个将立即得到通知。

      在 HandleMessage 方法中修改您喜欢的任何方法。它将是永恒的,除非你让它可以被杀死。

      最诚挚的问候

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-11-09
        • 1970-01-01
        • 2019-10-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-15
        • 2021-11-14
        相关资源
        最近更新 更多