从服务器向安卓设备发送FCM消息

15

有了新的更新,现在将使用 FCM。

我尝试了来自 Git 的示例应用程序,一切都很正常。我可以从控制台发送通知。

但是我想在某个事件触发后从服务器发送通知。我采用了与 GCM 相同的方法,但它不起作用。

05-20 20:40:58.941 30132-30919/com.google.firebase.quickstart.fcm E/AndroidRuntime: FATAL EXCEPTION: pool-1-thread-1
                                                                                    Process: com.google.firebase.quickstart.fcm, PID: 30132
                                                                                    java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.google.firebase.messaging.RemoteMessage$Notification.getBody()' on a null object reference
                                                                                        at com.google.firebase.quickstart.fcm.MyFirebaseMessagingService.onMessageReceived(MyFirebaseMessagingService.java:53)
                                                                                        at com.google.firebase.messaging.FirebaseMessagingService.zzo(Unknown Source)
                                                                                        at com.google.firebase.messaging.FirebaseMessagingService.zzn(Unknown Source)
                                                                                        at com.google.firebase.messaging.FirebaseMessagingService.zzm(Unknown Source)
                                                                                        at com.google.firebase.iid.zzb$2.run(Unknown Source)
                                                                                        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
                                                                                        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
                                                                                        at java.lang.Thread.run(Thread.java:818)
05-20 20:40:59.118 30132-30279/com.google.firebase.quickstart.fcm E/Surface: getSlotFromBufferLocked: unknown buffer: 0xb9e83390

我正在遵循这个PHP脚本发送通知。 如果我尝试执行该脚本,我会得到以下结果。

{"multicast_id":4679427854122301046,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1463757518309261%31bd1c96f9fd7ecd"}]}

注意:我查阅了他们的文档,并修改了代码片段,只保留正文和标题。即使如此,它仍然无法正常工作。


你能添加你正在发送的消息吗?看起来你的消息没有包含正文,这可能是空指针的原因。 - Arthur Thompson
伊斯梅尔是正确的。这是我的答案: https://dev59.com/DloU5IYBdhLWcg3wi3WW#37471326 - Koot
7个回答

16

您可以使用此完整代码

<?php

function sendFCM($mess,$id) {
$url = 'https://fcm.googleapis.com/fcm/send';
$fields = array (
        'to' => $id,
        'notification' => array (
                "body" => $mess,
                "title" => "Title",
                "icon" => "myicon"
        )
);
$fields = json_encode ( $fields );
$headers = array (
        'Authorization: key=' . "AIzaSyA9vpL9OuX6moOYw-4n3YTSXpoSGQVGnyM",
        'Content-Type: application/json'
);

$ch = curl_init ();
curl_setopt ( $ch, CURLOPT_URL, $url );
curl_setopt ( $ch, CURLOPT_POST, true );
curl_setopt ( $ch, CURLOPT_HTTPHEADER, $headers );
curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt ( $ch, CURLOPT_POSTFIELDS, $fields );

$result = curl_exec ( $ch );
curl_close ( $ch );
}

?>
将消息和令牌ID作为参数传递给sendFCM($mess,$id)调用。

9

我尝试过这个方法并且有效:

<?php
$ch = curl_init("https://fcm.googleapis.com/fcm/send");
$header=array('Content-Type: application/json',
"Authorization: key=GoGdfsflknEFñslknaglksjfnklj");
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt( $ch,CURLOPT_SSL_VERIFYPEER, false );

curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "{ \"notification\": {    \"title\": \"Test desde curl\",    \"text\": \"Otra prueba\"  },    \"to\" : \"SGferg-qWEFWbI:dflñkndfakllvakrgalkgjdgjslfkgjdglksdjflksjglkjlkñerhTHDFSHFZDHzdfakjsdhskjhgkjashfdasjdkf\"}");

curl_exec($ch);
curl_close($ch);
?>

这是结果:

