如何有条件地通过AppIntents打开应用?

huangapple go评论85阅读模式
英文:

How to open App via AppIntents conditionally?

问题

我目前正在创建一个App,它应该通过一个AppIntent来启动。例如,每当我打开Instagram时,它应该触发AppIntent,然后决定是否要打开我的App。第一部分已经通过Apple Shortcuts正常工作。

问题是动态地打开不打开我的App。不幸的是,openAppWhenRun字段应该是静态的,不能在运行时计算。

这是到目前为止的AppIntent:

struct OpenTimeEfficientIntent: AppIntent {
    
    static var title: LocalizedStringResource = "Opens the app conditionally"
    static var openAppWhenRun: Bool = false
    @Parameter(title: "OpenedApp", optionsProvider: Provider())
    var app: String //这是最初打开的App,例如Instagram(我想传递它)
    
    @MainActor
    func perform() async throws -> some IntentResult & ProvidesDialog {
        //在这一点上,我想决定是否启动该App
    }
}

只是为了明确一下:我不想决定要打开哪个视图,而是要决定是否要打开这个App

我尝试了什么?

我已经尝试通过深层链接来打开App,但在iOS上是不允许的,因为AppIntent只是一个后台任务:“该App既不可见也没有权限,因此不能执行不受信任的用户操作”。

尝试动态设置openAppWhenRun也没有成功。

背景信息

这个App基本上是一个确认对话框。当我按下“否”时,App关闭,什么都不会发生。当我按下“是”时,Instagram会再次打开。但在这种情况下,我不想再次启动我的App,以防止陷入循环。

英文:

I am currently creating an App which is supposed to launch via an AppIntent. For example whenever I open Instagram it should trigger the AppIntent, which then decides if my App is supposed to open or not. The first part already works fine via Apple Shortcuts.
The problem is dynamically opening or not opening my App. Unfortunately the openAppWhenRun field is supposed to be static and cannot be computed at runtime.

Here is the AppIntent so far:

struct OpenTimeEfficientIntent: AppIntent {
    
    static var title: LocalizedStringResource = "Opens the app conditionally"
    static var openAppWhenRun: Bool = false
    @Parameter(title: "OpenedApp", optionsProvider: Provider())
    var app: String //this is the initially opened app e.g. Instagram (i want to pass it)
    
    @MainActor
    func perform() async throws -> some IntentResult & ProvidesDialog {
        //at this point I want to decide, whether the app should be launched or not
    }
}

Just to specify: I don't want to decide which view I want to open but rather if I want to open the App at all.

What did I try?

I already tried to open the app via Deeplinks which is not allowed on iOS as the AppIntent is just a background task: The App is neither visible nor entitled, so may not perform un-trusted user actions

Trying to set the openAppWhenRun dynamically didn't work either.

For context

The app is basically a confirmation dialog. When I press no, the app closes and nothing happens. When I press yes, Instagram would be opened again. But in that case I don't want to launch my app again to prevent being stuck in a loop.

答案1

得分: 0

如果您采用ForegroundContinuableIntent而不是AppIntent,它将在后台运行,直到您在perform函数中指示需要打开您的应用程序。这使您可以有条件地决定是否要打开您的应用程序。

@available(iOS 16.4, *)
struct OpenTimeEfficientIntent: ForegroundContinuableIntent {
    
    static var title: LocalizedStringResource = "有条件地打开应用"
    static var openAppWhenRun: Bool = false

    @Parameter(title: "已打开的应用", optionsProvider: Provider())
    var app: String // 这是最初打开的应用程序,例如 Instagram(我想要传递它)
    
    @MainActor
    func perform() async throws -> some IntentResult & ProvidesDialog {
        // 在这一点上,您可以决定是否应将应用程序置于前台

        // 停止执行应用程序意图并要求用户继续在前台打开应用程序
        throw needsToContinueInForegroundError()

        // 您可以自定义对话框,和/或提供一个在打开应用程序后执行某些操作的闭包
        throw needsToContinueInForegroundError("请继续打开应用程序。") {
            UIApplication.shared.open(URL(string: "yourapp://deeplinktocontent")!)
        }

        // 或者,您可以要求用户继续在前台执行意图 - 如果他们取消,意图将停止,如果他们继续,意图执行将与应用程序打开一起继续
        // 此API还接受可选的对话框和继续闭包
        try await requestToContinueInForeground()
        return .result(dialog: "我打开了应用程序。")
    }

}
英文:

If you adopt ForegroundContinuableIntent rather than AppIntent, it will run in the background until you indicate it needs to open your app in the perform function. This allows you to conditionally decide whether you want to open your app.

@available(iOS 16.4, *)
struct OpenTimeEfficientIntent: ForegroundContinuableIntent {
    
    static var title: LocalizedStringResource = "Opens the app conditionally"
    static var openAppWhenRun: Bool = false

    @Parameter(title: "OpenedApp", optionsProvider: Provider())
    var app: String //this is the initially opened app e.g. Instagram (i want to pass it)
    
    @MainActor
    func perform() async throws -> some IntentResult & ProvidesDialog {
        //at this point you can decide whether the app should be brought to the foreground or not

        // Stop performing the app intent and ask the user to continue to open the app in the foreground
        throw needsToContinueInForegroundError()

        // You can customize the dialog and/or provide a closure to do something in your app after it's opened
        throw needsToContinueInForegroundError("Please continue to open the app.") {
            UIApplication.shared.open(URL(string: "yourapp://deeplinktocontent")!)
        }

        // Or you could ask the user to continue performing the intent in the foreground - if they cancel the intent stops, if they continue the intent execution resumes with the app open
        // This API also accepts an optional dialog and continuation closure
        try await requestToContinueInForeground()
        return .result(dialog: "I opened the app.")
    }

}

huangapple
  • 本文由 发表于 2023年6月18日 19:46:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/76500378.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定