Firebase Cloud Messaging, issues in receiving noti

2019-05-21 22:15发布

问题:

I'm trying to write an application to receive notifications via Firebase Cloud Messaging. It initially worked when I tried to send the message via Firebase console but then the moment I tried doing the same using php webservice, in response, it showed success but I neither received the message nor am I able to get any more notifications via firebase console. Please help

My server side code:

MainActivity.java

package com.example.mojojojo.firebasenotifications;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.EditText;

import com.google.firebase.iid.FirebaseInstanceId;

public class MainActivity extends AppCompatActivity {

    private EditText etToken;
    private SharedPreferences sp;
    private SharedPreferences.Editor edit;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        etToken=(EditText)findViewById(R.id.etToken);

        sp=getSharedPreferences("pref",MODE_PRIVATE);
        edit=sp.edit();

        etToken.setText(FirebaseInstanceId.getInstance().getToken());
        BroadcastReceiver tokenReceiver=new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String token=intent.getExtras().getString("token");
                if(token!=null){
                    etToken.setText(token);
                }
            }
        };
        registerReceiver(tokenReceiver,new IntentFilter("TOKEN_GENERATED"));
    }
}

Messaging service

package com.example.mojojojo.firebasenotifications;

import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;

public class MessagingService extends FirebaseMessagingService {

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);
        String msg=remoteMessage.getNotification().getBody();
        sendNotification(msg);
        Log.i("/>/>",msg);
    }
    private void sendNotification(String messageBody) {
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 , intent,
                PendingIntent.FLAG_ONE_SHOT);

        Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("FCM Message")
                .setContentText(messageBody)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);

        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        notificationManager.notify(0 , notificationBuilder.build());
    }
}

Token Service

package com.example.mojojojo.firebasenotifications;

import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.IBinder;

import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;

public class TokenService extends FirebaseInstanceIdService {
    private SharedPreferences sp;
    private SharedPreferences.Editor edit;

    @Override
    public void onTokenRefresh() {
        super.onTokenRefresh();

        sp=getSharedPreferences("pref",MODE_PRIVATE);
        edit=sp.edit();

        String token= FirebaseInstanceId.getInstance().getToken();
        edit.putString("token",token);

        Intent tokenIntent=new Intent("TOKEN_GENERATED");
        tokenIntent.putExtra("token",token);
        sendBroadcast(tokenIntent);
    }
}

Manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.mojojojo.firebasenotifications">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service
            android:name=".MessagingService"
            android:enabled="false"
            android:exported="false" >
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT"/>
            </intent-filter>
        </service>

        <service
            android:name=".TokenService">
            <intent-filter>
                <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
            </intent-filter>
        </service>
    </application>

</manifest>

