如何使用导航和flutter后台服务

问题描述 投票:0回答:1

目标 我想创建一个后台服务来监听注册。如果用户成功登录,它将重定向到主页小部件

代码片段 这是我当前的代码片段,用于注册目标,但不用于导航

main.dart:

final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  setupLocator();
  BackgroundService.initializeService();
  // PermissionService.requestPermissions();
  runApp(MyApp());
}


class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        //..providers
      ],
      child: Consumer<AuthProvider>(
        builder: (context, authProvider, child) {
          return ToastificationWrapper(
              child: MaterialApp(
            debugShowCheckedModeBanner: false,
            title: 'My App',
            theme: ThemeData.light(),
            onGenerateRoute: Routes.generateRoute,
            initialRoute: Routes.login,
            navigatorKey: navigatorKey,
          ));
        },
      ),
    );
  }
}

background_service.dart:

class BackgroundService {
  static final SIPUAHelper _helper = SipHelperManager().getHelper();
  static Future<void> startBackgroundService() async {
    final service = FlutterBackgroundService();
    await service.startService();
  }

  static void stopBackgroundService() {
    final service = FlutterBackgroundService();
    service.invoke("stop");
  }

  static Future<void> initializeService() async {
    final service = FlutterBackgroundService();

    await service.configure(
      iosConfiguration: IosConfiguration(
        autoStart: true,
        onForeground: onStartForeground,
        onBackground: onIosBackground,
      ),
      androidConfiguration: AndroidConfiguration(
        autoStart: true,
        onStart: onStartForeground,
        isForegroundMode: true,
        autoStartOnBoot: true,
        initialNotificationTitle: 'My Softphone',
        initialNotificationContent: 'Online',
        foregroundServiceTypes: [
          AndroidForegroundType.phoneCall,
          AndroidForegroundType.microphone,
          AndroidForegroundType.mediaPlayback
        ],
      ),
    );
  }
  //....
  @pragma('vm:entry-point')
  static void onStartForeground(ServiceInstance service) async {

     service.on('login').listen((event) async {
          // ...
          SipUAListenerBackground newListener =
              SipUAListenerBackground(service);
          _helper.addSipUaHelperListener(newListener);
          //...

     }
  } 

}

class SipUAListenerBackground implements SipUaHelperListener{
  @override
  void registrationStateChanged(RegistrationState state) async {

             // if state is Registerd
             navigatorKey.currentState?.pushNamed('/home');     <--- currentState is null
  }

}

为什么我发布不起作用的代码片段 因为这可能是最接近我想要的存档的代码

我尝试了什么

我尝试使用 Get-It 定义一个 NavigationService 类,但它也不起作用。它说 NavigationService 未在 Get-It 中注册

我尝试使用 Isolate 创建后台服务,而不是依赖 flutter 后台服务,但出现错误:

UI actions are only available on root isolate.

我需要你的帮助

  • 谁能告诉我为什么我最近的代码片段中的 currentState 为空
  • 如果你不能,那么我们如何在前台服务中使用导航(我确实查过了,但似乎没有任何效果)
flutter navigation sip background-service
1个回答
0
投票
        The issue with navigatorKey.currentState being null stems from Flutter's background services being isolated from the main UI. Background services cannot directly access the UI thread, which includes manipulating the navigation state. This is why using FlutterBackgroundService or Isolates doesn’t permit UI changes like navigating between screens.
        
        One workaround is to utilize Flutter’s Stream or EventChannel to send data from the background service to the main UI, which then listens for that event and performs the navigation. Here's a structured approach you can follow:
        
        Use Stream or EventChannel for Communication: Set up a stream or event channel to allow the background service to communicate with the main isolate. Then, your AuthProvider (or any other provider) listens for changes and handles the navigation.
        
        Listen in AuthProvider: Add a listener in AuthProvider that listens for successful registration or login states, and when these states are detected, navigate to the Home screen.
        Here’s how you can implement it:
        
        1. Modify BackgroundService to Use Stream
        Use a StreamController to send login events.
        
            import 'dart:async';
        
        class BackgroundService {
          static final StreamController<String> _loginController = StreamController<String>.broadcast();
        
          static Stream<String> get loginStream => _loginController.stream;
        
          static Future<void> initializeService() async {
            final service = FlutterBackgroundService();
            await service.configure(
              androidConfiguration: AndroidConfiguration(
                autoStart: true,
                onStart: onStartForeground,
                isForegroundMode: true,
                autoStartOnBoot: true,
                initialNotificationTitle: 'My Softphone',
                initialNotificationContent: 'Online',
              ),
            );
          }
        
          @pragma('vm:entry-point')
          static void onStartForeground(ServiceInstance service) async {
            service.on('login').listen((event) async {
              // Example login event detection
              if (event == 'successful_login') {
                _loginController.add('login_successful');
              }
            });
          }
        }
    
    2. Listen for the Stream in AuthProvider
    In your AuthProvider (or other provider), listen to the stream and trigger navigation when the event is received.
    
        import 'package:flutter/material.dart';
    import 'background_service.dart';
    
    class AuthProvider with ChangeNotifier {
      AuthProvider() {
        _listenToLoginStream();
      }
    
      void _listenToLoginStream() {
        BackgroundService.loginStream.listen((event) {
          if (event == 'login_successful') {
            navigatorKey.currentState?.pushNamed('/home');
          }
        });
      }
    }

3. Update MyApp to Use the AuthProvider
Since AuthProvider is already used in MyApp, it will listen for background service events and handle navigation.

4. Trigger the Background Service Login Event
Make sure your background service sends the 'login' event when the user logs in. For example, in SipUAListenerBackground:

    class SipUAListenerBackground implements SipUaHelperListener {
  @override
  void registrationStateChanged(RegistrationState state) async {
    if (state == RegistrationState.registered) {
      BackgroundService.loginStream.add('login_successful');  // Send event to UI
    }
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.