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

Flutter iOS中如何先请求追踪透明权限再请求通知权限

问题:调整App追踪授权与通知弹窗的顺序

每次启动App时,通知授权弹窗总是比App追踪授权弹窗先出现,我希望用户先看到App Tracking Transparency授权弹窗,再看到通知授权弹窗。我尝试过在runApp()前后、推送通知请求代码await PushNotificationService().setupInteractedMessage();之前调用await AppTrackingTransparency.requestTrackingAuthorization();,也已在info.plist中添加了对应的权限键,但弹窗顺序还是未改变。

用户提供的代码:

int? initScreen;

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // await Firebase.initializeApp();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  // runApp(MyApp());
  SharedPreferences preferences = await SharedPreferences.getInstance();
  initScreen = await preferences.getInt('initScreen');
  await preferences.setInt('initScreen', 1);
  // MobileAds.instance.initialize();
  runApp(MyApp());
  //await AppTracking
  // final status = await AppTrackingTransparency.requestTrackingAuthorization();
  await AppTrackingTransparency.requestTrackingAuthorization();
  await PushNotificationService().setupInteractedMessage();
  MobileAds.instance.initialize();
  RemoteMessage? initialMessage =
      await FirebaseMessaging.instance.getInitialMessage();
  if (initialMessage != null) {
    // App received a notification when it was killed
  }
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  // final TrackingStatus status;
  //
  // MyApp({required this.status});

  static FirebaseAnalytics analytics = FirebaseAnalytics.instance;
  static FirebaseAnalyticsObserver observer =
      new FirebaseAnalyticsObserver(analytics: analytics);

  @override
  Widget build(BuildContext context) {
    // String statusText;

    // switch (status) {
    //   case TrackingStatus.authorized:
    //     statusText = 'Tracking Status Authorized';
    //     break;
    //   case TrackingStatus.denied:
    //     statusText = 'Tracking Status Denied';
    //     break;
    //   case TrackingStatus.notDetermined:
    //     statusText = 'Tracking Status Not Determined';
    //     break;
    //   case TrackingStatus.notSupported:
    //     statusText = 'Tracking Status Not Supported';
    //     break;
    //   case TrackingStatus.restricted:
    //     statusText = 'Tracking Status Restricted';
    //     break;
    //   default:
    //     statusText = 'You should not see this...';
    //     break;
    // }

    return GetMaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Culture Islamique',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      // home:

      initialRoute: initScreen == 0 || initScreen == null ? 'onboard' : 'home',
      routes: {
        'home': (context) => navbar(analytics: analytics, observer: observer),
        'onboard': (context) => onboardingHomePage(),
      },
    );
  }
}

弹窗顺序截图:
弹窗顺序截图


解决方案

问题出在main函数中,runApp()之后执行的异步操作会与App的UI初始化逻辑并行,导致推送通知的权限请求可能提前触发,无法保证顺序。正确的做法是将权限请求移到页面的初始化生命周期中,严格控制先后顺序:

  1. 修改main函数:移除runApp()之后的追踪授权和通知服务初始化代码,确保App先完成UI启动:
int? initScreen;

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  
  SharedPreferences preferences = await SharedPreferences.getInstance();
  initScreen = await preferences.getInt('initScreen');
  await preferences.setInt('initScreen', 1);
  
  MobileAds.instance.initialize();
  
  RemoteMessage? initialMessage =
      await FirebaseMessaging.instance.getInitialMessage();
  if (initialMessage != null) {
    // 处理App被杀状态下收到的通知
  }
  
  runApp(MyApp());
}
  1. 在首个加载的页面中添加权限请求逻辑:比如在引导页onboardingHomePage或首页navbar的initState中,先请求追踪授权,等待用户处理完毕后再请求通知权限:
class onboardingHomePage extends StatefulWidget {
  const onboardingHomePage({Key? key}) : super(key: key);

  @override
  State<onboardingHomePage> createState() => _onboardingHomePageState();
}

class _onboardingHomePageState extends State<onboardingHomePage> {
  @override
  void initState() {
    super.initState();
    _requestPermissionsInOrder();
  }

  Future<void> _requestPermissionsInOrder() async {
    // 先请求App追踪授权
    await AppTrackingTransparency.requestTrackingAuthorization();
    // 再初始化推送通知服务(内部包含通知权限请求)
    await PushNotificationService().setupInteractedMessage();
  }

  @override
  Widget build(BuildContext context) {
    // 页面原有代码
    return ...;
  }
}

原理说明

将权限请求移到页面的initState中,能保证在UI渲染完成后,严格按照代码顺序执行异步操作:必须等用户处理完追踪授权弹窗,才会触发通知权限请求,从而实现预期的弹窗顺序。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 09:34:55