使用 SignalR 进行 Flutter 推送通知

Mor*_*adi 3 signalr dart flutter

我在 Flutter 应用程序上使用 SignalR 推送通知,效果很好。我从后端获取消息并使用 flutter_local_notifications 显示通知。问题是 SignalR 服务会在一段时间后关闭。如何让我的应用程序保持在后台运行?甚至重新启动?

这是我的代码:

import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:isolate_test/Model/UserMessageModel.dart';
import 'package:signalr_core/signalr_core.dart';
import 'EndPointService.dart';
import 'NotificationService.dart';

class SignalRProvider {
  static String appName = "NOTIFICATION";
  static String? userName = "";
  static String deviceName = "android_app";
  static List<UserMessageModel> messages = <UserMessageModel>[];

  HubConnection connection = HubConnectionBuilder()
      .withUrl(
          'my_url',
          HttpConnectionOptions(
            logging: (level, message) => print(message),
          ))
      .withAutomaticReconnect()
      .withHubProtocol(JsonHubProtocol())
      .build();
  Function(bool update)? onMessagesUpdateCallback;
  SignalRProvider({
    this.onMessagesUpdateCallback,
  });

  setUsername(String username) {
    userName = username;
  }

  Future initSignalR(BuildContext context) async {
    WidgetsFlutterBinding.ensureInitialized();
    await NotificationService().init();
    connection.on('SignalRUserReceiveMessage', (message) async {
      var data = message!.first;
      if (data != null) {
        UserMessageModel msg = UserMessageModel.fromJson(data);
        messages.add(msg);
        msg.showNotification();
      }
      if (onMessagesUpdateCallback != null) {
        onMessagesUpdateCallback!(true);
      }
    });

    connection.on('SignalRMonitoringMessage', (message) async {
      var data = message!.first;
      if (data != null) {
        UserMessageModel msg = UserMessageModel.fromJson(data);
        messages.add(msg);
        msg.showNotification();
      }
      if (onMessagesUpdateCallback != null) {
        onMessagesUpdateCallback!(true);
      }
    });

    connection.on("SignalRReceiveConnectedMessage", (message) async {
      await connection.send(methodName: 'SignalRInit', args: [
        userName,
        appName,
        connection.connectionId,
      ]);
    });
    connection.on("SignalRReceiveDisconnectedMessage", (message) async {
      if (connection.state == HubConnectionState.disconnected) {
        connection.start();
      }
    });
    await connection.start();
  }

  List<UserMessageModel> getMessages() {
    return messages;
  }

  Future deleteMessage(UserMessageModel _msg) async {
    if (_msg == null) return;
    var response =
        await EndPointService().SetupApi("Message", "", []).httpDelete(
      HeaderEnum.BasicHeaderEnum,
      ResponseEnum.ResponseModelEnum,
      jsonEncode(_msg),
    );
  }

  addOrUpdateMessage(UserMessageModel _msg) {
    if (_msg == null) return;
    if (messages != null) {
      var found =
          messages.firstWhere((e) => e.user == _msg.user && e.id == _msg.id);
      var index =
          messages.indexWhere((e) => e.user == _msg.user && e.id == _msg.id);
      if (found != null) {
        messages[index] = _msg;
      } else {
        messages.add(_msg);
      }
      if (onMessagesUpdateCallback != null) {
        onMessagesUpdateCallback!(true);
      }
    }
  }

  setMessagesUpdateCallback(Function(bool update) func) {
    onMessagesUpdateCallback = func;
  }
}
Run Code Online (Sandbox Code Playgroud)

Ben*_*rth 9

SignalR 问题

SignalR for Flutter 使用 Web 套接字和 SSE 从SignalR 服务接收消息。如果应用程序因用户重新启动手机或操作系统关闭应用程序以节省电量而终止,则应用程序将不会收到这些推送通知。

为了克服这个问题,应用程序开发人员(和 SignalR)必须在 Android 上使用 FCM,在 iOS 上使用 APN(或者 FCM 也将在 iOS 上使用 APN)。所有其他方法都将受到更多限制,因为操作系统不允许用户始终保持后台进程运行。这实际上在几年前是允许的,但操作系统已经做出了这些更改以节省用户电池 - 它们强制所有应用程序都通过相同的推送通知介质 - Android 上的 FCM,iOS 上的 APN。

SignalR for Flutter 既不使用 FCM 也不使用 APN。在目前的状态下,SignalR 不太适合 Android 或 iOS - 请查看与您遇到类似问题的人们对如何在 Android 中使用 signalr 的评论。

替代解决方案

最简单的入门方法是使用Firebase Cloud Messaging

  • 在Android上,它将直接用于向设备发送消息,并且
  • 在 iOS 上,FCM 将使用 APN 可靠地访问设备

注意:在 Android 上,有一个更复杂的替代方案,称为Unifiedpush ,但其局限性包括始终向用户显示通知以处理后台通知。

我的分析:这一切都是基于我通过阅读、原始存储库pubspec.yaml上的 GitHub 问题、SignalR 文档以及为 Flutter 实现推送通知的一些经验进行的快速调查。

披露:我两天前刚刚发布了一个名为的推送通知库,push它非常适合这些类型的推送通知包,从而转变为在 Android 上使用 FCM 和在 iOS 上使用 APNs。但是,作为应用程序开发人员,在大多数情况下,您应该使用firebase_messaging,而不是push