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

了解如何使用Intent从系统UI启动应用程序。

The Launch Intents example with two applications running.

注意:如果您想在Linux机器上构建示例,请阅读此内容

简介

本示例显示了如何使用Intent作为系统UI中启动器的依据。

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

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

注意:任何针对应用程序的Intent都会启动它(如果它尚未运行)。为了本示例的目的,我们称我们的intents为launch,但应用程序管理器并没有给这个名称赋予特殊含义。

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

应用程序在其颜色的背景下显示其应用程序名称。此外,它们还显示它们收到launch分类intent的次数。

实现系统UI

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

import QtQuick
import QtApplicationManager
import QtApplicationManager.SystemUI

Item {
    width: 800
    height: 600

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

注意:分类的名字可以是您喜欢的任何名称 - 只要在这里、应用的 info.yaml 元数据和相关的 IntentHandler 一致即可。

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

接下来,我们在根项目左侧有一个列,在这里放置可用的意图及其名称的图标。

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

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

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

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

接下来,我们在根 Item 的右侧放置一个 Column。这个项与 "Hello World!" 示例中正好相同,显示了所有应用窗口。

实现应用

我们的启动意图应用在彩色背景下以文本形式显示其应用名称。

import QtQuick
import QtApplicationManager.Application

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: (request) => {
            txt.counter++
            request.sendReply({})
        }
    }
}

此示例与 "Hello World" 示例的唯一区别在于,我们通过一个 IntentHandler 处理额外的收到的 launch 意图请求:此意图处理程序在此示例中没有执行任何有用的操作,除了增加 Text 对象的计数器,以便您可以看到启动意图收到了多少次。请参阅 IntentHandler::requestReceived 文档以了解 IntentClientRequest::sendReply 调用的更多信息。

应用元数据

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 ]
别名处理

红色应用除了蓝色和绿色版本之外还做了一些操作:它使用意图实现了已弃用的 "aliases" 机制。

在其 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: (request) => {
            if (request.intentId === "launch")
                txt.counter++
            else
                txt.anotherCounter++
            request.sendReply({})
        }

注意:不是使用一个IntentHandler处理所有的意图,这也可以通过两个独立的IntentHandlers来实现,每个处理一个意图。

示例项目 @ code.qt.io

© 2024 Qt公司有限公司。此处所包含的文档贡献属于各自所有者的版权。此处提供的文档是根据自由软件基金会发布的GNU自由文档许可协议1.3版的条款许可的。Qt及其相关标志是芬兰和国外其他国家的Qt公司有限公司的商标。所有其他商标均为各自所有者的财产。