Flutter app_links 通用深层链接未在 URI 流监听中返回。不导航到应用程序中的路线,仅打开仪表板

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

我在 Android 中可以使用此功能,它会导航到应用程序深处的页面,但在 ios 上仍然遇到问题。我想通过链接导航到我的应用程序中的某些路线,单击链接时它会在 ios 中打开我的应用程序,但无法导航到我定义的路线,它甚至不会在 flutter 监听中返回任何内容,但是它正在捕获 url,因为 AppDelegate 中的调试输出输出了我单击的正确 url。我真的不知道此时我错过了什么。

使用此包进行深层链接:https://pub.dev/packages/app_links

我的链接就像 https://mydomain/pub-crawl/{unique-id}

我已将我的域作为 applinks:mydomain 添加到关联域中,并将 Info.plist 中的 FlutterDeepLinkingEnabled 设置为 false 并尝试使用 true,但结果是相同的。

这是我初始化它的控制器,我稍后在 setupInitialStuff 函数中调用handleIncomingLinks 函数,这样如果是冷启动,我可以进行初始用户设置。

class SplashController extends GetxController {
  late final AppLinks appLinks;
  StreamSubscription? streamSub;

  @override
  void onReady() async {
    appLinks = AppLinks();
    await setupInitialStuff();
    super.onReady();
  }

  @override
  void onClose() {
    streamSub?.cancel();  // Clean up the stream subscription
    super.onClose();
  }

  Future<void> handleIncomingLinks() async {
    // Listen for deep links while the app is running
    
    streamSub = appLinks.uriLinkStream.listen((Uri? uri) {
      if (uri != null) {
        deepLinkNavigation(uri);
      }
    }, onError: (err) {
      print('Failed to receive deep link: $err');
    });
  }



  Future<void> deepLinkNavigation(Uri uri) async {

    // Extract the first segment to determine the prefix (e.g., "pub-crawl" or "business")
    final prefix = uri.pathSegments.first;
    final uniqname = uri.pathSegments.last;

    // Add a small delay to ensure the home screen is visible first
    await Future.delayed(Duration(milliseconds: 500));

    if (prefix == "pub-crawl") {
      await MyApplication.pubCrawlController.goToPubCrawlDeepLink(uniqname);
    } else if (prefix == "business") {
      await MyApplication.businessController.goToBusinessDeepLink(uniqname);
    } else {
      // Handle unexpected prefixes or add a fallback
      print('Unknown prefix: $prefix');
    }
  }
  
  Future<void> setupInitialStuff() async {
    //do stuff at app start
    await handleIncomingLinks();
  }
}

我的AppDelegate.swift

import UIKit
import Flutter
import app_links

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)

    // Retrieve the link from parameters
    if let url = AppLinks.shared.getLink(launchOptions: launchOptions) {
      // We have a link, propagate it to your Flutter app or not
      AppLinks.shared.handleLink(url: url)
      return true // Returning true will stop the propagation to other packages
    }

    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }



}

我的 apple-app-site-association 在我的域/.well-known/apple-app-site-association 中以 json 形式提供

{
  "applinks": {
    "apps": [],
    "details": [
      {
        "appID": "MyTeamId.com.bundle.identifier",
        "paths": ["/pub-crawl/*", "/business/*"]
      }
    ]
  }
}
ios flutter deep-linking applinks
1个回答
0
投票

这不是理想的解决方案,因为我更喜欢简单地使用该包,但我已将其设置为专门用于 ios 的 MethodChannels,但继续使用适用于 android 的包。对我来说效果很好,所以无论如何,但仍然不确定为什么该包不起作用。

AppDelegate.swift

import UIKit
import Flutter
import app_links

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  
  var methodChannel: FlutterMethodChannel?

  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)

    // Set up method channel for deep links
    if let controller = window?.rootViewController as? FlutterViewController {
      methodChannel = FlutterMethodChannel(name: "my.bundle.identifier/deeplink", binaryMessenger: controller.binaryMessenger)
    }

    // Handle deep link if app is launched with a URL
    if let url = AppLinks.shared.getLink(launchOptions: launchOptions) {
      sendDeepLinkToFlutter(url: url)
      return true
    }

    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }

  // Handle Universal Links when the app is already running
  override func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
    if let incomingURL = userActivity.webpageURL {
      // Pass the URL to Flutter
      sendDeepLinkToFlutter(url: incomingURL)
    }
    return true
  }

  // Custom method to send the URL to Flutter using a platform channel
  private func sendDeepLinkToFlutter(url: URL) {
    methodChannel?.invokeMethod("onDeepLink", arguments: url.absoluteString)
  }
}

我的控制器


class SplashController extends GetxController {
  late final AppLinks appLinks;
  StreamSubscription? streamSub;
  static const platform = MethodChannel('my.bundle.identifier/deeplink');

  @override
  void onReady() async {
    appLinks = AppLinks();
    await setupInitialStuff();
    super.onReady();
  }

  @override
  void onClose() {
    streamSub?.cancel();  // Clean up the stream subscription
    super.onClose();
  }


  Future<void> handleIncomingLinks() async {
    streamSub = appLinks.uriLinkStream.listen((Uri? uri) {
      if (uri != null) {
        deepLinkNavigation(uri);
      } else {
        print('No URI received.');
      }
    }, onError: (err) {
      print('Failed to receive deep link: $err');
    });
  }

  // Method to handle incoming links via Method Channel for iOS
  void handleMethodChannelForIOS() {
    platform.setMethodCallHandler((MethodCall call) async {
      if (call.method == 'onDeepLink') {
        final String? url = call.arguments;
        if (url != null) {
          Uri uri = Uri.parse(url);
          print('Received deep link from iOS: $uri');
          deepLinkNavigation(uri);
        }
      }
    });
  }


  Future<void> deepLinkNavigation(Uri uri) async {
    final prefix = uri.pathSegments.first;
    final uniqname = uri.pathSegments.last;

    if (prefix == "pub-crawl") {
      await MyApplication.pubCrawlController.goToPubCrawlDeepLink(uniqname);
    } else if (prefix == "business") {
      await MyApplication.businessController.goToBusinessDeepLink(uniqname);
    } else {
      print('Unknown prefix: $prefix');
    }
  }

  Future<void> setupInitialStuff() async {
    if (Platform.isIOS) {
        handleMethodChannelForIOS();
      } else {
        handleIncomingLinks();
      }
  }

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