Flutter聊天通知问题:回复时如何显示当前用户的Person信息
问题
我用Flutter开发聊天应用,集成了flutter_local_notifications和Firebase Messaging处理通知。现在用MessagingStyleNotification展示聊天通知,添加了带输入操作的回复功能,但发送回复时,Person对象仍为原通知发送者的信息。请问能否将回复的当前用户详情设置为Person对象?
调研后得知可能需要创建BroadcastReceiver和PendingIntent实现,但我从未接触过Flutter中的Android原生开发,不清楚具体实现方法,希望得到帮助。
当前表现:用户发送回复时,回复内容旁显示原发送者的图标和名称,希望改为显示当前用户的名称和图标。
现有代码
显示聊天通知的方法
void showRecievedChatNotification(RemoteMessage message, {bool fromAction = false}) async { ChatMsgNotif notifData = ChatMsgNotif.fromJson(message.data); ProfileModel senderUser = notifData.senderUser; bool isGroup = notifData.dbCollection == DBCollections.groups.name; if((isGroup && notifData.senderUser.profileId == auth.currentUser!.uid && !fromAction) || (!isGroup && notifData.senderUser.profileId == auth.currentUser!.uid) ) return; final http.Response resPerson = await http.get(Uri.parse(senderUser.profilePic)); Person person = Person( key: senderUser.profilePic, name: senderUser.name, icon: ByteArrayAndroidIcon.fromBase64String(base64Encode(resPerson.bodyBytes)), ); Message newNotifMsg = Message( notifData.body, notifData.timeSent, person ); http.Response response; if(isGroup){ response = await http.get(Uri.parse(notifData.receiverProfile.profilePic)); } else{ response = await http.get(Uri.parse(fromAction ? notifData.receiverProfile.profilePic : notifData.senderUser.profilePic)); } int convertedIdForNotif = convertedIdToIntForNotifId(isGroup ? notifData.receiverProfile.profileId : senderUser.profileId); List<Message> notifMsgs = []; final MessagingStyleInformation? activeMessageNotification = await flutterLocalNotificationsPlugin .resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>() ?.getActiveNotificationMessagingStyle(convertedIdForNotif); // 如果该群组/对话已有历史通知 if(activeMessageNotification != null && activeMessageNotification.messages != null && activeMessageNotification.messages!.isNotEmpty ){ notifMsgs = activeMessageNotification.messages!; } notifMsgs.add(newNotifMsg); flutterLocalNotificationsPlugin.show( convertedIdForNotif, null, null, NotificationDetails( android: AndroidNotificationDetails( chatNotificationChannelId, chatNotificationChannelName, channelDescription: chatNotificationChannelDesc, groupKey: isGroup? notifData.receiverProfile.profileId : notifData.senderUser.profileId, importance: Importance.max, priority: Priority.max, color: colorPrimary, largeIcon: ByteArrayAndroidBitmap.fromBase64String(base64Encode(response.bodyBytes)), autoCancel: false, styleInformation: MessagingStyleInformation( person, conversationTitle: isGroup ? notifData.receiverProfile.name : notifData.senderUser.name, groupConversation: true, messages: notifMsgs ), actions: <AndroidNotificationAction>[ // 回复操作 const AndroidNotificationAction( actionReplyToMsg, 'Reply', allowGeneratedReplies: true, inputs: <AndroidNotificationActionInput>[ AndroidNotificationActionInput( label: 'Reply', ) ] ), ], ), ), payload: jsonEncode(message.data), ); }
处理回复的方法
void handleNotificationResponse(NotificationResponse notificationResponse, WidgetRef ref){ switch (notificationResponse.notificationResponseType){ // 选择了通知操作 case NotificationResponseType.selectedNotificationAction: switch (notificationResponse.actionId) { // 点赞消息 case actionLikeMsg: break; // 回复消息 case actionReplyToMsg: String replyTxt = notificationResponse.input!; ChatMsgNotif notifData = ChatMsgNotif.fromJson(jsonDecode(notificationResponse.payload!)); // 发送到数据库 ref.read(chatsApiProvider).sendMessage( receiverProfile: notifData.dbCollection == DBCollections.groups.name ? notifData.receiverProfile : notifData.senderUser, text: replyTxt, dbCollectionName: notifData.dbCollection ); break; } break; default: break; } }
解决方案
要实现回复时显示当前用户的信息,核心是在回复后更新通知时,将当前用户作为消息发送者传入Person对象。以下是具体步骤:
步骤1:封装当前用户信息获取逻辑
确保能从本地缓存或API获取当前登录用户的ProfileModel,比如添加一个工具方法:
Future<ProfileModel> getCurrentUserProfile() async { // 实现获取当前用户信息的逻辑,比如从SharedPreferences或用户状态管理中读取 }
步骤2:修改回复处理逻辑,更新通知
在handleNotificationResponse的回复分支中,发送消息后,构造包含当前用户信息的通知数据,调用showRecievedChatNotification更新通知:
case actionReplyToMsg: String replyTxt = notificationResponse.input!; ChatMsgNotif notifData = ChatMsgNotif.fromJson(jsonDecode(notificationResponse.payload!)); // 发送消息到数据库 await ref.read(chatsApiProvider).sendMessage( receiverProfile: notifData.dbCollection == DBCollections.groups.name ? notifData.receiverProfile : notifData.senderUser, text: replyTxt, dbCollectionName: notifData.dbCollection ); // 获取当前用户信息 ProfileModel currentUser = await getCurrentUserProfile(); // 构造回复的通知数据 ChatMsgNotif replyNotifData = ChatMsgNotif( senderUser: currentUser, receiverProfile: notifData.receiverProfile, body: replyTxt, timeSent: DateTime.now().millisecondsSinceEpoch.toString(), dbCollection: notifData.dbCollection, // 补充ChatMsgNotif模型所需的其他字段 ); // 转换为RemoteMessage格式 RemoteMessage replyMessage = RemoteMessage( data: replyNotifData.toJson(), ); // 显示回复的通知,fromAction设为true跳过当前用户发送判断 await showRecievedChatNotification(replyMessage, fromAction: true); break;
步骤3:调整通知显示方法的发送者逻辑
在showRecievedChatNotification中,根据fromAction参数切换消息发送者:
// 替换原有的senderUser赋值逻辑 ProfileModel messageSender = fromAction ? await getCurrentUserProfile() : senderUser; final http.Response resPerson = await http.get(Uri.parse(messageSender.profilePic)); Person person = Person( key: messageSender.profilePic, name: messageSender.name, icon: ByteArrayAndroidIcon.fromBase64String(base64Encode(resPerson.bodyBytes)), );
同时调整大图标获取逻辑,确保单聊时始终显示对方图标:
http.Response response; if(isGroup){ response = await http.get(Uri.parse(notifData.receiverProfile.profilePic)); } else{ // 单聊场景下,无论是否是回复,都显示对方的头像 response = await http.get(Uri.parse(notifData.senderUser.profilePic)); }
(可选)后台回复支持(Android原生)
如果需要应用在后台时也能正确处理回复并更新通知,需要配置Android原生BroadcastReceiver:
- 在
android/app/src/main/kotlin/[你的包名]/下创建NotificationReplyReceiver.kt:
import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import androidx.core.app.RemoteInput import io.flutter.plugin.common.MethodChannel class NotificationReplyReceiver : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { intent ?: return val action = intent.action ?: return if (action == "REPLY_ACTION") { val input = RemoteInput.getResultsFromIntent(intent)?.getCharSequence("reply_input")?.toString() val payload = intent.getStringExtra("payload") // 通过MethodChannel将回复数据传给Flutter val channel = MethodChannel(context!!, "notification_reply") channel.invokeMethod("onReplyReceived", mapOf( "input" to input, "payload" to payload )) } } }
- 在
AndroidManifest.xml中注册Receiver:
<receiver android:name=".NotificationReplyReceiver" android:exported="false"> <intent-filter> <action android:name="REPLY_ACTION" /> </intent-filter> </receiver>
- Flutter端监听MethodChannel:
final MethodChannel _replyChannel = MethodChannel('notification_reply'); @override void initState() { super.initState(); _replyChannel.setMethodCallHandler((call) async { if (call.method == 'onReplyReceived') { String? input = call.arguments['input'] as String?; String? payload = call.arguments['payload'] as String?; if (input != null && payload != null) { // 调用回复处理逻辑 handleNotificationResponse(NotificationResponse( actionId: actionReplyToMsg, input: input, payload: payload, notificationResponseType: NotificationResponseType.selectedNotificationAction ), ref); } } }); }
- 修改通知Action的PendingIntent:
// 替换原有的AndroidNotificationAction AndroidNotificationAction( actionReplyToMsg, 'Reply', allowGeneratedReplies: true, inputs: <AndroidNotificationActionInput>[ AndroidNotificationActionInput( label: 'Reply', key: 'reply_input' // 和原生RemoteInput的key对应 ) ], intent: PendingIntent.getBroadcast( context, 0, Intent("REPLY_ACTION").putExtra("payload", jsonEncode(message.data)), PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE ) ),
内容的提问来源于stack exchange,提问作者Ali99
相关产品推荐
相关产品推荐

