Alarm 闹钟扩展
下载
.aix拓展文件:
de.ullisroboterseite.ursai2alarm.aix
.aia示例文件:
版本历史
| 版本 | 修改内容 |
|---|---|
| 1.0 (2021-04-26) | 初始版本 |
| 2.0 (2021-05-15) | 当包名更改时,ScreenToOpen 在Kodular上无法工作 |
| 2.1 (2021-06-12) | - AlarmIntent 中的 FlagNewTask 属性未正确设置。从Android 10开始,此标志必须设置为 true 才能从闹钟启动新活动- AlarmIntent 中的 FlagNewTask 属性默认值更改为 true- 方法 CreateAlarm... 中的 WakeUp 参数未正确评估 |
| 2.2 (2021-07-21) | 在较长的闹钟时间且屏幕关闭时,闹钟无法可靠唤醒设备: - 闹钟接收器设置WakeLock以获得足够时间启动计划的活动 - EnableShowOnLockScreen 方法启用在锁屏上显示的功能参见”要启动活动的规则”部分 |
| 2.3 (2022-10-13) | 适配SDK31(Android 12): 所有 PendingIntent 都获得 FLAG_IMMUTABLE 标志请求 android.permission.SCHEDULE_EXACT_ALARM 权限捕获全局异常并写入日志 |
动机
尽管Android文档强烈建议使用通知(参见 developer.android.com),但在某些情况下,仍然需要在特定时间启动应用程序。使用此扩展,可以在指定时间启动应用程序。如果您想定时生成通知,必须使用扩展 UrsAI2Notifier。
⚠️ 重要提示
Android 10及以上版本用户注意:
在闹钟时间,扩展的一个类在后台启动。从Android 10开始,如果应用程序想在后台运行时启动另一个应用程序,需要额外的权限 (SYSTEM_ALERT_WINDOW)(参见 从后台启动活动的限制,最后一点)。此权限无法通过程序设置,必须通过对话框由用户确认(参见 Android 10和小米设备的额外权限)。示例中展示了解决此问题的可能方案。
为了启动新活动,`AlarmIntent` 中的 `FlagNewTask` 属性必须设置为 true!
小米设备制造商用户注意:
在闹钟时间,扩展的一个类在后台启动。对于小米设备,无论安装的Android版本如何,如果应用程序想在后台运行时启动另一个应用程序,都需要额外的权限。此权限无法通过程序设置,必须通过对话框由用户确认(参见 Android 10和小米设备的额外权限)。程序无法查询是否已授予此权限。示例中展示了解决此问题的可能方案。
使用Android 10及更新版本的小米设备用户必须授予两个权限。
⚠️ 注意:此扩展在AI伴侣中不起作用。闹钟通过广播消息触发。为了使应用程序在关闭时也能接收广播消息,应用程序必须提供广播接收器。此接收器必须在应用程序的清单中声明。这在AI伴侣中无法实现。
使用方法
要通过操作系统执行的任务通过意图(intent)提交。意图是要执行的操作的抽象描述。闹钟时间要执行的操作由这样的意图指定。
扩展包含两个模块:
- UrsAI2Alarm:提供生成闹钟的属性和方法
- AlarmIntent:指定闹钟发生时要执行的操作
闹钟 Alarms
UrsAI2Alarm 模块可以生成和删除闹钟。闹钟通过请求代码唯一标识。创建闹钟时,必须指定请求代码,以后可以用来删除闹钟。
不幸的是,Android没有提供找出哪些闹钟仍在等待触发的方法。您必须自己管理这些。通知闹钟测试示例展示了如何做到这一点。
CreateAlarm 和 CreateAlarmEx 在指定的延迟后生成闹钟。Android AlarmManager 即使应用程序关闭也会执行存储的操作。CreateAlarmAt 在特定时间生成闹钟。
CancelAlarm 取消尚未触发的闹钟。
意图 Intents
Android使用Intent对象向系统提交任务。Intent包含执行任务所需的所有信息。例如,AI2的ActivityStarter在内部使用Intents来启动其他应用程序。
传递给CreateAlarm...函数的AlarmIntent对象用于指定闹钟触发时要执行的操作。
此AlarmIntent组件是属性的集合。它既没有函数也没有事件。
ActionType 指定使用意图触发哪个操作:
Screen:点击通知时,打开您自己应用程序的指定屏幕Launcher:点击通知将打开任何应用程序。另请参阅App Inventor的ActivityStarter文档
要启动活动的规则
为了使应用程序(活动)可靠地唤醒设备,要启动的应用程序必须相应地配备。首先,应用程序必须具有适当的权限。对于小米设备,这必须通过单独的对话框由用户授予(参见下一节)。
然后,启动的活动(在App Inventor中这是Screen)必须请求打开显示,并显示在锁屏上。还必须关闭输入PIN码。这可以通过EnableShowOnLockScreen函数为AI2或Kodular应用程序实现。此外,活动必须设置WakeLock,否则设备将立即返回锁定状态。
如果选择AI2屏幕作为目标,建议为Screen.Initialize事件使用以下代码块:

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。这可以暂时切换为不可见,或者通过UrsAI2ComponentGroup扩展的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
- 返回是否允许从后台启动应用程序。
- 当前语言 CurrentLanguage
- 返回当前语言,例如 ‘de’ 或 ‘en’(参见 ISO 639-1代码列表)。
- 是否小米设备 IsXiaomi
- 返回这是否是小米设备。
- 制造商 Manufacturer
- 返回设备的制造商名称。
- 权限延迟 PermissionDelay
- 权限对话框关闭后内部请求
CanLaunchFromBackground的延迟时间(参见 Android 10和小米设备的额外权限)。默认值为500毫秒。 - 版本 Version
- 返回扩展的版本名称。
- 版本SDK VersionSDK
- 返回运行的Android SDK版本(API级别)。
事件 Events
- 后台权限后 AfterBackgroundPermssion(结果)
- 返回
CheckBackgroundLaunchPermission的结果。权限对话框关闭后有PermissionDelay毫秒的延迟(参见 Android 10和小米设备的额外权限)。
方法 Methods
- 取消闹钟 CancelAlarm(请求代码)
- 取消尚未触发的闹钟。
RequestCode:此闹钟的唯一数字ID。 - 检查后台启动权限 CheckBackgroundLaunchPermission()
- 检查是否允许从后台启动应用程序,如果不允许,请求权限。
- 创建闹钟 CreateAlarm(请求代码,延迟,类型,唤醒,闹钟意图对象)
- 在
Delay指定的延迟后执行由AlarmIntentObject定义的操作。RequestCode:此闹钟的唯一数字ID。Delay:延迟时间(秒)。Type:精度指示。WakeUp:时间到期时唤醒设备。AlarmIntentObject:定义闹钟时间要创建的通知的属性。
类型说明:Type 的值为0..3。根据 Type 调用不同的方法:
0:AlarmManager.set(自API级别1)
从API 19开始,传递给此方法的触发时间被视为不精确:闹钟不会在此时间之前发送,但可以推迟并在稍后时间发送。1:AlarmManager.setExact(自API级别19)
闹钟尽可能接近所需时间触发。2:AlarmManager.setAndAllowWhileIdle(自API级别23)
当系统处于打盹模式时也会触发此闹钟。3:AlarmManager.setExactAndAllowWhileIdle(自API级别23)
闹钟尽可能接近所需时间触发,并且当系统处于打盹模式时也会触发。
如果当前API级别不足,类型会被调整:1→0;2→0;3→1→0。
如果 Delay 的值小于零,不会创建通知,并触发 Screen.ErrorOccurred,错误号为17007。
如果 AlarmIntentObject 参数中指定的对象不是 AlarmIntent 类型,不会创建通知,并触发 Screen.ErrorOccurred,错误号为17006。
- 在指定时间创建闹钟 CreateAlarmAt(请求代码,毫秒时间,类型,唤醒,闹钟意图对象)
- 在
Millis指定的时间执行由AlarmIntentObject定义的操作。RequestCode:此闹钟的唯一数字ID。Millis:闹钟的时间(自1970年1月1日以来的毫秒数)。Type:精度指示。WakeUp:时间到期时唤醒设备。AlarmIntentObject:定义闹钟时间要创建的通知的属性。
Type 的值和调整规则与 CreateAlarm 方法相同。
Millis的值可以使用时钟组件的GetMillis方法获取。

