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

Flutter未集成Firebase时如何获取APNS推送所需设备Token

Flutter 无Firebase场景获取APNS推送设备Token方案

注意:设备UDID是硬件级唯一标识,和APNS要求的推送Token完全不通用,无法通过UDID转换得到APNS Token,必须通过iOS系统接口在用户授权通知权限后获取专属推送Token。

一、iOS端前置原生配置

必须先完成Xcode端配置,否则无法收到Token回调:

  • 打开iOS工程下的Runner.xcworkspace,选中Runner靶标,进入Signing & Capabilities页
  • 点击+ Capability,添加Push Notifications能力
  • 确认当前App的Bundle ID、签名证书和你生成的.pem文件所属环境(开发/生产)匹配,否则后续推送会鉴权失败
  • 调试必须使用iOS真机,模拟器无法生成真实可用于推送的APNS Token

你当前实现的通知权限判断逻辑运行效果参考:
通知权限状态判断运行截图


二、Flutter端快速实现(无Firebase依赖)

推荐使用纯APNS实现的维护库flutter_apns,不需要接入任何Firebase相关服务,适配你现有PHP后端+PEM证书的推送架构。

1. 添加依赖

在项目pubspec.yaml中添加依赖:

dependencies:
  flutter_apns: ^2.0.0
  # 你项目中已有的通知权限相关依赖保留即可

2. 整合现有权限逻辑,实现Token获取

在你原有通知权限判断的代码基础上,当权限为授权状态时注册APNS并监听Token回调,完整代码如下:

import 'package:flutter_apns/flutter_apns.dart';

final ApnsPushConnector apnsConnector = ApnsPushConnector();

void initPush() async {
  // 复用你已有的权限判断逻辑
  final status = await NotificationPermissions.getNotificationPermissionStatus();
  print(status);
  switch (status) {
    case PermissionStatus.denied:
      // 自行处理权限拒绝逻辑,比如引导用户去设置开权限
      return;
    case PermissionStatus.granted:
    case PermissionStatus.provisional:
      // 配置APNS回调
      apnsConnector.configureApns(
        onLaunch: (Map<String, dynamic> payload) async {},
        onResume: (Map<String, dynamic> payload) async {},
        onMessage: (Map<String, dynamic> payload) async {},
      );

      // 核心:监听APNS设备Token下发
      apnsConnector.token.addListener(() {
        final String? apnsToken = apnsConnector.token.value;
        if (apnsToken != null) {
          print('APNS设备Token:$apnsToken');
          // 将获取到的Token上传到你的PHP后端即可,后端调用APNS接口时传入该Token作为推送目标
        }
      });

      // 触发通知权限申请+APNS注册
      apnsConnector.requestNotificationPermissions(
        const IosNotificationSettings(
          alert: true,
          badge: true,
          sound: true,
        ),
      );
      break;
    case PermissionStatus.unknown:
      // 处理权限未知状态,可触发首次权限申请
      return;
    default:
      return;
  }
}

三、关键注意事项

  • 开发环境、生产环境生成的APNS Token不通用:本地调试安装包拿到的是开发环境Token,对应使用开发证书生成的.pem发推送;TestFlight、App Store安装的正式包拿到的是生产环境Token,对应使用生产证书生成的.pem发推送
  • APNS Token不是固定值:App卸载重装、系统还原、用户关闭通知后重新授权、系统版本升级都可能导致Token变化,建议每次App冷启动时都获取最新Token同步到后端,避免旧Token失效导致推送失败
  • 如果Token回调长时间不触发,优先检查Xcode中Push Notifications能力是否添加成功、签名是否和Bundle ID匹配、是否使用真机调试

四、零第三方依赖原生实现方案(可选)

如果不想引入第三方库,可以通过MethodChannel自行对接iOS原生接口实现:

  1. 在iOS工程的AppDelegate.swift中添加APNS注册、Token回调逻辑,通过MethodChannel把Token传给Flutter层:
import UIKit
import Flutter
import UserNotifications

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  private var apnsToken: String?

  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)
    UNUserNotificationCenter.current().delegate = self
    application.registerForRemoteNotifications()

    let controller = window?.rootViewController as! FlutterViewController
    let channel = FlutterMethodChannel(name: "com.yourapp/apns", binaryMessenger: controller.binaryMessenger)
    channel.setMethodCallHandler { call, result in
      if call.method == "getApnsToken" {
        result(self.apnsToken)
      } else {
        result(FlutterMethodNotImplemented)
      }
    }
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }

  override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    apnsToken = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
    super.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
  }

  override func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
    print("APNS注册失败:\(error.localizedDescription)")
    super.application(application, didFailToRegisterForRemoteNotificationsWithError: error)
  }
}
  1. Flutter层通过MethodChannel获取Token:
const apnsChannel = MethodChannel('com.yourapp/apns');

Future<String?> fetchApnsToken() async {
  try {
    return await apnsChannel.invokeMethod<String>('getApnsToken');
  } catch (e) {
    print("获取APNS Token失败:$e");
    return null;
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 13:48:24