意图

与移动操作系统中使用的意图概念类似,应用程序管理器的意图系统建立在应用程序和系统 UI 之间拥有轻量级进程间通信 (IPC) 机制的理念之上,而不依赖于硬编码的耦合或甚至是编译时的依赖。意图本身是发送应用程序希望由系统中最能胜任的部分执行的动作描述。确保这些意图请求被路由到正确的接收者,是应用程序管理器的责任。一个简单的例子是一个 showImage 意图,其中发送应用程序可以要求系统显示一个图像文件:如果系统已安装了一个注册处理 showImage 意图的图像查看器应用程序,则任何应用程序都可以显示图像文件,而无需了解图像查看器应用程序的任何具体信息。

Android 文档 也对这个概念有很好的介绍。

应用程序管理器对意图的处理方法非常简单:虽然与其它解决方案相比(例如,支持二进制数据或系统广播)仍缺少一些功能,但它也提供了一个非常简单和直接的 API。

注意:虽然移动操作系统提供了意图 机制 以及所有定义的 意图 API 的描述,但应用程序管理器只提供了这个机制。这与应用程序管理器其它模块中使用的哲学一致,其中系统 UI 负责定义系统的界面和行为。

以下是一些术语,以帮助理解意图请求中涉及的各个 ID 之间的区别

  • intentId:意图的名称或类。在复杂的系统中,使用反向 DNS 表示法在这里是有意义的,例如 io.qt.openUrl
  • requestId:UUID,用于在整个系统中跟踪意图请求,因为它跨越了系统 UI 和最多两个应用程序之间的进程边界。
  • 表示处理请求的应用程序。这直接映射到 ApplicationObject::id 的值。如果处理应用程序实际上是系统 UI,则此 ID 将具有特殊值 :sysui:
  • requestingApplicationIdapplicationId 做同样的事情,但针对发出请求的应用程序。如果请求应用程序实际上是系统 UI,则此 ID 将具有特殊值 :sysui:

可以在意图请求中附加上任意的数据(见 IntentClient::sendIntentRequest)和意图请求回复中(见 IntentRequest::sendReply)。请注意,必须首先将此数据从 JavaScript 对象序列化到底层的 IPC 传输,然后将它反序列化为JavaScript对象。强烈建议将参数对象和结果对象中的类型限制为 JSON 类型。

注册意图

每个应用程序在其 info.yaml 清单文件中定义它能够处理的意图。请注意,打包工具和应用程序管理器都无法验证清单文件中的意图 ID 对您具体的工程是否有效。

此外,系统UI本身也可以注册意图:在这种情况下不需要单独的清单文件,而是由QML处理器对象本身负责提供注册所需的数据;请参阅下一节

应用管理器在启动时解析所有这些清单文件(以及当应用程序在运行时安装)。只有应用管理器本身和系统UI可以访问所有应用程序定义的所有已注册意图的完整列表;出于安全和隐私原因,应用程序本身不能访问此列表。

在QML中处理意图

为了在您的QML应用程序中处理意图,您必须为在清单文件中定义的所有意图实例化IntentHandler项目。确保这些项目与应用程序的QML根对象一起构造,并且在之后永远不会被删除。

任何传入的意图请求都将与已在应用程序和系统UI中注册的所有先前意图进行匹配。当应用管理器确定您的应用程序负责处理此类意图时,它将首先启动您的应用程序(如果它尚未运行),然后在应用程序端发出适当的IntentHandlerrequestReceived信号。可以通过同步或异步方式响应对这些传入请求的回复。

至于在系统UI中处理意图:您必须实例化IntentServerHandler项目,而不是创建IntentHandler项目。实际上,IntentServerHandler是从IntentHandler派生出来的,所以它以与应用程序端对应方式相同工作:它只需添加所需属性以定义所有元数据(例如namesicon等),而对于应用程序而言这些是通过清单文件提供的。

在QML中创建意图请求

想要发送意图请求的应用程序可以通过调用工厂函数IntentClient::sendIntentRequest()来完成。这些请求不能通过其他方式创建。请求将立即发送到系统,然后可以使用返回的IntentRequest对象来跟踪此请求的完成和可能的结果值。

在系统UI中,您可以使用完全相同的机制来创建和跟踪意图请求。

在系统UI中消除意图请求的歧义

如果传入的意图请求可能由多个应用程序处理,应用管理器将联系系统UI以消除歧义并选择一个应用程序。系统UI可以通过连接到IntentServer::disambiguationRequest()信号来对此做出反应,然后通过acknowledgeDisambiguationRequest选择可能的其中一个应用程序。如果无法消除歧义,甚至可以通过rejectDisambiguationRequest来拒绝请求。

系统UI中的IntentModel

尽管应用只知道自己的意图,但System UI通过IntentServer单例和IntentModel类完全访问所有已注册意图的元数据。就像与ApplicationManager单例和ApplicationModel类一样,IntentServer是系统范围内持有所有数据的单例,而IntentModel类可以用来提供一个方便的排序和过滤模型接口,用于访问原始数据。

通过使用这些模型接口,原本在ApplicationModel上操作的经典启动器网格可以用一个使用IntentModel的版本来替换,这样应用程序就会通过特定的意图请求启动,这些请求可能包括参数,而不是仅仅调用ApplicationObject::start()函数。

原生应用的意图

意图机制使用D-Bus作为System UI和应用进程之间的传输协议。D-Bus接口定义在文件src/dbus-lib/io.qt.applicationmanager.intentinterface.xml中。D-Bus API与QML API非常相似。意图、应用程序和请求ID以字符串形式发送,而参数在JavaScript对象和D-Bus a{sv}变体字典之间进行转换。

如果您使用的是应用程序管理器的便利的launcher-lib作为您混合原生和QML应用程序的基本构建块,那么所有的D-Bus处理已经为您实现,并且您可以像上面描述的那样使用IntentHandler项。

©2019 Luxoft Sweden AB。本文件中包含的文档贡献是各自所有者的版权。提供的文档是根据自由软件基金会的规定,以GNU自由文档许可证版本1.3的条款许可的。Qt及其相应标志是芬兰Qt公司及/或世界其他地区的商标。所有其他商标均为各自所有者的财产。