使用意图系统UI启动应用程序示例

学习如何使用意图从系统UI启动应用程序。

The Launch Intents example with two applications running.

简介

本示例向您展示了如何将意图作为系统UI中启动器的依据。

先决条件:您已经熟悉在“Hello World!”系统UI示例中介绍的概念和主题。此示例使用相同的文件夹结构,并以相同的方式启动。

与“Hello World”示例不同,我们不是直接使用ApplicationObject抽象层启动应用程序,而是使用由软件包注册的launch意图。这样我们可以在启动器中拥有多个图标,可以启动相同的应用程序,触发应用程序内的不同功能。

注意:任何针对应用程序的意图都会启动它,如果它尚未运行。为了本示例的目的,我们将我们的意图命名为launch,但应用程序管理器并不赋予此名称特殊含义。

所有launcher类别的意图图标和名称都在左侧。您可以点击它们的图标将相应的意图请求发送到系统:如果相应的应用程序尚未运行,则会自动启动。在图标上按住并释放将停止ApplicationObject。就像在“Hello World!”示例中一样,右侧的列布局显示了所有运行应用程序的窗口。

应用程序在相应颜色的背景上显示其应用程序名称。此外,它们还显示它们收到多少次launch类别意图。

实现系统UI

与任何简单的QML应用程序一样,示例的代码从一些导入和一个根级的普通Item开始。唯一的区别是我们还导入了QtApplicationManagerQtApplicationManager.SystemUI模块,除了QtQuick

import QtQuick 2.12
import QtApplicationManager 2.0
import QtApplicationManager.SystemUI 2.0

Item {
    width: 800
    height: 600

与“Hello World”示例不同,我们现在创建了一个IntentModel来访问所有在launcher类别的意图。由于此模型默认未排序,我们还根据意图的名称设置排序顺序为降序。

注意:类别的名称可以是您喜欢的任何名称,只要它与应用程序的info.yaml元数据和应用程序内的相应IntentHandler之间保持一致。

    IntentModel {
        id: intentModel
        filterFunction: function(i) { return i.categories.contains("launcher") }
        sortFunction: function(li, ri) { return li.name > ri.name }
    }

然后,在根Item的左侧有一个列,我们放置了可用意图的图标及其名称。

    // Show intent names and icons
    Column {
        spacing: 20
        Repeater {
            model: intentModel
            Column {
                Image {
                    source: model.icon
                    MouseArea {
                        anchors.fill: parent
                        onPressAndHold: {
                            var app = ApplicationManager.application(model.applicationId)
                            if (app.runState === Am.Running)
                                app.stop()
                        }
                        onClicked: {
                            IntentClient.sendIntentRequest(model.intentId, model.applicationId, {})
                        }
                    }
                }
                Text {
                    font.pixelSize: 20
                    text: model.name
                }
            }
        }
    }

我们使用我们的IntentModel,该模型为每个可用意图提供一行。在每行中,我们有

  • 一个带有图标URL的icon角色
  • 一个带有本地化意图名称的name角色
  • 一个包含意图id的intentId角色
  • 一个包含处理应用程序id的applicationId角色

有关其他可用的角色的信息,请参阅IntentServer QML类型

接下来,我们在根Item的右侧放置一个锚定的Column。该项目与“Hello World!”示例中的完全相同,显示了所有应用程序窗口。

实现该应用程序

我们的启动 Intent 应用程序以文本形式在其彩色背景上显示应用程序名称。

import QtQuick 2.12
import QtApplicationManager.Application 2.0

ApplicationManagerWindow {
    color: "blue"

    Text {
        id: txt

        property int counter: 0

        anchors.centerIn: parent
        text: ApplicationInterface.name["en"] + "\nLaunch intents received: " + counter
    }

    IntentHandler {
        intentIds: [ "launch" ]
        onRequestReceived: {
            txt.counter++
            request.sendReply({})
        }
    }
}

与“Hello World”示例中的例子之间的唯一区别是,我们通过一个IntentHandler处理额外的传入 launch 意图请求:此 IntentHandler 在本示例中不做任何有用的事情,除了在 Text 对象中增加计数器,以便您可以查看启动意图被接收的次数。有关 IntentClientRequest::sendReply 调用的更多信息,请参阅IntentHandler::requestReceived 文档。

应用程序元数据

info.yaml 文件包含有关包的元数据。它以一些通用文本开始,描述了该文件包含 Qt 应用程序管理器的包元数据。

formatVersion: 1
formatType: am-package
---

然后是包 ID,它唯一地标识了该包。建议遵循反向 DNS 方案,但不是强制性的。这里是“Launch Intents”示例 UI 中的“Blue”包。

id:      'launch-intents.blue'

然后是图标文件名

icon:    'icon.png'

接下来是应用程序在任意多语言中的用户可见名称。对于此示例,我们只提供英语

name:
  en: 'Blue App'

对于每个包,我们定义一个应用程序,它获得与包本身相同的 id(这不是一个要求,但是一种有用的方法,用于单个应用程序的包)。

applications:
- id: launch-intents.blue
  runtime: 'qml'
  code:    'main.qml'

每个包至少将注册一个在 launcher 类别中的 launch 意图。在这个情况下,意图的确切名称并不重要,因为系统 UI 将请求所有在 launcher 类别中的意图。意图的名称和图标默认为包的名称和图标,但在这里我们覆盖了名称

intents:
- id: launch
  name:
    en: 'Launch Blue'
  categories: [ launcher ]
别名处理

红色应用程序比蓝色和绿色版本做得更多:它使用意图实现已废弃的“别名”机制。

在其 info.yaml 文件中,它定义了在 launcher 类别中的第二个意图,名称为 another-launch

- id: another-launch
  name:
    en: 'Launch Another Red'
  categories: [ launcher ]

为了处理此意图,main.qml 文件中的 IntentHandler 扩展到接受这两个意图

    IntentHandler {
        intentIds: [ "launch", "another-launch" ]

传入意图请求的信号处理器可以根据其 intentId 区分请求的意图,并增加文本字段中正常的 counteranotherCounter 属性。

        onRequestReceived: {
            if (request.intentId === "launch")
                txt.counter++
            else
                txt.anotherCounter++
            request.sendReply({})
        }

注意:除了一个IntentHandler处理两个意图之外,也可以使用两个单独的 IntentHandlers 实现此功能,每个处理一个意图。

示例项目 @ code.qt.io

©2019 瑞典乌克斯佛特 Luxoft AB。所包含的文档贡献的版权属于其各自的所有者。所提供的文档受GNU 自由文档许可证版本 1.3条款许可,由自由软件基金会发布。Qt 及其 respective 标志是芬兰和/或全球其他国家的 The Qt Company Ltd. 的商标。所有其他商标均为其各自所有者的财产。