【问题标题】:Flutter Push Notification using SignalR使用 SignalR 的颤振推送通知
【发布时间】:2022-01-24 17:29:06
【问题描述】:

我正在使用 SignalR 在我的 Flutter 应用程序上推送通知,并且工作正常。我从后端收到消息并使用 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;
  }
}

【问题讨论】:

    标签: flutter signalr


    【解决方案1】:

    SignalR 问题

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

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

    用于 Flutter 的 SignalR 既不使用 FCM 也不使用 APN。在目前的状态下,SignalR 不太适合 Android 或 iOS - 请在 How to use signalr in Android 上查看与您遇到类似问题的人的 cmets。

    替代解决方案

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

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

    警告:在 Android 上,有一个更复杂的替代方案,称为 unifiedpush,但限制包括始终向用户显示通知以处理后台通知.

    我的分析:这一切都是基于我通过阅读pubspec.yamloriginal repoSignalR documentation 上的 GitHub 问题以及一些实施推送通知的经验而完成的颤抖。

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

    【讨论】:

    • 感谢您提供这些有用的信息。你能给我解释一下如何使用push库吗?我无法运行示例代码。
    • 不要使用我创建的push 包,你应该使用firebase_messagingpush 是一个特殊的包,如果 firebase_messaging 不适合您的需求,您应该使用 - 特别是,如果您想在 iOS 上避免 FCM。这就是这个包的目的。 Firebase Messaging 有更详尽的指南,更适合一般用例。
    • 但是,我现在正在更新 push 存储库,以帮助用户更轻松地尝试示例应用程序。感谢您的反馈:)
    • 我会使用 Firebase,但主要问题是我担心它会受到限制并要求升级帐户。有什么想法吗?
    • FCM 的使用没有限制或费用。
    【解决方案2】:

    我使用 SignalR,但在原生平台(IOS 和 Android)上,我制作了股票应用程序并获得实时价格。当应用程序进入后台时,我将在 5 秒后断开与 SignalR 服务器的连接,当应用程序再次进入前台时,我检查应用程序的当前状态是否未连接到服务器 SignalR,我将再次连接。我认为如果您的应用程序仍然在后台状态下连接并接收来自 signalR 服务器的数据,那就不好了。

    【讨论】:

      猜你喜欢
      • 2021-12-28
      • 2020-06-26
      • 2021-11-04
      • 2021-09-14
      • 2022-01-23
      • 2021-07-14
      • 2018-03-16
      • 1970-01-01
      相关资源
      最近更新 更多