When received it show reply button by tapping on it, it shows the textfield and a button after inputing data and press the button it send the message button the button keeps on loading infinitely and text still remain in the textfield.
I tried adding below code in projects manifest it did allow to send perform the action but but keeps the state same
Androidmanifest.xml
<manifest xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<application
android:label="notiication_reply"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:taskAffinity=""
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize"
tools:targetApi="honeycomb"
>
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<receiver android:name=".NotificationReceiver"/>
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<!-- Add these lines -->
<service
android:name="com.google.firebase.messaging.FirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
<service
android:name="com.dexterous.flutterlocalnotifications.ForegroundService"
android:enabled="true"
android:exported="true"/>
<!--this is for action button to speen form
-->
<receiver
android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ActionBroadcastReceiver" />
</application>
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT"/>
<data android:mimeType="text/plain"/>
</intent>
</queries>
</manifest>
Main.dat
import 'dart:convert';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:get/get.dart';
import 'package:notiication_reply/chat/chat_screen.dart';
import 'package:notiication_reply/fcm/fcm_notification.dart';
import 'package:notiication_reply/firebase_options.dart';
import 'package:notiication_reply/my_app.dart';
// Global notification plugin instance
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
// Function to handle background messages
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
if (Firebase.apps.isEmpty) {
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
}
// Ensure only your custom notification is shown
if (message.data.isNotEmpty) {
_showLocalNotification(message);
}
// Handle the background message here
debugPrint('Handling a background message: ${message.messageId}');
}
int id = 0;
/// A notification action which triggers a reply action
// const String replyActionId = 'reply_action';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
// Initialize local notifications
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('@mipmap/ic_launcher');
const InitializationSettings initializationSettings = InitializationSettings(
android: initializationSettingsAndroid,
);
await flutterLocalNotificationsPlugin.initialize(
initializationSettings,
onDidReceiveNotificationResponse: forNotification,
onDidReceiveBackgroundNotificationResponse: forNotification,
);
// Request notification permissions
await FirebaseMessaging.instance.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
// Set background message handler
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
debugPrint('Foreground message received: ${message.messageId}');
debugPrint('Foreground message received: ${message.data}');
// if (message.notification != null) {
_showLocalNotification(message);
// }
});
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
debugPrint('Message opened: ${message.data}');
debugPrint('Notification opened from background: ${message.data}');
var payload = message.data;
if (payload.isNotEmpty) {
handlePayloadAction(payload);
}
});
runApp(MyApp());
}
// Function to show local notification
Future<void> _showLocalNotification(RemoteMessage message) async {
const AndroidNotificationDetails androidPlatformChannelSpecifics =
AndroidNotificationDetails(
'your_channel_id', // Make sure this matches the channel ID
'your_channel_name',
channelDescription: 'your_channel_description',
importance: Importance.max,
priority: Priority.high,
showWhen: false,
onlyAlertOnce: true,
enableLights: true,
enableVibration: true,
ongoing: false,
autoCancel: true,
actions: <AndroidNotificationAction>[
AndroidNotificationAction(
'text_id_1',
'Reply',
cancelNotification: false,
inputs: <AndroidNotificationActionInput>[
AndroidNotificationActionInput(
label: 'Type your reply',
allowFreeFormInput: true,
),
],
),
],
);
const NotificationDetails notificationDetails = NotificationDetails(
android: androidPlatformChannelSpecifics,
);
// debugPrint("Message title: ${message.notification!.title}");
// Update notification to clear input and stop spinner
flutterLocalNotificationsPlugin.cancel(id++);
debugPrint("Message data: ${message.data}");
await flutterLocalNotificationsPlugin.show(
id++,
message.data['title'] ?? 'New Message',
message.data['body'] ?? 'You have a new message',
notificationDetails,
payload: jsonEncode(message.data), // Ensure this is set properly
);
}
Future<void> forNotification(NotificationResponse notificationResponse) async {
if (Firebase.apps.isEmpty) {
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
}
debugPrint(
'Notification tapped with actionId: ${notificationResponse.actionId}');
debugPrint('Notification payload: ${notificationResponse.payload}');
if (notificationResponse.payload != null) {
var payload = jsonDecode(notificationResponse.payload!);
// Check if action is a reply action
if (notificationResponse.actionId == 'text_id_1') {
final String? userReply = notificationResponse.input;
debugPrint("User replied with: $userReply");
debugPrint("User replied with: ${notificationResponse.payload!}");
if (userReply != null) {
sendMessage(
userReply,
payload['senderId'],
payload['receiverName'],
payload['senderName'],
payload['current_user_fcm_token'],
);
} else {
debugPrint("No reply input found.");
}
} else {
// Handle other notification tap actions
handlePayloadAction(payload);
}
}
}
void handlePayloadAction(Map<String, dynamic> payload) {
debugPrint('Handling payload action: ${payload['senderName']}');
Get.to(ChatScreen(
userId: payload['senderId'],
userName: payload['senderName'],
targetToken: payload['current_user_fcm_token'],
currentUserName: payload['receiverName'],
));
}