You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FCM API问题:无法接收PHP服务器发送的通知

问题排查与解决方案

1. JavaScript参数传递错误

你的send_notification函数定义了3个参数(empno,charge,op),但调用时只传了2个参数:

await send_notification("Hi Leo","This is a test notification");

这会导致第三个参数op为undefined,最终AJAX发送的body字段值为空。PHP接收后,$_POST["body"]不存在,发送的通知内容为空,甚至可能触发Firebase消息发送异常。

修正方法:调整函数参数与调用逻辑匹配:

// 修改函数参数为2个,对应标题和内容
function send_notification(title, body){
    return $.ajax({
        url: '/notification_server/firebase_server.php',
        type: 'POST',
        data:{
              "employee": title,
              "body": body
        },
        cache: false
    })
}

// 调用时传递正确参数
(async() => {
    await send_notification("Hi Leo","This is a test notification");
})();

2. PHP端未捕获异常,无法定位发送失败原因

当前PHP代码没有捕获$messaging->send($message)可能抛出的异常,比如设备令牌无效、权限不足、服务配置错误等问题,即使发送失败也无法获取错误信息。

修正方法:添加异常捕获逻辑,输出错误详情:

<?php
require __DIR__.'/vendor/autoload.php';

use Kreait\Firebase\Factory;
use Kreait\Firebase\Messaging\CloudMessage;
use Kreait\Firebase\Exception\MessagingException;

try {
    $factory = (new Factory)
               ->withServiceAccount('admin.json')
               ->withDatabaseUri("https://nfr-qtr-electric-billing-default-rtdb.firebaseio.com");
    $deviceToken = '.....'; // 确保此处为当前设备的有效令牌
    $messaging = $factory->createMessaging();
    $message = CloudMessage::withTarget('token', $deviceToken)
               ->withNotification(['title' => $_POST["employee"], 'body' => $_POST["body"]]);

    $messaging->send($message);
    echo "消息发送成功";
} catch (MessagingException $e) {
    echo "发送失败:" . $e->getMessage();
} catch (\Exception $e) {
    echo "未知错误:" . $e->getMessage();
}
?>

执行AJAX请求后查看响应内容,即可明确Firebase消息发送状态。

3. Android端Firebase Messaging服务未注册

如果MyFirebaseMessagingService未在AndroidManifest.xml中注册,系统无法将消息传递到该服务,自然不会触发onMessageReceived方法。

需在Manifest的<application>标签内添加注册代码:

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

4. 设备令牌有效性问题

确保PHP中填写的$deviceToken是当前测试设备的有效令牌:

  • 在MyFirebaseMessagingService的onNewToken方法中打印令牌,或保存到本地/服务器,确保使用最新令牌;
  • 若令牌过期或无效,Firebase会返回发送失败,通过PHP的异常捕获可查看对应错误信息。

5. Android 8.0+通知渠道缺失

Android 8.0(API 26)及以上版本必须配置通知渠道,否则通知无法显示。你的代码未创建渠道,需补充逻辑:

修改sendLocalNotification方法:

private void sendLocalNotification(String notificationTitle, String notificationBody) {
    // 创建通知渠道(适配Android 8.0+)
    String channelId = "default_notification_channel";
    String channelName = "默认通知";
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_DEFAULT);
        NotificationManager notificationManager = getSystemService(NotificationManager.class);
        notificationManager.createNotificationChannel(channel);
    }

    Intent intent = new Intent(this, record_viewer.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    // 适配Android 12+,添加FLAG_IMMUTABLE
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,
            PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE);

    Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
    // 创建通知时指定渠道ID
    NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelId)
            .setAutoCancel(true)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentIntent(pendingIntent)
            .setContentTitle(notificationTitle)
            .setContentText(notificationBody)
            .setSound(defaultSoundUri);

    NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    notificationManager.notify(1234, notificationBuilder.build());
}

内容的提问来源于stack exchange,提问作者user20307020

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 23:15:55