Englisch version   English version


Version Adjustment
1.0 (2021-04-26) Initial version
2.0 (2021-05-15) ScreenToOpen did not work on Kodular when the package name was changed. .

Motivation

Although the Android documentation strongly recommends working with notifications (see developer.android.com), under certain circumstances it is still necessary for an app to be started at a certain point in time. With this extension, apps can be started at specified times. If you want to generate notifications at time, you have to use the extension UrsAI2Notifier.

Note for users of devices with Android 10  and up:

At the time of the alarm, a class of the extension is started in the background. Since Android 10, an app needs additional permissions (SYSTEM_ALERT_WINDOW) if it wants to start another app while it is running itself in the background (see Restrictions on starting activities from the background, last point). This permission cannot be set by program, but has to be confirmed by the user via a dialog (see Additional permissions since Android 10 and on Xiaomi devices). A possible solution to the problem is presented in the example.

 

Note for users of devices from the manufacturer Xiaomi:

At the time of the alarm, a class of the extension is started in the background. With Xiaomi devices, regardless of the Android version installed, a additional permission is required if an app wants to start another app while it is itself running in the background. This permission cannot be not set by the program, but has to be confirmed by the user via a dialog (see Additional permissions since Android 10 and on Xiaomi devices). The program cannot query whether this permission has already been granted. A possible solution to the problem is presented in the example.

Users of Xiaomi devices with Android 10 and newer must grant both permissions.


Content

Download

Usage

Alarms

Intents

Additional permissions since Android 10 and on Xiaomi devices

Android 10

Xiaomi devices

Reference

Properties

Methods

Events

Reference AlarmIntent

Example

Tools

Download

The  UrsAI2Alarm ZIP archive for download. The archive contains the source code, the compiled binary for uploading to the App Inventor and a sample application.

Usage

Note:

The extension does not work in the companion. Alarms are triggered via broadcast messages. In order for an app to send broadcast messages even when it is closed, the app must provide a broadcast receiver. This receiver must be declared in the app's manifest. This not possible with the Companion.

Tasks that are to be executed by the operating system are committed via an intent. A intent is an abstract description of an operation to be performed. The operation to be executed at the time of the alarm is specified by such an intent.

The extension contains two blocks:

UrsAI2Alarm: Provides properties and methods that generate alarms.

AlarmIntent: Specifies the operation to be executed when the alarm occurs.

Alarms

The UrsAI2Alarm block can generate and delete alarms. An alarm is uniquely identified by the request code. When creating an alarm, a request code must be specified and can be used to delete an alarm later.

Unfortunately, Android does not offer a way to find out which alarms are still waiting to be triggered. You have to manage this yourself. The Notification Alarm Test example shows how this can be done.

CreateAlarm and CreateAlarmEx generate alarms after a specified delay. The Android AlarmManager executes the stored action even if the app is closed. CreateAlarmAt generates the alarm at a specific point in time.

CancelAlarm cancels an alarm that has not yet been triggered.

Intents

Android uses Intent objects to submit tasks to the system. An Intent contains all information that is necessary to execute the task. The AI2 ActivityStarter, for example, uses Intents internally to start other apps.

An AlarmIntent object that is passed to the CreateAlarm... functions is used to specify which action is to be executed when the alarm is triggered.

This AlarmIntent component is a collection of properties. It has neither functions nor events.

The ActionType specifies which action is triggered with the intent:

Additional permissions since Android 10 and on Xiaomi devices

Note: Users of Xiaomi devices with Android 10 and newer must grant both permissions!

Android 10

Since Android 10, an app needs additional permissions (SYSTEM_ALERT_WINDOW) if it wants to start another app while it is running itself in the background (see Restrictions on starting activities from the background, last point). This permission cannot be set by program, but has to be confirmed by the user via a dialog (see Additional permissions since Android 10 and on Xiaomi devices).

The extension provides the CheckBackgroundLaunchPermission method. The method checks whether the installed Android version has an API level of 29 (Android 10) or higher and whether the SYSTEM_ALERT_WINDOW permission has been granted. If it is necessary that this permission is granted, a dialog for granting the permission is opened:

 
German variant   English variant

The result of the permission request is returned via the AfterBackgroundPermssion  event. The new state of the permission is not available immediately after closing the authorization dialog. The event is therefore triggered after a short delay (property PermissionDelay, default 500 ms) after closing the dialog. During this time, the state of the permission is undefined. It is advisable to ensure that no nonsensical data is displayed or problematic entries can be made meanwhile. It is best to put all the concerned screen elements into aVerticalArrangement. This can be temporarily switched invisible or, for example, deactivated via the EnableArrangement method of the UrsAI2ComponentGroup extension ( see example below).

For further detailed handling of this permission you can use:

Xiaomi devices

With Xiaomi devices, regardless of the Android version installed, a additional permission is required if an app wants to start another app while it is itself running in the background. This permission cannot be not set by the program, but has to be confirmed by the user via a dialog (see Additional permissions since Android 10 and on Xiaomi devices). The program cannot query whether this permission has already been granted.

