I have updated my flutter project to the new firebase versions.
And I have encountered the following problem.
The method 'configure' isn't defined for the class 'FirebaseMessaging'.
FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance;
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
...
},
onResume: (Map<String, dynamic> message) async {
...
},
onLaunch: (Map<String, dynamic> message) async {
...
},
);
How would you do with the new version?
Its old now : you can use this as per your requirement.
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
});
check this link : https://firebase.flutter.dev/docs/messaging/usage/
Related
I am new in Flutter. I have tried to developed Model class in dart. but always show the error message
Exception:type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'String', tt:#0 new User.fromJson
I don't understand, where my code will error. I want to solutions.
I want to convert model class in dart.
[
{
"route": {
"routeID": "aaaaaaaa",
"routeTitle": "bbbbbbbb"
},
"distributor": {
"distributorID": "cccccccccccc",
"distributorName": "ddddddddddd"
},
"visitDate": null
}
]
I have been tried to my source code. like below code
import 'dart:convert';
List<User> userFromJson(String str) =>
List<User>.from(json.decode(str).map((x) => User.fromJson(x)));
String userToJson(List<User> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class User {
User({
this.visitDate,
this.route,
this.distributor,
});
String visitDate;
String route;
String distributor;
factory User.fromJson(Map<String, dynamic> json) => User(
visitDate: json["visitDate"],
route: json["route"],
distributor: json["distributor"],
);
Map<String, dynamic> toJson() => {
"visitDate": visitDate,
"route": route,
"distributor": distributor,
};
}
Route RouteFromJson(String str) => Route.fromJson(json.decode(str));
String RouteToJson(Route data) => json.encode(data.toJson());
class Route {
Route({
this.routeID,
this.routeTitle,
});
String routeID;
String routeTitle;
factory Route.fromJson(Map<String, dynamic> json) => Route(
routeID: json["routeID"],
routeTitle: json["routeTitle"],
);
Map<String, dynamic> toJson() => {
"routeID": routeID,
"routeTitle": routeTitle,
};
}
Distributor DistributorFromJson(String str) => Distributor.fromJson(json.decode(str));
String DistributorToJson(Distributor data) => json.encode(data.toJson());
class Distributor {
Distributor({
this.distributorID,
this.distributorName,
});
String distributorID;
String distributorName;
factory Distributor.fromJson(Map<String, dynamic> json) => Distributor(
distributorID: json["distributorID"],
distributorName: json["distributorName"],
);
Map<String, dynamic> toJson() => {
"distributorID": distributorID,
"distributorName": distributorName,
};
}
how to correct my model class. please help me. thanks
Change your User class like this :
class User {
User({
this.visitDate,
this.route,
this.distributor,
});
String visitDate;
Route route;
Distributor distributor;
factory User.fromJson(Map<String, dynamic> json) => User(
visitDate: json["visitDate"],
route = json['route'] != null ? Route.fromJson(json['route']) : null;
distributor = json['distributor'] != null
? Distributor.fromJson(json['distributor'])
: null;
);
Map<String, dynamic> toJson() => {
"visitDate": visitDate,
if (route != null) {
data['route'] = this.route.toJson();
}
if (distributor != null) {
data['distributor'] = this.distributor.toJson();
}
};
}
You can also check out the json_serializable package for that.
This way, you don't have to write this code yourself.
https://pub.dev/packages/json_serializable
Flutter Box.!
You just need to do simple job is to visit following website. And need to put your response or map/list that you want to convert in model class and rest will be done by server.
By the way,
For your List<Map<String, dynamic> data's model class is,
// To parse this JSON data, do
//
// final routeModelClass = routeModelClassFromJson(jsonString);
import 'dart:convert';
List<RouteModelClass> routeModelClassFromJson(String str) => List<RouteModelClass>.from(json.decode(str).map((x) => RouteModelClass.fromJson(x)));
String routeModelClassToJson(List<RouteModelClass> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class RouteModelClass {
RouteModelClass({
this.route,
this.distributor,
this.visitDate,
});
Route route;
Distributor distributor;
dynamic visitDate;
factory RouteModelClass.fromJson(Map<String, dynamic> json) => RouteModelClass(
route: Route.fromJson(json["route"]),
distributor: Distributor.fromJson(json["distributor"]),
visitDate: json["visitDate"],
);
Map<String, dynamic> toJson() => {
"route": route.toJson(),
"distributor": distributor.toJson(),
"visitDate": visitDate,
};
}
class Distributor {
Distributor({
this.distributorId,
this.distributorName,
});
String distributorId;
String distributorName;
factory Distributor.fromJson(Map<String, dynamic> json) => Distributor(
distributorId: json["distributorID"],
distributorName: json["distributorName"],
);
Map<String, dynamic> toJson() => {
"distributorID": distributorId,
"distributorName": distributorName,
};
}
class Route {
Route({
this.routeId,
this.routeTitle,
});
String routeId;
String routeTitle;
factory Route.fromJson(Map<String, dynamic> json) => Route(
routeId: json["routeID"],
routeTitle: json["routeTitle"],
);
Map<String, dynamic> toJson() => {
"routeID": routeId,
"routeTitle": routeTitle,
};
}
List/Map to Model class
I am using FCM service in my flutter app for push notification. onMessage and onResume are working, the problem is when I remove my app from the recent apps list. I successfully get a push notification when my app is killed but the problem is when I click on it I am not getting the access of the data payload in my flutter code. callerInfo is not being set.
Notifications are not getting delivered when the app is swiped from the background(kill mode).
JSON file
{
"notification": {
"title": "bla bla",
"body" : "bla bla",
"icon":"incoming_call",
"color": "#008080",
"click_action":"FLUTTER_NOTIFICATION_CLICK",
"tag" : "call"
},
"data": {
"caller":"caller1",
"image":"
},
"to":"#token",
"android":{
"priority":"high"
}
}
flutter config code in the initState() {}
_configureFireBaseListeners(){
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async{
//_setMessage(message);
print("onMessage: $message");
},
onLaunch: (Map<String, dynamic> message) async{
//_setMessage(message);
print("onLaunch: $message");
setState((){
_isCall=message['data']['status'];
callerInfo = message['data'];
});
},
onResume: (Map<String, dynamic> message) async{
//_setMessage(message);
print("onResume: $message");
setState((){
_isCall=message['data']['status'];
callerInfo = message['data'];
});
},
);
}
Following instructions on https://pub.dev/packages/firebase_messaging, I have implemented FCM. Although I have set click_action: FLUTTER_NOTIFICATION_CLICK, when I click on the notification tray item, it does not open the app. The data received by the flutter app from the cloud function is as follows. How do I at least open the app upon notification click?
onMessage: {notification: {title: pi, body: text message.},
data: {USER_NAME: pi, click_action: FLUTTER_NOTIFICATION_CLICK, }}
Cloud function payload
const payload = {
notification: {
title: sender,
body: content,
clickAction: 'ChatActivity',
},
data: {
"click_action": 'FLUTTER_NOTIFICATION_CLICK',
"USER_NAME": sender,
}
};
I have also created the notification channels and AndroidManifest has been correctly configured.
private void createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = getString(R.string.app_name);
String description = getString(R.string.notification_channel_description);
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel channel = new NotificationChannel(getString(R.string.default_notification_channel_id), name, importance);
channel.setDescription(description);
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
I have put the click action to the notification json and it works for me.
notification: {
title: sender,
body: content,
click_action: 'FLUTTER_NOTIFICATION_CLICK'
}
The click action is only required for onResume and onLaunch callbacks, so be sure to implement it as stated in the pub.dev doc:
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
print("onMessage: $message");
_showItemDialog(message);
},
onBackgroundMessage: myBackgroundMessageHandler,
onLaunch: (Map<String, dynamic> message) async {
print("onLaunch: $message");
_navigateToItemDetail(message);
},
onResume: (Map<String, dynamic> message) async {
print("onResume: $message");
_navigateToItemDetail(message);
},
);
I need to show firebase notifications when the app is on foreground by using local notification but it is not working.
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin=new FlutterLocalNotificationsPlugin();
static FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
static StreamController<Map<String, dynamic>> _onMessageStreamController =
StreamController.broadcast();
static StreamController<Map<String, dynamic>> _streamController =
StreamController.broadcast();
static final Stream<Map<String, dynamic>> onFcmMessage =
_streamController.stream;
#override
void initState() {
super.initState();
var android=AndroidInitializationSettings('mipmap/ic_launcher.png');
var ios=IOSInitializationSettings();
var platform=new InitializationSettings(android,ios);
flutterLocalNotificationsPlugin.initialize(platform);
firebaseCloudMessaging_Listeners();
}
Here is the Firebase Code
void firebaseCloudMessaging_Listeners() {
if (Platform.isIOS) iOS_Permission();
_firebaseMessaging.getToken().then((token) {
print("FCM TOKEN--" + token);
});
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
print('on message $message');
showNotification(message);
},
onResume: (Map<String, dynamic> message) async {
print('on resume $message');
},
onLaunch: (Map<String, dynamic> message) async {
print('on launch $message');
},
);
}
This is showNotification method
void showNotification(Map<String, dynamic> msg) async{
print(msg);
var android = new AndroidNotificationDetails(
'my_package', 'my_organization', 'notification_channel', importance: Importance.Max, priority: Priority.High);
var iOS = new IOSNotificationDetails();
var platform=new NotificationDetails(android, iOS);
await flutterLocalNotificationsPlugin.show(
0,'My title', 'This is my custom Notification', platform,);
}
and Firebase Response
{notification: {title: Test Title, body: Test Notification Text}, data: {orderid: 2, click_action: FLUTTER_NOTIFICATION_CLICK, order name: farhana}}
You can find the answer in FlutterFire documentation
https://firebase.flutter.dev/docs/migration/#messaging
You just add to your code the following line
FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(alert: true, badge: true, sound: true);
There is an active issue logged on GitHub repository for the package regarding the same. Firebase messaging and local notifications won't work together on iOS since you can register only a single delegate for notifications.
Check out: https://github.com/MaikuB/flutter_local_notifications/issues/111
There's also an active flutter issue for the same:
https://github.com/flutter/flutter/issues/22099
Problem:
See the Push Notification while application is in foreground.
Solution:
I was using firebase_message plugin and I was able to see the Push Notification while application is in foreground by making these few changes in my flutter project's iOS AppDelegate.swift file in flutter project.
import UIKit
import Flutter
import UserNotifications
#UIApplicationMain
#objc class AppDelegate: FlutterAppDelegate, UNUserNotificationCenterDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
// set the delegate in didFinishLaunchingWithOptions
UNUserNotificationCenter.current().delegate = self
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
// This method will be called when app received push notifications in foreground
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void)
{
completionHandler([.alert, .badge, .sound])
}
}
Note:
This also works while using with flutter_local_notification plugin but with an issue that onSelectNotification is not working due to changes done above.
For not receiving the notification in foreground make sure the android drawable file contains the launcher_icon or the icon which you have set in shownotification function.
I also couldn't get firebase notifications with flutter_local_notifications working on iOS in foreground. Background notifications worked fine. Problem was that firebase notification data is different on iOS. Notification data is not ["notification"]["title"] as in android but ["aps"]["alert"]["title"].
I am using firebase console to send the notification to my android device, it's working fine when the app is in background or foreground state. But it's not receiving the notification in killed state since m not attaching any data it should not be a data notification.
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
MessageDialog messageDialog = new MessageDialog();
messageDialog.information(context, "Notification");
print('on message $message');
},
onResume: (Map<String, dynamic> message) async {
print('on resume $message');
},
onLaunch: (Map<String, dynamic> message) async {
print('on launch $message');
},
);
For receiving notification when an app is in background you can use onBackgroundMessage
firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) {
print('on message $message');
handleNotification(message);
return;
},
onBackgroundMessage: fcmBackgroundMessageHandler,
onResume: (Map<String, dynamic> message) {
print('$fcmTag on resume $message');
return;
},
onLaunch: (Map<String, dynamic> message) {
print('$fcmTag on launch $message');
return;
},
);
Here is the fcmBackgroundMessageHandler
static Future<dynamic> fcmBackgroundMessageHandler(Map<String, dynamic> message) {
if (message.containsKey('data')) {
// Handle data message
final dynamic data = message['data'];
//handleNotification(message);
}
if (message.containsKey('notification')) {
// Handle notification message
final dynamic notification = message['notification'];
} }
Note: I am still finding a solution to receive a solution when the app is in Kill state. I will update answer once get the solution