Android中Firebase Cloud Messaging通知体解析为HashMap失败
问题原因及解决方案
核心问题
你错误地使用了FCM的通知消息(Notification Message)的body字段传递结构化JSON数据,而这个字段的设计初衷是承载纯文本通知内容——哪怕后端传入的是JSON字符串,FCM也会将其作为普通文本传递,导致你拿到的body是带转义或完整格式的JSON字符串,直接解析容易失败。
要明确FCM的两种消息类型差异:
- 通知消息:由FCM SDK自动在系统通知栏展示内容,
notification字段下的title/body都是纯文本,适合直接展示的简单通知。 - 数据消息:需要开发者自行处理逻辑,
data字段支持键值对或结构化数据,是传递自定义业务参数的正确方式。
解决方案1:改用Data Message传递结构化数据(推荐)
让后端调整消息结构,将业务参数放在data字段中,示例后端发送的消息结构:
{ "data": { "title": "行程追踪", "message": "你的司机已出发", "rideId": "RD-12345", "type": "TRACK" }, "to": "目标设备Token" }
前端代码修改为直接读取data字段,无需JSON解析:
override fun onMessageReceived(message: RemoteMessage) { super.onMessageReceived(message) Log.i("FirebaseService ", "Message :: $message") val data = message.data val title = data["title"] val messageBody = data["message"] val rideId = data["rideId"] val type = data["type"] if(type == "TRACK"){ showNotification(title!!, messageBody!!) }else{ // 其他业务逻辑 } }
解决方案2:修复JSON字符串解析(仅当无法修改后端时使用)
如果后端必须将JSON放在通知body中,需要先清理字符串中的转义字符、移除外层可能存在的引号,再进行解析:
override fun onMessageReceived(message: RemoteMessage) { super.onMessageReceived(message) Log.i("FirebaseService ", "Message :: $message") val title = message.notification!!.title var body = message.notification!!.body // 清理转义字符并移除外层引号 body = body?.replace("\\\"", "\"")?.removeSurrounding("\"") // 使用TypeToken指定泛型类型,避免Gson解析时丢失类型信息 val notificationBody: HashMap<String, String> = Gson().fromJson(body, object : TypeToken<HashMap<String, String>>() {}.type) val messageBody = notificationBody["message"] val rideId = notificationBody["rideId"] if(notificationBody["type"] == "TRACK"){ showNotification(title!!, messageBody!!) }else{ // 其他业务逻辑 } }
总结
优先选择方案1,因为data字段是FCM专门为自定义业务数据设计的,能避免字符串转义、格式错误等问题,代码逻辑也更简洁。
内容的提问来源于stack exchange,提问作者Liagi
相关产品推荐
相关产品推荐

