App Launcher 应用启动器扩展:用于启动其他应用程序的强大工具,支持独立进程和依赖进程启动,支持参数传递和返回值获取

App Launcher 应用启动器扩展

下载

.aix拓展文件:

de.ullisroboterseite.ursai2applauncher.aix

.aia示例文件:

UrsAI2AppLauncherTest.aia

UrsAI2AppLauncherTestResponder.aia

版本历史

版本 修改内容
1.0 (2020-04-16) 初始版本
2.0 (2020-04-29) - 允许评估启动值和返回值
- 作为独立进程或依赖进程启动
2.1 (2020-06-03) 添加了 MyAppNameMyPackageName
2.2 (2021-05-12) 解决了Android 10设备和小米设备的问题(见说明)
添加属性:CanDrawOverlaysCanLaunchFromBackgroundCurrentLanguageIsXiaomiManufacturerPermissionDelayVersionNameVersionSDK
添加方法:CheckBackgroundLaunchPermissionLaunchAppFromIntentLaunchForResultFromIntentOpenMiuiPermissionEditor
添加事件:AfterBackgroundPermssion
添加权限:SYSTEM_ALERT_WINDOW & ACTION_MANAGE_OVERLAY_PERMISSION
额外的 LauncherIntent 模块提供了更多启动应用执行方式的选项
2.3 (2021-05-12) 如果更改了包名,启动AI2应用(意图类型 Screen)在Kodular上无法工作
2.4 (2021-05-15) 如果更改了包名,启动AI2应用(意图类型 Screen)在Kodular上无法工作。需要进一步更改
2.5 (2021-05-13) LauncherIntent 中的属性 FlagNewTask 被忽略但Android 10需要
属性 FlagNewTask 的默认值为 true
2.6 (2023-09-10) 从Android 11开始,如果要在 getNameListgetPackageList 函数中列出所有文件,需要 QUERY_ALL_PACKAGES 权限

动机

App Inventor允许使用ActivityStarter组件启动其他活动。不幸的是,启动已安装的应用程序非常麻烦。根据说明,必须下载要启动的应用程序的.apk并找到包名。这两者都不容易也不总是可能的。

这个扩展简化了启动应用程序的过程。

⚠️ 重要提示

Android 10及以上版本用户注意:

从Android 10开始,如果应用程序想在后台运行时启动另一个应用程序,需要额外的权限 (SYSTEM_ALERT_WINDOW)(参见 从后台启动活动的限制,最后一点)。此权限无法通过程序设置,必须通过对话框由用户确认(参见 Android 10和小米设备的额外权限)。示例中展示了解决此问题的可能方案。

小米设备制造商用户注意:

对于小米设备,无论安装的Android版本如何,如果应用程序想在后台运行时启动另一个应用程序,都需要额外的权限。此权限无法通过程序设置,必须通过对话框由用户确认(参见 Android 10和小米设备的额外权限)。程序无法查询是否已授予此权限。示例中展示了解决此问题的可能方案。

使用Android 10及更新版本的小米设备用户必须授予两个权限。

使用方法

包名 PackageNames

要启动应用程序,必须知道其包名(例如 “de.ullisroboterseite.ursai2applauncher”)。getNameList 方法提供所有可启动应用程序名称的列表。有过滤选项可以进行预选择。该列表可以在 ListPicker 组件中显示,例如。

PackageFromName 方法返回与指定应用程序关联的包名。然后可以使用包名启动指定的应用程序。

启动模式 LaunchModes

要启动的应用程序可以通过两种方式启动:

  • 应用程序可以作为独立进程启动,即启动的应用程序和被启动的应用程序完全独立工作。用于此的方法以 LaunchApp... 开头
  • 应用程序可以作为依赖进程启动,即启动的应用程序暂停,直到被启动的应用程序结束。这里可以将值从被启动的应用程序返回到调用应用程序。用于此选项的方法以 LaunchForResultApp... 开头

在这两种情况下,都可以用启动值启动被启动的应用程序。

启动应用程序后,会触发 AfterAppLaunched 事件。一个参数指示应用程序是否成功启动。

启动值 StartValues

在Android中,应用程序通过 Intent 启动。Intent 是要执行的操作的抽象描述。Intent包含启动应用程序所需的所有信息,也包含要交换的数据。

