一段时间或重启后未收到 FCM 推送通知

FCM Push Notification not received after some time or reboot

这里有个小问题,不幸的是,我目前无法真正解决它,所以在这里寻求帮助。

我正在尝试在我的应用程序中构建推送通知,并且我正在使用 FCM。 对于整个过程,我使用:

它的工作方式如下:每次生成新令牌时,我都会将此令牌发送到我的 MySQL 数据库,然后将其存储在那里。我有一个 PHP 脚本读取数据库以获取它可以找到的所有令牌并将推送通知发送到所有设备。

我看了很多 youtube 视频并阅读了多篇关于如何做到这一点的文章,我设法让它工作,但是,它非常不稳定,我无法让它持续工作。

在某些情况下它无法正常工作,我不知道是什么原因。

案例一:

-- 注意:我还在“onMessageReceived()”中实现了一个方法来将消息保存到 MySQL 这样我就可以亲自监控设备是否至少收到了消息以更好地理解它是如何有效,但设备从未收到它。

案例二:

我上面描述的行为对我的理解来说非常混乱。我不遵循任何逻辑。

我的代码:

PHP 脚本:

<?php 

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

    //var_dump($fields);

    $headers = array(
        'Authorization: key = KJAdkashdkhaiiwueyIhAXZ.....',
        '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);
   
   print($ch);
   print("<br>");
   print("<br>");
   print($result);
   print("<br>");
   print("<br>");
   print(json_encode($fields));
   print("<br>");
   print("<br>");
   
   if ($result === FALSE) {
       die('Curl failed: ' . curl_error($ch));
   }
   curl_close($ch);
   return $result;
}

$conn = mysqli_connect('ip_address', 'username', "password", 'mydatabasename');

$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);

$data = array(
    'title' => 'This is title of the message',
    'body' => 'This is body of the message',
    'contents' => 'Simple contents of the message'
    );

$android = array(
    'priority' => 'high'
);

$message_status = send_notification($tokens, $data, $android);
echo $message_status;

Android:

MyFirebaseMessagingService

class MyFirebaseMessagingService : FirebaseMessagingService() {

    /**
     * Called when message is received.
     *
     * @param remoteMessage Object representing the message received from Firebase Cloud Messaging.
     */
    override fun onMessageReceived(remoteMessage: RemoteMessage) {

        // Save received message to MySQL
        HUC.success()

        // Check if message contains a data payload.
        if (remoteMessage.data.isNotEmpty()) {
            Log.d(TAG, "Message data payload: ${remoteMessage.data}")
        }

        // Check if message contains a notification payload.
        remoteMessage.notification?.let {
            Log.d(TAG, "Message Notification Body: ${it.body}")
        }

        // Send notification containing the body of data payload
        sendNotification(remoteMessage.data["body"].toString())
    }
    // [END receive_message]

    // [START on_new_token]
    /**
     * Called if InstanceID token is updated. This may occur if the security of
     * the previous token had been compromised. Note that this is called when the InstanceID token
     * is initially generated so this is where you would retrieve the token.
     */
    override fun onNewToken(token: String) {
        Log.d(TAG, "Refreshed token: $token")
        
        // Saving my registration token to MySQL
        sendRegistrationToServer(token)
    }
    // [END on_new_token]

    /**
     * Persist token to third-party servers.
     *
     * Modify this method to associate the user's FCM InstanceID token with any server-side account
     * maintained by your application.
     *
     * @param token The new token.
     */
    private fun sendRegistrationToServer(token: String?) {
        CoroutineScope(IO).launch {
            // HttpURLConnection function to save token to MySQL
            val response = HUC.saveToken(token)
            withContext(Main){
                Log.d(TAG, "Server response: $response")
            }
        }
    }

    /**
     * Create and show a simple notification containing the received FCM message.
     *
     * @param messageBody FCM message body received.
     */
    private fun sendNotification(messageBody: String) {
        val intent = Intent(this, MainActivity::class.java)
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
        val pendingIntent = PendingIntent.getActivity(
            this, 0 /* Request code */, intent,
            PendingIntent.FLAG_ONE_SHOT
        )

        val channelId = getString(R.string.default_notification_channel_id)
        val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
        val notificationBuilder = NotificationCompat.Builder(this, channelId)
            .setSmallIcon(R.drawable.ic_notification)
            .setContentTitle(getString(R.string.fcm_message))
            .setContentText(messageBody)
            .setAutoCancel(true)
            .setSound(defaultSoundUri)
            .setContentIntent(pendingIntent)

        val notificationManager =
            getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

        // Since android Oreo notification channel is needed.
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(
                channelId,
                "Channel human readable title",
                NotificationManager.IMPORTANCE_HIGH
            )
            notificationManager.createNotificationChannel(channel)
        }

        notificationManager.notify(0 /* ID of notification */, notificationBuilder.build())
    }

    companion object {
        private const val TAG = "MyFirebaseMsgService"
    }
}

请帮我理解这里。也许我做错了什么或者我错过了什么。

事实上,当我硬重置 phone 时,一切都开始正常工作,这让我相信这是内部 phone 问题,而不是我的实现问题。