You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

如何在Flutter双应用(管理端/客户端)中基于PHP后端实现无需Firebase的图片上传触发推送通知功能

嘿,这个需求完全可以搞定,不用Firebase也有好几种靠谱的实现思路,我给你拆解一下最实用的几个方案,附上具体的代码片段供你参考:

方案一:WebSocket实时推送(最推荐,实时性拉满)

这个方案是最适合实时场景的,管理端上传完图片后能立刻给客户端发通知,而且全程自己掌控,不用依赖第三方平台。

步骤1:PHP后端搭建WebSocket服务

可以用Workerman或者Swoole这两个PHP异步框架来快速搭建,这里以Workerman为例:

  • 首先通过Composer安装依赖:composer require workerman/workerman
  • 写一个简单的WebSocket服务端代码,用来监听客户端连接并推送消息:
<?php
require_once __DIR__ . '/vendor/autoload.php';

use Workerman\Worker;

// 创建WebSocket服务,监听8080端口(可以自己改)
$ws_worker = new Worker("websocket://0.0.0.0:8080");

// 启动4个进程处理连接,根据服务器配置调整
$ws_worker->count = 4;

// 客户端连接时触发,可以在这里记录客户端信息(比如用户ID)
$ws_worker->onConnect = function($connection) {
    echo "新客户端上线\n";
};

// 自定义推送函数,供图片上传接口调用
function pushToClients($notificationData) {
    global $ws_worker;
    // 遍历所有在线客户端,发送通知
    foreach($ws_worker->connections as $connection) {
        $connection->send(json_encode($notificationData));
    }
}

// 启动WebSocket服务
Worker::runAll();
  • 然后在你现有的图片上传接口里,当图片上传成功后,调用这个pushToClients函数,传入通知内容,比如:
// 假设你的上传逻辑完成后得到了图片URL
$uploadedImageUrl = 'https://your-server.com/uploads/new.jpg';
// 构造推送数据
$notification = [
    'type' => 'new_image',
    'message' => '管理端上传了新图片!',
    'image_url' => $uploadedImageUrl
];
// 推送通知
pushToClients($notification);

步骤2:Flutter客户端对接WebSocket并展示本地通知

  • 首先在pubspec.yaml里添加依赖:
dependencies:
  web_socket_channel: ^2.4.0
  flutter_local_notifications: ^16.1.0
  • 实现WebSocket连接和本地通知逻辑:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:web_socket_channel/io.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';

// 本地通知服务类
class LocalNotificationService {
  static final FlutterLocalNotificationsPlugin _plugin = FlutterLocalNotificationsPlugin();

  // 初始化通知服务
  static Future<void> init() async {
    const AndroidInitializationSettings androidSettings = AndroidInitializationSettings('@mipmap/ic_launcher');
    const InitializationSettings settings = InitializationSettings(android: androidSettings);
    await _plugin.initialize(settings);
  }

  // 显示通知
  static Future<void> showNotification(String title, String body) async {
    const AndroidNotificationDetails androidDetails = AndroidNotificationDetails(
      'image_upload_notif',
      '新图片通知',
      channelDescription: '管理端上传新图片时推送的通知',
      importance: Importance.max,
      priority: Priority.high,
    );
    const NotificationDetails notificationDetails = NotificationDetails(android: androidDetails);
    await _plugin.show(0, title, body, notificationDetails);
  }
}

// WebSocket管理类
class WebSocketManager {
  late IOWebSocketChannel _channel;

  // 连接WebSocket服务
  void connect(String serverUrl) {
    _channel = IOWebSocketChannel.connect(serverUrl);
    // 监听推送消息
    _channel.stream.listen((message) {
      final data = jsonDecode(message);
      if (data['type'] == 'new_image') {
        // 触发本地通知
        LocalNotificationService.showNotification('新图片提醒', data['message']);
        // 这里还可以更新你的图片列表UI
      }
    });
  }

  // 断开连接
  void disconnect() {
    _channel.sink.close();
  }
}

// 主应用初始化
void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // 初始化本地通知
  await LocalNotificationService.init();
  runApp(const MyClientApp());
}

class MyClientApp extends StatefulWidget {
  const MyClientApp({super.key});

  @override
  State<MyClientApp> createState() => _MyClientAppState();
}

class _MyClientAppState extends State<MyClientApp> {
  final WebSocketManager _wsManager = WebSocketManager();

  @override
  void initState() {
    super.initState();
    // 连接你的WebSocket服务地址,替换成实际的服务器IP和端口
    _wsManager.connect('ws://your-server-ip:8080');
  }

  @override
  void dispose() {
    _wsManager.disconnect();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('客户端')),
        body: const Center(child: Text('等待新图片通知...')),
      ),
    );
  }
}

注意事项

  • 要确保WebSocket服务的端口在服务器防火墙里是开放的,客户端能访问到。
  • 如果你的App是HTTPS的,需要用wss://协议,配置SSL证书后使用加密连接。
  • 要是需要给特定用户推送,就在客户端连接时发送用户ID,后端保存连接和用户ID的映射,推送时只给对应用户的连接发消息。
  • 离线消息的话,可以把未推送的消息存在数据库里,客户端下次上线时拉取。

方案二:轮询(简单粗暴,适合小体量应用)

如果你的用户量不大,实时性要求没那么高,可以用轮询的方式:

  • 客户端每隔一段时间(比如30秒)调用PHP后端的接口,查询有没有新上传的图片。
  • 后端维护一个图片上传的时间戳或者版本号,客户端每次请求时带上自己最后获取的时间戳,后端对比后返回新的记录。
  • 客户端拿到新记录后触发本地通知。
    这个方案优点是实现简单,不用维护WebSocket服务,缺点是实时性差,会增加服务器请求量。

方案三:第三方推送服务(非Firebase)

如果不想自己维护推送服务,也可以用非Firebase的第三方平台,比如国内的个推、JPush,或者国外的OneSignal(支持不用Firebase的HTTP API推送):

  • 管理端上传图片后,PHP后端调用第三方推送服务的API,发送通知。
  • Flutter客户端集成对应的SDK,接收并展示通知。
    这个方案省心,但需要依赖第三方平台,而且要注意隐私和合规问题。

内容的提问来源于stack exchange,提问作者G H Prakash

火山引擎 最新活动