要在应用程序之间交换的数据可以作为所谓的 Extras 存储在 Intent 中。Extras 是键值对的列表。被启动的应用程序可以检索并评估这些值。

可以通过不同变体的 Launch... 方法为要启动的应用程序提供启动值:

  1. 首先,可以不使用任何额外的启动值启动应用程序(LaunchAppLaunchAppForResult
  2. 如果要启动的应用程序是AI2应用程序,可以使用AI2参数传输的标准方法。AI2评估 “APP_INVENTOR_START” 键并通过 Control - getStartValueControl - getPlainStartText 方法提供关联的值。参数 StartValue 通过方法 LaunchAI2AppLaunchForResultAI2App 用键 “APP_INVENTOR_START” 存储
  3. LauchAppExtraLauchForResultAppExtra 允许传输单个键值对
  4. LauchAppExtraListLauchForResultAppExtraList 传输键值对列表

返回值 ReturnValues

以下部分仅与作为依赖进程启动的应用程序相关。只有这些应用程序可以返回值。

被调用的应用程序总是可以在不返回结果的情况下被取消。在这种情况下,会触发 ActivityCanceled 事件。

如果被调用的应用程序正常终止,会触发 AfterActivity 事件并可以返回数据。与启动值一样,这些数据在内部作为键值对存储在Intent中。AI2应用程序可以通过块 close screen with valueclose screen with plain text 提供返回值。AI2将此值作为键值对与键 “APP_INVENTOR_RESULT” 一起设置在Intent中。

调用应用程序可以评估返回的Intent。扩展提供了相应的方法:

  1. AfterActivity 事件具有 Result 参数。如果被启动的应用程序返回一个键为 “APP_INVENTOR_RESULT” 的值,该值被转换为字符串并通过参数 Result 提供
  2. getResultKeys 方法提供所有键值对的所有键值的列表
  3. getResultValue 方法将与指定键关联的值作为 String 返回
  4. getResultObject 方法将与指定键关联的值作为 object 返回,即与被启动的应用程序存储的数据类型相同

关于Intent

Android使用 Intent 对象向系统发送命令。Intent包含执行指定操作所需的所有信息。例如,AI2的 ActivityStarter 在内部使用Intents来启动其他应用程序。

传递给 LaunchAppFromIntentLaunchForResultFromIntent 函数的 UrsIntent参考)对象用于指定点击通知时要触发哪个操作。

此组件是属性的集合。它既没有函数也没有事件。

ActionType 指定使用 Intent 触发哪个操作:

  • Screen:点击通知时,将打开应用程序的指定屏幕
  • Launcher:点击通知将打开任何应用程序。另请参阅App Inventor的 ActivityStarter 文档

Android 10和小米设备的额外权限

注意:使用Android 10及更新版本的小米设备用户必须授予两个权限!

Android 10

从Android 10开始,如果应用程序想在后台运行时启动另一个应用程序,需要额外的权限(SYSTEM_ALERT_WINDOW)(参见 从后台启动活动的限制,最后一点)。此权限无法通过程序设置,必须通过对话框由用户确认(参见 Android 10和小米设备的额外权限)。

扩展提供了 CheckBackgroundLaunchPermission 方法。该方法检查安装的Android版本是否具有API级别29(Android 10)或更高,以及是否已授予 SYSTEM_ALERT_WINDOW 权限。如果需要授予此权限,将打开授予权限的对话框:

德语变体 英语变体
德语变体 英语变体

权限请求的结果通过 AfterBackgroundPermssion 事件返回。关闭授权对话框后,权限的新状态不会立即可用。因此,事件在关闭对话框后短时间延迟后触发(属性 PermissionDelay,默认500毫秒)。在此期间,权限的状态未定义。建议确保不显示无意义的数据或在此期间不能进行有问题的输入。最好将所有相关的屏幕元素放入 VerticalArrangement。这可以暂时切换为不可见,或者通过 EnableArrangement 方法禁用(参见下面的示例)。

有关此权限的进一步详细处理,您可以使用:

  • 属性 VersionSDK:返回安装的API级别(Android 10为29)
  • 属性 CanDrawOverlays:返回是否已授予 SYSTEM_ALERT_WINDOW 权限
  • 属性 CanLaunchFromBackground:返回此应用程序在后台运行时是否可以启动其他应用程序,即API级别小于29或已授予 SYSTEM_ALERT_WINDOW 权限

小米设备