and my php code is as follows (I've removed the server Key in the code)

<?php
define( 'API_ACCESS_KEY', 'YOUR-API-ACCESS-KEY-GOES-HERE' );
$registrationIds = array( $_GET['id'] );
// prep the bundle
$msg = array
(
    'message'   => 'hi',
    'title'     => 'This is a title. title',
    'subtitle'  => 'This is a subtitle. subtitle',
    'tickerText'    => 'Ticker text here...Ticker text here...Ticker text here',
    'vibrate'   => 1,
    'sound'     => 1,
    'largeIcon' => 'large_icon',
    'smallIcon' => 'small_icon'
);
$fields = array
(
    'registration_ids'  => $registrationIds,
    'data'          => $msg
);

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

$ch = curl_init();
curl_setopt( $ch,CURLOPT_URL, 'https://fcm.googleapis.com/fcm/send' );
curl_setopt( $ch,CURLOPT_POST, true );
curl_setopt( $ch,CURLOPT_HTTPHEADER, $headers );
curl_setopt( $ch,CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch,CURLOPT_SSL_VERIFYPEER, false );
curl_setopt( $ch,CURLOPT_POSTFIELDS, json_encode( $fields ) );
$result = curl_exec($ch );
curl_close( $ch );
echo $result;
?>

回答1:

This php code finally worked for me.

<?php 
function send_notification ($tokens)
{

    $url = 'https://fcm.googleapis.com/fcm/send';
    $priority="high";
    $notification= array('title' => 'Some title','body' => 'hi' );

    $fields = array(
         'registration_ids' => $tokens,
         'notification' => $notification

        );


    $headers = array(
        'Authorization:key=xxxxxxxxxxxxx',
        '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);           
   echo curl_error($ch);
   if ($result === FALSE) {
       die('Curl failed: ' . curl_error($ch));
   }
   curl_close($ch);
   return $result;
}
$tokens = array('RECEIVER-TOKEN-1'
    ,'RECEIVER_TOKEN-2');

  $message_status = send_notification($tokens);
  echo $message_status;
?>

P.S: I've hard coded the receiver tokens as of now (for testing purposes)



回答2:

You have not posted what you get as result message after you echo $result. So for now after going through your code, I found:

String msg=remoteMessage.getNotification().getBody();

This line is causing problem. You should instead use it like this:

remoteMessage.getData().get("message")
remoteMessage.getData().get("title")
remoteMessage.getData().get("subtitle")

and so on..

For further clearance, we use:

remoteMessage.getNotification().getBody() when we have notification object in the JSON that we sent to fcm server. Which in your case is not there, instead you have data object and for that we use :

remoteMessage.getData().get("key_name")



回答3:

try this:

<?php 

function send_notification ($tokens, $message)
{
    $url = 'https://fcm.googleapis.com/fcm/send';
    $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));
   $result = curl_exec($ch);           
   if ($result === FALSE) {
       die('Curl failed: ' . curl_error($ch));
   }
   curl_close($ch);
   return $result;
}


$conn = mysqli_connect("localhost","root","","fcm");

$sql = " Select Token From users";

$result = mysqli_query($conn,$sql);
$tokens = array();

if(mysqli_num_rows($result) > 0 ){

    while ($row = mysqli_fetch_assoc($result)) {
        $tokens[] = $row["Token"];
    }
}

mysqli_close($conn);

   $message = array("message" => " FCM PUSH NOTIFICATION TEST MESSAGE");
   $message_status = send_notification($tokens, $message);
   echo $message_status;

?>


回答4:

    <?php 

    function send_notification ($tokens, $message)
    {
        $url = 'https://fcm.googleapis.com/fcm/send';
        $fields = array(
             'registration_ids' => $tokens,
             'data' => $message
            );

        $headers = array(
            'Authorization:key = your token ',
            '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));
       $result = curl_exec($ch);           
       if ($result === FALSE) {
           die('Curl failed: ' . curl_error($ch));
       }
       curl_close($ch);
       return $result;
    }

//Checking post request 
if($_SERVER['REQUEST_METHOD']=='POST'){

    //Connection to database

    $conn = mysqli_connect("localhost","root","","bbdd");

     //Geting email and message from the request 

    $email = $_POST['Email'];
    $msg = $_POST['message'];

    //Getting the firebase id of the person selected to send notification
    $sql = "SELECT * FROM users WHERE email = '$email'";


    $result = mysqli_query($conn,$sql);
    $tokens = array();

    if(mysqli_num_rows($result) > 0 ){

        while ($row = mysqli_fetch_assoc($result)) {
            $tokens[] = $row["Token"];
        }
    }

    mysqli_close($conn);

    $message = array("message" =>"$msg");
    $message_status = send_notification($tokens, $message);
    echo $message_status;

    //redirecting back to the sendnotification page 
    header('Location: sendPushNotification.php?success');
}else{
    header('Location: sendPushNotification.php');
}



 ?>

to one user



回答5:

This worked for me ... the FCM endpoint is maybe not that reliable . Try this

  $url = 'https://gcm-http.googleapis.com/gcm/send';

Just this dont change anything else. Also this endpoint will continue to live , google has no plans to deprecate GCM as mentioned in their Developer videos.

One more thing.. is there a delay or you are not getting the message at all .If there is a delay that maybe due to TCP timeout problem . Try this and let me know . Good Luck !!