Как запросить разрешение на прозрачность отслеживания перед разрешением уведомления во флаттер iOS

Каждый раз, когда я запускаю приложение, диалоговое окно уведомления появляется задолго до авторизации отслеживания приложения. Я бы хотел, чтобы пользователь сначала видел диалоговое окно «Прозрачность отслеживания приложений», а затем диалоговое окно «Уведомление». Я попробовал запросить авторизацию отслеживания await AppTrackingTransparency.requestTrackingAuthorization(); до runApp() или после него и над запросом push-уведомления await PushNotificationService().setupInteractedMessage(); и добавил ключ в 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(),
      },
    );
  }
}```

[![][1]][1]


  [1]: https://i.sstatic.net/R3eHd.png
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
454
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

IOS не позволяет отображать несколько собственных диалогов.

Вот мой обходной путь, вдохновленный примером, предоставленным пакетом app-tracking-transparency на pub.dev.

Во-первых, я удалил await AppTrackingTransparency.requestTrackingAuthorization(); из главного меню, а не вызывал его на главном экране (навигационной панели).

Далее на HomeScreen вызовите эту функцию initPlugin() и initState() посмотрите код.

class navbar extends StatefulWidget {
  const navbar({
    Key? key,
    required this.analytics,
    required this.observer,
  }) : super(key: key);

  final FirebaseAnalytics analytics;
  final FirebaseAnalyticsObserver observer;

  @override
  _navbarState createState() => _navbarState();
}

class _navbarState extends State<navbar> {
  String _authStatus = 'Unknown';
  int currentindex = 0;


  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> initPlugin() async {
    final TrackingStatus status =
        await AppTrackingTransparency.trackingAuthorizationStatus;
    setState(() => _authStatus = '$status');
    // If the system can show an authorization request dialog
    if (status == TrackingStatus.notDetermined) {
      // Show a custom explainer dialog before the system dialog
      await showCustomTrackingDialog(context);
      // Wait for dialog popping animation
      await Future.delayed(const Duration(milliseconds: 200));
      // Request system's tracking authorization dialog
      final TrackingStatus status =
          await AppTrackingTransparency.requestTrackingAuthorization();
      setState(() => _authStatus = '$status');
    }

    // final uuid = await AppTrackingTransparency.getAdvertisingIdentifier();
    final uuid = await AppTrackingTransparency.getAdvertisingIdentifier();
    print("UUID: $uuid");
  }

  Future<void> showCustomTrackingDialog(BuildContext context) async =>
      await showDialog<void>(
        context: context,
        builder: (context) => AlertDialog(
          title: const Text('Dear User'),
          content: const Text(
            "We care about your privacy and data security. We keep this app free by showing ads. Can we continue to use your data to tailor ads for you?\n\nYou can change your choice anytime in the app settings. Our partners will collect data and use a unique identifier on your device to show you ads.",
          ),
          actions: [
            TextButton(
              onPressed: () => Navigator.pop(context),
              style: TextButton.styleFrom(
                  backgroundColor: color.AppColor.homePageDetail),
              child: const Text(
                'Continue',
                style: TextStyle(color: Colors.white),
              ),
            ),
          ],
        ),
      );

  @override
  void initState() {
    super.initState();
// It is safer to call native code using addPostFrameCallback after the widget has been fully built and initialized.
    // Directly calling native code from initState may result in errors due to the widget tree not being fully built at that point. 
    WidgetsFlutterBinding.ensureInitialized()
        .addPostFrameCallback((_) => initPlugin());
    print("Tracking status: $_authStatus\n");
  }

  List ListOfColors = [
    HomeScreen(),
    All(),
    ProfileScreen(),
  ];
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListOfColors[currentindex],
      bottomNavigationBar: BottomNavyBar(
        selectedIndex: currentindex,
        onItemSelected: (index) {
          setState(
            () {
              interstitialAd?.show();
              currentindex = index;
              print("$_authStatus");
            },
          );
        },
        items: [
          BottomNavyBarItem(
              icon: Icon(Icons.question_answer),
              title: Text("Quiz"),
              activeColor: Color(0xFF6985e8),
              inactiveColor: Color(0xffa2a2b1)),
          BottomNavyBarItem(
              icon: Icon(Icons.book),
              title: Text("Histoires "),
              activeColor: Color(0xFF6985e8),
              inactiveColor: Color(0xffa2a2b1)),
          BottomNavyBarItem(
              icon: Icon(Icons.settings),
              title: Text("Paramètres"),
              activeColor: Color(0xFF6985e8),
              inactiveColor: Color(0xffa2a2b1)),
        ],
      ),
    );
  }
}

После этого, как только вы запустите приложение, сначала появится разрешение на уведомление, затем появится поясняющее диалоговое окно, после чего будет запрошено разрешение на авторизацию отслеживания приложения. Это предотвратит отказ вашего приложения в App Store.

Для получения дополнительной информации проверьте [пример][1]

[1]: https://pub.dev/packages/app_tracking_transparency/example на pub.dev

Другие вопросы по теме