对于小米设备,无论安装的Android版本如何,如果应用程序想在后台运行时启动另一个应用程序,都需要额外的权限。此权限无法通过程序设置,必须通过对话框由用户确认(参见 Android 10和小米设备的额外权限)。程序无法查询是否已授予此权限。

以下是处理此问题的可用元素:

  • 属性 Manufacturer:返回制造商名称(例如 “Xiaomi”)
  • 属性 IsXiaomi:返回设备是否来自制造商小米
  • 属性 CurrentLanguage:返回设置的语言(”de”、”en” 等,参见 ISO 639-1代码列表)。有助于显示相关信息(参见示例)
  • 方法 OpenMiuiPermissionEditor:打开特殊的小米权限编辑器

小米权限编辑器:

德语变体 英语变体
德语变体 英语变体

示例项目展示了处理这些权限的一种方法。

您也可以通过设置应用程序获取权限。此博客条目展示了如何操作:在新小米手机上启用”显示弹出窗口”。另一种访问方式:长按应用程序图标,然后选择”应用信息”。

参考

属性 Properties

可绘制覆盖层 CanDrawOverlays
返回是否已授予 SYSTEM_ALERT_WINDOW 权限。
可从后台启动 CanLaunchFromBackground
返回此应用程序在后台运行时是否可以启动其他应用程序,即API级别小于29或已授予 SYSTEM_ALERT_WINDOW 权限。
当前语言 CurrentLanguage
返回设置的语言(”de”、”en” 等参见 ISO 639-1代码列表)。有助于显示相关信息。
是否小米设备 IsXiaomi
返回设备是否来自制造商小米。
制造商 Manufacturer
返回制造商名称(例如 “Xiaomi”)。
我的应用名称 MyAppName
提供当前应用程序的名称。
我的包名 MyPackageName
提供当前应用程序的包名。
权限延迟 PermissionDelay
关闭授权对话框后触发 AfterBackgroundPermssion 事件的延迟时间(毫秒)。默认值为500毫秒。
版本名称 VersionName
返回系统的版本名称。
版本SDK VersionSDK
返回安装的API级别(Android 10为29)。

事件 Events

活动结束后 AfterActivity(结果)
被启动的应用程序正常终止时触发。返回的值在参数 Result 中。
应用启动后 AfterAppLaunched(启动成功)
应用程序启动尝试后触发。参数指示启动是否成功。
后台权限后 AfterBackgroundPermssion(权限已授予)
请求后台启动权限后触发。参数指示是否已授予权限。
活动被取消 ActivityCanceled()
被启动的应用程序在未返回结果的情况下被取消时触发。

方法 Methods

检查后台启动权限 CheckBackgroundLaunchPermission()
检查是否需要后台启动权限并在需要时请求它。
获取名称列表 getNameList(过滤器)
提供已安装和可启动应用程序的名称作为按字母排序的列表。

可以使用 Filter 参数进行预选择。只返回那些名称包含指定文本的应用程序。指定空文本(”“)表示不进行过滤。过滤器值不区分大小写。
获取包名列表 getPackageList(过滤器)
提供已安装和可启动应用程序的包名作为按字母排序的列表。

可以使用Filter参数进行预选择。只返回那些名称包含指定文本的应用程序。指定空文本(”“)表示不进行过滤。过滤器值不区分大小写。
启动应用 LaunchApp(包名)
使用指定包名启动应用程序作为独立进程。
启动应用并返回结果 LaunchAppForResult(包名)
使用指定包名启动应用程序作为依赖进程。
启动AI2应用 LaunchAI2App(包名,启动值)
使用指定包名启动AI2应用程序作为独立进程。通过AI2标准参数传输方法传输启动值。
启动AI2应用并返回结果 LaunchForResultAI2App(包名,启动值)
使用指定包名启动AI2应用程序作为依赖进程。通过AI2标准参数传输方法传输启动值。
启动应用(额外值) LaunchAppExtra(包名,,)
使用指定包名启动应用程序作为独立进程,并传输单个键值对。
启动应用并返回结果(额外值) LaunchForResultAppExtra(包名,,)
使用指定包名启动应用程序作为依赖进程,并传输单个键值对。
启动应用(额外值列表) LaunchAppExtraList(包名,键值对)
使用指定包名启动应用程序作为独立进程。Pairs 参数是一个包含两个值的列表的列表。第一个值被解释为键,第二个值被解释为关联的值。
启动应用并返回结果(额外值列表) LaunchForResultAppExtraList(包名,键值对)
使用指定包名启动应用程序作为依赖进程。Pairs 参数是一个包含两个值的列表的列表。第一个值被解释为键,第二个值被解释为关联的值。
从Intent启动应用 LaunchAppFromIntent(意图对象)
使用指定的Intent对象启动应用程序作为独立进程。
从Intent启动应用并返回结果 LaunchForResultFromIntent(意图对象)
使用指定的Intent对象启动应用程序作为依赖进程。
打开小米权限编辑器 OpenMiuiPermissionEditor()
打开特殊的小米权限编辑器。
从名称获取包名 PackageFromName(应用名称)
返回在 AppName 参数中指定其应用程序名称的应用程序的包名。
获取结果键 getResultKeys()
提供所有键值对的所有键值的列表。
获取结果值 getResultValue()
将与指定键关联的值作为 String 返回。
获取结果对象 getResultObject()
将与指定键关联的值作为 object 返回,即与被启动的应用程序存储的数据类型相同。

