我在 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 的 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();
}
}
}