Flutter Siri 集成:应用程序未启动并导航到页面

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

我有一个 Flutter 应用程序,我使用 GetX 进行状态管理。在项目中,我想集成Siri。当我对 Siri 说“打开作业 MyApp”时,我希望应用程序打开并导航到作业页面。为了实现这一点,我在 Apple 方面使用了意图和快捷方式,并尝试使用 MethodChannel 来处理导航。

当我按照流程进行调试时,场景是这样展开的:我打开 Siri 并说出这句话,我可以跟踪我设置的打印和断点,并且我看到如下所示的日志。但是,该应用程序不会立即打开和导航。但是当我手动打开应用程序时,导航就会开始。

我想要实现的是,一旦说出该短语,应用程序就会打开并导航到相关页面。我包含了我在 Flutter 端编写的意图、快捷方式、应用程序委托和 MethodChannel 代码。

应用程序委托:

import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  private let navigationChannel = "com.example.myapp/navigation"
 
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)
    setupSiriShortcuts(application: application)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
 
  private func setupSiriShortcuts(application: UIApplication) {
    let activity = NSUserActivity(activityType: "com.example.myapp.openhomework")
    activity.title = "Open Homework Page"
    activity.isEligibleForSearch = true
    activity.isEligibleForPrediction = true
    activity.isEligibleForPublicIndexing = true
    activity.persistentIdentifier = NSUserActivityPersistentIdentifier("com.example.myapp.openhomework")
    activity.userInfo = ["intentName": "openHomeworkPage"]
    
    self.userActivity = activity
    application.userActivity = activity
  }
 
  override func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
    if userActivity.activityType == "com.example.myapp.openhomework",
       let viewController = window.rootViewController as? FlutterViewController {
      let navigationChannel = FlutterMethodChannel(name: self.navigationChannel, binaryMessenger: viewController.binaryMessenger)
      
        application.windows.first?.makeKeyAndVisible()
        
        navigationChannel.invokeMethod("openHomeworkPage", arguments: nil)
        
    
      
    }
    return true
  }
}

意图:

import Foundation
import AppIntents
import Flutter

@available(iOS 16.0, *)
struct OpenHomeworkPageIntent: AppIntent {
    static let title: LocalizedStringResource = "Open Homework MyApp"
    
    func perform() async throws -> some IntentResult & ProvidesDialog {
        print("Perform function started.")
        
         guard let windowScene = await UIApplication.shared.connectedScenes.first as? UIWindowScene,
               let viewController = await windowScene.windows.first?.rootViewController as? FlutterViewController else {
             return .result(dialog: "Error: App not started.")
          }
        
        
        let navigationChannel = await FlutterMethodChannel(name: "com.example.myapp.openhomework", binaryMessenger: viewController.binaryMessenger)
        
        // Dispatch the invokeMethod call on the main thread
        DispatchQueue.main.async {
            print("Invoking openHomeworkPage method.")
        
            navigationChannel.invokeMethod("openHomeworkPage", arguments: nil)
        }
        
        print("Perform function completed.")
        return .result(dialog: "Homework page open.")
    }
}


快捷键:

import Foundation
import AppIntents

@available(iOS 16.0, *)
struct OpenHomeworkPageShortcuts: AppShortcutsProvider {
    static var appShortcuts: [AppShortcut] {
        AppShortcut(
         intent: OpenHomeworkPageIntent(),
         phrases: [
            "Open homework \(.applicationName)"
         ],
         shortTitle: "Homework open"
        )
    }
}

flutter 中的方法通道:

static const platform = MethodChannel('com.example.myapp.openhomework');

  @override
  void initState() {
    platform.setMethodCallHandler(_handleMethodCall);
  }


  Future<void> _handleMethodCall(MethodCall call) async {
    print("methodChannel: ${call.method} ${call.arguments}");

    switch (call.method) {
      case 'openHomeworkPage':
        try {
          print("Navigating to HomeworkScreen...");
          Get.offNamed(AppNavigation.HOMEWORK);
        } catch (e) {
          print("Error navigating to HomeworkScreen: $e");
        }
        break;
      default:
        print('Unknown method: ${call.method}');
    }
  }

调试日志:

-[WFBackgroundShortcutRunner runWorkflowWithDescriptor:request:inEnvironment:runningContext:completion:] Disabling privacy prompts because this is an on-the-fly shortcut.
Starting shortcut run: <WFWorkflow: 0xa660a9180, name: Open homework Metodbox , actions: 1>, request: <WFSiriWorkflowRunRequest: 0xa66114780, runSource: siri, input: no, presentationMode: Siri, output behavior: Ignore, automationType: (null), allowsHandoff: no, allowsDialogNotifications: no>
Running action <WFLinkAction: 0x102a7caf0, identifier: com.bkmobil.metodboxxx.OpenHomeworkPageIntent>
Action finished running <WFLinkAction: 0x102a7caf0, identifier: com.bkmobil.metodboxxx.OpenHomeworkPageIntent>.
Shortcut <private> has finished running with output: (null).
-[WFBackgroundShortcutRunner callWorkflowRunningCompletionBlockWithResult:] Workflow Did Finish: Calling Completion Block
-[WFBackgroundShortcutRunner listener:shouldAcceptNewConnection:]_block_invoke XPC connection invalidated
-[WFBackgroundShortcutRunnerStateMachine invalidateWithReason:] connection invalidated/interrupted while finishing shortcut or exiting runner. Exiting should already be in process, not transitioning.
-[WFBackgroundShortcutRunner unaliveProcess]_block_invoke_2 Exiting process
flutter: methodChannel: openHomeworkPage null
flutter: Navigating to HomeworkScreen...
[GETX] REPLACE ROUTE /main
[GETX] NEW ROUTE /splash

Flutter医生总结: enter image description here

我尝试了deeplink而不是methodChannel,我尝试直接用appIntents来做,但我最终决定不走捷径。我想要实现的是,一旦说出该短语,应用程序就会打开并导航到相关页面。

flutter siri sirishortcuts flutter-method-channel
1个回答
0
投票

您尝试通过快捷方式访问的 Flutter 引擎仅在应用程序启动时生成。默认情况下,快捷方式不会启动应用程序。可以添加

static var openAppWhenRun: Bool = true

添加到您的快捷方式,这将确保您的应用程序使用快捷方式启动,但即便如此,Flutter 引擎也需要一些时间来设置才能从 Swift 接收消息。

我建议使用像intelligence这样的插件来为您处理快捷方式的复杂性。

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