示例

两个AI2应用之间的数据交换

此示例展示如何从主应用启动响应器应用并交换数据。

  1. 主应用启动响应器应用并传输启动值
  2. 响应器应用接收启动值并处理
  3. 响应器应用返回处理结果
  4. 主应用接收返回结果

通过应用列表启动

  1. 使用 getNameList 获取所有可启动应用列表
  2. ListPicker 中显示应用列表
  3. 用户选择应用后,使用 PackageFromName 获取包名
  4. 使用获取的包名启动应用

Android 10权限处理

  1. 检查 VersionSDK 是否 >= 29
  2. 检查 CanDrawOverlays 是否为false
  3. 如果需要权限,调用 CheckBackgroundLaunchPermission
  4. AfterBackgroundPermssion 事件中处理权限结果
  5. 在权限请求期间禁用相关UI元素

小米设备权限处理

  1. 检查 IsXiaomi 是否为true
  2. 调用 OpenMiuiPermissionEditor 打开权限编辑器
  3. 引导用户手动授予权限
  4. 根据 CurrentLanguage 显示相应语言的说明

LauncherIntent参考

⚠️ 注意:从Android 10开始,FlagNewTask 属性必须设置为 true

ActionType 指定使用Intent触发哪个操作:

  • Screen:点击通知时,将打开应用程序的指定屏幕
  • Launcher:点击通知将打开任何应用程序。另请参阅App Inventor的ActivityStarter文档

列说明S 列标记与 ActionType Screen 相关的字段,L 列标记与 ActionType Launcher 相关的字段。

属性表格 Properties Table

名称 类型 S L 功能 默认值
ActionType choice
(仅设计器)
X X 指定操作类型。可能的值:NoneScreenLauncherEventGoBack。根据 ActionType 评估不同的字段 None
ActivityAction text - X 指定将用于启动 Activity 的操作 -none-
ActivityClass text - X 指定要启动的特定组件的类部分。ActivityPackageActivityClass 定义点击通知时要启动的 Activity -none-
ActivityPackage text - X 指定要启动的特定组件的包部分。ActivityPackageActivityClass 定义点击通知时要启动的 Activity -none-
DataType text - X 指定要传递给Activity的MIME类型 -none-
DataUri text - X 指定将用于启动活动的数据URI -none-
FlagClearTask boolean X X 此标志将导致在活动启动之前清除与该活动关联的任何现有任务 false
FlagClearTop boolean X X 如果设置,并且正在启动的 Activity 已在当前任务中运行,则不会启动该 Activity 的新实例,而是关闭其上方的所有其他活动,并将此 Intent 作为新的 Intent 传递给(现在在顶部的)旧 Activity false
FlagExcludeFromRecent boolean X X 如果设置,新的 Activity 不会保留在最近启动活动的列表中 false
FlagNewTask boolean X X 如果设置,此 Activity 将成为此历史堆栈上新任务的开始。
从Android 10开始,此标志必须设置为 true
true
FlagNoAnimation boolean X X 此标志将阻止系统应用 Activity 过渡动画到下一个活动状态 false
FlagNoHistory boolean X X 如果设置,新的 Activity 不会保留在历史堆栈中。一旦用户离开它,活动即结束 false
FlagPreviousIsTop boolean X X 如果设置并使用此 Intent 从现有活动启动新 Activity,则当前 Activity 将不被视为决定是否应将新 Intent 传递到顶部而不是启动新活动的顶部 Activity。将使用前一个 Activity 作为顶部,假设当前 Activity 将立即完成 false
FlagReorderToFront boolean X X 如果正在运行的 Activity 已在运行,此标志将导致启动的 Activity 被带到其任务历史堆栈的前面 false
FlagResetTaskIfNeeded boolean X X 如果设置,并且此 Activity 要么在新任务中启动,要么将现有任务带到前面,则它将作为任务的前门启动。这将导致应用任何必要的亲和力来使该任务处于适当状态(要么将活动移入或移出,要么只是根据需要将该任务重置为其初始状态) false
FlagSingleTop boolean X X 如果设置,如果 Activity 已在历史堆栈顶部运行,则不会启动 false
FlagTaskOnHome boolean X X 此标志将导致新启动的任务置于当前家庭活动任务(如果有的话)之上。也就是说,从任务按回将始终返回用户到家庭,即使那不是他们看到的最后一个活动。这只能与 FLAG_ACTIVITY_NEW_TASK 结合使用 false
ScreenStartValue text X - 要传输到要打开的 Screen 的启动值。通过 Control.getStartValue 可用 -none-
ScreenToOpen text X - 点击通知时要打开的 Screen 的名称 “Screen1”

