使用Smack库连接FCM XMPP端点时遇'Content is not allowed in prolog'错误
解决Firebase XMPP端点连接的XML解析错误
问题场景
使用Java Smack库连接Firebase XMPP端点接收上行消息时,触发XML解析错误:Content is not allowed in prolog,相关代码、错误日志及依赖配置如下:
原连接代码
private static final String fcmServer = "fcm-xmpp.googleapis.com"; private static final int fcmPort = 5236; private static final String fcmSenderId = "101010101010@fcm-xmpp.googleapis.com"; private static final String fcmApiKey = "XYZ"; private XMPPTCPConnectionConfiguration configuration; private XMPPTCPConnection connection; public XmppClientModule() { try { configuration = XMPPTCPConnectionConfiguration.builder() .setUsernameAndPassword(fcmSenderId, fcmApiKey) .setXmppDomain("PROJECT_ID.fcm-xmpp.googleapis.com") .setHost(fcmServer) .setPort(fcmPort) .setSecurityMode(ConnectionConfiguration.SecurityMode.ifpossible) .build(); }catch (Exception e){ System.out.println("Error handling"); } connection = new XMPPTCPConnection(configuration); } public void run() { try { connection.connect(); connection.login(); System.out.println("Connected successfully"); } catch (SmackException | IOException | XMPPException | InterruptedException e) { e.printStackTrace(); } }
错误日志
org.jivesoftware.smack.SmackException$SmackWrappedException: org.jivesoftware.smack.xml.XmlPullParserException: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[1,1] Message: Content is not allowed in prolog. at org.jivesoftware.smack.AbstractXMPPConnection.setCurrentConnectionExceptionAndNotify(AbstractXMPPConnection.java:687) at org.jivesoftware.smack.AbstractXMPPConnection.notifyConnectionError(AbstractXMPPConnection.java:987) at org.jivesoftware.smack.tcp.XMPPTCPConnection.access$4100(XMPPTCPConnection.java:131) at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPConnection.java:1167) at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$700(XMPPTCPConnection.java:916) at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnection.java:939) at java.base/java.lang.Thread.run(Thread.java:833) Caused by: org.jivesoftware.smack.xml.XmlPullParserException: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[1,1] Caused by: org.jivesoftware.smack.xml.XmlPullParserException: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[1,1] Message: Content is not allowed in prolog. at org.jivesoftware.smack.xml.stax.StaxXmlPullParser.next(StaxXmlPullParser.java:193) at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPConnection.java:1143) ... 3 more Caused by: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[1,1] Caused by: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[1,1] Message: Content is not allowed in prolog. at java.xml/com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl.next(XMLStreamReaderImpl.java:652) at org.jivesoftware.smack.xml.stax.StaxXmlPullParser.next(StaxXmlPullParser.java:191) ... 4 more
原依赖配置
dependencies { testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.2' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.2' implementation 'org.igniterealtime.smack:smack-core:4.4.6' implementation 'org.igniterealtime.smack:smack-tcp:4.4.6' implementation 'org.igniterealtime.smack:smack-extensions:4.4.6' implementation 'org.igniterealtime.smack:smack-xmlparser-stax:4.4.6' implementation 'org.igniterealtime.smack:smack-resolver-dnsjava:4.4.6' }
问题原因及修复方案
这个错误的核心是连接未强制启用TLS加密:Firebase XMPP端点要求必须使用TLS加密,原代码使用SecurityMode.ifpossible可能未触发加密流程,导致服务器返回非XML格式内容,触发解析错误。同时存在两处配置错误:
- 修正XMPP Domain:Firebase XMPP的Domain是固定值
fcm-xmpp.googleapis.com,无需拼接项目ID - 修正Sender ID格式:Sender ID只需填写纯数字的项目编号,不需要添加
@fcm-xmpp.googleapis.com后缀 - 强制启用TLS:将安全模式改为
SecurityMode.required,确保连接必须加密 - 调整登录方式:Firebase XMPP无需常规
login(),使用loginAnonymously()即可,API Key已作为密码完成身份验证
修复后的连接代码
private static final String fcmServer = "fcm-xmpp.googleapis.com"; private static final int fcmPort = 5236; // 仅保留纯数字Sender ID private static final String fcmSenderId = "101010101010"; private static final String fcmApiKey = "XYZ"; private XMPPTCPConnectionConfiguration configuration; private XMPPTCPConnection connection; public XmppClientModule() { try { configuration = XMPPTCPConnectionConfiguration.builder() .setUsernameAndPassword(fcmSenderId, fcmApiKey) // 修正XMPP Domain .setXmppDomain("fcm-xmpp.googleapis.com") .setHost(fcmServer) .setPort(fcmPort) // 强制启用TLS .setSecurityMode(ConnectionConfiguration.SecurityMode.required) // 启用压缩提升传输效率 .setCompressionEnabled(true) .build(); } catch (Exception e) { e.printStackTrace(); } connection = new XMPPTCPConnection(configuration); } public void run() { try { connection.connect(); // 使用匿名登录完成身份验证 connection.loginAnonymously(); System.out.println("Connected successfully"); } catch (SmackException | IOException | XMPPException | InterruptedException e) { e.printStackTrace(); } }
额外说明
- 依赖配置无需修改,Smack 4.4.6版本完全兼容Firebase XMPP端点,不需要切换XML解析器
内容的提问来源于stack exchange,提问作者Dominik Kerestes
相关产品推荐
相关产品推荐

