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
相关产品推荐
相关产品推荐

