安卓推送通知Firebase有时无法发送通知

6
我正在创建具有推送通知功能的Android应用程序。我的问题是:有时我的应用程序会收到通知,但有时不会。我已经在Google上搜索了这个问题,但没有人遇到相同的问题。请帮助我解决。以下是我的代码。 这是gradle文件
apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.0"
    defaultConfig {
        applicationId "com.example.rusla.manual_notif"
        minSdkVersion 16
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.0.1'
    compile 'com.google.firebase:firebase-messaging:10.0.0'
    testCompile 'junit:junit:4.12'
    compile 'com.mcxiaoke.volley:library:1.0.19'
}


apply plugin: 'com.google.gms.google-services'

这是清单文件

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

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

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name=".MyFirebaseMessagingService">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT"/>
            </intent-filter>
        </service>


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

</manifest>

这是我的注册令牌类

package com.example.rusla.manual_notif;

import android.app.ProgressDialog;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.android.volley.AuthFailureError;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.google.firebase.iid.FirebaseInstanceId;

import java.util.HashMap;
import java.util.Map;

public class RegisterActivity extends AppCompatActivity {
    private EditText editTextEmail;
    String REGISTER_URL = "http://192.168.0.7/fcm_server/register.php";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.register_layout);
        Button regBtn = (Button) findViewById(R.id.buttonRegister);
        editTextEmail = (EditText) findViewById(R.id.editTextEmail);
        regBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                // Get token
                String token = FirebaseInstanceId.getInstance().getToken();
                //Finally we need to implement a method to store this unique id to our server
                sendIdToServer(token);
            }
        });
    }

    private void sendIdToServer(final String token) {
        //Creating a progress dialog to show while it is storing the data on server
        final ProgressDialog progressDialog = new ProgressDialog(this);
        progressDialog.setMessage("Registering device...");
        progressDialog.show();

        //getting the email entered
        final String email = editTextEmail.getText().toString().trim();

        //Creating a string request
        StringRequest req = new StringRequest(Request.Method.POST, REGISTER_URL,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        //dismissing the progress dialog
                        progressDialog.dismiss();
                        //if the server returned the string success
                        if (response.trim().equalsIgnoreCase("success")) {
                            //Displaying a success toast
                            Toast.makeText(RegisterActivity.this, "Registered successfully", Toast.LENGTH_SHORT).show();

                        } else {
                            Toast.makeText(RegisterActivity.this, "Choose a different email", Toast.LENGTH_SHORT).show();
                        }
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {

                    }
                }) {
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                Map<String, String> params = new HashMap<>();
                //adding parameters to post request as we need to send firebase id and email
                params.put("token", token);
                params.put("email", email);
                return params;
            }
        };

        //Adding the request to the queue
        RequestQueue requestQueue = Volley.newRequestQueue(this);
        requestQueue.add(req);
    }

}

这是我的Firebase服务类。
package com.example.rusla.manual_notif;

import android.util.Log;

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

public class FirebaseIDService extends FirebaseInstanceIdService {
    private static final String TAG = "FirebaseIDService";

    @Override
    public void onTokenRefresh() {
        // Get updated InstanceID token.
        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
        Log.d(TAG, "Refreshed token: " + refreshedToken);

        // TODO: Implement this method to send any registration to your app's servers.
        sendRegistrationToServer(refreshedToken);
    }

    private void sendRegistrationToServer(String token) {
        // Add custom implementation, as needed.
    }
}

这是

package com.example.rusla.manual_notif;

import android.util.Log;

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

public class MyFirebaseMessagingService extends FirebaseMessagingService {
    private static final String TAG = "FCM Service";
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        // TODO: Handle FCM messages here.
        // If the application is in the foreground handle both data and notification messages here.
        // Also if you intend on generating your own notifications as a result of a received FCM
        // message, here is where that should be initiated.
        Log.d(TAG, "From: " + remoteMessage.getFrom());
        Log.d(TAG, "Notification Message Body: " + remoteMessage.getNotification().getBody());
    }
}

以下是我使用的服务器端PHP代码,用于发送通知:

<!DOCTYPE html>
<html>
<head>
    <title>Firebase Push Notification</title>
</head>
<style type="text/css">
    html, body {
        height: 100%;
    }

    html {
        display: table;
        margin: auto;
    }

    body {
        display: table-cell;
        vertical-align: middle;
    }
    textarea {
        width: 300px;
        height: 150px;
    }
</style>

