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

Flutter应用启动时获取OneSignal userId(解决首次安装返回null问题)

Flutter首次安装时OneSignal获取userId为null的解决办法

为啥首次安装会拿不到?
首次装应用的时候,OneSignal得走一套异步流程:请求通知权限、注册设备、同步订阅状态,你现在初始化完直接调用getDeviceState(),流程还没走完自然返回null。

解决步骤

  • 别直接同步拿userId,监听订阅状态变化
    OneSignal提供了订阅状态监听,等设备完成订阅(用户授权后才会触发),再从状态里取userId,这比直接调用接口靠谱多了。

  • 异步初始化并等待完成
    把initNotification改成异步函数,main里await它,确保OneSignal初始化完再往下走。

修改后的代码

main函数部分

void main() async {
  var widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
  FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
  await Firebase.initializeApp();
  await _initController();
  // 等待通知模块初始化完成
  await initNotification();
  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
  runApp(const TLCustomerApp());
  ErrorWidget.builder = (FlutterErrorDetails details) => const Scaffold(
        body: Center(
          child: ListTile(
            minLeadingWidth: 10,
            leading: Icon(Icons.error_outline),
            title: Text("There is something went wrong,\n please try again!"),
          ),
        ),
      );
  FlutterNativeSplash.remove();
}

initNotification函数部分

Future<void> initNotification() async {
  OneSignal.shared.setAppId(oneSignalKey);

  // 监听订阅状态变化,首次订阅成功时获取userId
  OneSignal.shared.setSubscriptionObserver((OSSubscriptionStateChanges changes) {
    // 从未订阅变为已订阅时触发
    if (!changes.from.subscribed && changes.to.subscribed) {
      final osUserID = changes.to.userId;
      if (osUserID != null) {
        print("==>SUBSCRIBE_ID:${osUserID}");
        // 这里可以把userId存本地或者上传服务器
      }
    }
  });

  // 先检查当前设备状态(非首次安装能直接拿到)
  final status = await OneSignal.shared.getDeviceState();
  final osUserID = status?.userId;
  if (osUserID != null) {
    print("==>SUBSCRIBE_ID:${osUserID}");
    // 处理已存在的userId
  }

  // 其他原有配置保留
  OneSignal.shared.setNotificationWillShowInForegroundHandler((OSNotificationReceivedEvent event) {
    event.complete(event.notification);
  });
  OneSignal.shared.setNotificationOpenedHandler((OSNotificationOpenedResult result) {
    var data = result.notification.additionalData;
    // if (data != null) {
    //   var routeName = data["routeName"];
    //   Get.toNamed(routeName);
    // }
  });
  OneSignal.shared.setPermissionObserver((OSPermissionStateChanges changes) {
    // 可选:用户后来改权限为允许时,再拿一次userId
    if (changes.to.status == OSPermissionStatus.authorized) {
      OneSignal.shared.getDeviceState().then((status) {
        final osUserID = status?.userId;
        if (osUserID != null) {
          print("==>SUBSCRIBE_ID after permission:${osUserID}");
        }
      });
    }
  });
  OneSignal.shared.setEmailSubscriptionObserver(
      (OSEmailSubscriptionStateChanges emailChanges) {});
}

额外说明

  • 首次安装时,用户点了允许通知,订阅状态监听就会触发,这时就能拿到有效的userId。
  • 非首次打开应用,getDeviceState能直接返回之前保存的userId,不用等监听。
  • 权限监听可以处理用户后续修改权限的情况,确保userId能及时更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 05:54:38