You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

局域网内Docker化离线Android推送通知方案咨询(支持服务器切换)

实现方案

一、Docker化离线通知服务搭建

1. 选型:EMQX MQTT Broker

选择EMQX作为通知核心服务,它支持Docker容器化部署,完全无需外部依赖,可离线运行,同时支持原生MQTT协议(适配移动端)和MQTT over WebSocket(适配Web端),满足多端通知需求。

2. Docker-compose配置

在你的docker-compose.yml中添加EMQX服务,配置端口映射和本地存储挂载,确保重启后配置和消息不丢失:

version: '3.8'
services:
  emqx:
    image: emqx/emqx:5.1
    container_name: emqx-broker
    ports:
      - "1883:1883"  # MQTT原生端口(移动端用)
      - "8083:8083"  # MQTT over WebSocket端口(Web端用)
      - "18083:18083" # EMQX管理控制台端口(可选,用于调试)
    volumes:
      - ./emqx/data:/opt/emqx/data
      - ./emqx/log:/opt/emqx/log
      - ./emqx/etc:/opt/emqx/etc
    restart: always

主服务器和本地服务器都用这套配置启动EMQX即可。

3. 通知发送与接收逻辑

  • 服务端发通知:业务服务(同样Docker化)通过MQTT客户端连接EMQX,将通知消息发布到指定主题(如/notifications/user/{userId})。
  • Flutter端收通知:集成mqtt_client库,根据当前服务器地址连接对应的EMQX实例:
    • 移动端:连接tcp://{server_ip}:1883
    • Web端:连接ws://{server_ip}:8083/mqtt
      订阅对应主题后实时接收通知;同时用本地存储(如Hive、SharedPreferences)缓存通知记录,离线时也能查看历史通知。

二、Flutter应用多服务器切换实现

1. 服务器配置管理

在应用中添加服务器设置页面,允许用户输入或选择主服务器/本地服务器地址(可预设默认值),将选中的地址保存到本地存储:

import 'package:shared_preferences/shared_preferences.dart';

class ServerConfig {
  static const String _currentServerKey = 'current_server';
  static const String _mainServerUrl = 'https://main-server.com';
  static const String _localServerUrl = 'http://local-server:8080';

  static Future<String> getCurrentServer() async {
    final prefs = await SharedPreferences.getInstance();
    return prefs.getString(_currentServerKey) ?? _mainServerUrl;
  }

  static Future<void> switchToMainServer() async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.setString(_currentServerKey, _mainServerUrl);
  }

  static Future<void> switchToLocalServer() async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.setString(_currentServerKey, _localServerUrl);
  }
}

2. 全局连接切换逻辑

封装网络请求和MQTT连接工具类,依赖ServerConfig获取当前服务器地址,切换时自动断开旧连接并重新连接:

import 'package:mqtt_client/mqtt_client.dart';
import 'package:mqtt_client/mqtt_server_client.dart';

class MqttService {
  late MqttServerClient _client;
  String? _currentServer;

  Future<void> connect() async {
    final serverUrl = await ServerConfig.getCurrentServer();
    if (_currentServer == serverUrl && _client.connectionStatus?.state == MqttConnectionState.connected) {
      return;
    }

    // 断开旧连接
    if (_currentServer != null) {
      _client.disconnect();
    }

    // 初始化新连接
    final host = serverUrl.split('://')[1];
    _client = MqttServerClient.withPort(host, 'flutter-client', 1883);
    _client.setProtocolV311();
    _client.keepAlivePeriod = 30;

    try {
      await _client.connect();
      _currentServer = serverUrl;
      // 订阅用户专属通知主题
      _client.subscribe('/notifications/user/123', MqttQos.atLeastOnce);
      _client.updates?.listen((List<MqttReceivedMessage<MqttMessage>> messages) {
        final message = messages.first.payload as MqttPublishMessage;
        final payload = MqttPublishPayload.bytesToStringAsString(message.payload.message);
        // 处理通知逻辑(如弹出本地通知、更新UI)
        print('收到通知: $payload');
      });
    } catch (e) {
      print('MQTT连接失败: $e');
      _client.disconnect();
    }
  }
}

3. 状态同步与UI更新

使用状态管理工具(如Provider)维护当前服务器状态,所有依赖地址的UI和业务逻辑监听状态变化自动更新:

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

class ServerState with ChangeNotifier {
  String _currentServer = 'https://main-server.com';

  String get currentServer => _currentServer;

  Future<void> init() async {
    final prefs = await SharedPreferences.getInstance();
    _currentServer = prefs.getString('current_server') ?? _currentServer;
    notifyListeners();
  }

  Future<void> switchServer(String serverUrl) async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.setString('current_server', serverUrl);
    _currentServer = serverUrl;
    notifyListeners();
    // 触发MQTT重连和API客户端更新
    await MqttService().connect();
  }
}

4. 离线场景适配

本地服务器场景下,确保所有业务服务(API、EMQX)通过docker-compose一起部署,形成完整离线环境;Flutter端切换到本地服务器后,自动更新所有API请求的baseUrl,避免依赖外部网络。

内容的提问来源于stack exchange,提问作者unownone

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 15:57:51