{"multicast_id":4913280949692448120,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1473389987003950%ab9a0bb6ab9a0bb6"}]}

我认为上面的脚本只适用于一个用户,如果我想向多个用户发送PUSH消息... - techDigi
我该如何将这个结果存储到变量中? - Snehal Trapsiya

3
为了使用 remoteMessage.getNotification().getBody() 接收通知,您需要使用预定义的通知关键字选项。
在这种情况下,"notification" 是关键字。
JSON 响应必须格式化为以下形式。
   {
      "to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
      "notification" : {
          "body" : "great match!",
          "title" : "Portugal vs. Denmark",
          "icon" : "myicon"
      }
   }

您可以在同一JSON响应中发送通知和数据负载。
 {
    "to" : "APA91bHun4MxP5egoKMwt2KZFBaFUH-1RYqx...",
    "notification" : {
        "body" : "great match!",
        "title" : "Portugal vs. Denmark",
        "icon" : "myicon"
    },
    "data" : {
        "Nick" : "Mario",
        "Room" : "PortugalVSDenmark"
    }
 }

请查看:https://firebase.google.com/docs/cloud-messaging/concept-options#messages-with-both-notification-and-data-payloads,该文涉及到同时包含通知和数据有效载荷的消息。

2

是的。当我尝试通过remoteMessage.getData().get("body");获取数据时,我得到了文本。有什么想法如何在那里创建通知?文档指定所需的字段,但我该如何创建一个notification呢? - driftking9987
数据对象和通知对象是兄弟节点,因此您可以使用文档中的通知字段,在与数据对象相同的级别上创建一个通知对象。 - Arthur Thompson
我会尝试一下。 - driftking9987

2

我曾经遇到同样的问题,花了一些时间试图找出原因,我的观察是--

由于“notification”字段是RemoteMessage.Notification的JSON表示。 如果您在“通知”字段中设置了Notification类的任何预定义字段,则客户端成功解析JSON,并且您可以对其调用getBody() / getTopic() / getIcon()以获取非空值。

但是,如果您没有在“通知”json字段中设置Notification类的任何字段,则解析到类失败,您将获得一个null值,无法使用RemoteMessage.getNotification()

因此,以下三个JSON之一都是推送RemoteMessage.Notification的有效POST主体(除了Andrea在早期答案中分享的两个示例),即这三个不会导致上述NPE

    {
      "to" : "<<FIREBASE_INSTANCE_ID>>",
      "notification" : {
          "body" : "Notification Message Body"
      }
    }

    {
      "to" : "<<FIREBASE_INSTANCE_ID>>",
      "notification" : {
          "title" : "Notification Title"
      }
    }

    {
      "to" : "<<FIREBASE_INSTANCE_ID>>",
      "notification" : {
          "icon" : "Notification icon"
      }
    }

以下三种方法均不可用于推送RemoteMessage.Notification -
  1. Doesn't have the "notification" field

    {
      "to" : "<<FIREBASE_INSTANCE_ID>>"
    }
    
  2. "notification" field is an empty json

    {
      "to" : "<<FIREBASE_INSTANCE_ID>>",
      "notification" : {
      }
    }
    
  3. "notification" field has some key value pairs , but none of the fields defined in RemoteMessage.Notification class

    {
        "to" : "<<FIREBASE_INSTANCE_ID>>",
        "notification" : {
            "messageText" : "Notification Message Text",
            "messageBody" : "Notification Message Body"
        }
    }
    

1

function send_fcm($tokens,$message)
          {

     $url = 'https://fcm.googleapis.com/fcm/send';
     $priority="high";
   
 
     $fields = array(
          'registration_ids' =>$tokens,         
           'data' =>$message
            
         );

  
     $headers = array(
          'Authorization:key=your key',
          'Content-Type: application/json'
          );

     $ch = curl_init();
     curl_setopt($ch, CURLOPT_URL, $url);
     curl_setopt($ch, CURLOPT_POST, true);
     curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
     curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
     curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);  
     curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
     curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
   echo  json_encode($fields);
     $result = curl_exec($ch);           
     curl_error($ch);
     if ($result === FALSE)
      {
         die('Curl failed: ' . curl_error($ch));
         }
                  curl_close($ch);
                  return $result;
             }

将设备ID以数组格式存储在令牌变量中


0
尝试以下代码,它将从PHP服务器端提供Android的推送通知,您可以从Android获取设备令牌,需要动态传递以获取更多Android设备的推送通知。
<?php
 function sendmessage_android($devicetoken,$message){ 
        $api_key     =   'AIzaSyCtDch9K3ZqGF_SSLYCz4JjMS4-fkJuW';//get the api key from FCM backend
        $url = 'https://fcm.googleapis.com/fcm/send';
        $fields = array('registration_ids'  => array($devicetoken));//get the device token from Android 
        $headers = array( 'Authorization: key=' . $api_key,'Content-Type: application/json');
        $ch = curl_init();
        curl_setopt( $ch, CURLOPT_URL, $url );
        curl_setopt( $ch, CURLOPT_POST, true );
        curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
        curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode($fields) );
        $result = curl_exec($ch);
        if(curl_errno($ch)){
            return 'Curl error: ' . curl_error($ch);
        }
        curl_close($ch);
        $cur_message=json_decode($result);
        if($cur_message->success==1)
            return true;
        else
            return false;
}
?>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接