【问题标题】:Flutter - FCM: how to store background message to SQLiteFlutter - FCM:如何将后台消息存储到 SQLite
【发布时间】:2020-07-21 21:49:16
【问题描述】:

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

这是我的代码:

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");
    });
}

以及处理后台消息的代码:

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();
}

目前,我的应用程序可以: 接收前台消息并将其存储到 SQLite 中(通过调用 service.insertItem),但由于某种原因,即使显示在 SQLite 上,后台消息也不会存储在 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();
  }

【问题讨论】:

  • 问题出在 iOS 还是 Android 上,还是两者都有?你能分享一下MySQLService的代码吗?也许您没有以正确的方式启动服务?看看这个包,pub.dev/packages/sqflite,它假设在后台执行数据库任务。
  • 我不认为我的插入功能有什么问题,因为它在前台消息的情况下工作。仅不插入背景消息。也许 onBackgroundMessageHangler 从一开始就没有调用,不能肯定地说,因为我不知道如何在后台调试。
  • 我认为即使您的应用程序已关闭,您仍然可以以某种方式进行调试。例如,如果您的 android 手机已连接到您的机器并且在后台收到一条消息,这将执行 print("onBackground: $message");,因此请检查您的 IDE 中的日志。我想我已经在 Android IDE 中尝试过一次。如果您发现您的手机在连接后仍会记录来自不同应用程序的大量内容。
  • 当我询问这是否由于您启动服务的方式而在 Android 或 iOS 中不起作用时,我想到了此页面中的信息。 flutter.dev/docs/cookbook/persistence/…。但就像你说的,我猜如果它在前台工作,它必须在后台工作:路径已经正确设置。
  • 据我所知,print("onBackground: $message"); 未被调用。我的模拟器确实收到了消息,但调试控制台上没有记录任何内容。

标签: android sqlite flutter firebase-cloud-messaging


【解决方案1】:

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

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

// 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",
    );
  });
}

为此,所有相关插件必须提前注册,如下所述“默认情况下后台消息未启用。在后台处理消息”在firebase_messaging

试图将那里写的内容翻译成一个 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"))
    }
}

【讨论】:

    猜你喜欢
    • 2020-08-26
    • 2014-02-28
    • 1970-01-01
    • 2021-07-09
    • 2021-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多