示例

下载压缩包包含两个示例应用程序:

App Launcher UrsAI2AppLauncherTest.aia:用于启动其他应用程序

App Launcher Responder UrsAI2AppLauncherTestResponder.aia:显示启动和返回值

两个AI2应用之间的数据交换

第一个示例显示两个AI2应用之间的数据交换。

示例1概览

启动应用块 返回列表 结果块
启动应用块 返回列表 结果块
应用程序通过其名称启动。
显示尝试的结果。
应用程序返回包含文本值的列表。 显示键值对的键列表和键为 “APP_INVENTOR_RESULT” 的键值对的值。

通过应用列表启动

以下示例显示如何使用 getNameListPackageFromName 方法启动应用程序。调用 LaunchForResult 会导致启动应用程序暂停,直到启动的应用程序终止。

示例2

| 显示可用应用列表 | 选择”相机”应用(德语Android版本) | 启动应用 | 显示启动应用程序的终止状态 | |—————-|——————————–|———|————————|

Android 10权限

当应用程序启动(Screen.Initialize)时,会检查是否可以从后台启动其他应用程序。所有相关的屏幕元素都嵌入在 HiddenPart VerticalArrangement 中,以便在请求必要权限和响应之间的时间内无法进行输入。此安排在应用程序启动时使用我的扩展 UrsAI2ComponentGroupEnableArrangement 方法阻止。

Android 10权限处理 Android 10 - 隐藏部分 Android 10 - 权限检查

顶部有不可见的警告。所有基本元素都嵌入在 HiddenPart 中。 所有基本元素都嵌入在 HiddenPart 中。 当应用程序启动时,HiddenPart 被阻止并检查授权。

当接收到权限请求的响应时,HiddenPart 被激活。如果未授予从后台启动应用程序的权限,则警告变为可见。

Android 10权限结果

小米设备权限

小米权限编辑器块

当应用程序启动时,会检查是否为小米设备。在这种情况下,打开Miui权限编辑器的按钮被激活。当应用程序首次启动时,会显示一个通知屏幕,要求用户设置所需的权限。为了使这种情况不会每次启动应用程序时都发生,数据库(TinyDB)存储是否已显示消息。通知提供两种语言:德语和英语。

通知

德语变体 英语变体
德语通知 英语通知

工具

ZIP压缩包包含以下文件:

  • 源代码(.java文件)
  • 编译的扩展文件(.aix)
  • 示例应用程序(.aia文件)
  • 文档和图标

示例应用程序

示例应用程序演示了扩展的所有主要功能,包括:

  • 基本应用启动
  • 参数传输
  • 返回值处理
  • 权限管理
  • 小米设备特殊处理

开发工具

  • 调试实用工具:用于开发和调试的辅助工具
  • 组件图标:用于可视化界面的图标资源
  • 文档:完整的API参考和使用说明

原文链接

原版英文文档:Ullis Roboter Seite - AI2 App Launcher

文档反馈