我正在尝试使用 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 上处理深度链接:
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 应用程序设置了深度链接处理。MethodChannel
,以允许 Dart 调用 Swift 中的方法。EventChannel
来监听从Swift到Dart的深层链接事件。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 应用程序。
EventChannel
来监听从Swift到Dart的深层链接事件。MethodChannel
来调用 Swift 中的方法。startUri
是一个尝试从 Swift 调用“initialLink”方法并处理异常的函数。onRedirected
是一个处理深度链接URI的函数,使用GoRouter包推送相应的路由。router
对象定义GoRouter包的路由和页面。这些代码段共同实现了 Flutter 和本机 iOS 代码之间的深层链接的无缝处理,从而允许使用 Swift 控制 iOS 上的 Flutter 应用程序内的深层链接转换。
更多详情,您可以参考文章这里。