Android flatter-FCM:如何将背景消息存储到SQLite

Android flatter-FCM:如何将背景消息存储到SQLite,android,sqlite,flutter,firebase-cloud-messaging,Android,Sqlite,Flutter,Firebase Cloud Messaging,我正在为我的移动应用程序构建一个通知系统,其想法是将从Firebase Cloud message接收到的前台和后台消息存储到SQLite。我已经按照这里的设置来设置我的项目 这是我的代码: void initState() { super.initState(); service = MySQLService(); _firebaseMessaging.configure( onMessage: (Map<String, dynamic> me

我正在为我的移动应用程序构建一个通知系统,其想法是将从Firebase Cloud message接收到的前台和后台消息存储到SQLite。我已经按照这里的设置来设置我的项目

这是我的代码:

void initState() {
    super.initState();
    service = MySQLService();

    _firebaseMessaging.configure(
      onMessage: (Map<String, dynamic> message) async {
        print("onMessage: $message");
        service.insertItem(Item.fromMessage(message)); // It's working, here.
      },
      onBackgroundMessage: myBackgroundMessageHandler,
      onLaunch: (Map<String, dynamic> message) async {
        print("onLaunch: $message");
      },
      onResume: (Map<String, dynamic> message) async {
        print("onResume: $message");
      },
    );

    _firebaseMessaging.requestNotificationPermissions(
        const IosNotificationSettings(
            sound: true, badge: true, alert: true, provisional: true));
    _firebaseMessaging.onIosSettingsRegistered
        .listen((IosNotificationSettings settings) {
      print("Settings registered: $settings");
    });
    _firebaseMessaging.getToken().then((String token) {
      assert(token != null);
      print("Push Messaging token: $token");
    });
}
void initState(){
super.initState();
service=MySQLService();
_firebaseMessaging.configure(
onMessage:(映射消息)异步{
打印(“onMessage:$message”);
service.insertItem(Item.fromMessage(message));//它在这里工作。
},
onBackgroundMessage:myBackgroundMessageHandler,
onLaunch:(映射消息)异步{
打印(“onLaunch:$message”);
},
onResume:(映射消息)异步{
打印(“onResume:$message”);
},
);
_firebaseMessaging.requestNotificationPermissions(
const IosNotificationSettings(
声音:真,徽章:真,警报:真,临时:真);
_firebaseMessaging.onissettings已注册
.listen((IONotificationSettings){
打印(“已注册设置:$Settings”);
});
_firebaseMessaging.getToken().then((字符串标记){
断言(令牌!=null);
打印(“推送消息传递令牌:$token”);
});
}
以及处理背景信息的代码:

Future<dynamic> myBackgroundMessageHandler(Map<String, dynamic> message) async {
  print("onBackground: $message");
  var service = MySQLService();
  await service.insertItem(Item.fromMessage(message)); // It's not working, here.
  return Future<void>.value();
}
未来myBackgroundMessageHandler(映射消息)异步{ 打印(“onBackground:$message”); var service=MySQLService(); wait service.insertItem(Item.fromMessage(message));//在这里它不起作用。 返回Future.value(); } 目前,我的应用程序可以:接收前台消息并将其存储到SQLite中(通过调用service.insertItem),但由于某些原因,后台消息不会存储在SQLite中,即使它显示在设备的通知列表上

更新:这里是插入消息的代码

  Future<void> insertItem(Item notification) async {
    final Database db = await MyDatabase.getDatabase();
    await db.insert('notification', notification.toMap(),
        conflictAlgorithm: ConflictAlgorithm.replace);
    return Future<void>.value();
  }
Future insertItem(项目通知)异步{
final Database db=wait MyDatabase.getDatabase();
等待db.insert('notification',notification.toMap(),
conflictAlgorithm:conflictAlgorithm.replace);
返回Future.value();
}

出于某种原因,仅当FCM消息不包含
通知时(例如,是纯数据消息),才会调用
onBackgroundMessage
。默认情况下,这样的消息不会触发设备上的通知

我最后做的只是发送数据消息(以便能够在后台捕获它们),并用包自己处理设备上的通知部分

// TOP-LEVEL or STATIC function to handle background messages
static Future<dynamic> onBackgroundMessage(
    Map<String, dynamic> notification) async {

  var msg;
  if (Platform.isAndroid) {
    msg = notification['data'];
  } else {
    msg = notification;
  }

  DatabaseService _dbService = DatabaseService();
  msg = await _dbService.insertMessage(msg);
  _showNotification(msg);
  return Future<void>.value();
}

static Future _showNotification(Map<String, dynamic> msg) async {
  // TODO: Use a proper channel
  var platformChannelSpecificsAndroid = AndroidNotificationDetails(
      'your channel id', 'your channel name', 'your channel description',
      importance: Importance.Max, priority: Priority.High);
  var platformChannelSpecificsIos =
      IOSNotificationDetails(presentSound: true);
  var platformChannelSpecifics = NotificationDetails(
      platformChannelSpecificsAndroid, platformChannelSpecificsIos);

  return Future.delayed(Duration.zero, () {
    _flutterLocalNotificationsPlugin.show(
      "some id",
      msg["title"],
      msg["body"],
      platformChannelSpecifics,
      payload: "some id",
    );
  });
}
//处理后台消息的顶级或静态函数
静态未来背景消息(
映射通知)异步{
var-msg;
if(Platform.isAndroid){
msg=通知['data'];
}否则{
msg=通知;
}
DatabaseService _dbService=DatabaseService();
msg=wait_dbService.insertMessage(msg);
_显示通知(msg);
返回Future.value();
}
静态未来显示通知(映射消息)异步{
//TODO:使用适当的频道
var平台ChannelSpecificSandroid=AndroidNotificationDetails(
“您的频道id”、“您的频道名称”、“您的频道描述”,
重要性:重要性。最大,优先级:优先级。高);
var平台=
IONotificationDetails(当前声音:true);
var platformChannelSpecifics=通知详细信息(
platformChannelSpecificsAndroid,platformChannelSpecificsIos);
返回未来。延迟(Duration.zero,(){
_flatterLocalNotificationsPlugin.show(
“某个id”,
msg[“标题”],
味精[“正文”],
平台通道细节,
有效载荷:“某个id”,
);
});
}
要使其正常工作,所有涉及的插件必须提前注册,如中的“默认情况下,后台消息传递未启用。要在后台处理消息”,如下所述

试图将那里写的内容翻译成kotlin项目,我最终创建了一个文件/android/app/src/main/kotlin//Application.kt,用于注册插件,如:

package <your package>

import io.flutter.app.FlutterApplication
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback
import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService
import com.tekartik.sqflite.SqflitePlugin
import com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin

public class Application: FlutterApplication(), PluginRegistrantCallback {
    override fun onCreate() {
        super.onCreate()
        FlutterFirebaseMessagingService.setPluginRegistrant(this)
    }

    override fun registerWith(registry: PluginRegistry) {
        io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin.registerWith(
                registry.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin"))

        com.tekartik.sqflite.SqflitePlugin.registerWith(
                registry.registrarFor("com.tekartik.sqflite.SqflitePlugin"))

        com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.registerWith(
                registry.registrarFor("com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin"))
    }
}
包
导入io.flatter.app.flatterApplication
导入io.flatter.plugin.common.PluginRegistry
导入io.flatter.plugin.common.PluginRegistry.PluginRegistrantCallback
导入io.flatter.plugins.firebasemessaging.FlatterFireBaseMessagingService
导入com.tekartik.sqflite.SqflitePlugin
导入com.dexterous.flatterLocalNotifications.flatterLocalNotificationsPlugin
公共类应用程序:flatterApplication(),PluginRegistrantCallback{
重写fun onCreate(){
super.onCreate()
FlatterFireBaseMessAgingService.setPluginRegistrNet(此)
}
用(注册表:PluginRegistry)覆盖乐趣注册表{
io.flatter.plugins.firebasemessaging.FirebaseMessagingPlugin.registerWith(
registry.registrrfor(“io.flatter.plugins.firebasemessaging.FirebaseMessagingPlugin”))
com.tekartik.sqflite.SqflitePlugin.registerWith(
registry.registerFor(“com.tekartik.sqflite.SqflitePlugin”))
com.dexterous.flatterLocalNotifications.flatterLocalNotificationsPlugin.registerWith(
RegistrFor(“com.dexterous.flatterLocalNotifications.flatterLocalNotificationsPlugin”))
}
}

问题出在iOS还是Android,还是两者都有?你能分享MySQLService的代码吗?也许你启动服务的方式不对?看看这个包,它假设在后台执行DB任务。我不认为我的插入函数有什么问题,因为它在前台消息的情况下工作。仅不插入背景消息。也许onBackgroundMessageHangler从一开始就没有打电话,不能确定,因为我不知道如何在后台调试。我认为即使你的应用程序关闭了,你仍然可以进行调试。例如,如果您的android手机连接到您的机器,并且在后台收到一条消息,则将执行
print(“onBackground:$message”)因此请检查您的ID中的日志