I want to change the notification sound with the local notification package in flutter, it works fine on the android side but there is a problem on the iOS side
no problem when i send this body to this link https://fcm.googleapis.com/fcm/send with postman i can hear the notification sound I want
{
"to" : "My device Id",
"notification" : {
"title" : "Sound test",
"body" : "Sound body",
"sound" : "sound.wav"
}
}
but when I want to get this sound in all notifications, the notification comes but I don't hear any sound. This is my complete code
class NotificationServices {
CustomerViewModel customerViewModel = CustomerViewModel();
//initialising firebase message plugin
FirebaseMessaging messaging = FirebaseMessaging.instance;
//initialising firebase message plugin
final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
//function to initialise flutter local notification plugin to show notifications for android when app is active
void initLocalNotifications(
BuildContext context, RemoteMessage message) async {
var androidInitializationSettings =
const AndroidInitializationSettings('@drawable/ic_launcher');
var iosInitializationSettings = const DarwinInitializationSettings(
requestAlertPermission: true,
requestBadgePermission: true,
requestSoundPermission: true,
);
var initializationSetting = InitializationSettings(
android: androidInitializationSettings, iOS: iosInitializationSettings);
await _flutterLocalNotificationsPlugin.initialize(initializationSetting,
onDidReceiveNotificationResponse: (payload) {
// handle interaction when app is active for android
handleMessage(context, message);
});
}
void firebaseInit(BuildContext context) {
FirebaseMessaging.onMessage.listen((message) {
RemoteNotification? notification = message.notification;
AndroidNotification? android = message.notification!.android;
if (kDebugMode) {
print("notifications title:${notification!.title}");
print("notifications body:${notification.body}");
print('count:${android!.count}');
print('data:${message.data.toString()}');
}
if (Platform.isIOS) {
forgroundMessage();
}
if (Platform.isAndroid) {
initLocalNotifications(context, message);
showNotification(message);
}
});
}
void requestNotificationPermission() async {
NotificationSettings settings = await messaging.requestPermission(
alert: true,
announcement: true,
badge: true,
carPlay: true,
criticalAlert: true,
provisional: false,
sound: true,
);
if (settings.authorizationStatus == AuthorizationStatus.authorized) {
if (kDebugMode) {
print('user granted permission');
}
} else if (settings.authorizationStatus ==
AuthorizationStatus.provisional) {
if (kDebugMode) {
print('user granted provisional permission');
}
} else {
if (kDebugMode) {
print('user denied permission');
}
}
}
// function to show visible notification when app is active
Future<void> showNotification(RemoteMessage message) async {
AndroidNotificationChannel channel = AndroidNotificationChannel(
message.notification!.android!.channelId.toString(),
message.notification!.android!.channelId.toString(),
importance: Importance.max,
showBadge: true,
playSound: true,
sound: const RawResourceAndroidNotificationSound('notification'));
AndroidNotificationDetails androidNotificationDetails =
AndroidNotificationDetails(
'bana_lazimsin_channel', 'High Importance Notifications',
channelDescription:
'This channel is used for important notifications',
importance: Importance.high,
priority: Priority.high,
playSound: true,
ticker: 'ticker',
icon: '@drawable/ic_launcher',
color: const Color.fromARGB(255, 255, 15, 123),
sound: channel.sound);
DarwinNotificationDetails darwinNotificationDetails =
const DarwinNotificationDetails(sound: 'notification.wav'
// presentAlert: true,
// presentBadge: true,
// presentSound: true,
);
NotificationDetails notificationDetails = NotificationDetails(
android: androidNotificationDetails, iOS: darwinNotificationDetails);
Future.delayed(Duration.zero, () {
_flutterLocalNotificationsPlugin.show(
0,
message.notification!.title.toString(),
message.notification!.body.toString(),
notificationDetails,
);
});
}
//function to get device token on which we will send the notifications
Future<String> getDeviceToken() async {
String? token = await messaging.getToken();
return token!;
}
void isTokenRefresh() async {
messaging.onTokenRefresh.listen((event) {
event.toString();
if (kDebugMode) {
print('refresh');
}
});
}
//handle tap on notification when app is in background or terminated
Future<void> setupInteractMessage(BuildContext context) async {
// when app is terminated
RemoteMessage? initialMessage =
await FirebaseMessaging.instance.getInitialMessage();
if (initialMessage != null) {
handleMessage(context, initialMessage);
}
//when app ins background
FirebaseMessaging.onMessageOpenedApp.listen((event) {
handleMessage(context, event);
});
}
void handleMessage(BuildContext context, RemoteMessage message) async {
if (message.data['type'] == 'message') {
String customerId = message.data['customerId'];
Customer? customer =
await customerViewModel.fetchOtherCustomer(customerId);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ChatPage(customer: customer!)));
} else if (message.data['type'] == 'Job') {
String jobId = message.data['itemId'];
int parsedJobId = int.parse(jobId);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => UserJobDetailPage(
jobId: parsedJobId,
)));
} else if (message.data['type'] == 'JobOffer') {
String jobId = message.data['itemId'];
int parsedJobId = int.parse(jobId);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => JobOfferDetailPage(
jobId: parsedJobId,
isActive: true,
)));
} else if (message.data['type'] == 'NewJob') {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const MainPage(
isBidder: true,
),
));
} else {}
}
Future forgroundMessage() async {
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
}
}
If (Platform.isIOS) { in firebaseInit function
forgroundMessage();
}
part I think it only runs the forgroundMessage part without running other functions related to iOS and finishes
and my main.dart file
@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
}
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
SystemChrome.setSystemUIOverlayStyle(
const SystemUiOverlayStyle(statusBarColor: Colors.transparent));
runApp(const MyApp());
}
and the part where I call them in initState on the main_page of my application
@override
void initState() {
loginViewModel = Provider.of<LoginViewModel>(context, listen: false);
notificationServices.requestNotificationPermission();
notificationServices.forgroundMessage();
notificationServices.firebaseInit(context);
notificationServices.setupInteractMessage(context);
notificationServices.isTokenRefresh();
notificationServices.getDeviceToken().then((value) {
if (kDebugMode) {
print('device token');
print(value);
}
});
upBody = widget.isBidder ? const HomePageForBidder() : const HomePage();
for (var tab in tabIconsList) {
tab.isSelected = false;
}
tabIconsList[0].isSelected = true;
animationController = AnimationController(
duration: const Duration(milliseconds: 600), vsync: this);
super.initState();
}
Let make sure you saved notification.wav in the root folder of Runner.xcworkspace