当应用程序未在 iOS 上启动时,与 go router 的深度链接不会导航到正确的屏幕

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

我正在尝试使用 go_router 实现深度链接。在 Android 上一切正常,但在 iOS 上,仅当应用程序打开且位于后台时,打开深层链接 URL 才会将应用程序打开到正确的屏幕。如果应用程序关闭,深层链接 URL 仅打开登录屏幕。

这是我的设置

信息.plist

<key>CFBundleURLTypes</key>
<array>
<dict>
    <key>CFBundleTypeRole</key>
    <string>Editor</string>
    <key>CFBundleURLSchemes</key>
    <array>
        <string>appscheme</string>
        <string>${GOOGLE_REVERSED_CLIENT_ID}</string>
    </array>
</dict>
</array>

app.dart

MaterialApp.router(
  debugShowCheckedModeBanner: false,
  routerConfig: GoRouter(
    routes: [ 
      GoRoute( 
        path: '/',
        builder: (context, state) => const LoginPage( key: Key('loginPage',),),
      ), 
      GoRoute( 
        path: '/sign-up',
        builder: (context, state) => const SignUpPage( key: Key('signUpPage'), ), 
      ),
    ],
  ),
);

调用深层链接

xcrun simctl openurl booted "appscheme:/sign-up"

ios flutter deep-linking flutter-go-router
1个回答
0
投票

让我们看看如何在 iOS 上处理深度链接:

AppDelegate.swift 中的 Swift 代码:

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  
  private var methodChannel: FlutterMethodChannel?
  private var eventChannel: FlutterEventChannel?
  
  private let linkStreamHandler = LinkStreamHandler()
  
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    
    let controller = window.rootViewController as! FlutterViewController
    
    // Create a MethodChannel for invoking methods from Dart to Swift
    methodChannel = FlutterMethodChannel(name: "deeplink.flutter.dev/channel", binaryMessenger: controller.binaryMessenger)
    
    // Create an EventChannel to listen for deep link events from Swift to Dart
    eventChannel = FlutterEventChannel(name: "deeplink.flutter.dev/events", binaryMessenger: controller.binaryMessenger)

    // Set up a method call handler for incoming method calls from Dart
    methodChannel?.setMethodCallHandler({ (call: FlutterMethodCall, result: FlutterResult) in
      guard call.method == "initialLink" else {
        result(FlutterMethodNotImplemented)
        return
      }
    })

    // Register Flutter plugins
    GeneratedPluginRegistrant.register(with: self)
    
    // Set the stream handler for the EventChannel to handle incoming deep links
    eventChannel?.setStreamHandler(linkStreamHandler)
    
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
  
  // Handle deep link events when the app is already open
  override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    // Set the stream handler for the EventChannel to handle the deep link
    eventChannel?.setStreamHandler(linkStreamHandler)
    return linkStreamHandler.handleLink(url.absoluteString)
  }
}

// Create a class to handle incoming deep links
class LinkStreamHandler: NSObject, FlutterStreamHandler {
  
  var eventSink: FlutterEventSink?
  
  // Store links in a queue until the sink is ready to process them
  var queuedLinks = [String]()
  
  func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
    self.eventSink = events
    
    // Send any queued links to the sink
    queuedLinks.forEach({ events($0) })
    queuedLinks.removeAll()
    
    return nil
  }
  
  func onCancel(withArguments arguments: Any?) -> FlutterError? {
    self.eventSink = nil
    return nil
  }
  
  func handleLink(_ link: String) -> Bool {
    guard let eventSink = eventSink else {
      // Queue the link if the event sink is not ready
      queuedLinks.append(link)
      return false
    }
    // Send the link to the event sink
    eventSink(link)
    return true
  }
}

AppDelegate.swift说明:

  • AppDelegate.swift
    中,我们为在 iOS 上运行的 Flutter 应用程序设置了深度链接处理。
  • 我们创建一个名为“deeplink.flutter.dev/channel”的
    MethodChannel
    ,以允许 Dart 调用 Swift 中的方法。
  • 创建一个名为“deeplink.flutter.dev/events”的
    EventChannel
    来监听从Swift到Dart的深层链接事件。
  • 我们设置了一个方法调用处理程序来处理来自 Dart 的方法调用,特别是“initialLink”方法。
  • Flutter 插件已注册到
    GeneratedPluginRegistrant.register(with: self)
  • LinkStreamHandler
    类处理传入的深层链接并将其发送到 Flutter 应用程序。

现在,我们来解释一下

main.dart
中的Dart代码:

main.dart 中的 Dart 代码:

final navigatorKey = GlobalKey<NavigatorState>();
void main() {
  WidgetsFlutterBinding.ensureInitialized();

  // Event Channel creation
  const stream = EventChannel('deeplink.flutter.dev/events');

  // Method channel creation
  const platform = MethodChannel('deeplink.flutter.dev/channel');

  Future<String?> startUri() async {
    try {
      return platform.invokeMethod('initialLink');
    } on PlatformException catch (e) {
      return "Failed to Invoke: '${e.message}'.";
    }
  }

  onRedirected(String? uri) {
    debugPrint("uri: $uri");
    if (uri == "deeplink://login") {
      GoRouter.of(navigatorKey.currentContext!).push('/login');
    } else if (uri == "deeplink://sign-up") {
      GoRouter.of(navigatorKey.currentContext!).push('/sign-up');
    }
  }

  stream.receiveBroadcastStream().listen((d) {
    // Checking application start by deep link
    startUri().then(onRedirected);
    // Checking broadcast stream if a deep link was clicked in an opened application
    stream.receiveBroadcastStream().listen((d) => onRedirected(d));
  });

  runApp(MaterialApp.router(routerConfig: router));
}

// Define your GoRouter routes and pages
final router = GoRouter(
  debugLogDiagnostics: true,
  initialLocation: "/login",
  navigatorKey: navigatorKey,
  routes: [
    GoRoute(
      path: '/login',
      builder: (context, state) => const LoginPage(
        key: Key('loginPage'),
      ),
    ),
    GoRoute(
      path: '/sign-up',
      builder: (context, state) => const SignUpPage(
        key: Key('signUpPage'),
      ),
    ),
  ],
);

// Define your Flutter pages
class LoginPage extends StatelessWidget {
  const LoginPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("Login")),
      body: const Center(child: Text("Login Page")),
    );
  }
}

class SignUpPage extends StatelessWidget {
  const SignUpPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("Sign Up")),
      body: const Center(child: Text("Sign Up Page")),
    );
  }
}

main.dart 说明:

  • main.dart
    中,我们设置了深层链接处理

适用于 Flutter 应用程序。

  • 我们创建一个名为“deeplink.flutter.dev/events”的
    EventChannel
    来监听从Swift到Dart的深层链接事件。
  • 创建一个名为“deeplink.flutter.dev/channel”的
    MethodChannel
    来调用 Swift 中的方法。
  • startUri
    是一个尝试从 Swift 调用“initialLink”方法并处理异常的函数。
  • onRedirected
    是一个处理深度链接URI的函数,使用GoRouter包推送相应的路由。
  • 我们在应用程序启动和运行时收听广播流以检查深层链接。
  • router
    对象定义GoRouter包的路由和页面。

这些代码段共同实现了 Flutter 和本机 iOS 代码之间的深层链接的无缝处理,从而允许使用 Swift 控制 iOS 上的 Flutter 应用程序内的深层链接转换。

更多详情,您可以参考文章这里

© www.soinside.com 2019 - 2024. All rights reserved.