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

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:

  1. 在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
            ))
        }
    }
}
  1. 在AndroidManifest.xml中注册Receiver:
<receiver android:name=".NotificationReplyReceiver" android:exported="false">
    <intent-filter>
        <action android:name="REPLY_ACTION" />
    </intent-filter>
</receiver>
  1. 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);
      }
    }
  });
}
  1. 修改通知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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 03:35:00