I'm developing an app where I need a custom sound to play whenever I receive a notification in foreground and background. It works fine in the foreground but on the background, it plays the default sound from the device.
I'm using a physical phone to test the app Realme GT (RMX2202). I already tried in the emulator as well and the same happens
I am using the package flutter_local_notifications
Could I be missing something? I've checked multiples tutorials and people with the same problem, but none of them solves my issue.
This is my code:
WidgetsFlutterBinding.ensureInitialized();
RemoteMessage? initialMessage = newLogged == true
? await FirebaseMessaging.instance.getInitialMessage()
: null;
void initMessaging() async {
final token = await FirebaseMessaging.instance.getToken();
log(DateTime.now().toString() +
' ' +
' ------------ FIREBASE TOKEN -----> $token ');
firebaseToken = token.toString();
FirebaseMessaging messaging = FirebaseMessaging.instance;
late FlutterLocalNotificationsPlugin fltNotification;
var androiInit = AndroidInitializationSettings("@mipmap/ic_launcher");
var iosInit = DarwinInitializationSettings();
var initSetting = InitializationSettings(android: androiInit, iOS: iosInit);
fltNotification = FlutterLocalNotificationsPlugin();
fltNotification.initialize(initSetting);
var androidDetails = AndroidNotificationDetails(
'id',
'name',
channelDescription: 'description',
importance: Importance.max,
priority: Priority.high,
playSound: true,
ticker: 'ticker',
icon: ('@mipmap/ic_launcher'),
sound: RawResourceAndroidNotificationSound('newservice'),
// sound: UriAndroidNotificationSound("assets/sounds/classic.mp3"),
);
var iosDetails = DarwinNotificationDetails();
var generalNotificationDetails =
NotificationDetails(android: androidDetails, iOS: iosDetails);
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
RemoteNotification? notification = message.notification;
AndroidNotification? android = message.notification?.android;
if (notification != null && android != null) {
fltNotification.show(notification.hashCode, notification.title,
notification.body, generalNotificationDetails);
}
});
}
Android Manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mkis.gb24">
<application
android:label="new GB24"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- 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"
/>
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@mipmap/ic_launcher"
/>
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="default_notification_channel_id" />
<intent-filter>
<action android:name="FLUTTER_NOTIFICATION_CLICK" />
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>
Solved it by forcing the name of the channel.id, channel.name and channel.description to be all the same.
So basically changed this:
NotificationDetails(
android: AndroidNotificationDetails(
channel.id,
channel.name,
channel.description,
icon: android?.smallIcon,
),
));
To this
NotificationDetails(
android: AndroidNotificationDetails(
'MyID',
'MyName',
description: 'MyDescription',
icon: android?.smallIcon,
),
));
And added this:
await Firebase.initializeApp();
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
log('Handling a background message ${message.messageId}');
log('${message.data}');
flutterLocalNotificationsPlugin.show(
message.data.hashCode,
message.data['title'],
message.data['body'],
NotificationDetails(
android: AndroidNotificationDetails(
'MyID',
'MyName',
channelDescription: 'MyDescription',
importance: Importance.max,
priority: Priority.high,
playSound: true,
ticker: 'ticker',
icon: ('@mipmap/ic_launcher'),
sound: RawResourceAndroidNotificationSound('mySound'),
// sound: UriAndroidNotificationSound("assets/sounds/classic.mp3"),
),
),
);
}
EDIT: It's also important to mention that when using firebase, the notification channel has to be specified when sending a notification along with the click_action
.
And finally, in AndroidManifest.xml:
<meta-data
android:name=
"com.google.firebase.messaging.default_notification_channel_id"
android:value=
"default_channel_id"
/>
Because if the channel is not specified, Android will use the Miscellaneous channel instead and use the device's default notification sound.