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

如何在Flutter应用中检测用户卸载并发送消息?(Firebase与私有数据库)

Flutter应用卸载检测与用户消息推送方案(基于Firebase+私有服务器)

因为Android和iOS都没有提供应用卸载的直接回调接口,所以我们只能通过间接检测机制来实现需求,核心思路是结合Firebase Cloud Messaging(FCM)的令牌有效性验证,搭配私有服务器的心跳监控来判断用户是否卸载应用。以下是具体实现步骤:

一、集成FCM并同步设备令牌到私有数据库

  1. 在Flutter项目中集成FCM SDK,获取每个用户的唯一设备令牌(token)。
  2. 应用启动、令牌刷新时,将用户ID、FCM令牌、最后活跃时间同步到你的私有数据库。

示例Flutter代码片段:

import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:http/http.dart' as http;

// 保存/更新FCM令牌到私有服务器
Future<void> syncFCMToken(String userId) async {
  String? token = await FirebaseMessaging.instance.getToken();
  if (token == null) return;

  // 调用私有服务器API写入数据库
  await http.post(
    Uri.parse('你的服务器地址/api/save-token'),
    body: {
      'user_id': userId,
      'fcm_token': token,
      'last_active': DateTime.now().toIso8601String(),
    },
  );

  // 监听令牌自动刷新,实时更新
  FirebaseMessaging.instance.onTokenRefresh.listen((newToken) {
    http.post(
      Uri.parse('你的服务器地址/api/update-token'),
      body: {
        'user_id': userId,
        'fcm_token': newToken,
        'last_active': DateTime.now().toIso8601String(),
      },
    );
  });
}

二、私有服务器实现心跳监控与卸载检测

  1. 在Flutter应用中添加定时心跳任务(比如每12小时一次),调用服务器接口更新当前用户的最后活跃时间,确保数据库中记录的用户状态是最新的。
  2. 服务器端设置定时扫描任务(比如每天凌晨执行):
    • 筛选出最后活跃时间超过阈值(比如48小时)的令牌记录;
    • 调用FCM接口向这些令牌发送静默通知(无弹窗,仅用于验证令牌有效性);
    • 如果FCM返回InvalidRegistration或NotRegistered错误,说明该令牌对应的应用已被卸载,标记用户状态为“已卸载”,并触发消息发送逻辑。

示例服务器端伪代码(Node.js):

const admin = require('firebase-admin');
const db = require('./你的私有数据库连接');

// 初始化Firebase Admin
admin.initializeApp({
  credential: admin.credential.cert('./firebase-service-account.json'),
});

// 定时检测卸载用户
async function checkUninstalledUsers() {
  const threshold = Date.now() - 48 * 60 * 60 * 1000; // 48小时无活跃阈值
  const inactiveTokens = await db.query(
    'SELECT user_id, fcm_token FROM user_tokens WHERE last_active < ?',
    [threshold]
  );

  for (const { user_id, fcm_token } of inactiveTokens) {
    try {
      // 发送静默通知检测令牌有效性
      await admin.messaging().send({
        token: fcm_token,
        data: { type: 'heartbeat_check' },
        apns: { payload: { aps: { contentAvailable: true } } }, // iOS静默通知配置
        android: { priority: 'low' }, // Android低优先级,避免打扰用户
      });
      // 推送成功,更新活跃时间
      await db.query(
        'UPDATE user_tokens SET last_active = ? WHERE fcm_token = ?',
        [Date.now(), fcm_token]
      );
    } catch (error) {
      // 令牌无效,判定为应用已卸载
      if (['messaging/invalid-registration-token', 'messaging/registration-token-not-registered'].includes(error.code)) {
        // 标记用户为已卸载
        await db.query('UPDATE users SET is_uninstalled = 1 WHERE id = ?', [user_id]);
        // 删除无效令牌
        await db.query('DELETE FROM user_tokens WHERE fcm_token = ?', [fcm_token]);
        // 发送卸载提醒消息(比如邮件/短信)
        await sendUninstallAlert(user_id);
      }
    }
  }
}

// 发送卸载提醒的逻辑(示例)
async function sendUninstallAlert(userId) {
  const user = await db.query('SELECT email FROM users WHERE id = ?', [userId]);
  if (user.length > 0) {
    // 调用你的邮件API发送提醒
    await yourEmailService.send(user[0].email, '我们想念你', '欢迎重新安装我们的应用');
  }
}

// 定时任务(比如用node-schedule每天凌晨2点执行)
const schedule = require('node-schedule');
schedule.scheduleJob('0 2 * * *', checkUninstalledUsers);

三、平台特殊注意事项

  • iOS:需要在Xcode中开启Remote notifications后台权限,并且静默通知仅能在应用后台运行时接收。另外iOS用户卸载应用后,FCM令牌会快速失效,检测阈值可以设为24小时。
  • Android:部分国产厂商的后台限制可能导致心跳任务无法按时执行,建议用WorkManager实现可靠的定时任务,确保心跳请求能正常上报到服务器。

四、合规提示

发送卸载提醒前,必须确保用户已同意接收此类消息,严格遵守GDPR、CCPA等隐私法规,避免违规。

内容的提问来源于stack exchange,提问作者ff .n

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 15:24:24