使用exponent-server-sdk-php推送安卓通知失败,求排查指导
Expo PHP推送通知失败问题排查
核心问题
使用exponent-server-sdk-php实现PHP后端向安卓APP用户推送通知,但推送未成功:无报错日志,首次执行生成token文件,但安卓设备未收到通知。
关键错误点
- Recipient字段填写错误:将Firebase服务器密钥填入
ExponentPushToken[]是完全错误的用法。ExponentPushToken必须是客户端(React Native/Expo APP)生成的用户设备推送令牌,而非Firebase服务器密钥。
当前代码存在的问题
- 订阅后立即取消订阅:代码中先执行
$expo->subscribe($channelName, $recipient),紧接着调用$expo->unSubscribe($channelName, $recipient),导致目标用户根本不在订阅频道内,无法收到通知。 - Notification数据格式错误:
data字段使用json_encode处理,Expo通知的data应直接传入数组,无需提前JSON编码,否则客户端解析会异常。 - 异常捕获不完整:仅捕获
ExpoException,未覆盖其他类型异常,导致部分错误无法被记录。
修复步骤与建议
1. 获取正确的Expo Push Token
在React Native/Expo客户端通过expo-notifications库生成用户设备的推送令牌,示例客户端代码:
import * as Notifications from 'expo-notifications'; async function getPushToken() { const { status } = await Notifications.requestPermissionsAsync(); if (status === 'granted') { const token = await Notifications.getExpoPushTokenAsync({ projectId: '你的Expo项目ID', }); // 将token发送到PHP后端存储(如数据库) console.log(token.data); // 格式为ExponentPushToken[xxxxxxx] } }
后端需从存储中取出所有有效的用户Push Token,而非填入Firebase服务器密钥。
2. 修复PHP代码
$response = array(); require_once __DIR__.'/exponent-server-sdk-php/vendor/autoload.php'; use ExponentPhpSDK\Expo; use ExponentPhpSDK\ExpoException; $channelName = 'video_alert'; // 从数据库获取的用户Push Token列表(示例取单个测试) $recipientTokens = [ 'ExponentPushToken[AAAAnrlyESE:APA91bHYeOkFi5MlUB9eitKn1yEuReJ1dNrRSnlMob0lcBLAjoanDaAIposGTBWQD164CGMV8F0hriJtsXuaFPdoKxEpjtrnXshoxlZQmxdlrCjP_F5TyRToNGP43YqwahCd6XYhKvwX]' ]; $expo = Expo::normalSetup(); // 批量订阅用户到频道(按需使用) foreach ($recipientTokens as $token) { $expo->subscribe($channelName, $token); } // 构建正确格式的通知数据 $notification = [ 'title' => 'Watch Movies', 'body' => 'Catch new latest movie ('.$movie_title.') on DooBuxx Movies today!', 'data' => ['notification_type' => 'service_requested'] ]; try { // 通知频道内的所有订阅用户 $expo->notify([$channelName], $notification); $response["message"] = "通知已发送"; } catch (ExpoException $e) { $response["message"] = "Expo错误:".$e->getMessage(); } catch (\Exception $e) { $response["message"] = "系统错误:".$e->getMessage(); } // 按需取消订阅(如不需要长期保留频道订阅) // foreach ($recipientTokens as $token) { // $expo->unSubscribe($channelName, $token); // }
3. 额外排查项
- 确认Expo项目已正确配置Firebase安卓凭据:在Expo控制台项目设置中,填入
google-services.json相关信息。 - 单Token测试:先用单个有效客户端Token调用
$expo->notify($singleToken, $notification),排除频道订阅逻辑问题。 - 服务器网络检查:确保PHP服务器可访问Expo推送API(https://exp.host/--/api/v2/push/send),无防火墙或代理限制。
- 查看Expo推送记录:在Expo控制台的「Notifications」面板,查看推送状态及失败原因。
内容的提问来源于stack exchange,提问作者Tosin Seyi
相关产品推荐
相关产品推荐