<body>
    <?php
    require_once 'database.php';
    $sql = "SELECT * FROM users";
    $result = mysqli_query($conn,$sql);

    ?>
    <?php
    //Displaying a success message when the notification is sent 
    if(isset($_REQUEST['success'])){
        ?>
        <strong>Great!</strong> Your message has been sent successfully...
        <?php
    }
    ?>

    <form action='send.php' method='post'>
        <select name='token'>
            <?php 
            //Traversing trhough all values 
            while($row = mysqli_fetch_array($result)){
            //displaying the values in a dropdown list 
                ?>
                <option value='<?php echo $row['token'];?>'><?php echo $row['email'];?></option>

                <?php
            }
            ?>
        </select><br /><br />
        <textarea name='message'></textarea><br />

        <button>Send Notification</button><br />
    </form>

</body>
</html>

and thi is

<?php 

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

    $msg = array
    (
        'body'  => "$message",
        'title'     => "SATPOL PP SDA - SIAP",
        'sound'     => 'default'

        );
    $fields = array
    (
        'registration_ids'  => $tokens,
        'notification'          => $msg
        );


    $headers = array(
        'Authorization:key = AIzaSyAdnDaeFRbG7jD74-yo0R72n7b24Wzsh7k',
        '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'){
    //Geting email and message from the request 
    $tokens[] = $_POST['token'];
    $message = $_POST['message'];
    $message_status = send_notification($tokens, $message);
    $result = json_decode($message_status);

    if($result->success){
        header('Location: sendNotification.php?success');
    }else{
        echo "<pre>";print_r($result);die; 
    }
}else{
    header('Location: sendNotification.php');
}


?>

也许有人可以纠正我的代码,我会非常感谢。

1
请检查您未收到通知的情况。在您未收到通知时,您的应用程序是否在后台运行?您是否正在使用最新版本的Firebase? - Arnaldo
@user5195185在应用程序关闭和打开时没有收到通知。是的,我使用最新版本.. - Ruslan Wahyudi
当我重启我的安卓手机时,通知也无法接收。需要先打开应用,这样才能收到通知。 - Ruslan Wahyudi
2个回答

5

我建议您使用data而不是notification。数据消息始终在onMessageReceived上加载。

阅读如何使用数据,编辑您的脚本(php)以使用数据而不是通知。

然后,创建您自己的通知,如下所示:

@Override
    public void onMessageReceived(RemoteMessage remoteMessage) {

        // Use data! (:
        if(remoteMessage.getData().size() > 0) {

            if (remoteMessage.getData().get("message") != null) {

                String title = (remoteMessage.getData().get("title") != null) ? remoteMessage.getData().get("title") : "Default Notification Title";
                showNotification(title, remoteMessage.getData().get("message"));

            }

        }

        // When you send notification from the firebase console (avoid it for now. Is still very new)
        if (remoteMessage.getNotification() != null) {

            String title = (remoteMessage.getNotification().getTitle() != null) ? remoteMessage.getNotification().getTitle() : "Default Notification Title";

            showNotification(title, remoteMessage.getNotification().getBody());


        }
    }

private void showNotification(String title, String message){

Intent iNotifi;
iNotifi = new Intent(this, MainActivity.class);
            iNotifi.setAction(Intent.ACTION_MAIN);
            iNotifi.addCategory(Intent.CATEGORY_LAUNCHER);

PendingIntent pi = PendingIntent.getActivity(this, 0, iNotifi, 0);

NotificationCompat.Builder builder = new NotificationCompat.Builder(this);

        builder.setSmallIcon(R.drawable.yourNotificationIcon);
        builder.setTicker(title);
        builder.setContentTitle(title);
        builder.setContentText(message);
builder.setContentIntent(pi);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            int color = ContextCompat.getColor(this, R.color.yourAccentColor);
            builder.setColor(color);
        }

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

        try {
            nm.notify(0, builder.build());
        } catch (Exception e) {
            e.printStackTrace();
        }

}

在Manifest文件中添加以下内容:

<application...>


<!-- Firebase notification icon -->
        <meta-data android:name="com.google.firebase.messaging.default_notification_icon"
            android:resource="@drawable/yourNotificationIcon" />
        <meta-data android:name="com.google.firebase.messaging.default_notification_color"
            android:resource="@color/yourAccentColor" />

</application>

我希望我能有所帮助(:)

请查看此链接 - Arnaldo

3

如果您没有更新Firebase注册令牌,那么您的服务器端令牌可能已过期。令牌会动态更新,因此消息可能无法接收。

您需要从设备更新令牌。

根据我的研究,要么是由于有效载荷有时超过“4KB”大小限制,要么是Firebase存在错误,但我对后者表示怀疑。


1
谢谢Joe,这是我情况下的正确答案。我想我的有效载荷超过了4kb。 - Leo S

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