The following elements are available to handle this problem:

The Xiaomi permission editor:

 
German variant   English variant

The sample project shows one way how these permissions can be handled.

You can also get the permision via the Settings app. This blog entry shows how to do it: Enable “display pop-up windows” on new Xiaomi phones. Another access option: Long press the app icon, then select "App-Info".

Reference

Properties

CanDrawOverlays
Returns whether permission SYSTEM_ALERT_WINDOW is granted.
CanLaunchFromBackground
Returns whether you are permitted to lauch apps while in background.
CurrentLanguage
Returns the current language, e.g. 'de' or 'en'." (see List of ISO 639-1 codes).
IsXiaomi
Returns whether this is a Xiaomi device.
Manufacturer
Returns the manufacturer name of the device.
PermissionDelay
Delay for internal request of CanLaunchFromBackground after permission dialog was closed (see Additional permissions since Android 10 and on Xiaomi devices). The default is 500 ms.
Version
Returns the extension's version name.
VersionSDK
Returns running Android SDK version (API level).

Methods

CancelAlarm (RequestCode)
Cancels an alarm that has not yet been triggered. RequestCode: Unique numeric ID for this alarm.
CheckBackgroundLaunchPermission ()
Checks if lauching apps from the background is permitted and if not, asks for the permission.
CreateAlarm (RequestCode, Delay, Type, WakeUp, AlarmIntentObject)
Executes the operation defined by AlarmIntentObject after a delay specified by Delay. RequestCode: Unique numeric ID for this alarm. Delay: Delay in seconds. Type: indication of the accuracy. WakeUp: Wakes up the device when the time has expired. UrsNotificationObject: defines the properties of the notification to be created at the time of the alarm. UrsIntentObject: defines what action is executed when the notification is tapped.

Type has the values 0..3. These methods are called depending on Type:

  • 0: AlarmManager.set (since API Level 1)
    As of API 19, the trigger time passed to this method is treated as imprecise: the alarm is not sent before this time, but can be postponed and sent some time later.
  • 1: AlarmManager.setExact (since API Level 19) The alarm is triggered as close as possible to the desired time.
  • 2: AlarmManager.setAndAllowWhileIdle (ab API Level 23) This alarm is also triggered when the system is in doze mode.
  • 3: AlarmManager.setExactAndAllowWhileIdle (ab API Level 23)
    The alarm is triggered as close as possible to the desired time and is also triggered when the system is in doze mode.

If the current API level is not sufficient, the type is adapted : 10; 20; 310;

If the value for Delay is less than zero, the notification is not created and Screen.ErrorOccurred is triggered with ErrorNumber 17007.

If the object specified in the AlarmIntentObject parameter is not of the AlarmIntent type, the notification is not created and Screen.ErrorOccurred is triggered with ErrorNumber 17006.

CreateAlarmAt (RequestCode, Millis, Type, WakeUp, AlarmIntentObject)
Executes the operation defined by AlarmIntentObject at the time specified by Millis. RequestCode: Unique numeric ID for this alarm. Millis: the time of the alarm in milliseconds since 1.1.1970. Type: indication of the accuracy. WakeUp: Wakes up the device when the time has expired. UrsNotificationObject: defines the properties of the notification to be created at the time of the alarm. UrsIntentObject: defines what action is executed when the notification is tapped.

Type has the values 0..3. These methods are called depending on Type:

  • 0: AlarmManager.set (since API Level 1)
    As of API 19, the trigger time passed to this method is treated as imprecise: the alarm is not sent before this time, but can be postponed and sent some time later.
  • 1: AlarmManager.setExact (since API Level 19) The alarm is triggered as close as possible to the desired time.
  • 2: AlarmManager.setAndAllowWhileIdle (ab API Level 23) This alarm is also triggered when the system is in doze mode.
  • 3: AlarmManager.setExactAndAllowWhileIdle (ab API Level 23)
    The alarm is triggered as close as possible to the desired time and is also triggered when the system is in doze mode.

If the current API level is not sufficient, the type is adapted : 10; 20; 310;

The value for Millis can be obtained from a clock component using the GetMillis method.

If the value for Millis is less than the current system time, the notification is not created and Screen.ErrorOccurred is triggered with ErrorNumber 17008.

If the object specified in the AlarmIntentObject parameter is not of the AlarmIntent type, the notification is not created and Screen.ErrorOccurred is triggered with ErrorNumber 17006.

CreateAlarmEx (RequestCode, Delay, Type, WakeUp, AlarmIntentObject)
Executes the operation defined by AlarmIntentObject after a delay specified by Delay. The time at which the notification is generated is returned. RequestCode: Unique numeric ID for this alarm. Delay: Delay in seconds. Type: indication of the accuracy. WakeUp: Wakes up the device when the time has expired. UrsNotificationObject: defines the properties of the notification to be created at the time of the alarm. UrsIntentObject: defines what action is executed when the notification is tapped.