如果 Millis 的值小于当前系统时间,不会创建通知,并触发 Screen.ErrorOccurred,错误号为17008。
如果 AlarmIntentObject 参数中指定的对象不是 AlarmIntent 类型,不会创建通知,并触发 Screen.ErrorOccurred,错误号为17006。
- 创建闹钟扩展 CreateAlarmEx(请求代码,延迟,类型,唤醒,闹钟意图对象)
- 在
Delay指定的延迟后执行由AlarmIntentObject定义的操作。返回生成通知的时间。RequestCode:此闹钟的唯一数字ID。Delay:延迟时间(秒)。Type:精度指示。WakeUp:时间到期时唤醒设备。AlarmIntentObject:定义闹钟时间要创建的通知的属性。
返回值:闹钟时间(自1970年1月1日以来的毫秒数)。此值可以传递给时钟组件的MakeInstantFromMillis方法以创建可读的日期时间格式。

Type 的值和调整规则与 CreateAlarm 方法相同。
- 启用锁屏显示 EnableShowOnLockScreen()
- 启用在锁屏上显示应用程序的能力。如果需要,这会请求必要的权限并显示系统密钥保护对话框。此方法应在应用程序的Screen.Initialize事件中使用。
AlarmIntent参考
⚠️ 注意:从Android 10开始,
FlagNewTask属性必须设置为true。
⚠️ 问题:如果目标不是
Screen1并且使用control.close application关闭屏幕,连续生成类型为Screen的意图的闹钟存在问题。原因是App Inventor程序中的内部进程。最好通过闹钟启动Screen1,评估control.get start value参数,并通过control.open another screen从Screen1打开请求的屏幕。
ActionType 指定使用Intent触发哪个操作:
Screen:点击通知时,将打开应用程序的指定屏幕Launcher:点击通知将打开任何应用程序。另请参阅App Inventor的ActivityStarter文档
列说明:S 列标记与 ActionType Screen 相关的字段,L 列标记与 ActionType Launcher 相关的字段。
属性表格 Properties Table
| 名称 | 类型 | S | L | 功能 | 默认值 |
|---|---|---|---|---|---|
| ActionType | choice (仅设计器) |
X | X | 指定操作类型。可能的值为 Screen 或 Launcher。根据 ActionType 评估不同的字段 |
None |
| ActivityAction | text | - | X | 指定将用于启动 Activity 的操作 |
-none- |
| ActivityClass | text | - | X | 指定要启动的特定组件的类部分。ActivityPackage 和 ActivityClass 定义点击通知时要启动的 Activity |
-none- |
| ActivityPackage | text | - | X | 指定要启动的特定组件的包部分。ActivityPackage 和 ActivityClass 定义点击通知时要启动的 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 |
false |
| 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” |
示例
下载压缩包包含一个示例项目:
UrsAlarmTest
⚠️ 注意:此扩展在AI伴侣中不起作用。闹钟通过广播消息触发。为了使应用程序在关闭时也能发送广播消息,应用程序必须提供广播接收器。此接收器必须在应用程序的清单中声明。这在AI伴侣中无法实现。
屏幕有两个按钮:
- 闹钟打开URS:创建一个闹钟,延迟10秒后打开标准浏览器并显示 “Ullis Roboter Seite”
- 闹钟打开Screen2:创建一个闹钟,延迟10秒后打开此应用程序的
Screen2
每次生成闹钟后都会关闭应用程序。因此闹钟在应用程序未打开时执行。
不幸的是,Android没有提供确定哪些闹钟仍在等待的方法。通知闹钟测试示例展示了如何管理闹钟。
AppLauncher扩展的示例展示了如何在Android 10或小米设备上请求特殊权限。
工具
对于开发自己的扩展,我收集了一些提示:AI2 FAQ:开发扩展。




扫码添加客服咨询