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

时间:2020-08-14 14:36:01

标签: android firebase firebase-cloud-messaging

我在这里有一个小问题,很不幸,我目前无法独自解决这个问题,所以请在这里寻求帮助。

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

  • 带有firebase的Android应用程序
  • 用于发送FCM推送通知的PHP脚本
  • 用于存储令牌的MySQL数据库。

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

我已经观看了许多youtube视频,并阅读了许多有关如何执行此操作的文章,但我设法使其正常运行,但是,它非常不稳定,无法使其持续运行。

在某些情况下,由于我的未知原因而无法使用。

情况1:

  • 第一天: 我刚刚安装了应用程序,启动了它,然后将其置于后台。发送推送并成功接收。在3-4小时内,我再次发送通知并成功收到通知。
  • 第2天:在第1天之后的第二天早上1点,我再次发送了通知,但从未收到。我上床睡觉了,早上仍然没有收到消息,因此我尝试再次发送消息,并且我的php脚本说已收到消息(根据Firebase控制台响应),但从未显示通知。

-注意:我还实现了“ onMessageReceived()”内部的方法来将消息保存到MySQL,以便我可以亲自监视设备是否至少收到消息以更好地了解消息的工作方式,但是设​​备从未甚至收到了。

情况2:

  • 第1天:已安装的应用程序。启动它,关闭它,然后发送Push。成功收到。 1小时后,我重启了手机。 20分钟后,我尝试发送Push,但没有收到。我尝试启动应用程序并将其置于后台,但仍然没有收到任何帮助。 我尝试不使用PHP脚本而是使用FCM Console发送一些通知,但仍然没有发送任何通知。 仅仅10分钟后,我收到了一段时间前发送的通知,但是我尝试使用PHP脚本发送通知,但仍然无法正常工作,只有再过几分钟,我才能再次使用PHP发送通知。

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

我的代码:

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"
    }
}

请在这里帮助我了解。也许我做错了什么,或者我错过了某些事情。

1 个答案:

答案 0 :(得分:0)

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