The return value is the alarm time in milliseconds since 1.1.1970. This value can e.g. be transferred to the MakeInstantFromMillis method of a Clock component to create a readable date-time format.

Type has the values 0..3. These methods are called depending on Type:

  • 0: AlarmManager.set (since API Level 1)
    As of API 19, the trigger time passed to this method is treated as imprecise: the alarm is not sent before this time, but can be postponed and sent some time later.
  • 1: AlarmManager.setExact (since API Level 19) The alarm is triggered as close as possible to the desired time.
  • 2: AlarmManager.setAndAllowWhileIdle (ab API Level 23) This alarm is also triggered when the system is in doze mode.
  • 3: AlarmManager.setExactAndAllowWhileIdle (ab API Level 23)
    The alarm is triggered as close as possible to the desired time and is also triggered when the system is in doze mode.

If the current API level is not sufficient, the type is adapted : 10; 20; 310;

If the value for Delay is less than zero, the notification is not created and Screen.ErrorOccurred is triggered with ErrorNumber 17007.

If the object specified in the AlarmIntentObject parameter is not of the AlarmIntent type, the notification is not created and Screen.ErrorOccurred is triggered with ErrorNumber 17006.

OpenMiuiPermissionEditor ()
Opens the MIUI permission editor.

Events

AfterBackgroundPermssion (Result)
Returns the result of CheckBackgroundLaunchPermission. There is a delay of PermissionDelay milliseconds after the permission dialog is closed (see Additional permissions since Android 10 and on Xiaomi devices).

Reference AlarmIntent

 The ActionType specifies which action is triggered with the Intent:

The column S marks fields that are relevant for the ActionType Screen, the column L those for the ActionType Launcher.

Type S L Functionality Default
choice
(Designer only)
X X Specifies the type of action. Possible values are None, Screen, Launcher, Event or GoBack. Different fields are evaluated depending on the ActionType. None
text - X Specifies the action that will be used to start the Activity. -none-
text - X Specifies the class part of the specific component that will be started.
ActivityPackage and ActivityClass define the Activity to be started when the notification is tapped.
-none-
text - X Specifies the class part of the specific component that will be started.
ActivityPackage and ActivityClass define the Activity to be started when the notification is tapped.
-none-
text - X Specifies the MIME type to pass to the Activity. -none-
text - X Specifies the data URI that will be used to start the activity. -none-
boolean X X This flag will cause any existing task that would be associated with the activity to be cleared before the activity is started. false
boolean X X If set, and the Activity being launched is already running in the current Task, then instead of launching a new instance of that Activity, all of the other activities on top of it will be closed and this Intent will be delivered to the (now on top) old Activity as a new Intent. false
boolean X X If set, the new Activity is not kept in the list of recently launched activities. false
boolean X X If set, this Activity will become the start of a new Task on this history stack false
boolean X X This flag will prevent the system from applying an Activity transition animation to go to the next activity state. false
boolean X X If set, the new Activity is not kept in the history stack. As soon as the user navigates away from it, the activity is finished. false
boolean X X If set and this Intent is being used to launch a new Activity from an existing one, the current Activity will not be counted as the top Activity for deciding whether the new Intent should be delivered to the top instead of starting a new one. The previous Activity will be used as the top, with the assumption being that the current Activity will finish itself immediately false
boolean X X This flag will cause the launched Activity to be brought to the front of its task's history stack if it is already running. false
boolean X X If set, and this Activity is either being started in a new Task or bringing to the top an existing Task, then it will be launched as the front door of the Task. This will result in the application of any affinities needed to have that Task in the proper state (either moving activities to or from it), or simply resetting that task to its initial state if needed. false
boolean X X If set, the Activity will not be launched if it is already running at the top of the history stack. false
boolean X X This flag will cause a newly launching task to be placed on top of the current home activity task (if there is one). That is, pressing back from the task will always return the user to home even if that was not the last activity they saw. This can only be used in conjunction with FLAG_ACTIVITY_NEW_TASK. false
text X X Unique ID of this Intent. -none-
text X - The start value to be transferred to the Screen to be opened. Available via Control.getStartValue . -none-
text X - The name of the Screen to open when you tap the notification. "Screen1"

Beispiel

The download archive contains a sample project:

 UrsAlarmTest

Note:

The extension does not work in the companion. Alarms are triggered via broadcast messages. In order for an app to send broadcast messages even when it is closed, the app must provide a broadcast receiver. This receiver must be declared in the app's manifest. This not possible with the Companion.

The screen has two buttons:

The app is closed each time after the alarm is generated. Therefore the alarm is executed when the app is not open.

Unfortunately, Android does not offer a way to determine which alarms are still pending. The Notification Alarm Test example shows how alarms can be managed.

The example for the AppLauncher extension shows how the special authorizations can be requested on Android 10 or Xiaomi devices.

Tools

For developing own extensions I gathered some tips: AI2 FAQ: Develop Extensions.